diff --git a/services/web/Makefile b/services/web/Makefile
index e59c7a4865..370695fa4b 100644
--- a/services/web/Makefile
+++ b/services/web/Makefile
@@ -132,9 +132,6 @@ compile_full:
$(MAKE) compile_modules_full
$(MAKE) compile # ide.js, main.js, share.js, and anything missed
-compile_css_full:
- $(MAKE) css_full
-
compile_modules: $(MODULE_MAKEFILES)
@set -e; \
for dir in $(MODULE_DIRS); \
diff --git a/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee b/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee
index 18948fa0df..8d95c9b41b 100644
--- a/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee
+++ b/services/web/app/coffee/Features/Authentication/AuthenticationController.coffee
@@ -203,7 +203,7 @@ module.exports = AuthenticationController =
return next()
else
logger.log url:req.url, "user trying to access endpoint not in global whitelist"
- AuthenticationController.setRedirectInSession(req)
+ AuthenticationController._setRedirectInSession(req)
return res.redirect "/login"
httpAuth: basicAuth (user, pass)->
@@ -212,16 +212,6 @@ module.exports = AuthenticationController =
logger.err user:user, pass:pass, "invalid login details"
return isValid
- setRedirectInSession: (req, value) ->
- if !value?
- value = if Object.keys(req.query).length > 0 then "#{req.path}?#{querystring.stringify(req.query)}" else "#{req.path}"
- if (
- req.session? &&
- !/^\/(socket.io|js|stylesheets|img)\/.*$/.test(value) &&
- !/^.*\.(png|jpeg|svg)$/.test(value)
- )
- req.session.postLoginRedirect = value
-
_redirectToLoginOrRegisterPage: (req, res)->
if (req.query.zipUrl? or req.query.project_name? or req.path == '/user/subscription/new')
return AuthenticationController._redirectToRegisterPage(req, res)
@@ -230,14 +220,14 @@ module.exports = AuthenticationController =
_redirectToLoginPage: (req, res) ->
logger.log url: req.url, "user not logged in so redirecting to login page"
- AuthenticationController.setRedirectInSession(req)
+ AuthenticationController._setRedirectInSession(req)
url = "/login?#{querystring.stringify(req.query)}"
res.redirect url
Metrics.inc "security.login-redirect"
_redirectToRegisterPage: (req, res) ->
logger.log url: req.url, "user not logged in so redirecting to register page"
- AuthenticationController.setRedirectInSession(req)
+ AuthenticationController._setRedirectInSession(req)
url = "/register?#{querystring.stringify(req.query)}"
res.redirect url
Metrics.inc "security.login-redirect"
@@ -255,6 +245,16 @@ module.exports = AuthenticationController =
Metrics.inc "user.login.failed"
callback()
+ _setRedirectInSession: (req, value) ->
+ if !value?
+ value = if Object.keys(req.query).length > 0 then "#{req.path}?#{querystring.stringify(req.query)}" else "#{req.path}"
+ if (
+ req.session? &&
+ !/^\/(socket.io|js|stylesheets|img)\/.*$/.test(value) &&
+ !/^.*\.(png|jpeg|svg)$/.test(value)
+ )
+ req.session.postLoginRedirect = value
+
_getRedirectFromSession: (req) ->
return req?.session?.postLoginRedirect || null
diff --git a/services/web/app/coffee/Features/Authorization/AuthorizationMiddlewear.coffee b/services/web/app/coffee/Features/Authorization/AuthorizationMiddlewear.coffee
index 54d54475f3..10daa41f75 100644
--- a/services/web/app/coffee/Features/Authorization/AuthorizationMiddlewear.coffee
+++ b/services/web/app/coffee/Features/Authorization/AuthorizationMiddlewear.coffee
@@ -117,5 +117,5 @@ module.exports = AuthorizationMiddlewear =
logger.log {from: from}, "redirecting to login"
redirect_to = "/login"
if from?
- AuthenticationController.setRedirectInSession(req, from)
+ AuthenticationController._setRedirectInSession(req, from)
res.redirect redirect_to
diff --git a/services/web/app/coffee/Features/Project/ProjectController.coffee b/services/web/app/coffee/Features/Project/ProjectController.coffee
index b3b8e9a6d4..618fc7c0b4 100644
--- a/services/web/app/coffee/Features/Project/ProjectController.coffee
+++ b/services/web/app/coffee/Features/Project/ProjectController.coffee
@@ -270,7 +270,7 @@ module.exports = ProjectController =
project: (cb)->
ProjectGetter.getProject(
project_id,
- { name: 1, lastUpdated: 1, track_changes: 1, owner_ref: 1, brandVariationId: 1, overleaf: 1 },
+ { name: 1, lastUpdated: 1, track_changes: 1, owner_ref: 1, brandVariationId: 1, 'overleaf.history.display': 1 },
cb
)
user: (cb)->
@@ -323,9 +323,6 @@ module.exports = ProjectController =
if subscription? and subscription.freeTrial? and subscription.freeTrial.expiresAt?
allowedFreeTrial = !!subscription.freeTrial.allowed || true
- showGitBridge =
- user.betaProgram && !project.overleaf?.id? # don't support v1 projects yet
-
logger.log project_id:project_id, "rendering editor page"
res.render 'project/editor',
title: project.name
@@ -373,7 +370,7 @@ module.exports = ProjectController =
brandVariation: brandVariation
allowedImageNames: Settings.allowedImageNames || []
gitBridgePublicBaseUrl: Settings.gitBridgePublicBaseUrl
- showGitBridge: showGitBridge
+ showGitBridge: req.query?.gitbridge == 'true' || user.isAdmin
timer.done()
_buildProjectList: (allProjects, v1Projects = [])->
diff --git a/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee b/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee
index 240980907a..dedc92e273 100644
--- a/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee
+++ b/services/web/app/coffee/Features/Project/ProjectDetailsHandler.coffee
@@ -74,7 +74,13 @@ module.exports = ProjectDetailsHandler =
if arguments.length is 3 && typeof suffixes is 'function' # make suffixes an optional argument
callback = suffixes
suffixes = []
- ProjectDetailsHandler.ensureProjectNameIsUnique user_id, name, suffixes, callback
+ timestamp = new Date().toISOString().replace(/T(\d+):(\d+):(\d+)\..*/,' $1$2$3') # strip out unwanted characters
+ ProjectDetailsHandler.ensureProjectNameIsUnique user_id, name, suffixes.concat(" (#{timestamp})"), callback
+
+ _addSuffixToProjectName: (name, suffix = '') ->
+ # append the suffix and truncate the project title if needed
+ truncatedLength = ProjectDetailsHandler.MAX_PROJECT_NAME_LENGTH - suffix.length
+ return name.substr(0, truncatedLength) + suffix
# FIXME: we should put a lock around this to make it completely safe, but we would need to do that at
# the point of project creation, rather than just checking the name at the start of the import.
@@ -100,12 +106,8 @@ module.exports = ProjectDetailsHandler =
candidateName = ProjectDetailsHandler._addSuffixToProjectName(name, suffix)
if isUnique(candidateName)
return callback(null, candidateName, true)
- # if there are no (more) suffixes, use a numeric one
- uniqueName = ProjectDetailsHandler._addNumericSuffixToProjectName(name, allProjectNames)
- if uniqueName?
- callback(null, uniqueName, true)
- else
- callback(new Error("Failed to generate a unique name for file: #{name}"))
+ # we couldn't make the name unique, something is wrong
+ return callback new Errors.InvalidNameError("Project name could not be made unique")
fixProjectName: (name) ->
if name == "" || !name
@@ -154,30 +156,3 @@ module.exports = ProjectDetailsHandler =
Project.update {_id: project_id}, {$set: {tokens: tokens}}, (err) ->
return callback(err) if err?
callback(null, tokens)
-
- _addSuffixToProjectName: (name, suffix = '') ->
- # append the suffix and truncate the project title if needed
- truncatedLength = ProjectDetailsHandler.MAX_PROJECT_NAME_LENGTH - suffix.length
- return name.substr(0, truncatedLength) + suffix
-
- _addNumericSuffixToProjectName: (name, allProjectNames) ->
- NUMERIC_SUFFIX_MATCH = / \((\d+)\)$/
- suffixedName = (basename, number) ->
- suffix = " (#{number})"
- return basename.substr(0, ProjectDetailsHandler.MAX_PROJECT_NAME_LENGTH - suffix.length) + suffix
-
- match = name.match(NUMERIC_SUFFIX_MATCH)
- basename = name
- n = 1
- last = allProjectNames.size + n
-
- if match?
- basename = name.replace(NUMERIC_SUFFIX_MATCH, '')
- n = parseInt(match[1])
-
- while n <= last
- candidate = suffixedName(basename, n)
- return candidate unless allProjectNames.has(candidate)
- n += 1
-
- return null
\ No newline at end of file
diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee
index bea41ecb6e..3a4280e4ec 100644
--- a/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee
+++ b/services/web/app/coffee/Features/Subscription/SubscriptionController.coffee
@@ -12,7 +12,6 @@ UserGetter = require "../User/UserGetter"
FeaturesUpdater = require './FeaturesUpdater'
planFeatures = require './planFeatures'
GroupPlansData = require './GroupPlansData'
-V1SubscriptionManager = require "./V1SubscriptionManager"
module.exports = SubscriptionController =
@@ -98,8 +97,7 @@ module.exports = SubscriptionController =
managedGroupSubscriptions,
confirmedMemberInstitutions,
managedInstitutions,
- v1Subscriptions,
- v1SubscriptionStatus
+ v1Subscriptions
} = results
logger.log {
user,
@@ -108,8 +106,7 @@ module.exports = SubscriptionController =
managedGroupSubscriptions,
confirmedMemberInstitutions,
managedInstitutions,
- v1Subscriptions,
- v1SubscriptionStatus
+ v1Subscriptions
}, "showing subscription dashboard"
plans = SubscriptionViewModelBuilder.buildViewModel()
data = {
@@ -121,8 +118,7 @@ module.exports = SubscriptionController =
managedGroupSubscriptions,
confirmedMemberInstitutions,
managedInstitutions,
- v1Subscriptions,
- v1SubscriptionStatus
+ v1Subscriptions
}
res.render "subscriptions/dashboard", data
@@ -162,15 +158,6 @@ module.exports = SubscriptionController =
return next(err)
res.redirect "/user/subscription"
- cancelV1Subscription: (req, res, next) ->
- user_id = AuthenticationController.getLoggedInUserId(req)
- logger.log {user_id}, "canceling v1 subscription"
- V1SubscriptionManager.cancelV1Subscription user_id, (err)->
- if err?
- logger.err err:err, user_id:user_id, "something went wrong canceling v1 subscription"
- return next(err)
- res.redirect "/user/subscription"
-
updateSubscription: (req, res, next)->
_origin = req?.query?.origin || null
user = AuthenticationController.getSessionUser(req)
diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionRouter.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionRouter.coffee
index c4155b58cb..d81b5f3f59 100644
--- a/services/web/app/coffee/Features/Subscription/SubscriptionRouter.coffee
+++ b/services/web/app/coffee/Features/Subscription/SubscriptionRouter.coffee
@@ -40,8 +40,6 @@ module.exports =
webRouter.post '/user/subscription/cancel', AuthenticationController.requireLogin(), SubscriptionController.cancelSubscription
webRouter.post '/user/subscription/reactivate', AuthenticationController.requireLogin(), SubscriptionController.reactivateSubscription
- webRouter.post '/user/subscription/v1/cancel', AuthenticationController.requireLogin(), SubscriptionController.cancelV1Subscription
-
webRouter.put '/user/subscription/extend', AuthenticationController.requireLogin(), SubscriptionController.extendTrial
webRouter.get "/user/subscription/upgrade-annual", AuthenticationController.requireLogin(), SubscriptionController.renderUpgradeToAnnualPlanPage
diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionUpdater.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionUpdater.coffee
index 22e2c00987..f4cdfcf86d 100644
--- a/services/web/app/coffee/Features/Subscription/SubscriptionUpdater.coffee
+++ b/services/web/app/coffee/Features/Subscription/SubscriptionUpdater.coffee
@@ -29,7 +29,13 @@ module.exports = SubscriptionUpdater =
@addUsersToGroup(subscriptionId, [userId], callback)
addUsersToGroup: (subscriptionId, memberIds, callback)->
- @addUsersToGroupWithoutFeaturesRefresh subscriptionId, memberIds, (err) ->
+ logger.log subscriptionId: subscriptionId, memberIds: memberIds, "adding members into mongo subscription"
+ searchOps =
+ _id: subscriptionId
+ insertOperation =
+ { $addToSet: { member_ids: { $each: memberIds } } }
+
+ Subscription.findAndModify searchOps, insertOperation, (err, subscription) ->
return callback(err) if err?
# Only apply features updates to users, not user stubs
@@ -39,14 +45,6 @@ module.exports = SubscriptionUpdater =
userIds = users.map (u) -> u._id.toString()
async.map userIds, FeaturesUpdater.refreshFeatures, callback
- addUsersToGroupWithoutFeaturesRefresh: (subscriptionId, memberIds, callback)->
- logger.log subscriptionId: subscriptionId, memberIds: memberIds, "adding members into mongo subscription"
- searchOps =
- _id: subscriptionId
- insertOperation =
- { $addToSet: { member_ids: { $each: memberIds } } }
-
- Subscription.findAndModify searchOps, insertOperation, callback
removeUserFromGroup: (subscriptionId, user_id, callback)->
searchOps =
diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionViewModelBuilder.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionViewModelBuilder.coffee
index 3f65cc5cf5..deebb04aa5 100644
--- a/services/web/app/coffee/Features/Subscription/SubscriptionViewModelBuilder.coffee
+++ b/services/web/app/coffee/Features/Subscription/SubscriptionViewModelBuilder.coffee
@@ -51,10 +51,6 @@ module.exports =
return cb(error) if error?
# Only return one argument to async.auto, otherwise it returns an array
cb(null, subscriptions)
- v1SubscriptionStatus: (cb) ->
- V1SubscriptionManager.getSubscriptionStatusFromV1 user._id, (error, status, v1Id) ->
- return cb(error) if error?
- cb(null, status)
}, (err, results) ->
return callback(err) if err?
{
@@ -64,7 +60,6 @@ module.exports =
confirmedMemberInstitutions,
managedInstitutions,
v1Subscriptions,
- v1SubscriptionStatus,
recurlySubscription,
plan
} = results
@@ -73,7 +68,6 @@ module.exports =
confirmedMemberInstitutions ?= []
managedInstitutions ?= []
v1Subscriptions ?= {}
- v1SubscriptionStatus ?= {}
if personalSubscription?.toObject?
@@ -103,8 +97,7 @@ module.exports =
memberGroupSubscriptions,
confirmedMemberInstitutions,
managedInstitutions,
- v1Subscriptions,
- v1SubscriptionStatus
+ v1Subscriptions
}
buildViewModel : ->
diff --git a/services/web/app/coffee/Features/Subscription/V1SubscriptionManager.coffee b/services/web/app/coffee/Features/Subscription/V1SubscriptionManager.coffee
index 0e63259734..2d25c8b3e5 100644
--- a/services/web/app/coffee/Features/Subscription/V1SubscriptionManager.coffee
+++ b/services/web/app/coffee/Features/Subscription/V1SubscriptionManager.coffee
@@ -39,18 +39,6 @@ module.exports = V1SubscriptionManager =
url: (v1Id) -> "/api/v1/sharelatex/users/#{v1Id}/subscriptions"
}, callback
- getSubscriptionStatusFromV1: (userId, callback=(err, status) ->) ->
- V1SubscriptionManager._v1Request userId, {
- method: 'GET',
- url: (v1Id) -> "/api/v1/sharelatex/users/#{v1Id}/subscription_status"
- }, callback
-
- cancelV1Subscription: (userId, callback=(err)->) ->
- V1SubscriptionManager._v1Request userId, {
- method: 'DELETE',
- url: (v1Id) -> "/api/v1/sharelatex/users/#{v1Id}/subscription"
- }, callback
-
v1IdForUser: (userId, callback=(err, v1Id) ->) ->
UserGetter.getUser userId, {'overleaf.id': 1}, (err, user) ->
return callback(err) if err?
@@ -88,7 +76,7 @@ module.exports = V1SubscriptionManager =
pass: settings.apis.v1.pass
sendImmediately: true
json: true,
- timeout: 15 * 1000
+ timeout: 5 * 1000
}, (error, response, body) ->
if error?
# Specially handle no connection err, so warning can be shown
diff --git a/services/web/app/coffee/Features/SudoMode/SudoModeMiddlewear.coffee b/services/web/app/coffee/Features/SudoMode/SudoModeMiddlewear.coffee
index b4f2b1cb91..64d238b543 100644
--- a/services/web/app/coffee/Features/SudoMode/SudoModeMiddlewear.coffee
+++ b/services/web/app/coffee/Features/SudoMode/SudoModeMiddlewear.coffee
@@ -21,5 +21,5 @@ module.exports = SudoModeMiddlewear =
return next()
else
logger.log {userId}, "[SudoMode] sudo mode not active, redirecting"
- AuthenticationController.setRedirectInSession(req)
+ AuthenticationController._setRedirectInSession(req)
return res.redirect('/confirm-password')
diff --git a/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee b/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee
index 07d3a67f2b..6a68825b8d 100644
--- a/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee
+++ b/services/web/app/coffee/Features/TokenAccess/TokenAccessController.coffee
@@ -60,7 +60,7 @@ module.exports = TokenAccessController =
else
logger.log {token, projectId: project._id},
"[TokenAccess] deny anonymous read-and-write token access"
- AuthenticationController.setRedirectInSession(req)
+ AuthenticationController._setRedirectInSession(req)
return res.redirect('/restricted')
if project.owner_ref.toString() == userId
logger.log {userId, projectId: project._id},
diff --git a/services/web/app/coffee/Features/User/UserPagesController.coffee b/services/web/app/coffee/Features/User/UserPagesController.coffee
index e906f3570e..5e6ea7d62b 100644
--- a/services/web/app/coffee/Features/User/UserPagesController.coffee
+++ b/services/web/app/coffee/Features/User/UserPagesController.coffee
@@ -51,7 +51,7 @@ module.exports =
# such as being sent from the editor to /login, then set the redirect explicitly
if req.query.redir? and !AuthenticationController._getRedirectFromSession(req)?
logger.log {redir: req.query.redir}, "setting explicit redirect from login page"
- AuthenticationController.setRedirectInSession(req, req.query.redir)
+ AuthenticationController._setRedirectInSession(req, req.query.redir)
res.render 'user/login',
title: 'login',
email: req.query.email
diff --git a/services/web/app/coffee/Features/UserMembership/UserMembershipAuthorization.coffee b/services/web/app/coffee/Features/UserMembership/UserMembershipAuthorization.coffee
index a7a5a45ef4..1b0e0ca442 100644
--- a/services/web/app/coffee/Features/UserMembership/UserMembershipAuthorization.coffee
+++ b/services/web/app/coffee/Features/UserMembership/UserMembershipAuthorization.coffee
@@ -6,39 +6,21 @@ Errors = require('../Errors/Errors')
logger = require("logger-sharelatex")
module.exports =
- requireTeamAccess: (req, res, next) ->
- requireAccessToEntity('team', req.params.id, req, res, next)
+ requireEntityAccess: (entityName, entityIdOverride = null) ->
+ (req, res, next) ->
+ loggedInUser = AuthenticationController.getSessionUser(req)
+ unless loggedInUser
+ return AuthorizationMiddlewear.redirectToRestricted req, res, next
- requireGroupAccess: (req, res, next) ->
- requireAccessToEntity('group', req.params.id, req, res, next)
+ entityId = entityIdOverride or req.params.id
+ getEntity entityName, entityId, loggedInUser, (error, entity, entityConfig) ->
+ return next(error) if error?
+ unless entity?
+ return AuthorizationMiddlewear.redirectToRestricted(req, res, next)
- requireGroupManagersAccess: (req, res, next) ->
- requireAccessToEntity('groupManagers', req.params.id, req, res, next)
-
- requireInstitutionAccess: (req, res, next) ->
- requireAccessToEntity('institution', req.params.id, req, res, next)
-
- requirePublisherAccess: (req, res, next) ->
- requireAccessToEntity('publisher', req.params.id, req, res, next)
-
- requireGraphAccess: (req, res, next) ->
- requireAccessToEntity(
- req.query.resource_type, req.query.resource_id, req, res, next
- )
-
-requireAccessToEntity = (entityName, entityId, req, res, next) ->
- loggedInUser = AuthenticationController.getSessionUser(req)
- unless loggedInUser
- return AuthorizationMiddlewear.redirectToRestricted req, res, next
-
- getEntity entityName, entityId, loggedInUser, (error, entity, entityConfig) ->
- return next(error) if error?
- unless entity?
- return AuthorizationMiddlewear.redirectToRestricted(req, res, next)
-
- req.entity = entity
- req.entityConfig = entityConfig
- next()
+ req.entity = entity
+ req.entityConfig = entityConfig
+ next()
getEntity = (entityName, entityId, userId, callback = (error, entity, entityConfig)->) ->
entityConfig = EntityConfigs[entityName]
diff --git a/services/web/app/coffee/Features/UserMembership/UserMembershipEntityConfigs.coffee b/services/web/app/coffee/Features/UserMembership/UserMembershipEntityConfigs.coffee
index 22d81c8821..733a82f66d 100644
--- a/services/web/app/coffee/Features/UserMembership/UserMembershipEntityConfigs.coffee
+++ b/services/web/app/coffee/Features/UserMembership/UserMembershipEntityConfigs.coffee
@@ -62,19 +62,3 @@ module.exports =
pathsFor: (id) ->
addMember: "/manage/institutions/#{id}/managers"
removeMember: "/manage/institutions/#{id}/managers"
-
- publisher:
- modelName: 'Publisher'
- fields:
- primaryKey: 'slug'
- read: ['managerIds']
- write: 'managerIds'
- access: 'managerIds'
- name: 'name'
- translations:
- title: 'publisher_account'
- subtitle: 'managers_management'
- remove: 'remove_manager'
- pathsFor: (id) ->
- addMember: "/manage/publishers/#{id}/managers"
- removeMember: "/manage/publishers/#{id}/managers"
diff --git a/services/web/app/coffee/Features/UserMembership/UserMembershipHandler.coffee b/services/web/app/coffee/Features/UserMembership/UserMembershipHandler.coffee
index ef197b83d9..b3f99e8966 100644
--- a/services/web/app/coffee/Features/UserMembership/UserMembershipHandler.coffee
+++ b/services/web/app/coffee/Features/UserMembership/UserMembershipHandler.coffee
@@ -4,7 +4,6 @@ Errors = require('../Errors/Errors')
EntityModels =
Institution: require('../../models/Institution').Institution
Subscription: require('../../models/Subscription').Subscription
- Publisher: require('../../models/Publisher').Publisher
UserMembershipViewModel = require('./UserMembershipViewModel')
UserGetter = require('../User/UserGetter')
logger = require('logger-sharelatex')
diff --git a/services/web/app/coffee/Features/UserMembership/UserMembershipRouter.coffee b/services/web/app/coffee/Features/UserMembership/UserMembershipRouter.coffee
index eb36f34114..c53a5af7c7 100644
--- a/services/web/app/coffee/Features/UserMembership/UserMembershipRouter.coffee
+++ b/services/web/app/coffee/Features/UserMembership/UserMembershipRouter.coffee
@@ -5,52 +5,36 @@ TeamInvitesController = require '../Subscription/TeamInvitesController'
module.exports =
apply: (webRouter) ->
- # group members routes
webRouter.get '/manage/groups/:id/members',
- UserMembershipAuthorization.requireGroupAccess,
+ UserMembershipAuthorization.requireEntityAccess('group'),
UserMembershipController.index
webRouter.post '/manage/groups/:id/invites',
- UserMembershipAuthorization.requireGroupAccess,
+ UserMembershipAuthorization.requireEntityAccess('group'),
TeamInvitesController.createInvite
webRouter.delete '/manage/groups/:id/user/:user_id',
- UserMembershipAuthorization.requireGroupAccess,
+ UserMembershipAuthorization.requireEntityAccess('group'),
SubscriptionGroupController.removeUserFromGroup
webRouter.delete '/manage/groups/:id/invites/:email',
- UserMembershipAuthorization.requireGroupAccess,
+ UserMembershipAuthorization.requireEntityAccess('group'),
TeamInvitesController.revokeInvite
webRouter.get '/manage/groups/:id/members/export',
- UserMembershipAuthorization.requireGroupAccess,
+ UserMembershipAuthorization.requireEntityAccess('group'),
UserMembershipController.exportCsv
- # group managers routes
- webRouter.get "/manage/groups/:id/managers",
- UserMembershipAuthorization.requireGroupManagersAccess,
- UserMembershipController.index
- webRouter.post "/manage/groups/:id/managers",
- UserMembershipAuthorization.requireGroupManagersAccess,
- UserMembershipController.add
- webRouter.delete "/manage/groups/:id/managers/:userId",
- UserMembershipAuthorization.requireGroupManagersAccess,
- UserMembershipController.remove
- # institution members routes
- webRouter.get "/manage/institutions/:id/managers",
- UserMembershipAuthorization.requireInstitutionAccess,
- UserMembershipController.index
- webRouter.post "/manage/institutions/:id/managers",
- UserMembershipAuthorization.requireInstitutionAccess,
- UserMembershipController.add
- webRouter.delete "/manage/institutions/:id/managers/:userId",
- UserMembershipAuthorization.requireInstitutionAccess,
- UserMembershipController.remove
+ regularEntitites =
+ groups: 'groupManagers'
+ institutions: 'institution'
+ for pathName, entityName of regularEntitites
+ do (pathName, entityName) ->
+ webRouter.get "/manage/#{pathName}/:id/managers",
+ UserMembershipAuthorization.requireEntityAccess(entityName),
+ UserMembershipController.index
- # publisher members routes
- webRouter.get "/manage/publishers/:id/managers",
- UserMembershipAuthorization.requirePublisherAccess,
- UserMembershipController.index
- webRouter.post "/manage/publishers/:id/managers",
- UserMembershipAuthorization.requirePublisherAccess,
- UserMembershipController.add
- webRouter.delete "/manage/publishers/:id/managers/:userId",
- UserMembershipAuthorization.requirePublisherAccess,
- UserMembershipController.remove
+ webRouter.post "/manage/#{pathName}/:id/managers",
+ UserMembershipAuthorization.requireEntityAccess(entityName),
+ UserMembershipController.add
+
+ webRouter.delete "/manage/#{pathName}/:id/managers/:userId",
+ UserMembershipAuthorization.requireEntityAccess(entityName),
+ UserMembershipController.remove
diff --git a/services/web/app/coffee/infrastructure/ExpressLocals.coffee b/services/web/app/coffee/infrastructure/ExpressLocals.coffee
index 2eb51b9bf8..9539ce61d1 100644
--- a/services/web/app/coffee/infrastructure/ExpressLocals.coffee
+++ b/services/web/app/coffee/infrastructure/ExpressLocals.coffee
@@ -16,7 +16,6 @@ hashedFiles = {}
Path = require 'path'
Features = require "./Features"
Modules = require "./Modules"
-moment = require 'moment'
jsPath =
if Settings.useMinifiedJs
@@ -127,7 +126,6 @@ module.exports = (app, webRouter, privateApiRouter, publicApiRouter)->
res.locals.fullJsPath = Url.resolve(staticFilesBase, jsPath)
res.locals.lib = PackageVersions.lib
- res.locals.moment = moment
res.locals.buildJsPath = (jsFile, opts = {})->
path = Path.join(jsPath, jsFile)
diff --git a/services/web/app/coffee/models/Publisher.coffee b/services/web/app/coffee/models/Publisher.coffee
deleted file mode 100644
index 3426b168ed..0000000000
--- a/services/web/app/coffee/models/Publisher.coffee
+++ /dev/null
@@ -1,34 +0,0 @@
-mongoose = require 'mongoose'
-Schema = mongoose.Schema
-ObjectId = Schema.ObjectId
-settings = require 'settings-sharelatex'
-request = require 'request'
-
-PublisherSchema = new Schema
- slug: { type: String, required: true }
- managerIds: [ type:ObjectId, ref:'User' ]
-
-# fetch publisher's (brand on v1) data from v1 API. Errors are ignored
-PublisherSchema.method 'fetchV1Data', (callback = (error, publisher)->) ->
- request {
- baseUrl: settings.apis.v1.url
- url: "/api/v2/brands/#{this.slug}"
- method: 'GET'
- auth:
- user: settings.apis.v1.user
- pass: settings.apis.v1.pass
- sendImmediately: true
- }, (error, response, body) =>
- try parsedBody = JSON.parse(body) catch e
- this.name = parsedBody?.name
- this.partner = parsedBody?.partner
- callback(null, this)
-
-conn = mongoose.createConnection(settings.mongo.url, {
- server: {poolSize: settings.mongo.poolSize || 10},
- config: {autoIndex: false}
-})
-
-Publisher = conn.model 'Publisher', PublisherSchema
-exports.Publisher = Publisher
-exports.PublisherSchema = PublisherSchema
diff --git a/services/web/app/coffee/models/User.coffee b/services/web/app/coffee/models/User.coffee
index 6ad504b0fa..fcfb06742b 100644
--- a/services/web/app/coffee/models/User.coffee
+++ b/services/web/app/coffee/models/User.coffee
@@ -50,7 +50,6 @@ UserSchema = new Schema
references: { type:Boolean, default: Settings.defaultFeatures.references }
trackChanges: { type:Boolean, default: Settings.defaultFeatures.trackChanges }
mendeley: { type:Boolean, default: Settings.defaultFeatures.mendeley }
- zotero: { type:Boolean, default: Settings.defaultFeatures.zotero }
referencesSearch: { type:Boolean, default: Settings.defaultFeatures.referencesSearch }
}
referal_id : {type:String, default:() -> uuid.v4().split("-")[0]}
diff --git a/services/web/app/views/project/editor/new-file-modal.pug b/services/web/app/views/project/editor/new-file-modal.pug
index 969b1e2564..cbe8124242 100644
--- a/services/web/app/views/project/editor/new-file-modal.pug
+++ b/services/web/app/views/project/editor/new-file-modal.pug
@@ -162,7 +162,7 @@ script(type='text/ng-template', id='newFileModalTemplate')
on-enter="create()",
name="url"
)
- .row-spaced-small
+ .row-spaced.small
label(for="name") File name in this project
input.form-control(
type="text",
diff --git a/services/web/app/views/project/list/modals.pug b/services/web/app/views/project/list/modals.pug
index 18c39a43e9..f89b26925c 100644
--- a/services/web/app/views/project/list/modals.pug
+++ b/services/web/app/views/project/list/modals.pug
@@ -351,7 +351,7 @@ script(type="text/ng-template", id="v1ImportModalTemplate")
| Direct git access to your projects is not yet available, but you can migrate your project to the Overleaf v2 GitHub integration
|
a(href='https://www.overleaf.com/help/343-working-offline-in-overleaf-v2', target='_blank') Read More.
- li There is no CiteULike integration
+ li There are no Zotero and CiteULike integrations yet
li Some Journals and Services in the Submit menu don't support direct submissions yet
.v1-import-cta
p
diff --git a/services/web/app/views/subscriptions/dashboard.pug b/services/web/app/views/subscriptions/dashboard.pug
index 17e8114036..3becea865a 100644
--- a/services/web/app/views/subscriptions/dashboard.pug
+++ b/services/web/app/views/subscriptions/dashboard.pug
@@ -35,9 +35,6 @@ block content
-if (settings.overleaf && v1Subscriptions)
include ./dashboard/_v1_subscriptions
- -if (v1SubscriptionStatus)
- include ./dashboard/_v1_subscription_status
-
-if (!hasAnySubscription)
p You're on the #{settings.appName} Free plan.
|
diff --git a/services/web/app/views/subscriptions/dashboard/_managed_groups.pug b/services/web/app/views/subscriptions/dashboard/_managed_groups.pug
index fd7c354db7..ce1fda22e8 100644
--- a/services/web/app/views/subscriptions/dashboard/_managed_groups.pug
+++ b/services/web/app/views/subscriptions/dashboard/_managed_groups.pug
@@ -5,20 +5,9 @@ each managedGroupSubscription in managedGroupSubscriptions
+teamName(managedGroupSubscription)
p
a.btn.btn-primary(href="/manage/groups/" + managedGroupSubscription._id + "/members")
- i.fa.fa-fw.fa-users
- |
| Manage members
|
- p
- a(href="/manage/groups/" + managedGroupSubscription._id + "/managers")
- i.fa.fa-fw.fa-users
- |
+ a.btn.btn-primary(href="/manage/groups/" + managedGroupSubscription._id + "/managers")
| Manage group managers
- |
- p
- a(href="/metrics/groups/" + managedGroupSubscription._id)
- i.fa.fa-fw.fa-line-chart
- |
- | View metrics
hr
diff --git a/services/web/app/views/subscriptions/dashboard/_managed_institutions.pug b/services/web/app/views/subscriptions/dashboard/_managed_institutions.pug
index 19a1add36d..31b3e4d225 100644
--- a/services/web/app/views/subscriptions/dashboard/_managed_institutions.pug
+++ b/services/web/app/views/subscriptions/dashboard/_managed_institutions.pug
@@ -4,18 +4,6 @@ each institution in managedInstitutions
|
strong= institution.name
p
- a.btn.btn-primary(href="/metrics/institutions/" + institution.v1Id)
- i.fa.fa-fw.fa-line-chart
- |
- | View metrics
- p
- a(href="/institutions/" + institution.v1Id + "/hub")
- i.fa.fa-fw.fa-user-circle
- |
- | View hub
- p
- a(href="/manage/institutions/" + institution.v1Id + "/managers")
- i.fa.fa-fw.fa-users
- |
+ a.btn.btn-primary(href="/manage/institutions/" + institution.v1Id + "/managers")
| Manage institution managers
hr
diff --git a/services/web/app/views/subscriptions/dashboard/_v1_subscription_status.pug b/services/web/app/views/subscriptions/dashboard/_v1_subscription_status.pug
deleted file mode 100644
index 4b2d01f7ca..0000000000
--- a/services/web/app/views/subscriptions/dashboard/_v1_subscription_status.pug
+++ /dev/null
@@ -1,60 +0,0 @@
-- if (v1SubscriptionStatus['team'])
- p
- | You have a legacy group licence from Overleaf v1.
- - if (v1SubscriptionStatus['team']['will_end_at'])
- p
- | Your current group licence ends on
- |
- strong= moment(v1SubscriptionStatus['team']['will_end_at']).format('Do MMM YY')
- |
- | and will
- |
- - if (v1SubscriptionStatus['team']['will_renew'])
- | be automatically renewed.
- - else
- | not be automatically renewed.
- - if (v1SubscriptionStatus['can_cancel_team'])
- p
- form(method="POST", action="/user/subscription/v1/cancel")
- input(type="hidden", name="_csrf", value=csrfToken)
- button().btn.btn-danger Stop automatic renewal
- - else
- p
- | Please
- |
- a(href="/contact") contact support
- |
- | to make changes to your plan
- hr
-
-- if (v1SubscriptionStatus['product'])
- p
- | You have a legacy Overleaf v1
- |
- strong= v1SubscriptionStatus['product']['display_name']
- |
- | plan.
- p
- | Your plan ends on
- |
- strong= moment(v1SubscriptionStatus['product']['will_end_at']).format('Do MMM YY')
- |
- | and will
- |
- - if (v1SubscriptionStatus['product']['will_renew'])
- | be automatically renewed.
- - else
- | not be automatically renewed.
- - if (v1SubscriptionStatus['can_cancel'])
- p
- form(method="POST", action="/user/subscription/v1/cancel")
- input(type="hidden", name="_csrf", value=csrfToken)
- button().btn.btn-danger Stop automatic renewal
- - else
- p
- | Please
- |
- a(href="/contact") contact support
- |
- | to make changes to your plan
- hr
diff --git a/services/web/app/views/subscriptions/dashboard/_v1_subscriptions.pug b/services/web/app/views/subscriptions/dashboard/_v1_subscriptions.pug
index e543c15960..1d0377df8c 100644
--- a/services/web/app/views/subscriptions/dashboard/_v1_subscriptions.pug
+++ b/services/web/app/views/subscriptions/dashboard/_v1_subscriptions.pug
@@ -1,3 +1,11 @@
+- if (v1Subscriptions.has_subscription)
+ -hasAnySubscription = true
+ p
+ | You are subscribed to Overleaf through Overleaf v1
+ p
+ a.btn.btn-primary(href='/sign_in_to_v1?return_to=/users/edit%23status') Manage v1 Subscription
+ hr
+
- if (v1Subscriptions.teams && v1Subscriptions.teams.length > 0)
-hasAnySubscription = true
for team in v1Subscriptions.teams
diff --git a/services/web/docker-compose.yml b/services/web/docker-compose.yml
index fb1fba2b8d..ebf164f606 100644
--- a/services/web/docker-compose.yml
+++ b/services/web/docker-compose.yml
@@ -17,7 +17,7 @@ services:
PROJECT_HISTORY_ENABLED: 'true'
ENABLED_LINKED_FILE_TYPES: 'url'
LINKED_URL_PROXY: 'http://localhost:6543'
- ENABLED_LINKED_FILE_TYPES: 'url,project_file,project_output_file,mendeley,zotero'
+ ENABLED_LINKED_FILE_TYPES: 'url,project_file,project_output_file,mendeley'
SHARELATEX_CONFIG: /app/test/acceptance/config/settings.test.coffee
NODE_ENV: production
depends_on:
diff --git a/services/web/public/img/other-brands/logo_ieee_white.png b/services/web/public/img/other-brands/logo_ieee_white.png
deleted file mode 100644
index 509d187104..0000000000
Binary files a/services/web/public/img/other-brands/logo_ieee_white.png and /dev/null differ
diff --git a/services/web/public/src/ide/file-tree/FileTreeManager.js b/services/web/public/src/ide/file-tree/FileTreeManager.js
index 0717a9039b..a72a988af8 100644
--- a/services/web/public/src/ide/file-tree/FileTreeManager.js
+++ b/services/web/public/src/ide/file-tree/FileTreeManager.js
@@ -79,8 +79,7 @@ define([
name: file.name,
id: file._id,
type: 'file',
- linkedFileData,
- created: file.created
+ linkedFileData
})
return this.recalculateDocList()
})
diff --git a/services/web/public/stylesheets/components/tabs.less b/services/web/public/stylesheets/components/tabs.less
index c7ddcf1307..ed03793ec7 100644
--- a/services/web/public/stylesheets/components/tabs.less
+++ b/services/web/public/stylesheets/components/tabs.less
@@ -16,7 +16,7 @@
color: @link-color-alt;
&:focus, &:hover {
background-color: transparent!important;
- border: 0;
+ border: 0!important;
color: @link-hover-color-alt;
}
}
@@ -36,4 +36,4 @@
background-color: transparent!important;
border: none!important;
}
-}
+}
\ No newline at end of file
diff --git a/services/web/public/stylesheets/core/ol-ieee-variables.less b/services/web/public/stylesheets/core/ol-ieee-variables.less
index 64d3f8f9d5..143d948aff 100644
--- a/services/web/public/stylesheets/core/ol-ieee-variables.less
+++ b/services/web/public/stylesheets/core/ol-ieee-variables.less
@@ -42,11 +42,3 @@
@editor-toggler-hover-bg-color: @ieee-blue;
@toggle-switch-highlight-color: @ieee-blue;
-
-@footer-link-color : @link-color;
-@footer-link-hover-color : @link-hover-color;
-
-@navbar-subdued-hover-color : @ieee-blue;
-@navbar-default-link-hover-bg : @ieee-blue;
-@navbar-default-link-hover-color: @ieee-blue;
-@navbar-default-link-active-bg : @ieee-blue;
diff --git a/services/web/public/stylesheets/ol-ieee-style.less b/services/web/public/stylesheets/ol-ieee-style.less
index daa0f85f42..1235633f5b 100644
--- a/services/web/public/stylesheets/ol-ieee-style.less
+++ b/services/web/public/stylesheets/ol-ieee-style.less
@@ -4,41 +4,3 @@
@is-overleaf : true;
@is-overleaf-light: false;
@show-rich-text : true;
-
-@ieee-wedge: 30px;
-
-body > .portal-ieee {
- padding-top: @header-height;
-}
-
-.portal-ieee {
- .ieee-header {
- background-color: @ieee-blue;
- margin-bottom: @margin-xl;
- padding-bottom: @padding-sm;
- padding-top: @padding-sm;
- h1 {
- margin: 0;
- }
- .ieee-logo {
- width: @navbar-brand-width;
- }
- }
- .ieee-subheader {
- background-color: @ieee-blue;
- color: #ffffff;
- line-height: 1;
- padding: @padding-md @ieee-wedge;
- position: relative;
- &:after {
- content: "";
- display: block;
- position: absolute;
- border-style: solid;
- left: -1px;
- top: -1px;
- border-color: @content-alt-bg-color transparent;
- border-width: @ieee-wedge @ieee-wedge 0 0;
- }
- }
-}
diff --git a/services/web/test/acceptance/coffee/SubscriptionTests.coffee b/services/web/test/acceptance/coffee/SubscriptionTests.coffee
index f68d5ea8f0..bb19c3c779 100644
--- a/services/web/test/acceptance/coffee/SubscriptionTests.coffee
+++ b/services/web/test/acceptance/coffee/SubscriptionTests.coffee
@@ -234,8 +234,7 @@ describe 'Subscriptions', ->
before (done) ->
v1Id = MockV1Api.nextV1Id()
MockV1Api.setUser v1Id, {
- subscription: {},
- subscription_status: {}
+ subscription: {}
}
MockV1Api.setAffiliations [{
email: 'confirmed-affiliation-email@stanford.example.edu'
@@ -282,10 +281,6 @@ describe 'Subscriptions', ->
name: 'Test team'
}]
}
- subscription_status: @subscription_status = {
- product: { 'mock': 'product' }
- team: null
- }
}
@user.setV1Id v1Id, (error) =>
return done(error) if error?
@@ -300,29 +295,4 @@ describe 'Subscriptions', ->
expect(@data.memberGroupSubscriptions).to.deep.equal []
it 'should return a v1Subscriptions', ->
- expect(@data.v1Subscriptions).to.deep.equal @subscription
-
- it 'should return a v1SubscriptionStatus', ->
- expect(@data.v1SubscriptionStatus).to.deep.equal @subscription_status
-
- describe.only 'canceling', ->
- before (done) ->
- @user = new User()
- MockV1Api.setUser v1Id = MockV1Api.nextV1Id(), @v1_user = {}
- async.series [
- (cb) => @user.login(cb)
- (cb) => @user.setV1Id(v1Id, cb)
- ], (error) =>
- @user.request {
- method: 'POST',
- url: '/user/subscription/v1/cancel'
- }, (error, @response) =>
- return done(error) if error?
- done()
-
- it 'should tell v1 to cancel the subscription', ->
- expect(@v1_user.canceled).to.equal true
-
- it 'should redirect to the subscription dashboard', ->
- expect(@response.statusCode).to.equal 302
- expect(@response.headers.location).to.equal '/user/subscription'
+ expect(@data.v1Subscriptions).to.deep.equal @subscription
\ No newline at end of file
diff --git a/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee b/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee
index e7babe54b5..91714af1d7 100644
--- a/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee
+++ b/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee
@@ -38,9 +38,6 @@ module.exports = MockDocUpdaterApi =
app.post "/project/:project_id/doc/:doc_id", (req, res, next) =>
res.sendStatus 204
- app.delete "/project/:project_id", (req, res) =>
- res.sendStatus 204
-
app.post "/project/:project_id/doc/:doc_id/flush", (req, res, next) =>
res.sendStatus 204
diff --git a/services/web/test/acceptance/coffee/helpers/MockV1Api.coffee b/services/web/test/acceptance/coffee/helpers/MockV1Api.coffee
index 04c1b6446b..dffebdc929 100644
--- a/services/web/test/acceptance/coffee/helpers/MockV1Api.coffee
+++ b/services/web/test/acceptance/coffee/helpers/MockV1Api.coffee
@@ -53,20 +53,6 @@ module.exports = MockV1Api =
else
res.sendStatus 404
- app.get "/api/v1/sharelatex/users/:v1_user_id/subscription_status", (req, res, next) =>
- user = @users[req.params.v1_user_id]
- if user?.subscription_status?
- res.json user.subscription_status
- else
- res.sendStatus 404
-
- app.delete "/api/v1/sharelatex/users/:v1_user_id/subscription", (req, res, next) =>
- user = @users[req.params.v1_user_id]
- if user?
- user.canceled = true
- res.sendStatus 200
- else
- res.sendStatus 404
app.post "/api/v1/sharelatex/users/:v1_user_id/sync", (req, res, next) =>
@syncUserFeatures(req.params.v1_user_id)
diff --git a/services/web/test/unit/coffee/Authentication/AuthenticationControllerTests.coffee b/services/web/test/unit/coffee/Authentication/AuthenticationControllerTests.coffee
index 3ffd08e08b..4fb31c7503 100644
--- a/services/web/test/unit/coffee/Authentication/AuthenticationControllerTests.coffee
+++ b/services/web/test/unit/coffee/Authentication/AuthenticationControllerTests.coffee
@@ -491,10 +491,10 @@ describe "AuthenticationController", ->
beforeEach ->
@req.headers = {}
@AuthenticationController.httpAuth = sinon.stub()
- @setRedirect = sinon.spy(@AuthenticationController, 'setRedirectInSession')
+ @_setRedirect = sinon.spy(@AuthenticationController, '_setRedirectInSession')
afterEach ->
- @setRedirect.restore()
+ @_setRedirect.restore()
describe "with white listed url", ->
beforeEach ->
@@ -540,7 +540,7 @@ describe "AuthenticationController", ->
@AuthenticationController.requireGlobalLogin @req, @res, @next
it 'should have called setRedirectInSession', ->
- @setRedirect.callCount.should.equal 1
+ @_setRedirect.callCount.should.equal 1
it "should redirect to the /login page", ->
@res.redirectedTo.should.equal "/login"
@@ -640,18 +640,18 @@ describe "AuthenticationController", ->
@callback.called.should.equal true
- describe 'setRedirectInSession', ->
+ describe '_setRedirectInSession', ->
beforeEach ->
@req = {session: {}}
@req.path = "/somewhere"
@req.query = {one: "1"}
it 'should set redirect property on session', ->
- @AuthenticationController.setRedirectInSession(@req)
+ @AuthenticationController._setRedirectInSession(@req)
expect(@req.session.postLoginRedirect).to.equal "/somewhere?one=1"
it 'should set the supplied value', ->
- @AuthenticationController.setRedirectInSession(@req, '/somewhere/specific')
+ @AuthenticationController._setRedirectInSession(@req, '/somewhere/specific')
expect(@req.session.postLoginRedirect).to.equal "/somewhere/specific"
describe 'with a png', ->
@@ -659,7 +659,7 @@ describe "AuthenticationController", ->
@req = {session: {}}
it 'should not set the redirect', ->
- @AuthenticationController.setRedirectInSession(@req, '/something.png')
+ @AuthenticationController._setRedirectInSession(@req, '/something.png')
expect(@req.session.postLoginRedirect).to.equal undefined
describe 'with a js path', ->
@@ -668,7 +668,7 @@ describe "AuthenticationController", ->
@req = {session: {}}
it 'should not set the redirect', ->
- @AuthenticationController.setRedirectInSession(@req, '/js/something.js')
+ @AuthenticationController._setRedirectInSession(@req, '/js/something.js')
expect(@req.session.postLoginRedirect).to.equal undefined
describe '_getRedirectFromSession', ->
diff --git a/services/web/test/unit/coffee/Project/ProjectDetailsHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectDetailsHandlerTests.coffee
index 116703fa4d..18d73ba77e 100644
--- a/services/web/test/unit/coffee/Project/ProjectDetailsHandlerTests.coffee
+++ b/services/web/test/unit/coffee/Project/ProjectDetailsHandlerTests.coffee
@@ -163,14 +163,12 @@ describe 'ProjectDetailsHandler', ->
describe "ensureProjectNameIsUnique", ->
beforeEach ->
@result = {
- owned: [{_id: 1, name:"name"}, {_id: 2, name: "name1"}, {_id: 3, name: "name11"}, {_id: 100, name: "numeric"}]
+ owned: [{_id: 1, name:"name"}, {_id: 2, name: "name1"}, {_id: 3, name: "name11"}]
readAndWrite: [{_id: 4, name:"name2"}, {_id: 5, name:"name22"}]
readOnly: [{_id:6, name:"name3"}, {_id:7, name: "name33"}]
tokenReadAndWrite: [{_id:8, name:"name4"}, {_id:9, name:"name44"}]
tokenReadOnly: [{_id:10, name:"name5"}, {_id:11, name:"name55"}, {_id:12, name:"x".repeat(15)}]
}
- for i in [1..20].concat([30..40])
- @result.owned.push {_id: 100 + i, name: "numeric (#{i})"}
@ProjectGetter.findAllUsersProjects = sinon.stub().callsArgWith(2, null, @result)
it "should leave a unique name unchanged", (done) ->
@@ -198,34 +196,9 @@ describe 'ProjectDetailsHandler', ->
expect(changed).to.equal true
done()
- it "should use a numeric index if no suffix is supplied", (done) ->
- @handler.ensureProjectNameIsUnique @user_id, "name1", [], (error, name, changed) ->
- expect(name).to.equal "name1 (1)"
- expect(changed).to.equal true
- done()
-
- it "should use a numeric index if all suffixes are exhausted", (done) ->
- @handler.ensureProjectNameIsUnique @user_id, "name", ["1", "11"], (error, name, changed) ->
- expect(name).to.equal "name (1)"
- expect(changed).to.equal true
- done()
-
- it "should find the next lowest available numeric index for the base name", (done) ->
- @handler.ensureProjectNameIsUnique @user_id, "numeric", [], (error, name, changed) ->
- expect(name).to.equal "numeric (21)"
- expect(changed).to.equal true
- done()
-
- it "should find the next available numeric index when a numeric index is already present", (done) ->
- @handler.ensureProjectNameIsUnique @user_id, "numeric (5)", [], (error, name, changed) ->
- expect(name).to.equal "numeric (21)"
- expect(changed).to.equal true
- done()
-
- it "should not find a numeric index lower than the one already present", (done) ->
- @handler.ensureProjectNameIsUnique @user_id, "numeric (31)", [], (error, name, changed) ->
- expect(name).to.equal "numeric (41)"
- expect(changed).to.equal true
+ it "should return an error if the name cannot be made unique", (done) ->
+ @handler.ensureProjectNameIsUnique @user_id, "name", ["1", "5", "55"], (error, name, changed) ->
+ expect(error).to.eql new Errors.InvalidNameError("Project name could not be made unique")
done()
describe "fixProjectName", ->
diff --git a/services/web/test/unit/coffee/Subscription/SubscriptionControllerTests.coffee b/services/web/test/unit/coffee/Subscription/SubscriptionControllerTests.coffee
index 74a85967ae..7fbb1df361 100644
--- a/services/web/test/unit/coffee/Subscription/SubscriptionControllerTests.coffee
+++ b/services/web/test/unit/coffee/Subscription/SubscriptionControllerTests.coffee
@@ -79,7 +79,6 @@ describe "SubscriptionController", ->
"./RecurlyWrapper": @RecurlyWrapper = {}
"./FeaturesUpdater": @FeaturesUpdater = {}
"./GroupPlansData": @GroupPlansData = {}
- "./V1SubscriptionManager": @V1SubscriptionManager = {}
@res = new MockResponse()
diff --git a/services/web/test/unit/coffee/SudoMode/SudoModeMiddlewearTests.coffee b/services/web/test/unit/coffee/SudoMode/SudoModeMiddlewearTests.coffee
index 51a168fe58..cc4f859ab2 100644
--- a/services/web/test/unit/coffee/SudoMode/SudoModeMiddlewearTests.coffee
+++ b/services/web/test/unit/coffee/SudoMode/SudoModeMiddlewearTests.coffee
@@ -13,7 +13,7 @@ describe 'SudoModeMiddlewear', ->
isSudoModeActive: sinon.stub()
@AuthenticationController =
getLoggedInUserId: sinon.stub().returns(@userId)
- setRedirectInSession: sinon.stub()
+ _setRedirectInSession: sinon.stub()
@SudoModeMiddlewear = SandboxedModule.require modulePath, requires:
'./SudoModeHandler': @SudoModeHandler
'../Authentication/AuthenticationController': @AuthenticationController
@@ -54,7 +54,7 @@ describe 'SudoModeMiddlewear', ->
describe 'when sudo mode is not active', ->
beforeEach ->
- @AuthenticationController.setRedirectInSession = sinon.stub()
+ @AuthenticationController._setRedirectInSession = sinon.stub()
@AuthenticationController.getLoggedInUserId = sinon.stub().returns(@userId)
@SudoModeHandler.isSudoModeActive = sinon.stub().callsArgWith(1, null, false)
@@ -71,8 +71,8 @@ describe 'SudoModeMiddlewear', ->
it 'should set redirect in session', (done) ->
@call () =>
- @AuthenticationController.setRedirectInSession.callCount.should.equal 1
- @AuthenticationController.setRedirectInSession.calledWith(@req).should.equal true
+ @AuthenticationController._setRedirectInSession.callCount.should.equal 1
+ @AuthenticationController._setRedirectInSession.calledWith(@req).should.equal true
done()
it 'should redirect to the password-prompt page', (done) ->
diff --git a/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee b/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee
index 550791cecd..a4c65d1aee 100644
--- a/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee
+++ b/services/web/test/unit/coffee/TokenAccess/TokenAccessControllerTests.coffee
@@ -61,7 +61,7 @@ describe "TokenAccessController", ->
@TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
.callsArgWith(2, null)
@ProjectController.loadEditor = sinon.stub()
- @AuthenticationController.setRedirectInSession = sinon.stub()
+ @AuthenticationController._setRedirectInSession = sinon.stub()
@TokenAccessController.readAndWriteToken @req, @res, @next
it 'should try to find a project with this token', (done) ->
@@ -173,7 +173,7 @@ describe "TokenAccessController", ->
.callsArgWith(2, null)
@ProjectController.loadEditor = sinon.stub()
@TokenAccessHandler.grantSessionTokenAccess = sinon.stub()
- @AuthenticationController.setRedirectInSession = sinon.stub()
+ @AuthenticationController._setRedirectInSession = sinon.stub()
@TokenAccessController.readAndWriteToken @req, @res, @next
it 'should not add the user to the project with read-write access', (done) ->
@@ -192,8 +192,8 @@ describe "TokenAccessController", ->
done()
it 'should set redirect in session', (done) ->
- expect(@AuthenticationController.setRedirectInSession.callCount).to.equal 1
- expect(@AuthenticationController.setRedirectInSession.calledWith(@req)).to.equal true
+ expect(@AuthenticationController._setRedirectInSession.callCount).to.equal 1
+ expect(@AuthenticationController._setRedirectInSession.calledWith(@req)).to.equal true
done()
it 'should redirect to restricted page', (done) ->
diff --git a/services/web/test/unit/coffee/User/UserPagesControllerTests.coffee b/services/web/test/unit/coffee/User/UserPagesControllerTests.coffee
index 6555dce1e0..a0f155846f 100644
--- a/services/web/test/unit/coffee/User/UserPagesControllerTests.coffee
+++ b/services/web/test/unit/coffee/User/UserPagesControllerTests.coffee
@@ -28,7 +28,7 @@ describe "UserPagesController", ->
getLoggedInUserId: sinon.stub().returns(@user._id)
getSessionUser: sinon.stub().returns(@user)
_getRedirectFromSession: sinon.stub()
- setRedirectInSession: sinon.stub()
+ _setRedirectInSession: sinon.stub()
@UserPagesController = SandboxedModule.require modulePath, requires:
"settings-sharelatex": @settings
"logger-sharelatex":
@@ -92,13 +92,13 @@ describe "UserPagesController", ->
beforeEach ->
@AuthenticationController._getRedirectFromSession = sinon.stub().returns(null)
- @AuthenticationController.setRedirectInSession = sinon.stub()
+ @AuthenticationController._setRedirectInSession = sinon.stub()
@req.query.redir = '/somewhere/in/particular'
it 'should set a redirect', (done) ->
@res.render = (page) =>
- @AuthenticationController.setRedirectInSession.callCount.should.equal 1
- expect(@AuthenticationController.setRedirectInSession.lastCall.args[1]).to.equal @req.query.redir
+ @AuthenticationController._setRedirectInSession.callCount.should.equal 1
+ expect(@AuthenticationController._setRedirectInSession.lastCall.args[1]).to.equal @req.query.redir
done()
@UserPagesController.loginPage @req, @res
diff --git a/services/web/test/unit/coffee/UserMembership/UserMembershipAuthorizationTests.coffee b/services/web/test/unit/coffee/UserMembership/UserMembershipAuthorizationTests.coffee
index 5a35eba898..4630b1c10d 100644
--- a/services/web/test/unit/coffee/UserMembership/UserMembershipAuthorizationTests.coffee
+++ b/services/web/test/unit/coffee/UserMembership/UserMembershipAuthorizationTests.coffee
@@ -30,9 +30,10 @@ describe "UserMembershipAuthorization", ->
log: ->
err: ->
- describe 'requireAccessToEntity', ->
+ describe 'requireEntityAccess', ->
it 'get entity', (done) ->
- @UserMembershipAuthorization.requireGroupAccess @req, null, (error) =>
+ middlewear = @UserMembershipAuthorization.requireEntityAccess 'group'
+ middlewear @req, null, (error) =>
expect(error).to.not.extist
sinon.assert.calledWithMatch(
@UserMembershipHandler.getEntity,
@@ -44,9 +45,19 @@ describe "UserMembershipAuthorization", ->
expect(@req.entityConfig).to.exist
done()
+ it 'handle unknown entity', (done) ->
+ middlewear = @UserMembershipAuthorization.requireEntityAccess 'foo'
+ middlewear @req, null, (error) =>
+ expect(error).to.extist
+ expect(error).to.be.an.instanceof(Errors.NotFoundError)
+ sinon.assert.notCalled(@UserMembershipHandler.getEntity)
+ expect(@req.entity).to.not.exist
+ done()
+
it 'handle entity not found', (done) ->
@UserMembershipHandler.getEntity.yields(null, null)
- @UserMembershipAuthorization.requireGroupAccess @req, null, (error) =>
+ middlewear = @UserMembershipAuthorization.requireEntityAccess 'institution'
+ middlewear @req, null, (error) =>
expect(error).to.extist
sinon.assert.called(@AuthorizationMiddlewear.redirectToRestricted)
sinon.assert.called(@UserMembershipHandler.getEntity)
@@ -55,63 +66,34 @@ describe "UserMembershipAuthorization", ->
it 'handle anonymous user', (done) ->
@AuthenticationController.getSessionUser.returns(null)
- @UserMembershipAuthorization.requireGroupAccess @req, null, (error) =>
+ middlewear = @UserMembershipAuthorization.requireEntityAccess 'institution'
+ middlewear @req, null, (error) =>
expect(error).to.extist
sinon.assert.called(@AuthorizationMiddlewear.redirectToRestricted)
sinon.assert.notCalled(@UserMembershipHandler.getEntity)
expect(@req.entity).to.not.exist
done()
- describe 'requireEntityAccess', ->
- it 'handle team access', (done) ->
- @UserMembershipAuthorization.requireTeamAccess @req, null, (error) =>
- expect(error).to.not.extist
- sinon.assert.calledWithMatch(
- @UserMembershipHandler.getEntity,
- @req.params.id,
- fields: primaryKey: 'overleaf.id'
- )
- done()
-
- it 'handle group access', (done) ->
- @UserMembershipAuthorization.requireGroupAccess @req, null, (error) =>
- expect(error).to.not.extist
- sinon.assert.calledWithMatch(
- @UserMembershipHandler.getEntity,
- @req.params.id,
- translations: title: 'group_account'
- )
- done()
-
- it 'handle group managers access', (done) ->
- @UserMembershipAuthorization.requireGroupManagersAccess @req, null, (error) =>
- expect(error).to.not.extist
- sinon.assert.calledWithMatch(
- @UserMembershipHandler.getEntity,
- @req.params.id,
- translations: subtitle: 'managers_management'
- )
- done()
-
- it 'handle institution access', (done) ->
- @UserMembershipAuthorization.requireInstitutionAccess @req, null, (error) =>
- expect(error).to.not.extist
- sinon.assert.calledWithMatch(
- @UserMembershipHandler.getEntity,
- @req.params.id,
- modelName: 'Institution',
- )
- done()
-
- it 'handle graph access', (done) ->
- @req.query.resource_id = 'mock-resource-id'
- @req.query.resource_type = 'institution'
- middlewear = @UserMembershipAuthorization.requireGraphAccess
+ it 'can override entity id', (done) ->
+ middlewear = @UserMembershipAuthorization.requireEntityAccess 'group', 'entity-id-override'
middlewear @req, null, (error) =>
expect(error).to.not.extist
sinon.assert.calledWithMatch(
@UserMembershipHandler.getEntity,
- @req.query.resource_id,
- modelName: 'Institution',
+ 'entity-id-override',
)
done()
+
+ it "doesn't cache entity id between requests", (done) ->
+ middlewear = @UserMembershipAuthorization.requireEntityAccess 'group'
+ middlewear @req, null, (error) =>
+ expect(error).to.not.extist
+ lastCallArs = @UserMembershipHandler.getEntity.lastCall.args
+ expect(lastCallArs[0]).to.equal @req.params.id
+ newEntityId = 'another-mock-id'
+ @req.params.id = newEntityId
+ middlewear @req, null, (error) =>
+ expect(error).to.not.extist
+ lastCallArs = @UserMembershipHandler.getEntity.lastCall.args
+ expect(lastCallArs[0]).to.equal newEntityId
+ done()
diff --git a/services/web/test/unit/coffee/UserMembership/UserMembershipHandlerTests.coffee b/services/web/test/unit/coffee/UserMembership/UserMembershipHandlerTests.coffee
index eaea0791b7..55fcb64943 100644
--- a/services/web/test/unit/coffee/UserMembership/UserMembershipHandlerTests.coffee
+++ b/services/web/test/unit/coffee/UserMembership/UserMembershipHandlerTests.coffee
@@ -29,11 +29,6 @@ describe 'UserMembershipHandler', ->
v1Id: 123
managerIds: [ObjectId(), ObjectId(), ObjectId()]
update: sinon.stub().yields(null)
- @publisher =
- _id: 'mock-publisher-id'
- slug: 'slug'
- managerIds: [ObjectId(), ObjectId()]
- update: sinon.stub().yields(null)
@UserMembershipViewModel =
buildAsync: sinon.stub().yields(null, { _id: 'mock-member-id'})
@@ -44,15 +39,12 @@ describe 'UserMembershipHandler', ->
findOne: sinon.stub().yields(null, @institution)
@Subscription =
findOne: sinon.stub().yields(null, @subscription)
- @Publisher =
- findOne: sinon.stub().yields(null, @publisher)
@UserMembershipHandler = SandboxedModule.require modulePath, requires:
'./UserMembershipViewModel': @UserMembershipViewModel
'../User/UserGetter': @UserGetter
'../Errors/Errors': Errors
'../../models/Institution': Institution: @Institution
'../../models/Subscription': Subscription: @Subscription
- '../../models/Publisher': Publisher: @Publisher
'logger-sharelatex':
log: ->
err: ->
@@ -102,15 +94,6 @@ describe 'UserMembershipHandler', ->
expect(error).to.not.be.an.instanceof(Errors.NotFoundError)
done()
- describe 'publishers', ->
- it 'get publisher', (done) ->
- @UserMembershipHandler.getEntity @publisher.slug, EntityConfigs.publisher, @user, (error, institution) =>
- should.not.exist(error)
- expectedQuery = slug: @publisher.slug, managerIds: ObjectId(@user._id)
- assertCalledWith(@Publisher.findOne, expectedQuery)
- expect(institution).to.equal @publisher
- done()
-
describe 'getUsers', ->
describe 'group', ->
it 'build view model for all users', (done) ->