mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 09:09:36 +02:00
Merge pull request #3495 from overleaf/ae-prettier-2
Upgrade Prettier to v2 GitOrigin-RevId: 85aa3fa1acb6332c4f58c46165a43d1a51471f33
This commit is contained in:
@@ -5,3 +5,4 @@ frontend/js/vendor
|
||||
modules/**/frontend/js/vendor
|
||||
public/js
|
||||
public/minjs
|
||||
frontend/stylesheets/components/nvd3.less
|
||||
|
||||
@@ -45,7 +45,7 @@ if (!module.parent) {
|
||||
}
|
||||
Promise.all([mongodb.waitForDb(), mongoose.connectionPromise])
|
||||
.then(() => {
|
||||
Server.server.listen(port, host, function() {
|
||||
Server.server.listen(port, host, function () {
|
||||
logger.info(`web starting up, listening on ${host}:${port}`)
|
||||
logger.info(`${require('http').globalAgent.maxSockets} sockets enabled`)
|
||||
// wait until the process is ready before monitoring the event loop
|
||||
@@ -59,7 +59,7 @@ if (!module.parent) {
|
||||
}
|
||||
|
||||
// handle SIGTERM for graceful shutdown in kubernetes
|
||||
process.on('SIGTERM', function(signal) {
|
||||
process.on('SIGTERM', function (signal) {
|
||||
logger.warn({ signal: signal }, 'received signal, shutting down')
|
||||
Settings.shuttingDown = true
|
||||
})
|
||||
|
||||
@@ -15,7 +15,7 @@ module.exports = {
|
||||
let countryCode = null
|
||||
|
||||
if (userId) {
|
||||
GeoIpLookup.getDetails(req.ip, function(err, geoDetails) {
|
||||
GeoIpLookup.getDetails(req.ip, function (err, geoDetails) {
|
||||
if (err) {
|
||||
metrics.inc('analytics_geo_ip_lookup_errors')
|
||||
} else if (geoDetails && geoDetails.country_code) {
|
||||
@@ -43,7 +43,7 @@ module.exports = {
|
||||
req.query.start_date,
|
||||
req.query.end_date,
|
||||
req.query.lag,
|
||||
function(error, licences) {
|
||||
function (error, licences) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -58,7 +58,7 @@ module.exports = {
|
||||
req.query.start_date,
|
||||
req.query.end_date,
|
||||
req.query.lag,
|
||||
function(error, licences) {
|
||||
function (error, licences) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ const AuthenticationController = {
|
||||
// This function is middleware which wraps the passport.authenticate middleware,
|
||||
// so we can send back our custom `{message: {text: "", type: ""}}` responses on failure,
|
||||
// and send a `{redir: ""}` response on success
|
||||
passport.authenticate('local', function(err, user, info) {
|
||||
passport.authenticate('local', function (err, user, info) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -81,86 +81,96 @@ const AuthenticationController = {
|
||||
} // OAuth2 'state' mismatch
|
||||
|
||||
const Modules = require('../../infrastructure/Modules')
|
||||
Modules.hooks.fire('preFinishLogin', req, res, user, function(
|
||||
error,
|
||||
results
|
||||
) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
if (results.some(result => result && result.doNotFinish)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (user.must_reconfirm) {
|
||||
return AuthenticationController._redirectToReconfirmPage(req, res, user)
|
||||
}
|
||||
|
||||
const redir =
|
||||
AuthenticationController._getRedirectFromSession(req) || '/project'
|
||||
_loginAsyncHandlers(req, user)
|
||||
const userId = user._id
|
||||
UserAuditLogHandler.addEntry(userId, 'login', userId, req.ip, err => {
|
||||
if (err) {
|
||||
return next(err)
|
||||
Modules.hooks.fire(
|
||||
'preFinishLogin',
|
||||
req,
|
||||
res,
|
||||
user,
|
||||
function (error, results) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
_afterLoginSessionSetup(req, user, function(err) {
|
||||
if (results.some(result => result && result.doNotFinish)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (user.must_reconfirm) {
|
||||
return AuthenticationController._redirectToReconfirmPage(
|
||||
req,
|
||||
res,
|
||||
user
|
||||
)
|
||||
}
|
||||
|
||||
const redir =
|
||||
AuthenticationController._getRedirectFromSession(req) || '/project'
|
||||
_loginAsyncHandlers(req, user)
|
||||
const userId = user._id
|
||||
UserAuditLogHandler.addEntry(userId, 'login', userId, req.ip, err => {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
AuthenticationController._clearRedirectFromSession(req)
|
||||
AsyncFormHelper.redirect(req, res, redir)
|
||||
_afterLoginSessionSetup(req, user, function (err) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
AuthenticationController._clearRedirectFromSession(req)
|
||||
AsyncFormHelper.redirect(req, res, redir)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
doPassportLogin(req, username, password, done) {
|
||||
const email = username.toLowerCase()
|
||||
const Modules = require('../../infrastructure/Modules')
|
||||
Modules.hooks.fire('preDoPassportLogin', req, email, function(
|
||||
err,
|
||||
infoList
|
||||
) {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
const info = infoList.find(i => i != null)
|
||||
if (info != null) {
|
||||
return done(null, false, info)
|
||||
}
|
||||
LoginRateLimiter.processLoginRequest(email, function(err, isAllowed) {
|
||||
Modules.hooks.fire(
|
||||
'preDoPassportLogin',
|
||||
req,
|
||||
email,
|
||||
function (err, infoList) {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
if (!isAllowed) {
|
||||
logger.log({ email }, 'too many login requests')
|
||||
return done(null, null, {
|
||||
text: req.i18n.translate('to_many_login_requests_2_mins'),
|
||||
type: 'error'
|
||||
})
|
||||
const info = infoList.find(i => i != null)
|
||||
if (info != null) {
|
||||
return done(null, false, info)
|
||||
}
|
||||
AuthenticationManager.authenticate({ email }, password, function(
|
||||
error,
|
||||
user
|
||||
) {
|
||||
if (error != null) {
|
||||
return done(error)
|
||||
LoginRateLimiter.processLoginRequest(email, function (err, isAllowed) {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
if (user != null) {
|
||||
// async actions
|
||||
done(null, user)
|
||||
} else {
|
||||
AuthenticationController._recordFailedLogin()
|
||||
logger.log({ email }, 'failed log in')
|
||||
done(null, false, {
|
||||
text: req.i18n.translate('email_or_password_wrong_try_again'),
|
||||
if (!isAllowed) {
|
||||
logger.log({ email }, 'too many login requests')
|
||||
return done(null, null, {
|
||||
text: req.i18n.translate('to_many_login_requests_2_mins'),
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
AuthenticationManager.authenticate(
|
||||
{ email },
|
||||
password,
|
||||
function (error, user) {
|
||||
if (error != null) {
|
||||
return done(error)
|
||||
}
|
||||
if (user != null) {
|
||||
// async actions
|
||||
done(null, user)
|
||||
} else {
|
||||
AuthenticationController._recordFailedLogin()
|
||||
logger.log({ email }, 'failed log in')
|
||||
done(null, false, {
|
||||
text: req.i18n.translate('email_or_password_wrong_try_again'),
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
ipMatchCheck(req, user) {
|
||||
@@ -215,9 +225,9 @@ const AuthenticationController = {
|
||||
},
|
||||
|
||||
requireLogin() {
|
||||
const doRequest = function(req, res, next) {
|
||||
const doRequest = function (req, res, next) {
|
||||
if (next == null) {
|
||||
next = function() {}
|
||||
next = function () {}
|
||||
}
|
||||
if (!AuthenticationController.isUserLoggedIn(req)) {
|
||||
if (acceptsJson(req)) return send401WithChallenge(res)
|
||||
@@ -234,45 +244,47 @@ const AuthenticationController = {
|
||||
requireOauth() {
|
||||
// require this here because module may not be included in some versions
|
||||
const Oauth2Server = require('../../../../modules/oauth2-server/app/src/Oauth2Server')
|
||||
return function(req, res, next) {
|
||||
return function (req, res, next) {
|
||||
if (next == null) {
|
||||
next = function() {}
|
||||
next = function () {}
|
||||
}
|
||||
const request = new Oauth2Server.Request(req)
|
||||
const response = new Oauth2Server.Response(res)
|
||||
return Oauth2Server.server.authenticate(request, response, {}, function(
|
||||
err,
|
||||
token
|
||||
) {
|
||||
if (err) {
|
||||
// use a 401 status code for malformed header for git-bridge
|
||||
if (
|
||||
err.code === 400 &&
|
||||
err.message === 'Invalid request: malformed authorization header'
|
||||
) {
|
||||
err.code = 401
|
||||
return Oauth2Server.server.authenticate(
|
||||
request,
|
||||
response,
|
||||
{},
|
||||
function (err, token) {
|
||||
if (err) {
|
||||
// use a 401 status code for malformed header for git-bridge
|
||||
if (
|
||||
err.code === 400 &&
|
||||
err.message === 'Invalid request: malformed authorization header'
|
||||
) {
|
||||
err.code = 401
|
||||
}
|
||||
// send all other errors
|
||||
return res
|
||||
.status(err.code)
|
||||
.json({ error: err.name, error_description: err.message })
|
||||
}
|
||||
// send all other errors
|
||||
return res
|
||||
.status(err.code)
|
||||
.json({ error: err.name, error_description: err.message })
|
||||
req.oauth = { access_token: token.accessToken }
|
||||
req.oauth_token = token
|
||||
req.oauth_user = token.user
|
||||
return next()
|
||||
}
|
||||
req.oauth = { access_token: token.accessToken }
|
||||
req.oauth_token = token
|
||||
req.oauth_user = token.user
|
||||
return next()
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
validateUserSession: function() {
|
||||
validateUserSession: function () {
|
||||
// Middleware to check that the user's session is still good on key actions,
|
||||
// such as opening a a project. Could be used to check that session has not
|
||||
// exceeded a maximum lifetime (req.session.session_created), or for session
|
||||
// hijacking checks (e.g. change of ip address, req.session.ip_address). For
|
||||
// now, just check that the session has been loaded from the session store
|
||||
// correctly.
|
||||
return function(req, res, next) {
|
||||
return function (req, res, next) {
|
||||
// check that the session store is returning valid results
|
||||
if (req.session && !SessionStoreManager.hasValidationToken(req)) {
|
||||
// force user to update session
|
||||
@@ -349,7 +361,7 @@ const AuthenticationController = {
|
||||
return next()
|
||||
},
|
||||
|
||||
httpAuth: basicAuth(function(user, pass) {
|
||||
httpAuth: basicAuth(function (user, pass) {
|
||||
let expectedPassword = Settings.httpAuthUsers[user]
|
||||
const isValid =
|
||||
expectedPassword &&
|
||||
@@ -424,7 +436,7 @@ const AuthenticationController = {
|
||||
|
||||
_recordSuccessfulLogin(userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
UserUpdater.updateUser(
|
||||
userId.toString(),
|
||||
@@ -432,7 +444,7 @@ const AuthenticationController = {
|
||||
$set: { lastLoggedIn: new Date() },
|
||||
$inc: { loginCount: 1 }
|
||||
},
|
||||
function(error) {
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
callback(error)
|
||||
}
|
||||
@@ -465,9 +477,9 @@ const AuthenticationController = {
|
||||
|
||||
function _afterLoginSessionSetup(req, user, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
req.login(user, function(err) {
|
||||
req.login(user, function (err) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error from req.login', {
|
||||
user_id: user._id
|
||||
@@ -477,7 +489,7 @@ function _afterLoginSessionSetup(req, user, callback) {
|
||||
// Regenerate the session to get a new sessionID (cookie value) to
|
||||
// protect against session fixation attacks
|
||||
const oldSession = req.session
|
||||
req.session.destroy(function(err) {
|
||||
req.session.destroy(function (err) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error when trying to destroy old session', {
|
||||
user_id: user._id
|
||||
@@ -493,14 +505,14 @@ function _afterLoginSessionSetup(req, user, callback) {
|
||||
req.session[key] = value
|
||||
}
|
||||
}
|
||||
req.session.save(function(err) {
|
||||
req.session.save(function (err) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error saving regenerated session after login', {
|
||||
user_id: user._id
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
UserSessionsManager.trackSession(user, req.sessionID, function() {})
|
||||
UserSessionsManager.trackSession(user, req.sessionID, function () {})
|
||||
callback(null)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -12,7 +12,7 @@ const util = require('util')
|
||||
const BCRYPT_ROUNDS = Settings.security.bcryptRounds || 12
|
||||
const BCRYPT_MINOR_VERSION = Settings.security.bcryptMinorVersion || 'a'
|
||||
|
||||
const _checkWriteResult = function(result, callback) {
|
||||
const _checkWriteResult = function (result, callback) {
|
||||
// for MongoDB
|
||||
if (result && result.modifiedCount === 1) {
|
||||
callback(null, true)
|
||||
@@ -33,7 +33,7 @@ const AuthenticationManager = {
|
||||
if (!user || !user.hashedPassword) {
|
||||
return callback(null, null)
|
||||
}
|
||||
bcrypt.compare(password, user.hashedPassword, function(error, match) {
|
||||
bcrypt.compare(password, user.hashedPassword, function (error, match) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -44,7 +44,7 @@ const AuthenticationManager = {
|
||||
user,
|
||||
user.hashedPassword,
|
||||
password,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -146,7 +146,7 @@ const AuthenticationManager = {
|
||||
},
|
||||
|
||||
hashPassword(password, callback) {
|
||||
bcrypt.genSalt(BCRYPT_ROUNDS, BCRYPT_MINOR_VERSION, function(error, salt) {
|
||||
bcrypt.genSalt(BCRYPT_ROUNDS, BCRYPT_MINOR_VERSION, function (error, salt) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -162,7 +162,7 @@ const AuthenticationManager = {
|
||||
if (validationError) {
|
||||
return callback(validationError)
|
||||
}
|
||||
this.hashPassword(password, function(error, hash) {
|
||||
this.hashPassword(password, function (error, hash) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -178,7 +178,7 @@ const AuthenticationManager = {
|
||||
password: true
|
||||
}
|
||||
},
|
||||
function(updateError, result) {
|
||||
function (updateError, result) {
|
||||
if (updateError) {
|
||||
return callback(updateError)
|
||||
}
|
||||
|
||||
@@ -54,20 +54,21 @@ const AuthorizationManager = {
|
||||
return callback(new Error('invalid project id'))
|
||||
}
|
||||
// Note, the Project property in the DB is `publicAccesLevel`, without the second `s`
|
||||
ProjectGetter.getProject(projectId, { publicAccesLevel: 1 }, function(
|
||||
error,
|
||||
project
|
||||
) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
ProjectGetter.getProject(
|
||||
projectId,
|
||||
{ publicAccesLevel: 1 },
|
||||
function (error, project) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
if (!project) {
|
||||
return callback(
|
||||
new Errors.NotFoundError(`no project found with id ${projectId}`)
|
||||
)
|
||||
}
|
||||
callback(null, project.publicAccesLevel)
|
||||
}
|
||||
if (!project) {
|
||||
return callback(
|
||||
new Errors.NotFoundError(`no project found with id ${projectId}`)
|
||||
)
|
||||
}
|
||||
callback(null, project.publicAccesLevel)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
// Get the privilege level that the user has for the project
|
||||
@@ -95,72 +96,78 @@ const AuthorizationManager = {
|
||||
|
||||
// User is present, get their privilege level from database
|
||||
getPrivilegeLevelForProjectWithUser(userId, projectId, token, callback) {
|
||||
CollaboratorsGetter.getMemberIdPrivilegeLevel(userId, projectId, function(
|
||||
error,
|
||||
privilegeLevel
|
||||
) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
if (privilegeLevel && privilegeLevel !== PrivilegeLevels.NONE) {
|
||||
// The user has direct access
|
||||
return callback(null, privilegeLevel, false, false)
|
||||
}
|
||||
AuthorizationManager.isUserSiteAdmin(userId, function(error, isAdmin) {
|
||||
CollaboratorsGetter.getMemberIdPrivilegeLevel(
|
||||
userId,
|
||||
projectId,
|
||||
function (error, privilegeLevel) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
if (isAdmin) {
|
||||
return callback(null, PrivilegeLevels.OWNER, false, true)
|
||||
if (privilegeLevel && privilegeLevel !== PrivilegeLevels.NONE) {
|
||||
// The user has direct access
|
||||
return callback(null, privilegeLevel, false, false)
|
||||
}
|
||||
// Legacy public-access system
|
||||
// User is present (not anonymous), but does not have direct access
|
||||
AuthorizationManager.getPublicAccessLevel(projectId, function(
|
||||
err,
|
||||
publicAccessLevel
|
||||
) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
AuthorizationManager.isUserSiteAdmin(userId, function (error, isAdmin) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
if (publicAccessLevel === PublicAccessLevels.READ_ONLY) {
|
||||
return callback(null, PrivilegeLevels.READ_ONLY, true, false)
|
||||
if (isAdmin) {
|
||||
return callback(null, PrivilegeLevels.OWNER, false, true)
|
||||
}
|
||||
if (publicAccessLevel === PublicAccessLevels.READ_AND_WRITE) {
|
||||
return callback(null, PrivilegeLevels.READ_AND_WRITE, true, false)
|
||||
}
|
||||
callback(null, PrivilegeLevels.NONE, false, false)
|
||||
// Legacy public-access system
|
||||
// User is present (not anonymous), but does not have direct access
|
||||
AuthorizationManager.getPublicAccessLevel(
|
||||
projectId,
|
||||
function (err, publicAccessLevel) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
if (publicAccessLevel === PublicAccessLevels.READ_ONLY) {
|
||||
return callback(null, PrivilegeLevels.READ_ONLY, true, false)
|
||||
}
|
||||
if (publicAccessLevel === PublicAccessLevels.READ_AND_WRITE) {
|
||||
return callback(
|
||||
null,
|
||||
PrivilegeLevels.READ_AND_WRITE,
|
||||
true,
|
||||
false
|
||||
)
|
||||
}
|
||||
callback(null, PrivilegeLevels.NONE, false, false)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
// User is Anonymous, Try Token-based access
|
||||
getPrivilegeLevelForProjectWithoutUser(projectId, token, callback) {
|
||||
AuthorizationManager.getPublicAccessLevel(projectId, function(
|
||||
err,
|
||||
publicAccessLevel
|
||||
) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
AuthorizationManager.getPublicAccessLevel(
|
||||
projectId,
|
||||
function (err, publicAccessLevel) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
if (publicAccessLevel === PublicAccessLevels.READ_ONLY) {
|
||||
// Legacy public read-only access for anonymous user
|
||||
return callback(null, PrivilegeLevels.READ_ONLY, true, false)
|
||||
}
|
||||
if (publicAccessLevel === PublicAccessLevels.READ_AND_WRITE) {
|
||||
// Legacy public read-write access for anonymous user
|
||||
return callback(null, PrivilegeLevels.READ_AND_WRITE, true, false)
|
||||
}
|
||||
if (publicAccessLevel === PublicAccessLevels.TOKEN_BASED) {
|
||||
return AuthorizationManager.getPrivilegeLevelForProjectWithToken(
|
||||
projectId,
|
||||
token,
|
||||
callback
|
||||
)
|
||||
}
|
||||
// Deny anonymous user access
|
||||
callback(null, PrivilegeLevels.NONE, false, false)
|
||||
}
|
||||
if (publicAccessLevel === PublicAccessLevels.READ_ONLY) {
|
||||
// Legacy public read-only access for anonymous user
|
||||
return callback(null, PrivilegeLevels.READ_ONLY, true, false)
|
||||
}
|
||||
if (publicAccessLevel === PublicAccessLevels.READ_AND_WRITE) {
|
||||
// Legacy public read-write access for anonymous user
|
||||
return callback(null, PrivilegeLevels.READ_AND_WRITE, true, false)
|
||||
}
|
||||
if (publicAccessLevel === PublicAccessLevels.TOKEN_BASED) {
|
||||
return AuthorizationManager.getPrivilegeLevelForProjectWithToken(
|
||||
projectId,
|
||||
token,
|
||||
callback
|
||||
)
|
||||
}
|
||||
// Deny anonymous user access
|
||||
callback(null, PrivilegeLevels.NONE, false, false)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
getPrivilegeLevelForProjectWithToken(projectId, token, callback) {
|
||||
@@ -170,7 +177,7 @@ const AuthorizationManager = {
|
||||
TokenAccessHandler.validateTokenForAnonymousAccess(
|
||||
projectId,
|
||||
token,
|
||||
function(err, isValidReadAndWrite, isValidReadOnly) {
|
||||
function (err, isValidReadAndWrite, isValidReadOnly) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -193,7 +200,7 @@ const AuthorizationManager = {
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function(error, privilegeLevel) {
|
||||
function (error, privilegeLevel) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -214,7 +221,7 @@ const AuthorizationManager = {
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function(error, privilegeLevel) {
|
||||
function (error, privilegeLevel) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -233,7 +240,7 @@ const AuthorizationManager = {
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function(error, privilegeLevel, becausePublic) {
|
||||
function (error, privilegeLevel, becausePublic) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -256,7 +263,7 @@ const AuthorizationManager = {
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function(error, privilegeLevel, becausePublic, becauseSiteAdmin) {
|
||||
function (error, privilegeLevel, becausePublic, becauseSiteAdmin) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -273,7 +280,7 @@ const AuthorizationManager = {
|
||||
if (!userId) {
|
||||
return callback(null, false)
|
||||
}
|
||||
User.findOne({ _id: userId }, { isAdmin: 1 }, function(error, user) {
|
||||
User.findOne({ _id: userId }, { isAdmin: 1 }, function (error, user) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ const TokenAccessHandler = require('../TokenAccess/TokenAccessHandler')
|
||||
module.exports = AuthorizationMiddleware = {
|
||||
ensureUserCanReadMultipleProjects(req, res, next) {
|
||||
const projectIds = (req.query.project_ids || '').split(',')
|
||||
AuthorizationMiddleware._getUserId(req, function(error, userId) {
|
||||
AuthorizationMiddleware._getUserId(req, function (error, userId) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -19,13 +19,13 @@ module.exports = AuthorizationMiddleware = {
|
||||
// errors in callbacks
|
||||
async.rejectSeries(
|
||||
projectIds,
|
||||
function(projectId, cb) {
|
||||
function (projectId, cb) {
|
||||
const token = TokenAccessHandler.getRequestToken(req, projectId)
|
||||
AuthorizationManager.canUserReadProject(
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function(error, canRead) {
|
||||
function (error, canRead) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -33,7 +33,7 @@ module.exports = AuthorizationMiddleware = {
|
||||
}
|
||||
)
|
||||
},
|
||||
function(unauthorizedProjectIds) {
|
||||
function (unauthorizedProjectIds) {
|
||||
if (unauthorizedProjectIds.length > 0) {
|
||||
return AuthorizationMiddleware.redirectToRestricted(req, res, next)
|
||||
}
|
||||
@@ -44,178 +44,173 @@ module.exports = AuthorizationMiddleware = {
|
||||
},
|
||||
|
||||
blockRestrictedUserFromProject(req, res, next) {
|
||||
AuthorizationMiddleware._getUserAndProjectId(req, function(
|
||||
error,
|
||||
userId,
|
||||
projectId
|
||||
) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
const token = TokenAccessHandler.getRequestToken(req, projectId)
|
||||
AuthorizationManager.isRestrictedUserForProject(
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
(err, isRestrictedUser) => {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
if (isRestrictedUser) {
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
next()
|
||||
AuthorizationMiddleware._getUserAndProjectId(
|
||||
req,
|
||||
function (error, userId, projectId) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
)
|
||||
})
|
||||
const token = TokenAccessHandler.getRequestToken(req, projectId)
|
||||
AuthorizationManager.isRestrictedUserForProject(
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
(err, isRestrictedUser) => {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
if (isRestrictedUser) {
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
next()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
ensureUserCanReadProject(req, res, next) {
|
||||
AuthorizationMiddleware._getUserAndProjectId(req, function(
|
||||
error,
|
||||
userId,
|
||||
projectId
|
||||
) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
const token = TokenAccessHandler.getRequestToken(req, projectId)
|
||||
AuthorizationManager.canUserReadProject(
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function(error, canRead) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
if (canRead) {
|
||||
AuthorizationMiddleware._getUserAndProjectId(
|
||||
req,
|
||||
function (error, userId, projectId) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
const token = TokenAccessHandler.getRequestToken(req, projectId)
|
||||
AuthorizationManager.canUserReadProject(
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function (error, canRead) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
if (canRead) {
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'allowing user read access to project'
|
||||
)
|
||||
return next()
|
||||
}
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'allowing user read access to project'
|
||||
'denying user read access to project'
|
||||
)
|
||||
return next()
|
||||
HttpErrorHandler.forbidden(req, res)
|
||||
}
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'denying user read access to project'
|
||||
)
|
||||
HttpErrorHandler.forbidden(req, res)
|
||||
}
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
ensureUserCanWriteProjectSettings(req, res, next) {
|
||||
AuthorizationMiddleware._getUserAndProjectId(req, function(
|
||||
error,
|
||||
userId,
|
||||
projectId
|
||||
) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
const token = TokenAccessHandler.getRequestToken(req, projectId)
|
||||
AuthorizationManager.canUserWriteProjectSettings(
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function(error, canWrite) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
if (canWrite) {
|
||||
AuthorizationMiddleware._getUserAndProjectId(
|
||||
req,
|
||||
function (error, userId, projectId) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
const token = TokenAccessHandler.getRequestToken(req, projectId)
|
||||
AuthorizationManager.canUserWriteProjectSettings(
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function (error, canWrite) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
if (canWrite) {
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'allowing user write access to project settings'
|
||||
)
|
||||
return next()
|
||||
}
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'allowing user write access to project settings'
|
||||
'denying user write access to project settings'
|
||||
)
|
||||
return next()
|
||||
HttpErrorHandler.forbidden(req, res)
|
||||
}
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'denying user write access to project settings'
|
||||
)
|
||||
HttpErrorHandler.forbidden(req, res)
|
||||
}
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
ensureUserCanWriteProjectContent(req, res, next) {
|
||||
AuthorizationMiddleware._getUserAndProjectId(req, function(
|
||||
error,
|
||||
userId,
|
||||
projectId
|
||||
) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
const token = TokenAccessHandler.getRequestToken(req, projectId)
|
||||
AuthorizationManager.canUserWriteProjectContent(
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function(error, canWrite) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
if (canWrite) {
|
||||
AuthorizationMiddleware._getUserAndProjectId(
|
||||
req,
|
||||
function (error, userId, projectId) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
const token = TokenAccessHandler.getRequestToken(req, projectId)
|
||||
AuthorizationManager.canUserWriteProjectContent(
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function (error, canWrite) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
if (canWrite) {
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'allowing user write access to project content'
|
||||
)
|
||||
return next()
|
||||
}
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'allowing user write access to project content'
|
||||
'denying user write access to project settings'
|
||||
)
|
||||
return next()
|
||||
HttpErrorHandler.forbidden(req, res)
|
||||
}
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'denying user write access to project settings'
|
||||
)
|
||||
HttpErrorHandler.forbidden(req, res)
|
||||
}
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
ensureUserCanAdminProject(req, res, next) {
|
||||
AuthorizationMiddleware._getUserAndProjectId(req, function(
|
||||
error,
|
||||
userId,
|
||||
projectId
|
||||
) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
const token = TokenAccessHandler.getRequestToken(req, projectId)
|
||||
AuthorizationManager.canUserAdminProject(
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function(error, canAdmin) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
if (canAdmin) {
|
||||
AuthorizationMiddleware._getUserAndProjectId(
|
||||
req,
|
||||
function (error, userId, projectId) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
const token = TokenAccessHandler.getRequestToken(req, projectId)
|
||||
AuthorizationManager.canUserAdminProject(
|
||||
userId,
|
||||
projectId,
|
||||
token,
|
||||
function (error, canAdmin) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
if (canAdmin) {
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'allowing user admin access to project'
|
||||
)
|
||||
return next()
|
||||
}
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'allowing user admin access to project'
|
||||
'denying user admin access to project'
|
||||
)
|
||||
return next()
|
||||
HttpErrorHandler.forbidden(req, res)
|
||||
}
|
||||
logger.log(
|
||||
{ userId, projectId },
|
||||
'denying user admin access to project'
|
||||
)
|
||||
HttpErrorHandler.forbidden(req, res)
|
||||
}
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
ensureUserIsSiteAdmin(req, res, next) {
|
||||
AuthorizationMiddleware._getUserId(req, function(error, userId) {
|
||||
AuthorizationMiddleware._getUserId(req, function (error, userId) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
AuthorizationManager.isUserSiteAdmin(userId, function(error, isAdmin) {
|
||||
AuthorizationManager.isUserSiteAdmin(userId, function (error, isAdmin) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -239,7 +234,7 @@ module.exports = AuthorizationMiddleware = {
|
||||
new Errors.NotFoundError(`invalid projectId: ${projectId}`)
|
||||
)
|
||||
}
|
||||
AuthorizationMiddleware._getUserId(req, function(error, userId) {
|
||||
AuthorizationMiddleware._getUserId(req, function (error, userId) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ const BetaProgramController = {
|
||||
if (userId == null) {
|
||||
return next(new Error('no user id in session'))
|
||||
}
|
||||
BetaProgramHandler.optIn(userId, function(err) {
|
||||
BetaProgramHandler.optIn(userId, function (err) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -26,7 +26,7 @@ const BetaProgramController = {
|
||||
if (userId == null) {
|
||||
return next(new Error('no user id in session'))
|
||||
}
|
||||
BetaProgramHandler.optOut(userId, function(err) {
|
||||
BetaProgramHandler.optOut(userId, function (err) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -37,7 +37,7 @@ const BetaProgramController = {
|
||||
optInPage(req, res, next) {
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
logger.log({ user_id: userId }, 'showing beta participation page for user')
|
||||
UserGetter.getUser(userId, function(err, user) {
|
||||
UserGetter.getUser(userId, function (err, user) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error fetching user', {
|
||||
userId
|
||||
|
||||
@@ -22,7 +22,7 @@ const V1Api = require('../V1/V1Api')
|
||||
module.exports = BrandVariationsHandler = {
|
||||
getBrandVariationById(brandVariationId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, brandVariationDetails) {}
|
||||
callback = function (error, brandVariationDetails) {}
|
||||
}
|
||||
if (brandVariationId == null || brandVariationId === '') {
|
||||
return callback(new Error('Branding variation id not provided'))
|
||||
@@ -32,7 +32,7 @@ module.exports = BrandVariationsHandler = {
|
||||
{
|
||||
uri: `/api/v2/brand_variations/${brandVariationId}`
|
||||
},
|
||||
function(error, response, brandVariationDetails) {
|
||||
function (error, response, brandVariationDetails) {
|
||||
if (error != null) {
|
||||
OError.tag(error, 'error getting brand variation details', {
|
||||
brandVariationId
|
||||
@@ -46,7 +46,7 @@ module.exports = BrandVariationsHandler = {
|
||||
}
|
||||
}
|
||||
|
||||
var _formatBrandVariationDetails = function(details) {
|
||||
var _formatBrandVariationDetails = function (details) {
|
||||
if (details.export_url != null) {
|
||||
details.export_url = _setV1AsHostIfRelativeURL(details.export_url)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ const Settings = require('settings-sharelatex')
|
||||
|
||||
module.exports = CaptchaMiddleware = {
|
||||
validateCaptcha(action) {
|
||||
return function(req, res, next) {
|
||||
return function (req, res, next) {
|
||||
if (
|
||||
(Settings.recaptcha != null ? Settings.recaptcha.siteKey : undefined) ==
|
||||
null
|
||||
@@ -42,7 +42,7 @@ module.exports = CaptchaMiddleware = {
|
||||
return request.post(
|
||||
'https://www.google.com/recaptcha/api/siteverify',
|
||||
options,
|
||||
function(error, response, body) {
|
||||
function (error, response, body) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ const settings = require('settings-sharelatex')
|
||||
module.exports = ChatApiHandler = {
|
||||
_apiRequest(opts, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, data) {}
|
||||
callback = function (error, data) {}
|
||||
}
|
||||
return request(opts, function(error, response, data) {
|
||||
return request(opts, function (error, response, data) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -71,7 +71,7 @@ module.exports = ChatApiHandler = {
|
||||
|
||||
sendComment(project_id, thread_id, user_id, content, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
@@ -85,7 +85,7 @@ module.exports = ChatApiHandler = {
|
||||
|
||||
getThreads(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
@@ -99,7 +99,7 @@ module.exports = ChatApiHandler = {
|
||||
|
||||
resolveThread(project_id, thread_id, user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
@@ -113,7 +113,7 @@ module.exports = ChatApiHandler = {
|
||||
|
||||
reopenThread(project_id, thread_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
@@ -126,7 +126,7 @@ module.exports = ChatApiHandler = {
|
||||
|
||||
deleteThread(project_id, thread_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
@@ -139,7 +139,7 @@ module.exports = ChatApiHandler = {
|
||||
|
||||
editMessage(project_id, thread_id, message_id, content, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
@@ -155,7 +155,7 @@ module.exports = ChatApiHandler = {
|
||||
|
||||
deleteMessage(project_id, thread_id, message_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ChatApiHandler._apiRequest(
|
||||
{
|
||||
|
||||
@@ -36,25 +36,25 @@ module.exports = ChatController = {
|
||||
project_id,
|
||||
user_id,
|
||||
content,
|
||||
function(err, message) {
|
||||
function (err, message) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
return UserInfoManager.getPersonalInfo(message.user_id, function(
|
||||
err,
|
||||
user
|
||||
) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
return UserInfoManager.getPersonalInfo(
|
||||
message.user_id,
|
||||
function (err, user) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
message.user = UserInfoController.formatPersonalInfo(user)
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project_id,
|
||||
'new-chat-message',
|
||||
message
|
||||
)
|
||||
return res.sendStatus(204)
|
||||
}
|
||||
message.user = UserInfoController.formatPersonalInfo(user)
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project_id,
|
||||
'new-chat-message',
|
||||
message
|
||||
)
|
||||
return res.sendStatus(204)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
@@ -66,13 +66,13 @@ module.exports = ChatController = {
|
||||
project_id,
|
||||
query.limit,
|
||||
query.before,
|
||||
function(err, messages) {
|
||||
function (err, messages) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
return ChatController._injectUserInfoIntoThreads(
|
||||
{ global: { messages } },
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -89,7 +89,7 @@ module.exports = ChatController = {
|
||||
// user fields
|
||||
let message, thread, thread_id, user_id
|
||||
if (callback == null) {
|
||||
callback = function(error, threads) {}
|
||||
callback = function (error, threads) {}
|
||||
}
|
||||
const user_ids = {}
|
||||
for (thread_id in threads) {
|
||||
@@ -108,7 +108,7 @@ module.exports = ChatController = {
|
||||
const _ = user_ids[user_id]
|
||||
;(user_id =>
|
||||
jobs.push(cb =>
|
||||
UserInfoManager.getPersonalInfo(user_id, function(error, user) {
|
||||
UserInfoManager.getPersonalInfo(user_id, function (error, user) {
|
||||
if (error != null) return cb(error)
|
||||
user = UserInfoController.formatPersonalInfo(user)
|
||||
users[user_id] = user
|
||||
@@ -117,7 +117,7 @@ module.exports = ChatController = {
|
||||
))(user_id)
|
||||
}
|
||||
|
||||
return async.series(jobs, function(error) {
|
||||
return async.series(jobs, function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ module.exports = CollaboratorsEmailHandler = {
|
||||
return Project.findOne({ _id: project_id })
|
||||
.select('name owner_ref')
|
||||
.populate('owner_ref')
|
||||
.exec(function(err, project) {
|
||||
.exec(function (err, project) {
|
||||
const emailOptions = {
|
||||
to: email,
|
||||
replyTo: project.owner_ref.email,
|
||||
|
||||
@@ -31,37 +31,38 @@ module.exports = CollaboratorsInviteController = {
|
||||
getAllInvites(req, res, next) {
|
||||
const projectId = req.params.Project_id
|
||||
logger.log({ projectId }, 'getting all active invites for project')
|
||||
return CollaboratorsInviteHandler.getAllInvites(projectId, function(
|
||||
err,
|
||||
invites
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting invites for project', {
|
||||
projectId
|
||||
})
|
||||
return next(err)
|
||||
return CollaboratorsInviteHandler.getAllInvites(
|
||||
projectId,
|
||||
function (err, invites) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting invites for project', {
|
||||
projectId
|
||||
})
|
||||
return next(err)
|
||||
}
|
||||
return res.json({ invites })
|
||||
}
|
||||
return res.json({ invites })
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
_checkShouldInviteEmail(email, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, shouldAllowInvite) {}
|
||||
callback = function (err, shouldAllowInvite) {}
|
||||
}
|
||||
if (Settings.restrictInvitesToExistingAccounts === true) {
|
||||
logger.log({ email }, 'checking if user exists with this email')
|
||||
return UserGetter.getUserByAnyEmail(email, { _id: 1 }, function(
|
||||
err,
|
||||
user
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
return UserGetter.getUserByAnyEmail(
|
||||
email,
|
||||
{ _id: 1 },
|
||||
function (err, user) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
const userExists =
|
||||
user != null && (user != null ? user._id : undefined) != null
|
||||
return callback(null, userExists)
|
||||
}
|
||||
const userExists =
|
||||
user != null && (user != null ? user._id : undefined) != null
|
||||
return callback(null, userExists)
|
||||
})
|
||||
)
|
||||
} else {
|
||||
return callback(null, true)
|
||||
}
|
||||
@@ -69,11 +70,11 @@ module.exports = CollaboratorsInviteController = {
|
||||
|
||||
_checkRateLimit(user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return LimitationsManager.allowedNumberOfCollaboratorsForUser(
|
||||
user_id,
|
||||
function(err, collabLimit) {
|
||||
function (err, collabLimit) {
|
||||
if (collabLimit == null) {
|
||||
collabLimit = 1
|
||||
}
|
||||
@@ -134,7 +135,7 @@ module.exports = CollaboratorsInviteController = {
|
||||
}
|
||||
return CollaboratorsInviteController._checkRateLimit(
|
||||
sendingUserId,
|
||||
function(error, underRateLimit) {
|
||||
function (error, underRateLimit) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -143,7 +144,7 @@ module.exports = CollaboratorsInviteController = {
|
||||
}
|
||||
return CollaboratorsInviteController._checkShouldInviteEmail(
|
||||
email,
|
||||
function(err, shouldAllowInvite) {
|
||||
function (err, shouldAllowInvite) {
|
||||
if (err != null) {
|
||||
OError.tag(
|
||||
err,
|
||||
@@ -171,7 +172,7 @@ module.exports = CollaboratorsInviteController = {
|
||||
sendingUser,
|
||||
email,
|
||||
privileges,
|
||||
function(err, invite) {
|
||||
function (err, invite) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error creating project invite', {
|
||||
projectId,
|
||||
@@ -207,7 +208,7 @@ module.exports = CollaboratorsInviteController = {
|
||||
return CollaboratorsInviteHandler.revokeInvite(
|
||||
projectId,
|
||||
inviteId,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error revoking invite', {
|
||||
projectId,
|
||||
@@ -232,7 +233,7 @@ module.exports = CollaboratorsInviteController = {
|
||||
const sendingUser = AuthenticationController.getSessionUser(req)
|
||||
return CollaboratorsInviteController._checkRateLimit(
|
||||
sendingUser._id,
|
||||
function(error, underRateLimit) {
|
||||
function (error, underRateLimit) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -243,7 +244,7 @@ module.exports = CollaboratorsInviteController = {
|
||||
projectId,
|
||||
sendingUser,
|
||||
inviteId,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error resending invite', {
|
||||
projectId,
|
||||
@@ -261,7 +262,7 @@ module.exports = CollaboratorsInviteController = {
|
||||
viewInvite(req, res, next) {
|
||||
const projectId = req.params.Project_id
|
||||
const { token } = req.params
|
||||
const _renderInvalidPage = function() {
|
||||
const _renderInvalidPage = function () {
|
||||
logger.log(
|
||||
{ projectId, token },
|
||||
'invite not valid, rendering not-valid page'
|
||||
@@ -273,7 +274,7 @@ module.exports = CollaboratorsInviteController = {
|
||||
return CollaboratorsGetter.isUserInvitedMemberOfProject(
|
||||
currentUser._id,
|
||||
projectId,
|
||||
function(err, isMember) {
|
||||
function (err, isMember) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error checking if user is member of project', {
|
||||
projectId
|
||||
@@ -291,7 +292,7 @@ module.exports = CollaboratorsInviteController = {
|
||||
return CollaboratorsInviteHandler.getInviteByToken(
|
||||
projectId,
|
||||
token,
|
||||
function(err, invite) {
|
||||
function (err, invite) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting invite by token', {
|
||||
projectId,
|
||||
@@ -308,7 +309,7 @@ module.exports = CollaboratorsInviteController = {
|
||||
return UserGetter.getUser(
|
||||
{ _id: invite.sendingUserId },
|
||||
{ email: 1, first_name: 1, last_name: 1 },
|
||||
function(err, owner) {
|
||||
function (err, owner) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting project owner', {
|
||||
projectId
|
||||
@@ -320,28 +321,29 @@ module.exports = CollaboratorsInviteController = {
|
||||
return _renderInvalidPage()
|
||||
}
|
||||
// fetch the project name
|
||||
return ProjectGetter.getProject(projectId, {}, function(
|
||||
err,
|
||||
project
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting project', {
|
||||
projectId
|
||||
return ProjectGetter.getProject(
|
||||
projectId,
|
||||
{},
|
||||
function (err, project) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting project', {
|
||||
projectId
|
||||
})
|
||||
return next(err)
|
||||
}
|
||||
if (project == null) {
|
||||
logger.log({ projectId }, 'no project found')
|
||||
return _renderInvalidPage()
|
||||
}
|
||||
// finally render the invite
|
||||
return res.render('project/invite/show', {
|
||||
invite,
|
||||
project,
|
||||
owner,
|
||||
title: 'Project Invite'
|
||||
})
|
||||
return next(err)
|
||||
}
|
||||
if (project == null) {
|
||||
logger.log({ projectId }, 'no project found')
|
||||
return _renderInvalidPage()
|
||||
}
|
||||
// finally render the invite
|
||||
return res.render('project/invite/show', {
|
||||
invite,
|
||||
project,
|
||||
owner,
|
||||
title: 'Project Invite'
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -362,7 +364,7 @@ module.exports = CollaboratorsInviteController = {
|
||||
projectId,
|
||||
token,
|
||||
currentUser,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error accepting invite by token', {
|
||||
projectId,
|
||||
|
||||
@@ -26,10 +26,10 @@ const { promisifyAll } = require('../../util/promises')
|
||||
const CollaboratorsInviteHandler = {
|
||||
getAllInvites(projectId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, invites) {}
|
||||
callback = function (err, invites) {}
|
||||
}
|
||||
logger.log({ projectId }, 'fetching invites for project')
|
||||
return ProjectInvite.find({ projectId }, function(err, invites) {
|
||||
return ProjectInvite.find({ projectId }, function (err, invites) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting invites from mongo', {
|
||||
projectId
|
||||
@@ -46,10 +46,10 @@ const CollaboratorsInviteHandler = {
|
||||
|
||||
getInviteCount(projectId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, count) {}
|
||||
callback = function (err, count) {}
|
||||
}
|
||||
logger.log({ projectId }, 'counting invites for project')
|
||||
return ProjectInvite.countDocuments({ projectId }, function(err, count) {
|
||||
return ProjectInvite.countDocuments({ projectId }, function (err, count) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting invites from mongo', {
|
||||
projectId
|
||||
@@ -62,55 +62,57 @@ const CollaboratorsInviteHandler = {
|
||||
|
||||
_trySendInviteNotification(projectId, sendingUser, invite, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
const { email } = invite
|
||||
return UserGetter.getUserByAnyEmail(email, { _id: 1 }, function(
|
||||
err,
|
||||
existingUser
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error checking if user exists', {
|
||||
projectId,
|
||||
email
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
if (existingUser == null) {
|
||||
logger.log({ projectId, email }, 'no existing user found, returning')
|
||||
return callback(null)
|
||||
}
|
||||
return ProjectGetter.getProject(projectId, { _id: 1, name: 1 }, function(
|
||||
err,
|
||||
project
|
||||
) {
|
||||
return UserGetter.getUserByAnyEmail(
|
||||
email,
|
||||
{ _id: 1 },
|
||||
function (err, existingUser) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting project', {
|
||||
OError.tag(err, 'error checking if user exists', {
|
||||
projectId,
|
||||
email
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
if (project == null) {
|
||||
logger.log(
|
||||
{ projectId },
|
||||
'no project found while sending notification, returning'
|
||||
)
|
||||
if (existingUser == null) {
|
||||
logger.log({ projectId, email }, 'no existing user found, returning')
|
||||
return callback(null)
|
||||
}
|
||||
return NotificationsBuilder.projectInvite(
|
||||
invite,
|
||||
project,
|
||||
sendingUser,
|
||||
existingUser
|
||||
).create(callback)
|
||||
})
|
||||
})
|
||||
return ProjectGetter.getProject(
|
||||
projectId,
|
||||
{ _id: 1, name: 1 },
|
||||
function (err, project) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting project', {
|
||||
projectId,
|
||||
email
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
if (project == null) {
|
||||
logger.log(
|
||||
{ projectId },
|
||||
'no project found while sending notification, returning'
|
||||
)
|
||||
return callback(null)
|
||||
}
|
||||
return NotificationsBuilder.projectInvite(
|
||||
invite,
|
||||
project,
|
||||
sendingUser,
|
||||
existingUser
|
||||
).create(callback)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
_tryCancelInviteNotification(inviteId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
return NotificationsBuilder.projectInvite(
|
||||
{ _id: inviteId },
|
||||
@@ -122,7 +124,7 @@ const CollaboratorsInviteHandler = {
|
||||
|
||||
_sendMessages(projectId, sendingUser, invite, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
logger.log(
|
||||
{ projectId, inviteId: invite._id },
|
||||
@@ -133,7 +135,7 @@ const CollaboratorsInviteHandler = {
|
||||
invite.email,
|
||||
invite,
|
||||
sendingUser,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -141,7 +143,7 @@ const CollaboratorsInviteHandler = {
|
||||
projectId,
|
||||
sendingUser,
|
||||
invite,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -154,13 +156,13 @@ const CollaboratorsInviteHandler = {
|
||||
|
||||
inviteToProject(projectId, sendingUser, email, privileges, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, invite) {}
|
||||
callback = function (err, invite) {}
|
||||
}
|
||||
logger.log(
|
||||
{ projectId, sendingUserId: sendingUser._id, email, privileges },
|
||||
'adding invite'
|
||||
)
|
||||
return Crypto.randomBytes(24, function(err, buffer) {
|
||||
return Crypto.randomBytes(24, function (err, buffer) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error generating random token', {
|
||||
projectId,
|
||||
@@ -177,7 +179,7 @@ const CollaboratorsInviteHandler = {
|
||||
projectId,
|
||||
privileges
|
||||
})
|
||||
return invite.save(function(err, invite) {
|
||||
return invite.save(function (err, invite) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error saving token', {
|
||||
projectId,
|
||||
@@ -191,7 +193,7 @@ const CollaboratorsInviteHandler = {
|
||||
projectId,
|
||||
sendingUser,
|
||||
invite,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return logger.err(
|
||||
{ err, projectId, email },
|
||||
@@ -207,98 +209,101 @@ const CollaboratorsInviteHandler = {
|
||||
|
||||
revokeInvite(projectId, inviteId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
logger.log({ projectId, inviteId }, 'removing invite')
|
||||
return ProjectInvite.deleteOne({ projectId, _id: inviteId }, function(err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error removing invite', {
|
||||
projectId,
|
||||
inviteId
|
||||
})
|
||||
return callback(err)
|
||||
return ProjectInvite.deleteOne(
|
||||
{ projectId, _id: inviteId },
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error removing invite', {
|
||||
projectId,
|
||||
inviteId
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
CollaboratorsInviteHandler._tryCancelInviteNotification(
|
||||
inviteId,
|
||||
function () {}
|
||||
)
|
||||
return callback(null)
|
||||
}
|
||||
CollaboratorsInviteHandler._tryCancelInviteNotification(
|
||||
inviteId,
|
||||
function() {}
|
||||
)
|
||||
return callback(null)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
resendInvite(projectId, sendingUser, inviteId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
logger.log({ projectId, inviteId }, 'resending invite email')
|
||||
return ProjectInvite.findOne({ _id: inviteId, projectId }, function(
|
||||
err,
|
||||
invite
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error finding invite', {
|
||||
projectId,
|
||||
inviteId
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
if (invite == null) {
|
||||
logger.err(
|
||||
{ err, projectId, inviteId },
|
||||
'no invite found, nothing to resend'
|
||||
)
|
||||
return callback(null)
|
||||
}
|
||||
return CollaboratorsInviteHandler._sendMessages(
|
||||
projectId,
|
||||
sendingUser,
|
||||
invite,
|
||||
function(err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error resending invite messages', {
|
||||
projectId,
|
||||
inviteId
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
return ProjectInvite.findOne(
|
||||
{ _id: inviteId, projectId },
|
||||
function (err, invite) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error finding invite', {
|
||||
projectId,
|
||||
inviteId
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
if (invite == null) {
|
||||
logger.err(
|
||||
{ err, projectId, inviteId },
|
||||
'no invite found, nothing to resend'
|
||||
)
|
||||
return callback(null)
|
||||
}
|
||||
)
|
||||
})
|
||||
return CollaboratorsInviteHandler._sendMessages(
|
||||
projectId,
|
||||
sendingUser,
|
||||
invite,
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error resending invite messages', {
|
||||
projectId,
|
||||
inviteId
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
return callback(null)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
getInviteByToken(projectId, tokenString, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, invite) {}
|
||||
callback = function (err, invite) {}
|
||||
}
|
||||
logger.log({ projectId, tokenString }, 'fetching invite by token')
|
||||
return ProjectInvite.findOne({ projectId, token: tokenString }, function(
|
||||
err,
|
||||
invite
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error fetching invite', {
|
||||
projectId
|
||||
})
|
||||
return callback(err)
|
||||
return ProjectInvite.findOne(
|
||||
{ projectId, token: tokenString },
|
||||
function (err, invite) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error fetching invite', {
|
||||
projectId
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
if (invite == null) {
|
||||
logger.err({ err, projectId, token: tokenString }, 'no invite found')
|
||||
return callback(null, null)
|
||||
}
|
||||
return callback(null, invite)
|
||||
}
|
||||
if (invite == null) {
|
||||
logger.err({ err, projectId, token: tokenString }, 'no invite found')
|
||||
return callback(null, null)
|
||||
}
|
||||
return callback(null, invite)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
acceptInvite(projectId, tokenString, user, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
logger.log({ projectId, userId: user._id, tokenString }, 'accepting invite')
|
||||
return CollaboratorsInviteHandler.getInviteByToken(
|
||||
projectId,
|
||||
tokenString,
|
||||
function(err, invite) {
|
||||
function (err, invite) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error finding invite', {
|
||||
projectId,
|
||||
@@ -320,7 +325,7 @@ const CollaboratorsInviteHandler = {
|
||||
invite.sendingUserId,
|
||||
user._id,
|
||||
invite.privileges,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error adding user to project', {
|
||||
projectId,
|
||||
@@ -331,7 +336,7 @@ const CollaboratorsInviteHandler = {
|
||||
}
|
||||
// Remove invite
|
||||
logger.log({ projectId, inviteId }, 'removing invite')
|
||||
return ProjectInvite.deleteOne({ _id: inviteId }, function(err) {
|
||||
return ProjectInvite.deleteOne({ _id: inviteId }, function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error removing invite', {
|
||||
projectId,
|
||||
@@ -341,7 +346,7 @@ const CollaboratorsInviteHandler = {
|
||||
}
|
||||
CollaboratorsInviteHandler._tryCancelInviteNotification(
|
||||
inviteId,
|
||||
function() {}
|
||||
function () {}
|
||||
)
|
||||
return callback()
|
||||
})
|
||||
|
||||
@@ -27,7 +27,7 @@ const clsiCookiesEnabled =
|
||||
(Settings.clsiCookie != null ? Settings.clsiCookie.key : undefined) != null &&
|
||||
Settings.clsiCookie.key.length !== 0
|
||||
|
||||
module.exports = function(backendGroup) {
|
||||
module.exports = function (backendGroup) {
|
||||
return {
|
||||
buildKey(project_id) {
|
||||
if (backendGroup != null) {
|
||||
@@ -39,7 +39,7 @@ module.exports = function(backendGroup) {
|
||||
|
||||
_getServerId(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, serverId) {}
|
||||
callback = function (err, serverId) {}
|
||||
}
|
||||
return rclient.get(this.buildKey(project_id), (err, serverId) => {
|
||||
if (err != null) {
|
||||
@@ -55,7 +55,7 @@ module.exports = function(backendGroup) {
|
||||
|
||||
_populateServerIdViaRequest(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, serverId) {}
|
||||
callback = function (err, serverId) {}
|
||||
}
|
||||
const url = `${Settings.apis.clsi.url}/project/${project_id}/status`
|
||||
return request.post(url, (err, res, body) => {
|
||||
@@ -65,7 +65,7 @@ module.exports = function(backendGroup) {
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
return this.setServerId(project_id, res, function(err, serverId) {
|
||||
return this.setServerId(project_id, res, function (err, serverId) {
|
||||
if (err != null) {
|
||||
logger.warn(
|
||||
{ err, project_id },
|
||||
@@ -88,7 +88,7 @@ module.exports = function(backendGroup) {
|
||||
|
||||
setServerId(project_id, response, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, serverId) {}
|
||||
callback = function (err, serverId) {}
|
||||
}
|
||||
if (!clsiCookiesEnabled) {
|
||||
return callback()
|
||||
@@ -112,7 +112,7 @@ module.exports = function(backendGroup) {
|
||||
|
||||
_setServerIdInRedis(rclient, project_id, serverId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
rclient.setex(
|
||||
this.buildKey(project_id),
|
||||
@@ -124,7 +124,7 @@ module.exports = function(backendGroup) {
|
||||
|
||||
clearServerId(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
if (!clsiCookiesEnabled) {
|
||||
return callback()
|
||||
@@ -134,7 +134,7 @@ module.exports = function(backendGroup) {
|
||||
|
||||
getCookieJar(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, jar) {}
|
||||
callback = function (err, jar) {}
|
||||
}
|
||||
if (!clsiCookiesEnabled) {
|
||||
return callback(null, request.jar())
|
||||
|
||||
@@ -26,7 +26,7 @@ module.exports = ClsiFormatChecker = {
|
||||
}
|
||||
}
|
||||
|
||||
return async.series(jobs, function(err, problems) {
|
||||
return async.series(jobs, function (err, problems) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -44,7 +44,7 @@ module.exports = ClsiFormatChecker = {
|
||||
_checkForConflictingPaths(resources, callback) {
|
||||
const paths = resources.map(resource => resource.path)
|
||||
|
||||
const conflicts = _.filter(paths, function(path) {
|
||||
const conflicts = _.filter(paths, function (path) {
|
||||
const matchingPaths = _.filter(
|
||||
paths,
|
||||
checkPath => checkPath.indexOf(path + '/') !== -1
|
||||
@@ -63,7 +63,7 @@ module.exports = ClsiFormatChecker = {
|
||||
|
||||
let totalSize = 0
|
||||
|
||||
let sizedResources = resources.map(function(resource) {
|
||||
let sizedResources = resources.map(function (resource) {
|
||||
const result = { path: resource.path }
|
||||
if (resource.content != null) {
|
||||
result.size = resource.content.replace(/\n/g, '').length
|
||||
@@ -79,9 +79,7 @@ module.exports = ClsiFormatChecker = {
|
||||
if (!tooLarge) {
|
||||
return callback()
|
||||
} else {
|
||||
sizedResources = _.sortBy(sizedResources, 'size')
|
||||
.reverse()
|
||||
.slice(0, 10)
|
||||
sizedResources = _.sortBy(sizedResources, 'size').reverse().slice(0, 10)
|
||||
return callback(null, { resources: sizedResources, totalSize })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,50 +34,48 @@ const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
|
||||
// unsetting it if it removes any documents from the doc updater.
|
||||
|
||||
const buildState = s =>
|
||||
crypto
|
||||
.createHash('sha1')
|
||||
.update(s, 'utf8')
|
||||
.digest('hex')
|
||||
crypto.createHash('sha1').update(s, 'utf8').digest('hex')
|
||||
|
||||
module.exports = ClsiStateManager = {
|
||||
computeHash(project, options, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, hash) {}
|
||||
callback = function (err, hash) {}
|
||||
}
|
||||
return ProjectEntityHandler.getAllEntitiesFromProject(project, function(
|
||||
err,
|
||||
docs,
|
||||
files
|
||||
) {
|
||||
const fileList = Array.from(files || []).map(
|
||||
f => `${f.file._id}:${f.file.rev}:${f.file.created}:${f.path}`
|
||||
)
|
||||
const docList = Array.from(docs || []).map(d => `${d.doc._id}:${d.path}`)
|
||||
const sortedEntityList = [
|
||||
...Array.from(docList),
|
||||
...Array.from(fileList)
|
||||
].sort()
|
||||
// ignore the isAutoCompile options as it doesn't affect the
|
||||
// output, but include all other options e.g. draft
|
||||
const optionsList = (() => {
|
||||
const result = []
|
||||
const object = options || {}
|
||||
for (let key in object) {
|
||||
const value = object[key]
|
||||
if (!['isAutoCompile'].includes(key)) {
|
||||
result.push(`option ${key}:${value}`)
|
||||
return ProjectEntityHandler.getAllEntitiesFromProject(
|
||||
project,
|
||||
function (err, docs, files) {
|
||||
const fileList = Array.from(files || []).map(
|
||||
f => `${f.file._id}:${f.file.rev}:${f.file.created}:${f.path}`
|
||||
)
|
||||
const docList = Array.from(docs || []).map(
|
||||
d => `${d.doc._id}:${d.path}`
|
||||
)
|
||||
const sortedEntityList = [
|
||||
...Array.from(docList),
|
||||
...Array.from(fileList)
|
||||
].sort()
|
||||
// ignore the isAutoCompile options as it doesn't affect the
|
||||
// output, but include all other options e.g. draft
|
||||
const optionsList = (() => {
|
||||
const result = []
|
||||
const object = options || {}
|
||||
for (let key in object) {
|
||||
const value = object[key]
|
||||
if (!['isAutoCompile'].includes(key)) {
|
||||
result.push(`option ${key}:${value}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
})()
|
||||
const sortedOptionsList = optionsList.sort()
|
||||
const hash = buildState(
|
||||
[
|
||||
...Array.from(sortedEntityList),
|
||||
...Array.from(sortedOptionsList)
|
||||
].join('\n')
|
||||
)
|
||||
return callback(null, hash)
|
||||
})
|
||||
return result
|
||||
})()
|
||||
const sortedOptionsList = optionsList.sort()
|
||||
const hash = buildState(
|
||||
[
|
||||
...Array.from(sortedEntityList),
|
||||
...Array.from(sortedOptionsList)
|
||||
].join('\n')
|
||||
)
|
||||
return callback(null, hash)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,11 +104,11 @@ module.exports = CompileController = {
|
||||
|
||||
stopCompile(req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
const project_id = req.params.Project_id
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
return CompileManager.stopCompile(project_id, user_id, function(error) {
|
||||
return CompileManager.stopCompile(project_id, user_id, function (error) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -119,7 +119,7 @@ module.exports = CompileController = {
|
||||
// Used for submissions through the public API
|
||||
compileSubmission(req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
res.setTimeout(COMPILE_TIMEOUT_MS)
|
||||
const { submission_id } = req.params
|
||||
@@ -150,7 +150,7 @@ module.exports = CompileController = {
|
||||
submission_id,
|
||||
req.body,
|
||||
options,
|
||||
function(error, status, outputFiles, clsiServerId, validationProblems) {
|
||||
function (error, status, outputFiles, clsiServerId, validationProblems) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -189,13 +189,13 @@ module.exports = CompileController = {
|
||||
|
||||
downloadPdf(req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
Metrics.inc('pdf-downloads')
|
||||
const project_id = req.params.Project_id
|
||||
const isPdfjsPartialDownload =
|
||||
req.query != null ? req.query.pdfng : undefined
|
||||
const rateLimit = function(callback) {
|
||||
const rateLimit = function (callback) {
|
||||
if (isPdfjsPartialDownload) {
|
||||
return callback(null, true)
|
||||
} else {
|
||||
@@ -209,51 +209,52 @@ module.exports = CompileController = {
|
||||
}
|
||||
}
|
||||
|
||||
return ProjectGetter.getProject(project_id, { name: 1 }, function(
|
||||
err,
|
||||
project
|
||||
) {
|
||||
res.contentType('application/pdf')
|
||||
const filename = `${CompileController._getSafeProjectName(project)}.pdf`
|
||||
return ProjectGetter.getProject(
|
||||
project_id,
|
||||
{ name: 1 },
|
||||
function (err, project) {
|
||||
res.contentType('application/pdf')
|
||||
const filename = `${CompileController._getSafeProjectName(project)}.pdf`
|
||||
|
||||
if (req.query.popupDownload) {
|
||||
res.setContentDisposition('attachment', { filename })
|
||||
} else {
|
||||
res.setContentDisposition('', { filename })
|
||||
}
|
||||
|
||||
return rateLimit(function(err, canContinue) {
|
||||
if (err != null) {
|
||||
logger.err({ err }, 'error checking rate limit for pdf download')
|
||||
return res.sendStatus(500)
|
||||
} else if (!canContinue) {
|
||||
logger.log(
|
||||
{ project_id, ip: req.ip },
|
||||
'rate limit hit downloading pdf'
|
||||
)
|
||||
return res.sendStatus(500)
|
||||
if (req.query.popupDownload) {
|
||||
res.setContentDisposition('attachment', { filename })
|
||||
} else {
|
||||
return CompileController._downloadAsUser(req, function(
|
||||
error,
|
||||
user_id
|
||||
) {
|
||||
const url = CompileController._getFileUrl(
|
||||
project_id,
|
||||
user_id,
|
||||
req.params.build_id,
|
||||
'output.pdf'
|
||||
)
|
||||
return CompileController.proxyToClsi(
|
||||
project_id,
|
||||
url,
|
||||
req,
|
||||
res,
|
||||
next
|
||||
)
|
||||
})
|
||||
res.setContentDisposition('', { filename })
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return rateLimit(function (err, canContinue) {
|
||||
if (err != null) {
|
||||
logger.err({ err }, 'error checking rate limit for pdf download')
|
||||
return res.sendStatus(500)
|
||||
} else if (!canContinue) {
|
||||
logger.log(
|
||||
{ project_id, ip: req.ip },
|
||||
'rate limit hit downloading pdf'
|
||||
)
|
||||
return res.sendStatus(500)
|
||||
} else {
|
||||
return CompileController._downloadAsUser(
|
||||
req,
|
||||
function (error, user_id) {
|
||||
const url = CompileController._getFileUrl(
|
||||
project_id,
|
||||
user_id,
|
||||
req.params.build_id,
|
||||
'output.pdf'
|
||||
)
|
||||
return CompileController.proxyToClsi(
|
||||
project_id,
|
||||
url,
|
||||
req,
|
||||
res,
|
||||
next
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
_getSafeProjectName(project) {
|
||||
@@ -264,18 +265,21 @@ module.exports = CompileController = {
|
||||
deleteAuxFiles(req, res, next) {
|
||||
const project_id = req.params.Project_id
|
||||
const { clsiserverid } = req.query
|
||||
return CompileController._compileAsUser(req, function(error, user_id) {
|
||||
return CompileController._compileAsUser(req, function (error, user_id) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
CompileManager.deleteAuxFiles(project_id, user_id, clsiserverid, function(
|
||||
error
|
||||
) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
CompileManager.deleteAuxFiles(
|
||||
project_id,
|
||||
user_id,
|
||||
clsiserverid,
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return res.sendStatus(200)
|
||||
}
|
||||
return res.sendStatus(200)
|
||||
})
|
||||
)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -283,7 +287,7 @@ module.exports = CompileController = {
|
||||
compileAndDownloadPdf(req, res, next) {
|
||||
const { project_id } = req.params
|
||||
// pass user_id as null, since templates are an "anonymous" compile
|
||||
return CompileManager.compile(project_id, null, {}, function(err) {
|
||||
return CompileManager.compile(project_id, null, {}, function (err) {
|
||||
if (err != null) {
|
||||
logger.err(
|
||||
{ err, project_id },
|
||||
@@ -298,10 +302,10 @@ module.exports = CompileController = {
|
||||
|
||||
getFileFromClsi(req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
const project_id = req.params.Project_id
|
||||
return CompileController._downloadAsUser(req, function(error, user_id) {
|
||||
return CompileController._downloadAsUser(req, function (error, user_id) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -317,7 +321,7 @@ module.exports = CompileController = {
|
||||
|
||||
getFileFromClsiWithoutUser(req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
const { submission_id } = req.params
|
||||
const url = CompileController._getFileUrl(
|
||||
@@ -367,7 +371,7 @@ module.exports = CompileController = {
|
||||
|
||||
proxySyncPdf(req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
const project_id = req.params.Project_id
|
||||
const { page, h, v } = req.query
|
||||
@@ -381,7 +385,7 @@ module.exports = CompileController = {
|
||||
return next(new Error('invalid v parameter'))
|
||||
}
|
||||
// whether this request is going to a per-user container
|
||||
return CompileController._compileAsUser(req, function(error, user_id) {
|
||||
return CompileController._compileAsUser(req, function (error, user_id) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -403,7 +407,7 @@ module.exports = CompileController = {
|
||||
|
||||
proxySyncCode(req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
const project_id = req.params.Project_id
|
||||
const { file, line, column } = req.query
|
||||
@@ -425,7 +429,7 @@ module.exports = CompileController = {
|
||||
if (!(column != null ? column.match(/^\d+$/) : undefined)) {
|
||||
return next(new Error('invalid column parameter'))
|
||||
}
|
||||
return CompileController._compileAsUser(req, function(error, user_id) {
|
||||
return CompileController._compileAsUser(req, function (error, user_id) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -447,7 +451,7 @@ module.exports = CompileController = {
|
||||
|
||||
proxyToClsi(project_id, url, req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
if (req.query != null ? req.query.compileGroup : undefined) {
|
||||
return CompileController.proxyToClsiWithLimits(
|
||||
@@ -459,28 +463,28 @@ module.exports = CompileController = {
|
||||
next
|
||||
)
|
||||
} else {
|
||||
return CompileManager.getProjectCompileLimits(project_id, function(
|
||||
error,
|
||||
limits
|
||||
) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
return CompileManager.getProjectCompileLimits(
|
||||
project_id,
|
||||
function (error, limits) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return CompileController.proxyToClsiWithLimits(
|
||||
project_id,
|
||||
url,
|
||||
limits,
|
||||
req,
|
||||
res,
|
||||
next
|
||||
)
|
||||
}
|
||||
return CompileController.proxyToClsiWithLimits(
|
||||
project_id,
|
||||
url,
|
||||
limits,
|
||||
req,
|
||||
res,
|
||||
next
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
proxyToClsiWithLimits(project_id, url, limits, req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
_getPersistenceOptions(req, project_id, (err, persistenceOptions) => {
|
||||
let qs
|
||||
@@ -541,7 +545,7 @@ module.exports = CompileController = {
|
||||
const project_id = req.params.Project_id
|
||||
const file = req.query.file || false
|
||||
const { clsiserverid } = req.query
|
||||
return CompileController._compileAsUser(req, function(error, user_id) {
|
||||
return CompileController._compileAsUser(req, function (error, user_id) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -550,7 +554,7 @@ module.exports = CompileController = {
|
||||
user_id,
|
||||
file,
|
||||
clsiserverid,
|
||||
function(error, body) {
|
||||
function (error, body) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
|
||||
@@ -30,10 +30,10 @@ module.exports = CompileManager = {
|
||||
options = {}
|
||||
}
|
||||
if (_callback == null) {
|
||||
_callback = function(error) {}
|
||||
_callback = function (error) {}
|
||||
}
|
||||
const timer = new Metrics.Timer('editor.compile')
|
||||
const callback = function(...args) {
|
||||
const callback = function (...args) {
|
||||
timer.done()
|
||||
return _callback(...Array.from(args || []))
|
||||
}
|
||||
@@ -41,7 +41,7 @@ module.exports = CompileManager = {
|
||||
return CompileManager._checkIfRecentlyCompiled(
|
||||
project_id,
|
||||
user_id,
|
||||
function(error, recentlyCompiled) {
|
||||
function (error, recentlyCompiled) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -52,20 +52,20 @@ module.exports = CompileManager = {
|
||||
return CompileManager._checkIfAutoCompileLimitHasBeenHit(
|
||||
options.isAutoCompile,
|
||||
'everyone',
|
||||
function(err, canCompile) {
|
||||
function (err, canCompile) {
|
||||
if (!canCompile) {
|
||||
return callback(null, 'autocompile-backoff', [])
|
||||
}
|
||||
|
||||
return ProjectRootDocManager.ensureRootDocumentIsSet(
|
||||
project_id,
|
||||
function(error) {
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return CompileManager.getProjectCompileLimits(
|
||||
project_id,
|
||||
function(error, limits) {
|
||||
function (error, limits) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -77,7 +77,7 @@ module.exports = CompileManager = {
|
||||
return CompileManager._checkCompileGroupAutoCompileLimit(
|
||||
options.isAutoCompile,
|
||||
limits.compileGroup,
|
||||
function(err, canCompile) {
|
||||
function (err, canCompile) {
|
||||
if (!canCompile) {
|
||||
return callback(null, 'autocompile-backoff', [])
|
||||
}
|
||||
@@ -89,7 +89,7 @@ module.exports = CompileManager = {
|
||||
project_id,
|
||||
compileAsUser,
|
||||
options,
|
||||
function(
|
||||
function (
|
||||
error,
|
||||
status,
|
||||
outputFiles,
|
||||
@@ -123,100 +123,105 @@ module.exports = CompileManager = {
|
||||
|
||||
stopCompile(project_id, user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return CompileManager.getProjectCompileLimits(project_id, function(
|
||||
error,
|
||||
limits
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
return CompileManager.getProjectCompileLimits(
|
||||
project_id,
|
||||
function (error, limits) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return ClsiManager.stopCompile(project_id, user_id, limits, callback)
|
||||
}
|
||||
return ClsiManager.stopCompile(project_id, user_id, limits, callback)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
deleteAuxFiles(project_id, user_id, clsiserverid, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return CompileManager.getProjectCompileLimits(project_id, function(
|
||||
error,
|
||||
limits
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
return CompileManager.getProjectCompileLimits(
|
||||
project_id,
|
||||
function (error, limits) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
ClsiManager.deleteAuxFiles(
|
||||
project_id,
|
||||
user_id,
|
||||
limits,
|
||||
clsiserverid,
|
||||
callback
|
||||
)
|
||||
}
|
||||
ClsiManager.deleteAuxFiles(
|
||||
project_id,
|
||||
user_id,
|
||||
limits,
|
||||
clsiserverid,
|
||||
callback
|
||||
)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
getProjectCompileLimits(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, limits) {}
|
||||
callback = function (error, limits) {}
|
||||
}
|
||||
return ProjectGetter.getProject(project_id, { owner_ref: 1 }, function(
|
||||
error,
|
||||
project
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return UserGetter.getUser(
|
||||
project.owner_ref,
|
||||
{ alphaProgram: 1, betaProgram: 1, features: 1 },
|
||||
function(err, owner) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
let ownerFeatures = (owner && owner.features) || {}
|
||||
// put alpha users into their own compile group
|
||||
if (owner && owner.alphaProgram) {
|
||||
ownerFeatures.compileGroup = 'alpha'
|
||||
}
|
||||
return callback(null, {
|
||||
timeout:
|
||||
ownerFeatures.compileTimeout ||
|
||||
Settings.defaultFeatures.compileTimeout,
|
||||
compileGroup:
|
||||
ownerFeatures.compileGroup ||
|
||||
Settings.defaultFeatures.compileGroup
|
||||
})
|
||||
return ProjectGetter.getProject(
|
||||
project_id,
|
||||
{ owner_ref: 1 },
|
||||
function (error, project) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
)
|
||||
})
|
||||
return UserGetter.getUser(
|
||||
project.owner_ref,
|
||||
{ alphaProgram: 1, betaProgram: 1, features: 1 },
|
||||
function (err, owner) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
let ownerFeatures = (owner && owner.features) || {}
|
||||
// put alpha users into their own compile group
|
||||
if (owner && owner.alphaProgram) {
|
||||
ownerFeatures.compileGroup = 'alpha'
|
||||
}
|
||||
return callback(null, {
|
||||
timeout:
|
||||
ownerFeatures.compileTimeout ||
|
||||
Settings.defaultFeatures.compileTimeout,
|
||||
compileGroup:
|
||||
ownerFeatures.compileGroup ||
|
||||
Settings.defaultFeatures.compileGroup
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
COMPILE_DELAY: 1, // seconds
|
||||
_checkIfRecentlyCompiled(project_id, user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, recentlyCompiled) {}
|
||||
callback = function (error, recentlyCompiled) {}
|
||||
}
|
||||
const key = `compile:${project_id}:${user_id}`
|
||||
return rclient.set(key, true, 'EX', this.COMPILE_DELAY, 'NX', function(
|
||||
error,
|
||||
ok
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
return rclient.set(
|
||||
key,
|
||||
true,
|
||||
'EX',
|
||||
this.COMPILE_DELAY,
|
||||
'NX',
|
||||
function (error, ok) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
if (ok === 'OK') {
|
||||
return callback(null, false)
|
||||
} else {
|
||||
return callback(null, true)
|
||||
}
|
||||
}
|
||||
if (ok === 'OK') {
|
||||
return callback(null, false)
|
||||
} else {
|
||||
return callback(null, true)
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
_checkCompileGroupAutoCompileLimit(isAutoCompile, compileGroup, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, canCompile) {}
|
||||
callback = function (err, canCompile) {}
|
||||
}
|
||||
if (!isAutoCompile) {
|
||||
return callback(null, true)
|
||||
@@ -236,7 +241,7 @@ module.exports = CompileManager = {
|
||||
|
||||
_checkIfAutoCompileLimitHasBeenHit(isAutoCompile, compileGroup, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, canCompile) {}
|
||||
callback = function (err, canCompile) {}
|
||||
}
|
||||
if (!isAutoCompile) {
|
||||
return callback(null, true)
|
||||
@@ -248,7 +253,7 @@ module.exports = CompileManager = {
|
||||
subjectName: compileGroup,
|
||||
throttle: Settings.rateLimit.autoCompile[compileGroup] || 25
|
||||
}
|
||||
return rateLimiter.addCount(opts, function(err, canCompile) {
|
||||
return rateLimiter.addCount(opts, function (err, canCompile) {
|
||||
if (err != null) {
|
||||
canCompile = false
|
||||
}
|
||||
@@ -261,23 +266,23 @@ module.exports = CompileManager = {
|
||||
|
||||
wordCount(project_id, user_id, file, clsiserverid, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return CompileManager.getProjectCompileLimits(project_id, function(
|
||||
error,
|
||||
limits
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
return CompileManager.getProjectCompileLimits(
|
||||
project_id,
|
||||
function (error, limits) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
ClsiManager.wordCount(
|
||||
project_id,
|
||||
user_id,
|
||||
file,
|
||||
limits,
|
||||
clsiserverid,
|
||||
callback
|
||||
)
|
||||
}
|
||||
ClsiManager.wordCount(
|
||||
project_id,
|
||||
user_id,
|
||||
file,
|
||||
limits,
|
||||
clsiserverid,
|
||||
callback
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,58 +22,63 @@ const Modules = require('../../infrastructure/Modules')
|
||||
module.exports = ContactsController = {
|
||||
getContacts(req, res, next) {
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
return ContactManager.getContactIds(user_id, { limit: 50 }, function(
|
||||
error,
|
||||
contact_ids
|
||||
) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return UserGetter.getUsers(
|
||||
contact_ids,
|
||||
{
|
||||
email: 1,
|
||||
first_name: 1,
|
||||
last_name: 1,
|
||||
holdingAccount: 1
|
||||
},
|
||||
function(error, contacts) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
|
||||
// UserGetter.getUsers may not preserve order so put them back in order
|
||||
const positions = {}
|
||||
for (let i = 0; i < contact_ids.length; i++) {
|
||||
const contact_id = contact_ids[i]
|
||||
positions[contact_id] = i
|
||||
}
|
||||
contacts.sort(
|
||||
(a, b) =>
|
||||
positions[a._id != null ? a._id.toString() : undefined] -
|
||||
positions[b._id != null ? b._id.toString() : undefined]
|
||||
)
|
||||
|
||||
// Don't count holding accounts to discourage users from repeating mistakes (mistyped or wrong emails, etc)
|
||||
contacts = contacts.filter(c => !c.holdingAccount)
|
||||
|
||||
contacts = contacts.map(ContactsController._formatContact)
|
||||
|
||||
return Modules.hooks.fire('getContacts', user_id, contacts, function(
|
||||
error,
|
||||
additional_contacts
|
||||
) {
|
||||
return ContactManager.getContactIds(
|
||||
user_id,
|
||||
{ limit: 50 },
|
||||
function (error, contact_ids) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return UserGetter.getUsers(
|
||||
contact_ids,
|
||||
{
|
||||
email: 1,
|
||||
first_name: 1,
|
||||
last_name: 1,
|
||||
holdingAccount: 1
|
||||
},
|
||||
function (error, contacts) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
contacts = contacts.concat(...Array.from(additional_contacts || []))
|
||||
return res.send({
|
||||
contacts
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
// UserGetter.getUsers may not preserve order so put them back in order
|
||||
const positions = {}
|
||||
for (let i = 0; i < contact_ids.length; i++) {
|
||||
const contact_id = contact_ids[i]
|
||||
positions[contact_id] = i
|
||||
}
|
||||
contacts.sort(
|
||||
(a, b) =>
|
||||
positions[a._id != null ? a._id.toString() : undefined] -
|
||||
positions[b._id != null ? b._id.toString() : undefined]
|
||||
)
|
||||
|
||||
// Don't count holding accounts to discourage users from repeating mistakes (mistyped or wrong emails, etc)
|
||||
contacts = contacts.filter(c => !c.holdingAccount)
|
||||
|
||||
contacts = contacts.map(ContactsController._formatContact)
|
||||
|
||||
return Modules.hooks.fire(
|
||||
'getContacts',
|
||||
user_id,
|
||||
contacts,
|
||||
function (error, additional_contacts) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
contacts = contacts.concat(
|
||||
...Array.from(additional_contacts || [])
|
||||
)
|
||||
return res.send({
|
||||
contacts
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
_formatContact(contact) {
|
||||
|
||||
@@ -23,7 +23,7 @@ module.exports = ContactManager = {
|
||||
options = { limits: 50 }
|
||||
}
|
||||
if (callback == null) {
|
||||
callback = function(error, contacts) {}
|
||||
callback = function (error, contacts) {}
|
||||
}
|
||||
const url = `${settings.apis.contacts.url}/user/${user_id}/contacts`
|
||||
return request.get(
|
||||
@@ -33,7 +33,7 @@ module.exports = ContactManager = {
|
||||
json: true,
|
||||
jar: false
|
||||
},
|
||||
function(error, res, data) {
|
||||
function (error, res, data) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -55,7 +55,7 @@ module.exports = ContactManager = {
|
||||
|
||||
addContact(user_id, contact_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
const url = `${settings.apis.contacts.url}/user/${user_id}/contacts`
|
||||
return request.post(
|
||||
@@ -66,7 +66,7 @@ module.exports = ContactManager = {
|
||||
},
|
||||
jar: false
|
||||
},
|
||||
function(error, res, data) {
|
||||
function (error, res, data) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ module.exports = CooldownManager = {
|
||||
|
||||
putProjectOnCooldown(projectId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
logger.log(
|
||||
{ projectId },
|
||||
@@ -41,16 +41,16 @@ module.exports = CooldownManager = {
|
||||
|
||||
isProjectOnCooldown(projectId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, isOnCooldown) {}
|
||||
callback = function (err, isOnCooldown) {}
|
||||
}
|
||||
return rclient.get(CooldownManager._buildKey(projectId), function(
|
||||
err,
|
||||
result
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
return rclient.get(
|
||||
CooldownManager._buildKey(projectId),
|
||||
function (err, result) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(null, result === '1')
|
||||
}
|
||||
return callback(null, result === '1')
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,21 +20,21 @@ module.exports = CooldownMiddleware = {
|
||||
if (projectId == null) {
|
||||
return next(new Error('[Cooldown] No projectId parameter on route'))
|
||||
}
|
||||
return CooldownManager.isProjectOnCooldown(projectId, function(
|
||||
err,
|
||||
projectIsOnCooldown
|
||||
) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
return CooldownManager.isProjectOnCooldown(
|
||||
projectId,
|
||||
function (err, projectIsOnCooldown) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
if (projectIsOnCooldown) {
|
||||
logger.log(
|
||||
{ projectId },
|
||||
'[Cooldown] project is on cooldown, denying request'
|
||||
)
|
||||
return res.sendStatus(429)
|
||||
}
|
||||
return next()
|
||||
}
|
||||
if (projectIsOnCooldown) {
|
||||
logger.log(
|
||||
{ projectId },
|
||||
'[Cooldown] project is on cooldown, denying request'
|
||||
)
|
||||
return res.sendStatus(429)
|
||||
}
|
||||
return next()
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ const TIMEOUT = 30 * 1000 // request timeout
|
||||
const DocstoreManager = {
|
||||
deleteDoc(project_id, doc_id, name, deletedAt, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}`
|
||||
const docMetaData = { deleted: true, deletedAt, name }
|
||||
const options = { url, json: docMetaData, timeout: TIMEOUT }
|
||||
request.patch(options, function(error, res) {
|
||||
request.patch(options, function (error, res) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -59,7 +59,7 @@ const DocstoreManager = {
|
||||
|
||||
getAllDocs(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
const url = `${settings.apis.docstore.url}/project/${project_id}/doc`
|
||||
return request.get(
|
||||
@@ -68,7 +68,7 @@ const DocstoreManager = {
|
||||
timeout: TIMEOUT,
|
||||
json: true
|
||||
},
|
||||
function(error, res, docs) {
|
||||
function (error, res, docs) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -87,29 +87,30 @@ const DocstoreManager = {
|
||||
|
||||
getAllDeletedDocs(project_id, callback) {
|
||||
const url = `${settings.apis.docstore.url}/project/${project_id}/doc-deleted`
|
||||
request.get({ url, timeout: TIMEOUT, json: true }, function(
|
||||
error,
|
||||
res,
|
||||
docs
|
||||
) {
|
||||
if (error) {
|
||||
callback(OError.tag(error, 'could not get deleted docs from docstore'))
|
||||
} else if (res.statusCode === 200) {
|
||||
callback(null, docs)
|
||||
} else {
|
||||
callback(
|
||||
new OError(
|
||||
`docstore api responded with non-success code: ${res.statusCode}`,
|
||||
{ project_id }
|
||||
request.get(
|
||||
{ url, timeout: TIMEOUT, json: true },
|
||||
function (error, res, docs) {
|
||||
if (error) {
|
||||
callback(
|
||||
OError.tag(error, 'could not get deleted docs from docstore')
|
||||
)
|
||||
)
|
||||
} else if (res.statusCode === 200) {
|
||||
callback(null, docs)
|
||||
} else {
|
||||
callback(
|
||||
new OError(
|
||||
`docstore api responded with non-success code: ${res.statusCode}`,
|
||||
{ project_id }
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
getAllRanges(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
const url = `${settings.apis.docstore.url}/project/${project_id}/ranges`
|
||||
return request.get(
|
||||
@@ -118,7 +119,7 @@ const DocstoreManager = {
|
||||
timeout: TIMEOUT,
|
||||
json: true
|
||||
},
|
||||
function(error, res, docs) {
|
||||
function (error, res, docs) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -140,7 +141,7 @@ const DocstoreManager = {
|
||||
options = {}
|
||||
}
|
||||
if (callback == null) {
|
||||
callback = function(error, lines, rev, version) {}
|
||||
callback = function (error, lines, rev, version) {}
|
||||
}
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
@@ -156,7 +157,7 @@ const DocstoreManager = {
|
||||
timeout: TIMEOUT,
|
||||
json: true
|
||||
},
|
||||
function(error, res, doc) {
|
||||
function (error, res, doc) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -191,36 +192,35 @@ const DocstoreManager = {
|
||||
|
||||
isDocDeleted(project_id, doc_id, callback) {
|
||||
const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}/deleted`
|
||||
request.get({ url, timeout: TIMEOUT, json: true }, function(
|
||||
err,
|
||||
res,
|
||||
body
|
||||
) {
|
||||
if (err) {
|
||||
callback(err)
|
||||
} else if (res.statusCode === 200) {
|
||||
callback(null, body.deleted)
|
||||
} else if (res.statusCode === 404) {
|
||||
callback(
|
||||
new Errors.NotFoundError({
|
||||
message: 'doc does not exist in project',
|
||||
info: { project_id, doc_id }
|
||||
})
|
||||
)
|
||||
} else {
|
||||
callback(
|
||||
new OError(
|
||||
`docstore api responded with non-success code: ${res.statusCode}`,
|
||||
{ project_id, doc_id }
|
||||
request.get(
|
||||
{ url, timeout: TIMEOUT, json: true },
|
||||
function (err, res, body) {
|
||||
if (err) {
|
||||
callback(err)
|
||||
} else if (res.statusCode === 200) {
|
||||
callback(null, body.deleted)
|
||||
} else if (res.statusCode === 404) {
|
||||
callback(
|
||||
new Errors.NotFoundError({
|
||||
message: 'doc does not exist in project',
|
||||
info: { project_id, doc_id }
|
||||
})
|
||||
)
|
||||
)
|
||||
} else {
|
||||
callback(
|
||||
new OError(
|
||||
`docstore api responded with non-success code: ${res.statusCode}`,
|
||||
{ project_id, doc_id }
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
updateDoc(project_id, doc_id, lines, version, ranges, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, modified, rev) {}
|
||||
callback = function (error, modified, rev) {}
|
||||
}
|
||||
const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}`
|
||||
return request.post(
|
||||
@@ -233,7 +233,7 @@ const DocstoreManager = {
|
||||
ranges
|
||||
}
|
||||
},
|
||||
function(error, res, result) {
|
||||
function (error, res, result) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -270,7 +270,7 @@ const DocstoreManager = {
|
||||
const url = `${settings.apis.docstore.url}/project/${project_id}/${method}`
|
||||
logger.log({ project_id }, `calling ${method} for project in docstore`)
|
||||
// use default timeout for archiving/unarchiving/destroying
|
||||
request.post(url, function(err, res, docs) {
|
||||
request.post(url, function (err, res, docs) {
|
||||
if (err != null) {
|
||||
OError.tag(err, `error calling ${method} project in docstore`, {
|
||||
project_id
|
||||
|
||||
@@ -101,7 +101,7 @@ function getDocument(projectId, docId, fromVersion, callback) {
|
||||
},
|
||||
projectId,
|
||||
'get-document',
|
||||
function(error, doc) {
|
||||
function (error, doc) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -133,7 +133,7 @@ function getProjectDocsIfMatch(projectId, projectStateHash, callback) {
|
||||
// fall back to getting them from mongo.
|
||||
const timer = new metrics.Timer('get-project-docs')
|
||||
const url = `${settings.apis.documentupdater.url}/project/${projectId}/get_and_flush_if_old?state=${projectStateHash}`
|
||||
request.post(url, function(error, res, body) {
|
||||
request.post(url, function (error, res, body) {
|
||||
timer.done()
|
||||
if (error) {
|
||||
OError.tag(error, 'error getting project docs from doc updater', {
|
||||
@@ -300,7 +300,7 @@ function _makeRequest(options, projectId, metricsKey, callback) {
|
||||
json: options.json,
|
||||
method: options.method || 'GET'
|
||||
},
|
||||
function(error, res, body) {
|
||||
function (error, res, body) {
|
||||
timer.done()
|
||||
if (error) {
|
||||
logger.warn(
|
||||
|
||||
@@ -23,7 +23,7 @@ const _ = require('lodash')
|
||||
module.exports = {
|
||||
getDocument(req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
const project_id = req.params.Project_id
|
||||
const { doc_id } = req.params
|
||||
@@ -32,7 +32,7 @@ module.exports = {
|
||||
return ProjectGetter.getProject(
|
||||
project_id,
|
||||
{ rootFolder: true, overleaf: true },
|
||||
function(error, project) {
|
||||
function (error, project) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -41,7 +41,7 @@ module.exports = {
|
||||
}
|
||||
return ProjectLocator.findElement(
|
||||
{ project, element_id: doc_id, type: 'doc' },
|
||||
function(error, doc, path) {
|
||||
function (error, doc, path) {
|
||||
if (error != null) {
|
||||
OError.tag(error, 'error finding element for getDocument', {
|
||||
doc_id,
|
||||
@@ -49,45 +49,43 @@ module.exports = {
|
||||
})
|
||||
return next(error)
|
||||
}
|
||||
return ProjectEntityHandler.getDoc(project_id, doc_id, function(
|
||||
error,
|
||||
lines,
|
||||
rev,
|
||||
version,
|
||||
ranges
|
||||
) {
|
||||
if (error != null) {
|
||||
OError.tag(
|
||||
error,
|
||||
'error finding doc contents for getDocument',
|
||||
{
|
||||
doc_id,
|
||||
project_id
|
||||
}
|
||||
)
|
||||
return next(error)
|
||||
return ProjectEntityHandler.getDoc(
|
||||
project_id,
|
||||
doc_id,
|
||||
function (error, lines, rev, version, ranges) {
|
||||
if (error != null) {
|
||||
OError.tag(
|
||||
error,
|
||||
'error finding doc contents for getDocument',
|
||||
{
|
||||
doc_id,
|
||||
project_id
|
||||
}
|
||||
)
|
||||
return next(error)
|
||||
}
|
||||
if (plain) {
|
||||
res.type('text/plain')
|
||||
return res.send(lines.join('\n'))
|
||||
} else {
|
||||
const projectHistoryId = _.get(project, 'overleaf.history.id')
|
||||
const projectHistoryType = _.get(
|
||||
project,
|
||||
'overleaf.history.display'
|
||||
)
|
||||
? 'project-history'
|
||||
: undefined // for backwards compatibility, don't send anything if the project is still on track-changes
|
||||
return res.json({
|
||||
lines,
|
||||
version,
|
||||
ranges,
|
||||
pathname: path.fileSystem,
|
||||
projectHistoryId,
|
||||
projectHistoryType
|
||||
})
|
||||
}
|
||||
}
|
||||
if (plain) {
|
||||
res.type('text/plain')
|
||||
return res.send(lines.join('\n'))
|
||||
} else {
|
||||
const projectHistoryId = _.get(project, 'overleaf.history.id')
|
||||
const projectHistoryType = _.get(
|
||||
project,
|
||||
'overleaf.history.display'
|
||||
)
|
||||
? 'project-history'
|
||||
: undefined // for backwards compatibility, don't send anything if the project is still on track-changes
|
||||
return res.json({
|
||||
lines,
|
||||
version,
|
||||
ranges,
|
||||
pathname: path.fileSystem,
|
||||
projectHistoryId,
|
||||
projectHistoryType
|
||||
})
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -96,7 +94,7 @@ module.exports = {
|
||||
|
||||
setDocument(req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
const project_id = req.params.Project_id
|
||||
const { doc_id } = req.params
|
||||
@@ -109,7 +107,7 @@ module.exports = {
|
||||
ranges,
|
||||
lastUpdatedAt,
|
||||
lastUpdatedBy,
|
||||
function(error) {
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
OError.tag(error, 'error finding element for getDocument', {
|
||||
doc_id,
|
||||
|
||||
@@ -22,34 +22,36 @@ module.exports = ProjectDownloadsController = {
|
||||
downloadProject(req, res, next) {
|
||||
const project_id = req.params.Project_id
|
||||
Metrics.inc('zip-downloads')
|
||||
return DocumentUpdaterHandler.flushProjectToMongo(project_id, function(
|
||||
error
|
||||
) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return ProjectGetter.getProject(project_id, { name: true }, function(
|
||||
error,
|
||||
project
|
||||
) {
|
||||
return DocumentUpdaterHandler.flushProjectToMongo(
|
||||
project_id,
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return ProjectZipStreamManager.createZipStreamForProject(
|
||||
return ProjectGetter.getProject(
|
||||
project_id,
|
||||
function(error, stream) {
|
||||
{ name: true },
|
||||
function (error, project) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
res.setContentDisposition('attachment', {
|
||||
filename: `${project.name}.zip`
|
||||
})
|
||||
res.contentType('application/zip')
|
||||
return stream.pipe(res)
|
||||
return ProjectZipStreamManager.createZipStreamForProject(
|
||||
project_id,
|
||||
function (error, stream) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
res.setContentDisposition('attachment', {
|
||||
filename: `${project.name}.zip`
|
||||
})
|
||||
res.contentType('application/zip')
|
||||
return stream.pipe(res)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
downloadMultipleProjects(req, res, next) {
|
||||
@@ -57,13 +59,13 @@ module.exports = ProjectDownloadsController = {
|
||||
Metrics.inc('zip-downloads-multiple')
|
||||
return DocumentUpdaterHandler.flushMultipleProjectsToMongo(
|
||||
project_ids,
|
||||
function(error) {
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return ProjectZipStreamManager.createZipStreamForMultipleProjects(
|
||||
project_ids,
|
||||
function(error, stream) {
|
||||
function (error, stream) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ module.exports = ProjectZipStreamManager = {
|
||||
// We'll build up a zip file that contains multiple zip files
|
||||
|
||||
if (callback == null) {
|
||||
callback = function(error, stream) {}
|
||||
callback = function (error, stream) {}
|
||||
}
|
||||
const archive = archiver('zip')
|
||||
archive.on('error', err =>
|
||||
@@ -41,38 +41,39 @@ module.exports = ProjectZipStreamManager = {
|
||||
for (let project_id of Array.from(project_ids || [])) {
|
||||
;(project_id =>
|
||||
jobs.push(callback =>
|
||||
ProjectGetter.getProject(project_id, { name: true }, function(
|
||||
error,
|
||||
project
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
logger.log(
|
||||
{ project_id, name: project.name },
|
||||
'appending project to zip stream'
|
||||
)
|
||||
return ProjectZipStreamManager.createZipStreamForProject(
|
||||
project_id,
|
||||
function(error, stream) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
archive.append(stream, { name: `${project.name}.zip` })
|
||||
return stream.on('end', function() {
|
||||
logger.log(
|
||||
{ project_id, name: project.name },
|
||||
'zip stream ended'
|
||||
)
|
||||
return callback()
|
||||
})
|
||||
ProjectGetter.getProject(
|
||||
project_id,
|
||||
{ name: true },
|
||||
function (error, project) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
)
|
||||
})
|
||||
logger.log(
|
||||
{ project_id, name: project.name },
|
||||
'appending project to zip stream'
|
||||
)
|
||||
return ProjectZipStreamManager.createZipStreamForProject(
|
||||
project_id,
|
||||
function (error, stream) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
archive.append(stream, { name: `${project.name}.zip` })
|
||||
return stream.on('end', function () {
|
||||
logger.log(
|
||||
{ project_id, name: project.name },
|
||||
'zip stream ended'
|
||||
)
|
||||
return callback()
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
))(project_id)
|
||||
}
|
||||
|
||||
return async.series(jobs, function() {
|
||||
return async.series(jobs, function () {
|
||||
logger.log(
|
||||
{ project_ids },
|
||||
'finished creating zip stream of multiple projects'
|
||||
@@ -83,7 +84,7 @@ module.exports = ProjectZipStreamManager = {
|
||||
|
||||
createZipStreamForProject(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, stream) {}
|
||||
callback = function (error, stream) {}
|
||||
}
|
||||
const archive = archiver('zip')
|
||||
// return stream immediately before we start adding things to it
|
||||
@@ -115,20 +116,20 @@ module.exports = ProjectZipStreamManager = {
|
||||
|
||||
addAllDocsToArchive(project_id, archive, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ProjectEntityHandler.getAllDocs(project_id, function(error, docs) {
|
||||
return ProjectEntityHandler.getAllDocs(project_id, function (error, docs) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
const jobs = []
|
||||
for (let path in docs) {
|
||||
const doc = docs[path]
|
||||
;(function(path, doc) {
|
||||
;(function (path, doc) {
|
||||
if (path[0] === '/') {
|
||||
path = path.slice(1)
|
||||
}
|
||||
return jobs.push(function(callback) {
|
||||
return jobs.push(function (callback) {
|
||||
logger.log({ project_id }, 'Adding doc')
|
||||
archive.append(doc.lines.join('\n'), { name: path })
|
||||
return callback()
|
||||
@@ -141,37 +142,42 @@ module.exports = ProjectZipStreamManager = {
|
||||
|
||||
addAllFilesToArchive(project_id, archive, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ProjectEntityHandler.getAllFiles(project_id, function(error, files) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
return ProjectEntityHandler.getAllFiles(
|
||||
project_id,
|
||||
function (error, files) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
const jobs = []
|
||||
for (let path in files) {
|
||||
const file = files[path]
|
||||
;((path, file) =>
|
||||
jobs.push(callback =>
|
||||
FileStoreHandler.getFileStream(
|
||||
project_id,
|
||||
file._id,
|
||||
{},
|
||||
function (error, stream) {
|
||||
if (error != null) {
|
||||
logger.warn(
|
||||
{ err: error, project_id, file_id: file._id },
|
||||
'something went wrong adding file to zip archive'
|
||||
)
|
||||
return callback(err)
|
||||
}
|
||||
if (path[0] === '/') {
|
||||
path = path.slice(1)
|
||||
}
|
||||
archive.append(stream, { name: path })
|
||||
return stream.on('end', () => callback())
|
||||
}
|
||||
)
|
||||
))(path, file)
|
||||
}
|
||||
return async.parallelLimit(jobs, 5, callback)
|
||||
}
|
||||
const jobs = []
|
||||
for (let path in files) {
|
||||
const file = files[path]
|
||||
;((path, file) =>
|
||||
jobs.push(callback =>
|
||||
FileStoreHandler.getFileStream(project_id, file._id, {}, function(
|
||||
error,
|
||||
stream
|
||||
) {
|
||||
if (error != null) {
|
||||
logger.warn(
|
||||
{ err: error, project_id, file_id: file._id },
|
||||
'something went wrong adding file to zip archive'
|
||||
)
|
||||
return callback(err)
|
||||
}
|
||||
if (path[0] === '/') {
|
||||
path = path.slice(1)
|
||||
}
|
||||
archive.append(stream, { name: path })
|
||||
return stream.on('end', () => callback())
|
||||
})
|
||||
))(path, file)
|
||||
}
|
||||
return async.parallelLimit(jobs, 5, callback)
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ const { promisifyAll } = require('../../util/promises')
|
||||
const EditorController = {
|
||||
addDoc(project_id, folder_id, docName, docLines, source, user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, doc) {}
|
||||
callback = function (error, doc) {}
|
||||
}
|
||||
return EditorController.addDocWithRanges(
|
||||
project_id,
|
||||
@@ -56,7 +56,7 @@ const EditorController = {
|
||||
callback
|
||||
) {
|
||||
if (callback == null) {
|
||||
callback = function(error, doc) {}
|
||||
callback = function (error, doc) {}
|
||||
}
|
||||
docName = docName.trim()
|
||||
Metrics.inc('editor.add-doc')
|
||||
@@ -99,7 +99,7 @@ const EditorController = {
|
||||
callback
|
||||
) {
|
||||
if (callback == null) {
|
||||
callback = function(error, file) {}
|
||||
callback = function (error, file) {}
|
||||
}
|
||||
fileName = fileName.trim()
|
||||
Metrics.inc('editor.add-file')
|
||||
@@ -143,7 +143,7 @@ const EditorController = {
|
||||
callback
|
||||
) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
return ProjectEntityUpdateHandler.upsertDoc(
|
||||
project_id,
|
||||
@@ -152,7 +152,7 @@ const EditorController = {
|
||||
docLines,
|
||||
source,
|
||||
user_id,
|
||||
function(err, doc, didAddNewDoc) {
|
||||
function (err, doc, didAddNewDoc) {
|
||||
if (didAddNewDoc) {
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project_id,
|
||||
@@ -179,7 +179,7 @@ const EditorController = {
|
||||
callback
|
||||
) {
|
||||
if (callback == null) {
|
||||
callback = function(err, file) {}
|
||||
callback = function (err, file) {}
|
||||
}
|
||||
return ProjectEntityUpdateHandler.upsertFile(
|
||||
project_id,
|
||||
@@ -188,7 +188,7 @@ const EditorController = {
|
||||
fsPath,
|
||||
linkedFileData,
|
||||
user_id,
|
||||
function(err, newFile, didAddFile, existingFile) {
|
||||
function (err, newFile, didAddFile, existingFile) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -230,14 +230,14 @@ const EditorController = {
|
||||
docLines,
|
||||
source,
|
||||
user_id,
|
||||
function(err, doc, didAddNewDoc, newFolders, lastFolder) {
|
||||
function (err, doc, didAddNewDoc, newFolders, lastFolder) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return EditorController._notifyProjectUsersOfNewFolders(
|
||||
project_id,
|
||||
newFolders,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -273,14 +273,21 @@ const EditorController = {
|
||||
fsPath,
|
||||
linkedFileData,
|
||||
user_id,
|
||||
function(err, newFile, didAddFile, existingFile, newFolders, lastFolder) {
|
||||
function (
|
||||
err,
|
||||
newFile,
|
||||
didAddFile,
|
||||
existingFile,
|
||||
newFolders,
|
||||
lastFolder
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return EditorController._notifyProjectUsersOfNewFolders(
|
||||
project_id,
|
||||
newFolders,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -312,7 +319,7 @@ const EditorController = {
|
||||
|
||||
addFolder(project_id, folder_id, folderName, source, userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, folder) {}
|
||||
callback = function (error, folder) {}
|
||||
}
|
||||
folderName = folderName.trim()
|
||||
Metrics.inc('editor.add-folder')
|
||||
@@ -335,7 +342,7 @@ const EditorController = {
|
||||
folder_id,
|
||||
folder,
|
||||
userId,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -348,7 +355,7 @@ const EditorController = {
|
||||
|
||||
mkdirp(project_id, path, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, newFolders, lastFolder) {}
|
||||
callback = function (error, newFolders, lastFolder) {}
|
||||
}
|
||||
logger.log({ project_id, path }, "making directories if they don't exist")
|
||||
return ProjectEntityUpdateHandler.mkdirp(
|
||||
@@ -366,7 +373,7 @@ const EditorController = {
|
||||
return EditorController._notifyProjectUsersOfNewFolders(
|
||||
project_id,
|
||||
newFolders,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -379,7 +386,7 @@ const EditorController = {
|
||||
|
||||
deleteEntity(project_id, entity_id, entityType, source, userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
Metrics.inc('editor.delete-entity')
|
||||
return ProjectEntityUpdateHandler.deleteEntity(
|
||||
@@ -387,7 +394,7 @@ const EditorController = {
|
||||
entity_id,
|
||||
entityType,
|
||||
userId,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'could not delete entity', {
|
||||
project_id,
|
||||
@@ -416,7 +423,7 @@ const EditorController = {
|
||||
project_id,
|
||||
path,
|
||||
user_id,
|
||||
function(err, entity_id) {
|
||||
function (err, entity_id) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -433,13 +440,13 @@ const EditorController = {
|
||||
|
||||
updateProjectDescription(project_id, description, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
logger.log({ project_id, description }, 'updating project description')
|
||||
return ProjectDetailsHandler.setProjectDescription(
|
||||
project_id,
|
||||
description,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(
|
||||
err,
|
||||
@@ -468,7 +475,7 @@ const EditorController = {
|
||||
|
||||
renameEntity(project_id, entity_id, entityType, newName, userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
newName = sanitize.escape(newName)
|
||||
Metrics.inc('editor.rename-entity')
|
||||
@@ -478,7 +485,7 @@ const EditorController = {
|
||||
entityType,
|
||||
newName,
|
||||
userId,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error renaming entity', {
|
||||
project_id,
|
||||
@@ -503,7 +510,7 @@ const EditorController = {
|
||||
|
||||
moveEntity(project_id, entity_id, folder_id, entityType, userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
Metrics.inc('editor.move-entity')
|
||||
return ProjectEntityUpdateHandler.moveEntity(
|
||||
@@ -512,7 +519,7 @@ const EditorController = {
|
||||
folder_id,
|
||||
entityType,
|
||||
userId,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error moving entity', {
|
||||
project_id,
|
||||
@@ -534,73 +541,79 @@ const EditorController = {
|
||||
|
||||
renameProject(project_id, newName, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
return ProjectDetailsHandler.renameProject(project_id, newName, function(
|
||||
err
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error renaming project', {
|
||||
return ProjectDetailsHandler.renameProject(
|
||||
project_id,
|
||||
newName,
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error renaming project', {
|
||||
project_id,
|
||||
newName
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project_id,
|
||||
'projectNameUpdated',
|
||||
newName
|
||||
})
|
||||
return callback(err)
|
||||
)
|
||||
return callback()
|
||||
}
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project_id,
|
||||
'projectNameUpdated',
|
||||
newName
|
||||
)
|
||||
return callback()
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
setCompiler(project_id, compiler, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
return ProjectOptionsHandler.setCompiler(project_id, compiler, function(
|
||||
err
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
return ProjectOptionsHandler.setCompiler(
|
||||
project_id,
|
||||
compiler,
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project_id,
|
||||
'compilerUpdated',
|
||||
compiler
|
||||
)
|
||||
return callback()
|
||||
}
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project_id,
|
||||
'compilerUpdated',
|
||||
compiler
|
||||
)
|
||||
return callback()
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
setImageName(project_id, imageName, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
return ProjectOptionsHandler.setImageName(project_id, imageName, function(
|
||||
err
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
return ProjectOptionsHandler.setImageName(
|
||||
project_id,
|
||||
imageName,
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project_id,
|
||||
'imageNameUpdated',
|
||||
imageName
|
||||
)
|
||||
return callback()
|
||||
}
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project_id,
|
||||
'imageNameUpdated',
|
||||
imageName
|
||||
)
|
||||
return callback()
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
setSpellCheckLanguage(project_id, languageCode, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
return ProjectOptionsHandler.setSpellCheckLanguage(
|
||||
project_id,
|
||||
languageCode,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -616,12 +629,12 @@ const EditorController = {
|
||||
|
||||
setPublicAccessLevel(project_id, newAccessLevel, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
return ProjectDetailsHandler.setPublicAccessLevel(
|
||||
project_id,
|
||||
newAccessLevel,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -633,7 +646,7 @@ const EditorController = {
|
||||
if (newAccessLevel === PublicAccessLevels.TOKEN_BASED) {
|
||||
return ProjectDetailsHandler.ensureTokensArePresent(
|
||||
project_id,
|
||||
function(err, tokens) {
|
||||
function (err, tokens) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -654,12 +667,12 @@ const EditorController = {
|
||||
|
||||
setRootDoc(project_id, newRootDocID, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
return ProjectEntityUpdateHandler.setRootDoc(
|
||||
project_id,
|
||||
newRootDocID,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -675,7 +688,7 @@ const EditorController = {
|
||||
|
||||
_notifyProjectUsersOfNewFolders(project_id, folders, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return async.eachSeries(
|
||||
folders,
|
||||
@@ -699,7 +712,7 @@ const EditorController = {
|
||||
callback
|
||||
) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project_id,
|
||||
|
||||
@@ -49,41 +49,41 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
|
||||
return ExportsHandler.exportProject(export_params, function(
|
||||
err,
|
||||
export_data
|
||||
) {
|
||||
if (err != null) {
|
||||
if (err.forwardResponse != null) {
|
||||
logger.log(
|
||||
{ responseError: err.forwardResponse },
|
||||
'forwarding response'
|
||||
)
|
||||
const statusCode = err.forwardResponse.status || 500
|
||||
return res.status(statusCode).json(err.forwardResponse)
|
||||
} else {
|
||||
return next(err)
|
||||
return ExportsHandler.exportProject(
|
||||
export_params,
|
||||
function (err, export_data) {
|
||||
if (err != null) {
|
||||
if (err.forwardResponse != null) {
|
||||
logger.log(
|
||||
{ responseError: err.forwardResponse },
|
||||
'forwarding response'
|
||||
)
|
||||
const statusCode = err.forwardResponse.status || 500
|
||||
return res.status(statusCode).json(err.forwardResponse)
|
||||
} else {
|
||||
return next(err)
|
||||
}
|
||||
}
|
||||
logger.log(
|
||||
{
|
||||
user_id,
|
||||
project_id,
|
||||
brand_variation_id,
|
||||
export_v1_id: export_data.v1_id
|
||||
},
|
||||
'exported project'
|
||||
)
|
||||
return res.json({
|
||||
export_v1_id: export_data.v1_id,
|
||||
message: export_data.message
|
||||
})
|
||||
}
|
||||
logger.log(
|
||||
{
|
||||
user_id,
|
||||
project_id,
|
||||
brand_variation_id,
|
||||
export_v1_id: export_data.v1_id
|
||||
},
|
||||
'exported project'
|
||||
)
|
||||
return res.json({
|
||||
export_v1_id: export_data.v1_id,
|
||||
message: export_data.message
|
||||
})
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
exportStatus(req, res) {
|
||||
const { export_id } = req.params
|
||||
return ExportsHandler.fetchExport(export_id, function(err, export_json) {
|
||||
return ExportsHandler.fetchExport(export_id, function (err, export_json) {
|
||||
let json
|
||||
if (err != null) {
|
||||
json = {
|
||||
@@ -112,15 +112,16 @@ module.exports = {
|
||||
const { type, export_id } = req.params
|
||||
|
||||
AuthenticationController.getLoggedInUserId(req)
|
||||
return ExportsHandler.fetchDownload(export_id, type, function(
|
||||
err,
|
||||
export_file_url
|
||||
) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
return ExportsHandler.fetchDownload(
|
||||
export_id,
|
||||
type,
|
||||
function (err, export_file_url) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
|
||||
return res.redirect(export_file_url)
|
||||
})
|
||||
return res.redirect(export_file_url)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,13 +30,13 @@ settings = require('settings-sharelatex')
|
||||
module.exports = ExportsHandler = self = {
|
||||
exportProject(export_params, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, export_data) {}
|
||||
callback = function (error, export_data) {}
|
||||
}
|
||||
return self._buildExport(export_params, function(err, export_data) {
|
||||
return self._buildExport(export_params, function (err, export_data) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return self._requestExport(export_data, function(err, body) {
|
||||
return self._requestExport(export_data, function (err, body) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -50,7 +50,7 @@ module.exports = ExportsHandler = self = {
|
||||
|
||||
_buildExport(export_params, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, export_data) {}
|
||||
callback = function (err, export_data) {}
|
||||
}
|
||||
const {
|
||||
project_id,
|
||||
@@ -70,17 +70,18 @@ module.exports = ExportsHandler = self = {
|
||||
rootDoc: [
|
||||
'project',
|
||||
(cb, results) =>
|
||||
ProjectRootDocManager.ensureRootDocumentIsValid(project_id, function(
|
||||
error
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
ProjectRootDocManager.ensureRootDocumentIsValid(
|
||||
project_id,
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return ProjectLocator.findRootDoc(
|
||||
{ project: results.project, project_id },
|
||||
cb
|
||||
)
|
||||
}
|
||||
return ProjectLocator.findRootDoc(
|
||||
{ project: results.project, project_id },
|
||||
cb
|
||||
)
|
||||
})
|
||||
)
|
||||
],
|
||||
user(cb) {
|
||||
return UserGetter.getUser(
|
||||
@@ -92,7 +93,7 @@ module.exports = ExportsHandler = self = {
|
||||
historyVersion(cb) {
|
||||
return ProjectHistoryHandler.ensureHistoryExistsForProject(
|
||||
project_id,
|
||||
function(error) {
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -102,7 +103,7 @@ module.exports = ExportsHandler = self = {
|
||||
}
|
||||
}
|
||||
|
||||
return async.auto(jobs, function(err, results) {
|
||||
return async.auto(jobs, function (err, results) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error building project export', {
|
||||
project_id,
|
||||
@@ -167,7 +168,7 @@ module.exports = ExportsHandler = self = {
|
||||
|
||||
_requestExport(export_data, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, export_v1_id) {}
|
||||
callback = function (err, export_v1_id) {}
|
||||
}
|
||||
return request.post(
|
||||
{
|
||||
@@ -175,7 +176,7 @@ module.exports = ExportsHandler = self = {
|
||||
auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass },
|
||||
json: export_data
|
||||
},
|
||||
function(err, res, body) {
|
||||
function (err, res, body) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error making request to v1 export', {
|
||||
export: export_data
|
||||
@@ -197,14 +198,14 @@ module.exports = ExportsHandler = self = {
|
||||
|
||||
_requestVersion(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, export_v1_id) {}
|
||||
callback = function (err, export_v1_id) {}
|
||||
}
|
||||
return request.get(
|
||||
{
|
||||
url: `${settings.apis.project_history.url}/project/${project_id}/version`,
|
||||
json: true
|
||||
},
|
||||
function(err, res, body) {
|
||||
function (err, res, body) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error making request to project history', {
|
||||
project_id
|
||||
@@ -225,14 +226,14 @@ module.exports = ExportsHandler = self = {
|
||||
|
||||
fetchExport(export_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, export_json) {}
|
||||
callback = function (err, export_json) {}
|
||||
}
|
||||
return request.get(
|
||||
{
|
||||
url: `${settings.apis.v1.url}/api/v1/sharelatex/exports/${export_id}`,
|
||||
auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass }
|
||||
},
|
||||
function(err, res, body) {
|
||||
function (err, res, body) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error making request to v1 export', {
|
||||
export: export_id
|
||||
@@ -253,14 +254,14 @@ module.exports = ExportsHandler = self = {
|
||||
|
||||
fetchDownload(export_id, type, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, file_url) {}
|
||||
callback = function (err, file_url) {}
|
||||
}
|
||||
return request.get(
|
||||
{
|
||||
url: `${settings.apis.v1.url}/api/v1/sharelatex/exports/${export_id}/${type}_url`,
|
||||
auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass }
|
||||
},
|
||||
function(err, res, body) {
|
||||
function (err, res, body) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error making request to v1 export', {
|
||||
export: export_id
|
||||
|
||||
@@ -20,7 +20,7 @@ const _ = require('underscore')
|
||||
module.exports = FileHashManager = {
|
||||
computeHash(filePath, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, hashValue) {}
|
||||
callback = function (error, hashValue) {}
|
||||
}
|
||||
callback = _.once(callback) // avoid double callbacks
|
||||
|
||||
@@ -28,20 +28,20 @@ module.exports = FileHashManager = {
|
||||
const getGitBlobHeader = byteLength => `blob ${byteLength}` + '\x00'
|
||||
|
||||
const getByteLengthOfFile = cb =>
|
||||
fs.stat(filePath, function(err, stats) {
|
||||
fs.stat(filePath, function (err, stats) {
|
||||
if (err != null) {
|
||||
return cb(err)
|
||||
}
|
||||
return cb(null, stats.size)
|
||||
})
|
||||
|
||||
return getByteLengthOfFile(function(err, byteLength) {
|
||||
return getByteLengthOfFile(function (err, byteLength) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
const input = fs.createReadStream(filePath)
|
||||
input.on('error', function(err) {
|
||||
input.on('error', function (err) {
|
||||
logger.warn({ filePath, err }, 'error opening file in computeHash')
|
||||
return callback(err)
|
||||
})
|
||||
@@ -49,7 +49,7 @@ module.exports = FileHashManager = {
|
||||
const hash = crypto.createHash('sha1')
|
||||
hash.setEncoding('hex')
|
||||
hash.update(getGitBlobHeader(byteLength))
|
||||
hash.on('readable', function() {
|
||||
hash.on('readable', function () {
|
||||
const result = hash.read()
|
||||
if (result != null) {
|
||||
return callback(null, result.toString('hex'))
|
||||
|
||||
@@ -12,7 +12,7 @@ module.exports = {
|
||||
const userAgent = req.get('User-Agent')
|
||||
ProjectLocator.findElement(
|
||||
{ project_id: projectId, element_id: fileId, type: 'file' },
|
||||
function(err, file) {
|
||||
function (err, file) {
|
||||
if (err) {
|
||||
logger.err(
|
||||
{ err, projectId, fileId, queryString },
|
||||
@@ -20,24 +20,26 @@ module.exports = {
|
||||
)
|
||||
return res.sendStatus(500)
|
||||
}
|
||||
FileStoreHandler.getFileStream(projectId, fileId, queryString, function(
|
||||
err,
|
||||
stream
|
||||
) {
|
||||
if (err) {
|
||||
logger.err(
|
||||
{ err, projectId, fileId, queryString },
|
||||
'error getting file stream for downloading file'
|
||||
)
|
||||
return res.sendStatus(500)
|
||||
FileStoreHandler.getFileStream(
|
||||
projectId,
|
||||
fileId,
|
||||
queryString,
|
||||
function (err, stream) {
|
||||
if (err) {
|
||||
logger.err(
|
||||
{ err, projectId, fileId, queryString },
|
||||
'error getting file stream for downloading file'
|
||||
)
|
||||
return res.sendStatus(500)
|
||||
}
|
||||
// mobile safari will try to render html files, prevent this
|
||||
if (isMobileSafari(userAgent) && isHtml(file)) {
|
||||
res.setHeader('Content-Type', 'text/plain')
|
||||
}
|
||||
res.setContentDisposition('attachment', { filename: file.name })
|
||||
stream.pipe(res)
|
||||
}
|
||||
// mobile safari will try to render html files, prevent this
|
||||
if (isMobileSafari(userAgent) && isHtml(file)) {
|
||||
res.setHeader('Content-Type', 'text/plain')
|
||||
}
|
||||
res.setContentDisposition('attachment', { filename: file.name })
|
||||
stream.pipe(res)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
@@ -17,7 +17,7 @@ const FileStoreHandler = {
|
||||
RETRY_ATTEMPTS: 3,
|
||||
|
||||
uploadFileFromDisk(projectId, fileArgs, fsPath, callback) {
|
||||
fs.lstat(fsPath, function(err, stat) {
|
||||
fs.lstat(fsPath, function (err, stat) {
|
||||
if (err) {
|
||||
logger.warn({ err, projectId, fileArgs, fsPath }, 'error stating file')
|
||||
callback(err)
|
||||
@@ -45,7 +45,7 @@ const FileStoreHandler = {
|
||||
fsPath,
|
||||
cb
|
||||
),
|
||||
function(err, result) {
|
||||
function (err, result) {
|
||||
if (err) {
|
||||
OError.tag(err, 'Error uploading file, retries failed', {
|
||||
projectId,
|
||||
@@ -62,21 +62,21 @@ const FileStoreHandler = {
|
||||
_doUploadFileFromDisk(projectId, fileArgs, fsPath, callback) {
|
||||
const callbackOnce = _.once(callback)
|
||||
|
||||
FileHashManager.computeHash(fsPath, function(err, hashValue) {
|
||||
FileHashManager.computeHash(fsPath, function (err, hashValue) {
|
||||
if (err) {
|
||||
return callbackOnce(err)
|
||||
}
|
||||
const fileRef = new File(Object.assign({}, fileArgs, { hash: hashValue }))
|
||||
const fileId = fileRef._id
|
||||
const readStream = fs.createReadStream(fsPath)
|
||||
readStream.on('error', function(err) {
|
||||
readStream.on('error', function (err) {
|
||||
logger.warn(
|
||||
{ err, projectId, fileId, fsPath },
|
||||
'something went wrong on the read stream of uploadFileFromDisk'
|
||||
)
|
||||
callbackOnce(err)
|
||||
})
|
||||
readStream.on('open', function() {
|
||||
readStream.on('open', function () {
|
||||
const url = FileStoreHandler._buildUrl(projectId, fileId)
|
||||
const opts = {
|
||||
method: 'post',
|
||||
@@ -87,14 +87,14 @@ const FileStoreHandler = {
|
||||
} // send the hash to the filestore as a custom header so it can be checked
|
||||
}
|
||||
const writeStream = request(opts)
|
||||
writeStream.on('error', function(err) {
|
||||
writeStream.on('error', function (err) {
|
||||
logger.warn(
|
||||
{ err, projectId, fileId, fsPath },
|
||||
'something went wrong on the write stream of uploadFileFromDisk'
|
||||
)
|
||||
callbackOnce(err)
|
||||
})
|
||||
writeStream.on('response', function(response) {
|
||||
writeStream.on('response', function (response) {
|
||||
if (![200, 201].includes(response.statusCode)) {
|
||||
err = new OError(
|
||||
`non-ok response from filestore for upload: ${response.statusCode}`,
|
||||
@@ -168,7 +168,7 @@ const FileStoreHandler = {
|
||||
uri: this._buildUrl(projectId, fileId),
|
||||
timeout: FIVE_MINS_IN_MS
|
||||
}
|
||||
return request(opts, function(err, response) {
|
||||
return request(opts, function (err, response) {
|
||||
if (err) {
|
||||
logger.warn(
|
||||
{ err, projectId, fileId },
|
||||
@@ -217,7 +217,7 @@ const FileStoreHandler = {
|
||||
uri: this._buildUrl(newProjectId, newFileId),
|
||||
timeout: FIVE_MINS_IN_MS
|
||||
}
|
||||
return request(opts, function(err, response) {
|
||||
return request(opts, function (err, response) {
|
||||
if (err) {
|
||||
OError.tag(
|
||||
err,
|
||||
|
||||
@@ -61,7 +61,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
checkRedis(req, res, next) {
|
||||
return rclient.healthCheck(function(error) {
|
||||
return rclient.healthCheck(function (error) {
|
||||
if (error != null) {
|
||||
logger.err({ err: error }, 'failed redis health check')
|
||||
return res.sendStatus(500)
|
||||
@@ -72,23 +72,23 @@ module.exports = {
|
||||
},
|
||||
|
||||
checkMongo(req, res, next) {
|
||||
return UserGetter.getUserEmail(settings.smokeTest.userId, function(
|
||||
err,
|
||||
email
|
||||
) {
|
||||
if (err != null) {
|
||||
logger.err({ err }, 'mongo health check failed, error present')
|
||||
return res.sendStatus(500)
|
||||
} else if (email == null) {
|
||||
logger.err(
|
||||
{ err },
|
||||
'mongo health check failed, no emai present in find result'
|
||||
)
|
||||
return res.sendStatus(500)
|
||||
} else {
|
||||
return res.sendStatus(200)
|
||||
return UserGetter.getUserEmail(
|
||||
settings.smokeTest.userId,
|
||||
function (err, email) {
|
||||
if (err != null) {
|
||||
logger.err({ err }, 'mongo health check failed, error present')
|
||||
return res.sendStatus(500)
|
||||
} else if (email == null) {
|
||||
logger.err(
|
||||
{ err },
|
||||
'mongo health check failed, no emai present in find result'
|
||||
)
|
||||
return res.sendStatus(500)
|
||||
} else {
|
||||
return res.sendStatus(200)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = HistoryController = {
|
||||
selectHistoryApi(req, res, next) {
|
||||
const { Project_id: projectId } = req.params
|
||||
// find out which type of history service this project uses
|
||||
ProjectDetailsHandler.getDetails(projectId, function(err, project) {
|
||||
ProjectDetailsHandler.getDetails(projectId, function (err, project) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -52,7 +52,7 @@ module.exports = HistoryController = {
|
||||
}
|
||||
})
|
||||
getReq.pipe(res)
|
||||
getReq.on('error', function(err) {
|
||||
getReq.on('error', function (err) {
|
||||
logger.warn({ url, err }, 'history API error')
|
||||
next(err)
|
||||
})
|
||||
@@ -71,11 +71,11 @@ module.exports = HistoryController = {
|
||||
'X-User-Id': userId
|
||||
}
|
||||
},
|
||||
function(err, body) {
|
||||
function (err, body) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
HistoryManager.injectUserDetails(body, function(err, data) {
|
||||
HistoryManager.injectUserDetails(body, function (err, data) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -97,7 +97,7 @@ module.exports = HistoryController = {
|
||||
|
||||
resyncProjectHistory(req, res, next) {
|
||||
const projectId = req.params.Project_id
|
||||
ProjectEntityUpdateHandler.resyncProjectHistory(projectId, function(err) {
|
||||
ProjectEntityUpdateHandler.resyncProjectHistory(projectId, function (err) {
|
||||
if (err instanceof Errors.ProjectHistoryDisabledError) {
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
@@ -117,7 +117,7 @@ module.exports = HistoryController = {
|
||||
projectId,
|
||||
version,
|
||||
pathname,
|
||||
function(err, entity) {
|
||||
function (err, entity) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -158,7 +158,7 @@ module.exports = HistoryController = {
|
||||
url: `${settings.apis.project_history.url}/project/${projectId}/labels`,
|
||||
json: true
|
||||
},
|
||||
function(err, labels) {
|
||||
function (err, labels) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -182,7 +182,7 @@ module.exports = HistoryController = {
|
||||
url: `${settings.apis.project_history.url}/project/${projectId}/user/${userId}/labels`,
|
||||
json: { comment, version }
|
||||
},
|
||||
function(err, label) {
|
||||
function (err, label) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -230,7 +230,7 @@ module.exports = HistoryController = {
|
||||
UserGetter.getUsers(
|
||||
Array.from(uniqueUsers),
|
||||
{ first_name: 1, last_name: 1, email: 1 },
|
||||
function(err, rawUsers) {
|
||||
function (err, rawUsers) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -274,7 +274,7 @@ module.exports = HistoryController = {
|
||||
method: 'DELETE',
|
||||
url: `${settings.apis.project_history.url}/project/${projectId}/user/${userId}/labels/${labelId}`
|
||||
},
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -284,7 +284,7 @@ module.exports = HistoryController = {
|
||||
},
|
||||
|
||||
_makeRequest(options, callback) {
|
||||
return request(options, function(err, response, body) {
|
||||
return request(options, function (err, response, body) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -301,7 +301,7 @@ module.exports = HistoryController = {
|
||||
|
||||
downloadZipOfVersion(req, res, next) {
|
||||
const { project_id: projectId, version } = req.params
|
||||
ProjectDetailsHandler.getDetails(projectId, function(err, project) {
|
||||
ProjectDetailsHandler.getDetails(projectId, function (err, project) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -344,7 +344,7 @@ module.exports = HistoryController = {
|
||||
method: 'post',
|
||||
url
|
||||
}
|
||||
request(options, function(err, response, body) {
|
||||
request(options, function (err, response, body) {
|
||||
if (err) {
|
||||
OError.tag(err, 'history API error', {
|
||||
v1ProjectId,
|
||||
@@ -362,7 +362,7 @@ module.exports = HistoryController = {
|
||||
async.retry(
|
||||
40,
|
||||
callback =>
|
||||
setTimeout(function() {
|
||||
setTimeout(function () {
|
||||
if (req.aborted) {
|
||||
// client has disconnected -- skip s3 download
|
||||
return callback() // stop async.retry loop
|
||||
@@ -384,7 +384,7 @@ module.exports = HistoryController = {
|
||||
req.off('aborted', abortS3Request)
|
||||
res.off('timeout', abortS3Request)
|
||||
}
|
||||
getReq.on('response', function(response) {
|
||||
getReq.on('response', function (response) {
|
||||
if (response.statusCode !== 200) {
|
||||
cleanupAbortTrigger()
|
||||
return callback(new Error('invalid response'))
|
||||
@@ -407,7 +407,7 @@ module.exports = HistoryController = {
|
||||
})
|
||||
callback()
|
||||
})
|
||||
getReq.on('error', function(err) {
|
||||
getReq.on('error', function (err) {
|
||||
logger.warn(
|
||||
{ err, v1ProjectId, version, retryAttempt },
|
||||
'history s3 download error'
|
||||
@@ -416,7 +416,7 @@ module.exports = HistoryController = {
|
||||
callback(err)
|
||||
})
|
||||
}, retryDelay),
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err) {
|
||||
OError.tag(err, 'history s3 download failed', {
|
||||
v1ProjectId,
|
||||
|
||||
@@ -28,13 +28,13 @@ module.exports = RestoreManager = {
|
||||
// It looks up the deleted doc's contents, and then creates a new doc with the same content.
|
||||
// We don't actually remove the deleted doc entry, just create a new one from its lines.
|
||||
if (callback == null) {
|
||||
callback = function(error, doc, folder_id) {}
|
||||
callback = function (error, doc, folder_id) {}
|
||||
}
|
||||
return ProjectEntityHandler.getDoc(
|
||||
project_id,
|
||||
doc_id,
|
||||
{ include_deleted: true },
|
||||
function(error, lines) {
|
||||
function (error, lines) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -59,13 +59,13 @@ module.exports = RestoreManager = {
|
||||
|
||||
restoreFileFromV2(user_id, project_id, version, pathname, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, entity) {}
|
||||
callback = function (error, entity) {}
|
||||
}
|
||||
return RestoreManager._writeFileVersionToDisk(
|
||||
project_id,
|
||||
version,
|
||||
pathname,
|
||||
function(error, fsPath) {
|
||||
function (error, fsPath) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -75,54 +75,55 @@ module.exports = RestoreManager = {
|
||||
// no directory
|
||||
dirname = ''
|
||||
}
|
||||
return RestoreManager._findOrCreateFolder(project_id, dirname, function(
|
||||
error,
|
||||
parent_folder_id
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
const addEntityWithName = (name, callback) =>
|
||||
FileSystemImportManager.addEntity(
|
||||
user_id,
|
||||
project_id,
|
||||
parent_folder_id,
|
||||
name,
|
||||
fsPath,
|
||||
false,
|
||||
return RestoreManager._findOrCreateFolder(
|
||||
project_id,
|
||||
dirname,
|
||||
function (error, parent_folder_id) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
const addEntityWithName = (name, callback) =>
|
||||
FileSystemImportManager.addEntity(
|
||||
user_id,
|
||||
project_id,
|
||||
parent_folder_id,
|
||||
name,
|
||||
fsPath,
|
||||
false,
|
||||
callback
|
||||
)
|
||||
return RestoreManager._addEntityWithUniqueName(
|
||||
addEntityWithName,
|
||||
basename,
|
||||
callback
|
||||
)
|
||||
return RestoreManager._addEntityWithUniqueName(
|
||||
addEntityWithName,
|
||||
basename,
|
||||
callback
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
_findOrCreateFolder(project_id, dirname, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, folder_id) {}
|
||||
callback = function (error, folder_id) {}
|
||||
}
|
||||
return EditorController.mkdirp(project_id, dirname, function(
|
||||
error,
|
||||
newFolders,
|
||||
lastFolder
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
return EditorController.mkdirp(
|
||||
project_id,
|
||||
dirname,
|
||||
function (error, newFolders, lastFolder) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return callback(null, lastFolder != null ? lastFolder._id : undefined)
|
||||
}
|
||||
return callback(null, lastFolder != null ? lastFolder._id : undefined)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
_addEntityWithUniqueName(addEntityWithName, basename, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return addEntityWithName(basename, function(error, entity) {
|
||||
return addEntityWithName(basename, function (error, entity) {
|
||||
if (error != null) {
|
||||
if (error instanceof Errors.InvalidNameError) {
|
||||
// likely a duplicate name, so try with a prefix
|
||||
@@ -146,7 +147,7 @@ module.exports = RestoreManager = {
|
||||
|
||||
_writeFileVersionToDisk(project_id, version, pathname, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, fsPath) {}
|
||||
callback = function (error, fsPath) {}
|
||||
}
|
||||
const url = `${
|
||||
Settings.apis.project_history.url
|
||||
|
||||
@@ -22,7 +22,7 @@ module.exports = {
|
||||
return InactiveProjectManager.deactivateOldProjects(
|
||||
numberOfProjectsToArchive,
|
||||
ageOfProjects,
|
||||
function(err, projectsDeactivated) {
|
||||
function (err, projectsDeactivated) {
|
||||
if (err != null) {
|
||||
return res.sendStatus(500)
|
||||
} else {
|
||||
@@ -34,7 +34,7 @@ module.exports = {
|
||||
|
||||
deactivateProject(req, res) {
|
||||
const { project_id } = req.params
|
||||
return InactiveProjectManager.deactivateProject(project_id, function(err) {
|
||||
return InactiveProjectManager.deactivateProject(project_id, function (err) {
|
||||
if (err != null) {
|
||||
return res.sendStatus(500)
|
||||
} else {
|
||||
|
||||
@@ -24,35 +24,36 @@ const { ObjectId } = require('mongodb')
|
||||
const MILISECONDS_IN_DAY = 86400000
|
||||
module.exports = InactiveProjectManager = {
|
||||
reactivateProjectIfRequired(project_id, callback) {
|
||||
return ProjectGetter.getProject(project_id, { active: true }, function(
|
||||
err,
|
||||
project
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting project', {
|
||||
project_id
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
logger.log(
|
||||
{ project_id, active: project.active },
|
||||
'seeing if need to reactivate project'
|
||||
)
|
||||
|
||||
if (project.active) {
|
||||
return callback()
|
||||
}
|
||||
|
||||
return DocstoreManager.unarchiveProject(project_id, function(err) {
|
||||
return ProjectGetter.getProject(
|
||||
project_id,
|
||||
{ active: true },
|
||||
function (err, project) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error reactivating project in docstore', {
|
||||
OError.tag(err, 'error getting project', {
|
||||
project_id
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
return ProjectUpdateHandler.markAsActive(project_id, callback)
|
||||
})
|
||||
})
|
||||
logger.log(
|
||||
{ project_id, active: project.active },
|
||||
'seeing if need to reactivate project'
|
||||
)
|
||||
|
||||
if (project.active) {
|
||||
return callback()
|
||||
}
|
||||
|
||||
return DocstoreManager.unarchiveProject(project_id, function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error reactivating project in docstore', {
|
||||
project_id
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
return ProjectUpdateHandler.markAsActive(project_id, callback)
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
deactivateOldProjects(limit, daysOld, callback) {
|
||||
@@ -73,12 +74,12 @@ module.exports = InactiveProjectManager = {
|
||||
.sort({ _id: 1 })
|
||||
.limit(limit)
|
||||
.read('secondary')
|
||||
.exec(function(err, projects) {
|
||||
.exec(function (err, projects) {
|
||||
if (err != null) {
|
||||
logger.err({ err }, 'could not get projects for deactivating')
|
||||
}
|
||||
const jobs = _.map(projects, project => cb =>
|
||||
InactiveProjectManager.deactivateProject(project._id, function(err) {
|
||||
InactiveProjectManager.deactivateProject(project._id, function (err) {
|
||||
if (err) {
|
||||
logger.err(
|
||||
{ project_id: project._id, err: err },
|
||||
@@ -92,7 +93,7 @@ module.exports = InactiveProjectManager = {
|
||||
{ numberOfProjects: projects && projects.length },
|
||||
'deactivating projects'
|
||||
)
|
||||
async.series(jobs, function(err) {
|
||||
async.series(jobs, function (err) {
|
||||
if (err != null) {
|
||||
logger.warn({ err }, 'error deactivating projects')
|
||||
}
|
||||
@@ -107,7 +108,7 @@ module.exports = InactiveProjectManager = {
|
||||
cb => DocstoreManager.archiveProject(project_id, cb),
|
||||
cb => ProjectUpdateHandler.markAsInactive(project_id, cb)
|
||||
]
|
||||
return async.series(jobs, function(err) {
|
||||
return async.series(jobs, function (err) {
|
||||
if (err != null) {
|
||||
logger.warn({ err, project_id }, 'error deactivating project')
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ const InstitutionsAPI = {
|
||||
},
|
||||
defaultErrorMessage: "Couldn't create affiliation"
|
||||
},
|
||||
function(error, body) {
|
||||
function (error, body) {
|
||||
if (error) {
|
||||
if (error.info && error.info.statusCode === 422) {
|
||||
return callback(
|
||||
@@ -115,7 +115,7 @@ const InstitutionsAPI = {
|
||||
// have notifications delete any ip matcher notifications for this university
|
||||
NotificationsBuilder.ipMatcherAffiliation(userId).read(
|
||||
university.id,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err) {
|
||||
// log and ignore error
|
||||
logger.err(
|
||||
@@ -191,7 +191,7 @@ const InstitutionsAPI = {
|
||||
}
|
||||
}
|
||||
|
||||
var makeAffiliationRequest = function(requestOptions, callback) {
|
||||
var makeAffiliationRequest = function (requestOptions, callback) {
|
||||
if (!settings.apis.v1.url) {
|
||||
return callback(null)
|
||||
} // service is not configured
|
||||
@@ -207,7 +207,7 @@ var makeAffiliationRequest = function(requestOptions, callback) {
|
||||
json: true,
|
||||
timeout: 20 * 1000
|
||||
},
|
||||
function(error, response, body) {
|
||||
function (error, response, body) {
|
||||
if (error) {
|
||||
return callback(
|
||||
new V1ConnectionError('error getting affiliations from v1').withCause(
|
||||
|
||||
@@ -8,7 +8,7 @@ const ASYNC_AFFILIATIONS_LIMIT = 10
|
||||
module.exports = {
|
||||
confirmDomain(req, res, next) {
|
||||
const { hostname } = req.body
|
||||
affiliateUsers(hostname, function(error) {
|
||||
affiliateUsers(hostname, function (error) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -17,13 +17,9 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
|
||||
var affiliateUsers = function(hostname, callback) {
|
||||
const reversedHostname = hostname
|
||||
.trim()
|
||||
.split('')
|
||||
.reverse()
|
||||
.join('')
|
||||
UserGetter.getUsersByHostname(hostname, { _id: 1 }, function(error, users) {
|
||||
var affiliateUsers = function (hostname, callback) {
|
||||
const reversedHostname = hostname.trim().split('').reverse().join('')
|
||||
UserGetter.getUsersByHostname(hostname, { _id: 1 }, function (error, users) {
|
||||
if (error) {
|
||||
OError.tag(error, 'problem fetching users by hostname')
|
||||
return callback(error)
|
||||
@@ -44,7 +40,7 @@ var affiliateUsers = function(hostname, callback) {
|
||||
})
|
||||
}
|
||||
|
||||
var affiliateUserByReversedHostname = function(
|
||||
var affiliateUserByReversedHostname = function (
|
||||
user,
|
||||
reversedHostname,
|
||||
callback
|
||||
|
||||
@@ -5,18 +5,21 @@ const Settings = require('settings-sharelatex')
|
||||
|
||||
module.exports = InstitutionsFeatures = {
|
||||
getInstitutionsFeatures(userId, callback) {
|
||||
InstitutionsFeatures.getInstitutionsPlan(userId, function(error, planCode) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
InstitutionsFeatures.getInstitutionsPlan(
|
||||
userId,
|
||||
function (error, planCode) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
const plan = planCode && PlansLocator.findLocalPlanInSettings(planCode)
|
||||
const features = plan && plan.features
|
||||
callback(null, features || {})
|
||||
}
|
||||
const plan = planCode && PlansLocator.findLocalPlanInSettings(planCode)
|
||||
const features = plan && plan.features
|
||||
callback(null, features || {})
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
getInstitutionsPlan(userId, callback) {
|
||||
InstitutionsFeatures.hasLicence(userId, function(error, hasLicence) {
|
||||
InstitutionsFeatures.hasLicence(userId, function (error, hasLicence) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -28,7 +31,7 @@ module.exports = InstitutionsFeatures = {
|
||||
},
|
||||
|
||||
hasLicence(userId, callback) {
|
||||
UserGetter.getUserFullEmails(userId, function(error, emailsData) {
|
||||
UserGetter.getUserFullEmails(userId, function (error, emailsData) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ const UserMembershipEntityConfigs = require('../UserMembership/UserMembershipEnt
|
||||
|
||||
module.exports = InstitutionsGetter = {
|
||||
getConfirmedAffiliations(userId, callback) {
|
||||
UserGetter.getUserFullEmails(userId, function(error, emailsData) {
|
||||
UserGetter.getUserFullEmails(userId, function (error, emailsData) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ module.exports = {
|
||||
async.waterfall(
|
||||
[
|
||||
cb => fetchInstitutionAndAffiliations(institutionId, cb),
|
||||
function(institution, affiliations, cb) {
|
||||
affiliations = _.map(affiliations, function(affiliation) {
|
||||
function (institution, affiliations, cb) {
|
||||
affiliations = _.map(affiliations, function (affiliation) {
|
||||
affiliation.institutionName = institution.name
|
||||
affiliation.institutionId = institutionId
|
||||
return affiliation
|
||||
@@ -50,7 +50,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
getInstitutionUsersSubscriptions(institutionId, callback) {
|
||||
getInstitutionAffiliations(institutionId, function(error, affiliations) {
|
||||
getInstitutionAffiliations(institutionId, function (error, affiliations) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -84,12 +84,12 @@ var fetchInstitutionAndAffiliations = (institutionId, callback) =>
|
||||
callback
|
||||
)
|
||||
|
||||
var refreshFeatures = function(affiliation, callback) {
|
||||
var refreshFeatures = function (affiliation, callback) {
|
||||
const userId = ObjectId(affiliation.user_id)
|
||||
FeaturesUpdater.refreshFeatures(userId, callback)
|
||||
}
|
||||
|
||||
var refreshFeaturesAndNotify = function(affiliation, callback) {
|
||||
var refreshFeaturesAndNotify = function (affiliation, callback) {
|
||||
const userId = ObjectId(affiliation.user_id)
|
||||
async.waterfall(
|
||||
[
|
||||
@@ -124,7 +124,7 @@ var getUserInfo = (userId, callback) =>
|
||||
var notifyUser = (user, affiliation, subscription, featuresChanged, callback) =>
|
||||
async.parallel(
|
||||
[
|
||||
function(cb) {
|
||||
function (cb) {
|
||||
if (featuresChanged) {
|
||||
NotificationsBuilder.featuresUpgradedByAffiliation(
|
||||
affiliation,
|
||||
@@ -134,7 +134,7 @@ var notifyUser = (user, affiliation, subscription, featuresChanged, callback) =>
|
||||
cb()
|
||||
}
|
||||
},
|
||||
function(cb) {
|
||||
function (cb) {
|
||||
if (
|
||||
subscription &&
|
||||
!subscription.planCode.match(/(free|trial)/) &&
|
||||
@@ -152,7 +152,7 @@ var notifyUser = (user, affiliation, subscription, featuresChanged, callback) =>
|
||||
callback
|
||||
)
|
||||
|
||||
var checkFeatures = function(institutionId, users) {
|
||||
var checkFeatures = function (institutionId, users) {
|
||||
const usersSummary = {
|
||||
confirmedEmailUsers: {
|
||||
total: users.length, // all users are confirmed email users
|
||||
@@ -167,7 +167,7 @@ var checkFeatures = function(institutionId, users) {
|
||||
nonProUsers: []
|
||||
}
|
||||
}
|
||||
users.forEach(function(user) {
|
||||
users.forEach(function (user) {
|
||||
let isSSOEntitled = SAMLIdentityManager.userHasEntitlement(
|
||||
user,
|
||||
institutionId
|
||||
|
||||
@@ -75,7 +75,7 @@ module.exports = LinkedFilesController = {
|
||||
name,
|
||||
parent_folder_id,
|
||||
user_id,
|
||||
function(err, newFileId) {
|
||||
function (err, newFileId) {
|
||||
if (err != null) {
|
||||
return LinkedFilesController.handleError(err, req, res, next)
|
||||
}
|
||||
@@ -88,47 +88,46 @@ module.exports = LinkedFilesController = {
|
||||
const { project_id, file_id } = req.params
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
|
||||
return LinkedFilesHandler.getFileById(project_id, file_id, function(
|
||||
err,
|
||||
file,
|
||||
path,
|
||||
parentFolder
|
||||
) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
if (file == null) {
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
const { name } = file
|
||||
const { linkedFileData } = file
|
||||
if (
|
||||
linkedFileData == null ||
|
||||
(linkedFileData != null ? linkedFileData.provider : undefined) == null
|
||||
) {
|
||||
return res.sendStatus(409)
|
||||
}
|
||||
const { provider } = linkedFileData
|
||||
const parent_folder_id = parentFolder._id
|
||||
const Agent = LinkedFilesController._getAgent(provider)
|
||||
if (Agent == null) {
|
||||
return res.sendStatus(400)
|
||||
}
|
||||
|
||||
return Agent.refreshLinkedFile(
|
||||
project_id,
|
||||
linkedFileData,
|
||||
name,
|
||||
parent_folder_id,
|
||||
user_id,
|
||||
function(err, newFileId) {
|
||||
if (err != null) {
|
||||
return LinkedFilesController.handleError(err, req, res, next)
|
||||
}
|
||||
return res.json({ new_file_id: newFileId })
|
||||
return LinkedFilesHandler.getFileById(
|
||||
project_id,
|
||||
file_id,
|
||||
function (err, file, path, parentFolder) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
)
|
||||
})
|
||||
if (file == null) {
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
const { name } = file
|
||||
const { linkedFileData } = file
|
||||
if (
|
||||
linkedFileData == null ||
|
||||
(linkedFileData != null ? linkedFileData.provider : undefined) == null
|
||||
) {
|
||||
return res.sendStatus(409)
|
||||
}
|
||||
const { provider } = linkedFileData
|
||||
const parent_folder_id = parentFolder._id
|
||||
const Agent = LinkedFilesController._getAgent(provider)
|
||||
if (Agent == null) {
|
||||
return res.sendStatus(400)
|
||||
}
|
||||
|
||||
return Agent.refreshLinkedFile(
|
||||
project_id,
|
||||
linkedFileData,
|
||||
name,
|
||||
parent_folder_id,
|
||||
user_id,
|
||||
function (err, newFileId) {
|
||||
if (err != null) {
|
||||
return LinkedFilesController.handleError(err, req, res, next)
|
||||
}
|
||||
return res.json({ new_file_id: newFileId })
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
handleError(error, req, res, next) {
|
||||
|
||||
@@ -28,7 +28,7 @@ const {
|
||||
module.exports = LinkedFilesHandler = {
|
||||
getFileById(project_id, file_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, file) {}
|
||||
callback = function (err, file) {}
|
||||
}
|
||||
return ProjectLocator.findElement(
|
||||
{
|
||||
@@ -36,7 +36,7 @@ module.exports = LinkedFilesHandler = {
|
||||
element_id: file_id,
|
||||
type: 'file'
|
||||
},
|
||||
function(err, file, path, parentFolder) {
|
||||
function (err, file, path, parentFolder) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -47,14 +47,14 @@ module.exports = LinkedFilesHandler = {
|
||||
|
||||
getSourceProject(data, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, project) {}
|
||||
callback = function (err, project) {}
|
||||
}
|
||||
const projection = { _id: 1, name: 1 }
|
||||
if (data.v1_source_doc_id != null) {
|
||||
return Project.findOne(
|
||||
{ 'overleaf.id': data.v1_source_doc_id },
|
||||
projection,
|
||||
function(err, project) {
|
||||
function (err, project) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -68,7 +68,7 @@ module.exports = LinkedFilesHandler = {
|
||||
return ProjectGetter.getProject(
|
||||
data.source_project_id,
|
||||
projection,
|
||||
function(err, project) {
|
||||
function (err, project) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -93,32 +93,33 @@ module.exports = LinkedFilesHandler = {
|
||||
callback
|
||||
) {
|
||||
if (callback == null) {
|
||||
callback = function(err, file) {}
|
||||
callback = function (err, file) {}
|
||||
}
|
||||
callback = _.once(callback)
|
||||
return FileWriter.writeStreamToDisk(project_id, readStream, function(
|
||||
err,
|
||||
fsPath
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return EditorController.upsertFile(
|
||||
project_id,
|
||||
parent_folder_id,
|
||||
name,
|
||||
fsPath,
|
||||
linkedFileData,
|
||||
'upload',
|
||||
user_id,
|
||||
(err, file) => {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(null, file)
|
||||
return FileWriter.writeStreamToDisk(
|
||||
project_id,
|
||||
readStream,
|
||||
function (err, fsPath) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
)
|
||||
})
|
||||
return EditorController.upsertFile(
|
||||
project_id,
|
||||
parent_folder_id,
|
||||
name,
|
||||
fsPath,
|
||||
linkedFileData,
|
||||
'upload',
|
||||
user_id,
|
||||
(err, file) => {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(null, file)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
importContent(
|
||||
@@ -131,31 +132,32 @@ module.exports = LinkedFilesHandler = {
|
||||
callback
|
||||
) {
|
||||
if (callback == null) {
|
||||
callback = function(err, file) {}
|
||||
callback = function (err, file) {}
|
||||
}
|
||||
callback = _.once(callback)
|
||||
return FileWriter.writeContentToDisk(project_id, content, function(
|
||||
err,
|
||||
fsPath
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return EditorController.upsertFile(
|
||||
project_id,
|
||||
parent_folder_id,
|
||||
name,
|
||||
fsPath,
|
||||
linkedFileData,
|
||||
'upload',
|
||||
user_id,
|
||||
(err, file) => {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(null, file)
|
||||
return FileWriter.writeContentToDisk(
|
||||
project_id,
|
||||
content,
|
||||
function (err, fsPath) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
)
|
||||
})
|
||||
return EditorController.upsertFile(
|
||||
project_id,
|
||||
parent_folder_id,
|
||||
name,
|
||||
fsPath,
|
||||
linkedFileData,
|
||||
'upload',
|
||||
user_id,
|
||||
(err, file) => {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(null, file)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ module.exports = ProjectFileAgent = {
|
||||
|
||||
_prepare(project_id, linkedFileData, user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, linkedFileData) {}
|
||||
callback = function (err, linkedFileData) {}
|
||||
}
|
||||
return this._checkAuth(
|
||||
project_id,
|
||||
@@ -118,7 +118,7 @@ module.exports = ProjectFileAgent = {
|
||||
return DocstoreManager.getDoc(
|
||||
source_project._id,
|
||||
entity._id,
|
||||
function(err, lines) {
|
||||
function (err, lines) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -129,7 +129,7 @@ module.exports = ProjectFileAgent = {
|
||||
name,
|
||||
parent_folder_id,
|
||||
user_id,
|
||||
function(err, file) {
|
||||
function (err, file) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -143,7 +143,7 @@ module.exports = ProjectFileAgent = {
|
||||
source_project._id,
|
||||
entity._id,
|
||||
null,
|
||||
function(err, fileStream) {
|
||||
function (err, fileStream) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -154,7 +154,7 @@ module.exports = ProjectFileAgent = {
|
||||
name,
|
||||
parent_folder_id,
|
||||
user_id,
|
||||
function(err, file) {
|
||||
function (err, file) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -174,18 +174,18 @@ module.exports = ProjectFileAgent = {
|
||||
|
||||
_getEntity(linkedFileData, current_user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, entity, type) {}
|
||||
callback = function (err, entity, type) {}
|
||||
}
|
||||
callback = _.once(callback)
|
||||
const { source_entity_path } = linkedFileData
|
||||
return this._getSourceProject(linkedFileData, function(err, project) {
|
||||
return this._getSourceProject(linkedFileData, function (err, project) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
const source_project_id = project._id
|
||||
return DocumentUpdaterHandler.flushProjectToMongo(
|
||||
source_project_id,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -195,7 +195,7 @@ module.exports = ProjectFileAgent = {
|
||||
path: source_entity_path,
|
||||
exactCaseMatch: true
|
||||
},
|
||||
function(err, entity, type) {
|
||||
function (err, entity, type) {
|
||||
if (err != null) {
|
||||
if (/^not found.*/.test(err.toString())) {
|
||||
err = new SourceFileNotFoundError()
|
||||
@@ -236,13 +236,13 @@ module.exports = ProjectFileAgent = {
|
||||
|
||||
_checkAuth(project_id, data, current_user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, allowed) {}
|
||||
callback = function (error, allowed) {}
|
||||
}
|
||||
callback = _.once(callback)
|
||||
if (!ProjectFileAgent._validate(data)) {
|
||||
return callback(new BadDataError())
|
||||
}
|
||||
return this._getSourceProject(data, function(err, project) {
|
||||
return this._getSourceProject(data, function (err, project) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -250,7 +250,7 @@ module.exports = ProjectFileAgent = {
|
||||
current_user_id,
|
||||
project._id,
|
||||
null,
|
||||
function(err, canRead) {
|
||||
function (err, canRead) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ const logger = require('logger-sharelatex')
|
||||
module.exports = ProjectOutputFileAgent = {
|
||||
_prepare(project_id, linkedFileData, user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, linkedFileData) {}
|
||||
callback = function (err, linkedFileData) {}
|
||||
}
|
||||
return this._checkAuth(
|
||||
project_id,
|
||||
@@ -91,7 +91,7 @@ module.exports = ProjectOutputFileAgent = {
|
||||
name,
|
||||
parent_folder_id,
|
||||
user_id,
|
||||
function(err, file) {
|
||||
function (err, file) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -147,7 +147,7 @@ module.exports = ProjectOutputFileAgent = {
|
||||
name,
|
||||
parent_folder_id,
|
||||
user_id,
|
||||
function(err, file) {
|
||||
function (err, file) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -197,13 +197,13 @@ module.exports = ProjectOutputFileAgent = {
|
||||
|
||||
_checkAuth(project_id, data, current_user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, allowed) {}
|
||||
callback = function (err, allowed) {}
|
||||
}
|
||||
callback = _.once(callback)
|
||||
if (!this._validate(data)) {
|
||||
return callback(new BadDataError())
|
||||
}
|
||||
return this._getSourceProject(data, function(err, project) {
|
||||
return this._getSourceProject(data, function (err, project) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -211,7 +211,7 @@ module.exports = ProjectOutputFileAgent = {
|
||||
current_user_id,
|
||||
project._id,
|
||||
null,
|
||||
function(err, canRead) {
|
||||
function (err, canRead) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -223,11 +223,11 @@ module.exports = ProjectOutputFileAgent = {
|
||||
|
||||
_getFileStream(linkedFileData, user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, fileStream) {}
|
||||
callback = function (err, fileStream) {}
|
||||
}
|
||||
callback = _.once(callback)
|
||||
const { source_output_file_path, build_id } = linkedFileData
|
||||
return this._getSourceProject(linkedFileData, function(err, project) {
|
||||
return this._getSourceProject(linkedFileData, function (err, project) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -237,7 +237,7 @@ module.exports = ProjectOutputFileAgent = {
|
||||
user_id,
|
||||
build_id,
|
||||
source_output_file_path,
|
||||
function(err, readStream) {
|
||||
function (err, readStream) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -250,48 +250,49 @@ module.exports = ProjectOutputFileAgent = {
|
||||
|
||||
_compileAndGetFileStream(linkedFileData, user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, stream, build_id) {}
|
||||
callback = function (err, stream, build_id) {}
|
||||
}
|
||||
callback = _.once(callback)
|
||||
const { source_output_file_path } = linkedFileData
|
||||
return this._getSourceProject(linkedFileData, function(err, project) {
|
||||
return this._getSourceProject(linkedFileData, function (err, project) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
const source_project_id = project._id
|
||||
return CompileManager.compile(source_project_id, user_id, {}, function(
|
||||
err,
|
||||
status,
|
||||
outputFiles
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
if (status !== 'success') {
|
||||
return callback(new OutputFileFetchFailedError())
|
||||
}
|
||||
const outputFile = _.find(
|
||||
outputFiles,
|
||||
o => o.path === source_output_file_path
|
||||
)
|
||||
if (outputFile == null) {
|
||||
return callback(new OutputFileFetchFailedError())
|
||||
}
|
||||
const build_id = outputFile.build
|
||||
return ClsiManager.getOutputFileStream(
|
||||
source_project_id,
|
||||
user_id,
|
||||
build_id,
|
||||
source_output_file_path,
|
||||
function(err, readStream) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
readStream.pause()
|
||||
return callback(null, readStream, build_id)
|
||||
return CompileManager.compile(
|
||||
source_project_id,
|
||||
user_id,
|
||||
{},
|
||||
function (err, status, outputFiles) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
)
|
||||
})
|
||||
if (status !== 'success') {
|
||||
return callback(new OutputFileFetchFailedError())
|
||||
}
|
||||
const outputFile = _.find(
|
||||
outputFiles,
|
||||
o => o.path === source_output_file_path
|
||||
)
|
||||
if (outputFile == null) {
|
||||
return callback(new OutputFileFetchFailedError())
|
||||
}
|
||||
const build_id = outputFile.build
|
||||
return ClsiManager.getOutputFileStream(
|
||||
source_project_id,
|
||||
user_id,
|
||||
build_id,
|
||||
source_output_file_path,
|
||||
function (err, readStream) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
readStream.pause()
|
||||
return callback(null, readStream, build_id)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,40 +30,42 @@ module.exports = UrlAgent = {
|
||||
callback
|
||||
) {
|
||||
linkedFileData = this._sanitizeData(linkedFileData)
|
||||
return this._getUrlStream(project_id, linkedFileData, user_id, function(
|
||||
err,
|
||||
readStream
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
readStream.on('error', callback)
|
||||
return readStream.on('response', function(response) {
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
readStream.resume()
|
||||
return LinkedFilesHandler.importFromStream(
|
||||
project_id,
|
||||
readStream,
|
||||
linkedFileData,
|
||||
name,
|
||||
parent_folder_id,
|
||||
user_id,
|
||||
function(err, file) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(null, file._id)
|
||||
}
|
||||
) // Created
|
||||
} else {
|
||||
const error = new UrlFetchFailedError(
|
||||
`url fetch failed: ${linkedFileData.url}`
|
||||
)
|
||||
error.statusCode = response.statusCode
|
||||
return callback(error)
|
||||
return this._getUrlStream(
|
||||
project_id,
|
||||
linkedFileData,
|
||||
user_id,
|
||||
function (err, readStream) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
readStream.on('error', callback)
|
||||
return readStream.on('response', function (response) {
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
readStream.resume()
|
||||
return LinkedFilesHandler.importFromStream(
|
||||
project_id,
|
||||
readStream,
|
||||
linkedFileData,
|
||||
name,
|
||||
parent_folder_id,
|
||||
user_id,
|
||||
function (err, file) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(null, file._id)
|
||||
}
|
||||
) // Created
|
||||
} else {
|
||||
const error = new UrlFetchFailedError(
|
||||
`url fetch failed: ${linkedFileData.url}`
|
||||
)
|
||||
error.statusCode = response.statusCode
|
||||
return callback(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
refreshLinkedFile(
|
||||
@@ -93,7 +95,7 @@ module.exports = UrlAgent = {
|
||||
|
||||
_getUrlStream(project_id, data, current_user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, fsPath) {}
|
||||
callback = function (error, fsPath) {}
|
||||
}
|
||||
callback = _.once(callback)
|
||||
let { url } = data
|
||||
|
||||
@@ -21,22 +21,22 @@ module.exports = MetaController = {
|
||||
getMetadata(req, res, next) {
|
||||
const { project_id } = req.params
|
||||
logger.log({ project_id }, 'getting all labels for project')
|
||||
return MetaHandler.getAllMetaForProject(project_id, function(
|
||||
err,
|
||||
projectMeta
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(
|
||||
err,
|
||||
'[MetaController] error getting all labels from project',
|
||||
{
|
||||
project_id
|
||||
}
|
||||
)
|
||||
return next(err)
|
||||
return MetaHandler.getAllMetaForProject(
|
||||
project_id,
|
||||
function (err, projectMeta) {
|
||||
if (err != null) {
|
||||
OError.tag(
|
||||
err,
|
||||
'[MetaController] error getting all labels from project',
|
||||
{
|
||||
project_id
|
||||
}
|
||||
)
|
||||
return next(err)
|
||||
}
|
||||
return res.json({ projectId: project_id, projectMeta })
|
||||
}
|
||||
return res.json({ projectId: project_id, projectMeta })
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
broadcastMetadataForDoc(req, res, next) {
|
||||
@@ -44,27 +44,28 @@ module.exports = MetaController = {
|
||||
const { doc_id } = req.params
|
||||
const { broadcast } = req.body
|
||||
logger.log({ project_id, doc_id, broadcast }, 'getting labels for doc')
|
||||
return MetaHandler.getMetaForDoc(project_id, doc_id, function(
|
||||
err,
|
||||
docMeta
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(err, '[MetaController] error getting labels from doc', {
|
||||
project_id,
|
||||
doc_id
|
||||
})
|
||||
return next(err)
|
||||
return MetaHandler.getMetaForDoc(
|
||||
project_id,
|
||||
doc_id,
|
||||
function (err, docMeta) {
|
||||
if (err != null) {
|
||||
OError.tag(err, '[MetaController] error getting labels from doc', {
|
||||
project_id,
|
||||
doc_id
|
||||
})
|
||||
return next(err)
|
||||
}
|
||||
// default to broadcasting, unless explicitly disabled (for backwards compatibility)
|
||||
if (broadcast !== false) {
|
||||
EditorRealTimeController.emitToRoom(project_id, 'broadcastDocMeta', {
|
||||
docId: doc_id,
|
||||
meta: docMeta
|
||||
})
|
||||
return res.sendStatus(200)
|
||||
} else {
|
||||
return res.json({ docId: doc_id, meta: docMeta })
|
||||
}
|
||||
}
|
||||
// default to broadcasting, unless explicitly disabled (for backwards compatibility)
|
||||
if (broadcast !== false) {
|
||||
EditorRealTimeController.emitToRoom(project_id, 'broadcastDocMeta', {
|
||||
docId: doc_id,
|
||||
meta: docMeta
|
||||
})
|
||||
return res.sendStatus(200)
|
||||
} else {
|
||||
return res.json({ docId: doc_id, meta: docMeta })
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,43 +33,49 @@ module.exports = MetaHandler = {
|
||||
|
||||
getAllMetaForProject(projectId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, projectMeta) {}
|
||||
callback = function (err, projectMeta) {}
|
||||
}
|
||||
return DocumentUpdaterHandler.flushProjectToMongo(projectId, function(err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return ProjectEntityHandler.getAllDocs(projectId, function(err, docs) {
|
||||
return DocumentUpdaterHandler.flushProjectToMongo(
|
||||
projectId,
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
const projectMeta = MetaHandler.extractMetaFromProjectDocs(docs)
|
||||
return callback(null, projectMeta)
|
||||
})
|
||||
})
|
||||
return ProjectEntityHandler.getAllDocs(projectId, function (err, docs) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
const projectMeta = MetaHandler.extractMetaFromProjectDocs(docs)
|
||||
return callback(null, projectMeta)
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
getMetaForDoc(projectId, docId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, docMeta) {}
|
||||
callback = function (err, docMeta) {}
|
||||
}
|
||||
return DocumentUpdaterHandler.flushDocToMongo(projectId, docId, function(
|
||||
err
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return ProjectEntityHandler.getDoc(projectId, docId, function(
|
||||
err,
|
||||
lines
|
||||
) {
|
||||
return DocumentUpdaterHandler.flushDocToMongo(
|
||||
projectId,
|
||||
docId,
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
const docMeta = MetaHandler.extractMetaFromDoc(lines)
|
||||
return callback(null, docMeta)
|
||||
})
|
||||
})
|
||||
return ProjectEntityHandler.getDoc(
|
||||
projectId,
|
||||
docId,
|
||||
function (err, lines) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
const docMeta = MetaHandler.extractMetaFromDoc(lines)
|
||||
return callback(null, docMeta)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
extractMetaFromDoc(lines) {
|
||||
|
||||
@@ -180,10 +180,7 @@ function makeMailchimpProvider() {
|
||||
}
|
||||
|
||||
function hashEmail(email) {
|
||||
return crypto
|
||||
.createHash('md5')
|
||||
.update(email.toLowerCase())
|
||||
.digest('hex')
|
||||
return crypto.createHash('md5').update(email.toLowerCase()).digest('hex')
|
||||
}
|
||||
|
||||
function getMergeFields(user) {
|
||||
|
||||
@@ -8,7 +8,7 @@ function dropboxDuplicateProjectNames(userId) {
|
||||
key: `dropboxDuplicateProjectNames-${userId}`,
|
||||
create(projectName, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
NotificationsHandler.createNotification(
|
||||
userId,
|
||||
@@ -22,7 +22,7 @@ function dropboxDuplicateProjectNames(userId) {
|
||||
},
|
||||
read(callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
NotificationsHandler.markAsReadWithKey(userId, this.key, callback)
|
||||
}
|
||||
@@ -34,7 +34,7 @@ function featuresUpgradedByAffiliation(affiliation, user) {
|
||||
key: `features-updated-by=${affiliation.institutionId}`,
|
||||
create(callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
const messageOpts = { institutionName: affiliation.institutionName }
|
||||
NotificationsHandler.createNotification(
|
||||
@@ -49,7 +49,7 @@ function featuresUpgradedByAffiliation(affiliation, user) {
|
||||
},
|
||||
read(callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
|
||||
}
|
||||
@@ -61,7 +61,7 @@ function redundantPersonalSubscription(affiliation, user) {
|
||||
key: `redundant-personal-subscription-${affiliation.institutionId}`,
|
||||
create(callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
const messageOpts = { institutionName: affiliation.institutionName }
|
||||
NotificationsHandler.createNotification(
|
||||
@@ -76,7 +76,7 @@ function redundantPersonalSubscription(affiliation, user) {
|
||||
},
|
||||
read(callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
|
||||
}
|
||||
@@ -88,7 +88,7 @@ function projectInvite(invite, project, sendingUser, user) {
|
||||
key: `project-invite-${invite._id}`,
|
||||
create(callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
const messageOpts = {
|
||||
userName: sendingUser.first_name,
|
||||
@@ -107,7 +107,7 @@ function projectInvite(invite, project, sendingUser, user) {
|
||||
},
|
||||
read(callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
|
||||
}
|
||||
@@ -118,7 +118,7 @@ function ipMatcherAffiliation(userId) {
|
||||
return {
|
||||
create(ip, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
if (!settings.apis.v1.url) {
|
||||
// service is not configured
|
||||
@@ -133,7 +133,7 @@ function ipMatcherAffiliation(userId) {
|
||||
json: true,
|
||||
timeout: 20 * 1000
|
||||
},
|
||||
function(error, response, body) {
|
||||
function (error, response, body) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -167,7 +167,7 @@ function ipMatcherAffiliation(userId) {
|
||||
|
||||
read(universityId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
const key = `ip-matched-affiliation-${universityId}`
|
||||
NotificationsHandler.markAsReadWithKey(userId, key, callback)
|
||||
@@ -180,7 +180,7 @@ function tpdsFileLimit(userId) {
|
||||
key: `tpdsFileLimit-${userId}`,
|
||||
create(projectName, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
const messageOpts = {
|
||||
projectName: projectName
|
||||
@@ -197,7 +197,7 @@ function tpdsFileLimit(userId) {
|
||||
},
|
||||
read(callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
|
||||
}
|
||||
@@ -215,7 +215,7 @@ const NotificationsBuilder = {
|
||||
}
|
||||
|
||||
NotificationsBuilder.promises = {
|
||||
redundantPersonalSubscription: function(affiliation, user) {
|
||||
redundantPersonalSubscription: function (affiliation, user) {
|
||||
return promisifyAll(redundantPersonalSubscription(affiliation, user))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,19 +17,22 @@ const _ = require('underscore')
|
||||
module.exports = {
|
||||
getAllUnreadNotifications(req, res) {
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
return NotificationsHandler.getUserNotifications(user_id, function(
|
||||
err,
|
||||
unreadNotifications
|
||||
) {
|
||||
unreadNotifications = _.map(unreadNotifications, function(notification) {
|
||||
notification.html = req.i18n.translate(
|
||||
notification.templateKey,
|
||||
notification.messageOpts
|
||||
return NotificationsHandler.getUserNotifications(
|
||||
user_id,
|
||||
function (err, unreadNotifications) {
|
||||
unreadNotifications = _.map(
|
||||
unreadNotifications,
|
||||
function (notification) {
|
||||
notification.html = req.i18n.translate(
|
||||
notification.templateKey,
|
||||
notification.messageOpts
|
||||
)
|
||||
return notification
|
||||
}
|
||||
)
|
||||
return notification
|
||||
})
|
||||
return res.send(unreadNotifications)
|
||||
})
|
||||
return res.send(unreadNotifications)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
markNotificationAsRead(req, res) {
|
||||
|
||||
@@ -17,7 +17,7 @@ const logger = require('logger-sharelatex')
|
||||
|
||||
const oneSecond = 1000
|
||||
|
||||
const makeRequest = function(opts, callback) {
|
||||
const makeRequest = function (opts, callback) {
|
||||
if (
|
||||
(settings.apis.notifications != null
|
||||
? settings.apis.notifications.url
|
||||
@@ -41,7 +41,7 @@ module.exports = {
|
||||
timeout: oneSecond,
|
||||
method: 'GET'
|
||||
}
|
||||
return makeRequest(opts, function(err, res, unreadNotifications) {
|
||||
return makeRequest(opts, function (err, res, unreadNotifications) {
|
||||
const statusCode = res != null ? res.statusCode : 500
|
||||
if (err != null || statusCode !== 200) {
|
||||
const e = new Error(
|
||||
|
||||
@@ -17,14 +17,14 @@ const logger = require('logger-sharelatex')
|
||||
module.exports = {
|
||||
getProjectDetails(req, res, next) {
|
||||
const { project_id } = req.params
|
||||
return ProjectDetailsHandler.getDetails(project_id, function(
|
||||
err,
|
||||
projDetails
|
||||
) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
return ProjectDetailsHandler.getDetails(
|
||||
project_id,
|
||||
function (err, projDetails) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
return res.json(projDetails)
|
||||
}
|
||||
return res.json(projDetails)
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
|
||||
callback
|
||||
) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
return ProjectCollabratecDetailsHandler.setCollabratecUsers(
|
||||
project_id,
|
||||
@@ -36,7 +36,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
|
||||
|
||||
isLinkedCollabratecUserProject(project_id, user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, isLinked) {}
|
||||
callback = function (err, isLinked) {}
|
||||
}
|
||||
try {
|
||||
project_id = ObjectId(project_id)
|
||||
@@ -53,7 +53,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
|
||||
}
|
||||
}
|
||||
}
|
||||
return Project.findOne(query, { _id: 1 }, function(err, project) {
|
||||
return Project.findOne(query, { _id: 1 }, function (err, project) {
|
||||
if (err != null) {
|
||||
callback(err)
|
||||
}
|
||||
@@ -68,7 +68,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
|
||||
callback
|
||||
) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
try {
|
||||
project_id = ObjectId(project_id)
|
||||
@@ -102,7 +102,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
|
||||
setCollabratecUsers(project_id, collabratec_users, callback) {
|
||||
let err
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
try {
|
||||
project_id = ObjectId(project_id)
|
||||
@@ -127,7 +127,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
|
||||
|
||||
unlinkCollabratecUserProject(project_id, user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
try {
|
||||
project_id = ObjectId(project_id)
|
||||
@@ -149,7 +149,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
|
||||
|
||||
updateCollabratecUserIds(old_user_id, new_user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
try {
|
||||
old_user_id = ObjectId(old_user_id)
|
||||
|
||||
@@ -64,10 +64,7 @@ const ProjectController = {
|
||||
return true
|
||||
}
|
||||
const data = `${rolloutName}:${objectId.toString()}`
|
||||
const md5hash = crypto
|
||||
.createHash('md5')
|
||||
.update(data)
|
||||
.digest('hex')
|
||||
const md5hash = crypto.createHash('md5').update(data).digest('hex')
|
||||
const counter = parseInt(md5hash.slice(26, 32), 16)
|
||||
return counter % 100 < percentage
|
||||
},
|
||||
@@ -162,7 +159,7 @@ const ProjectController = {
|
||||
const projectId = req.params.Project_id
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
|
||||
ProjectDeleter.archiveProject(projectId, userId, function(err) {
|
||||
ProjectDeleter.archiveProject(projectId, userId, function (err) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
} else {
|
||||
@@ -175,7 +172,7 @@ const ProjectController = {
|
||||
const projectId = req.params.Project_id
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
|
||||
ProjectDeleter.unarchiveProject(projectId, userId, function(err) {
|
||||
ProjectDeleter.unarchiveProject(projectId, userId, function (err) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
} else {
|
||||
@@ -188,7 +185,7 @@ const ProjectController = {
|
||||
const projectId = req.params.project_id
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
|
||||
ProjectDeleter.trashProject(projectId, userId, function(err) {
|
||||
ProjectDeleter.trashProject(projectId, userId, function (err) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
} else {
|
||||
@@ -201,7 +198,7 @@ const ProjectController = {
|
||||
const projectId = req.params.project_id
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
|
||||
ProjectDeleter.untrashProject(projectId, userId, function(err) {
|
||||
ProjectDeleter.untrashProject(projectId, userId, function (err) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
} else {
|
||||
|
||||
@@ -33,7 +33,7 @@ const AnalyticsManager = require('../Analytics/AnalyticsManager')
|
||||
const ProjectCreationHandler = {
|
||||
createBlankProject(owner_id, projectName, attributes, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, project) {}
|
||||
callback = function (error, project) {}
|
||||
}
|
||||
metrics.inc('project-creation')
|
||||
if (arguments.length === 3) {
|
||||
@@ -41,59 +41,60 @@ const ProjectCreationHandler = {
|
||||
attributes = {}
|
||||
}
|
||||
|
||||
return ProjectDetailsHandler.validateProjectName(projectName, function(
|
||||
error
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
if (attributes.overleaf !== undefined && attributes.overleaf != null) {
|
||||
return ProjectCreationHandler._createBlankProject(
|
||||
owner_id,
|
||||
projectName,
|
||||
attributes,
|
||||
function(error, project) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
AnalyticsManager.recordEvent(owner_id, 'project-imported', {
|
||||
projectId: project._id,
|
||||
attributes
|
||||
})
|
||||
return callback(error, project)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
return HistoryManager.initializeProject(function(error, history) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
attributes.overleaf = {
|
||||
history: { id: history != null ? history.overleaf_id : undefined }
|
||||
}
|
||||
return ProjectDetailsHandler.validateProjectName(
|
||||
projectName,
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
if (attributes.overleaf !== undefined && attributes.overleaf != null) {
|
||||
return ProjectCreationHandler._createBlankProject(
|
||||
owner_id,
|
||||
projectName,
|
||||
attributes,
|
||||
function(error, project) {
|
||||
function (error, project) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
AnalyticsManager.recordEvent(owner_id, 'project-created', {
|
||||
AnalyticsManager.recordEvent(owner_id, 'project-imported', {
|
||||
projectId: project._id,
|
||||
attributes
|
||||
})
|
||||
return callback(error, project)
|
||||
}
|
||||
)
|
||||
})
|
||||
} else {
|
||||
return HistoryManager.initializeProject(function (error, history) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
attributes.overleaf = {
|
||||
history: { id: history != null ? history.overleaf_id : undefined }
|
||||
}
|
||||
return ProjectCreationHandler._createBlankProject(
|
||||
owner_id,
|
||||
projectName,
|
||||
attributes,
|
||||
function (error, project) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
AnalyticsManager.recordEvent(owner_id, 'project-created', {
|
||||
projectId: project._id,
|
||||
attributes
|
||||
})
|
||||
return callback(error, project)
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
_createBlankProject(owner_id, projectName, attributes, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, project) {}
|
||||
callback = function (error, project) {}
|
||||
}
|
||||
const rootFolder = new Folder({ name: 'rootFolder' })
|
||||
|
||||
@@ -113,28 +114,29 @@ const ProjectCreationHandler = {
|
||||
}
|
||||
}
|
||||
project.rootFolder[0] = rootFolder
|
||||
return User.findById(owner_id, 'ace.spellCheckLanguage', function(
|
||||
err,
|
||||
user
|
||||
) {
|
||||
project.spellCheckLanguage = user.ace.spellCheckLanguage
|
||||
return project.save(function(err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(err, project)
|
||||
})
|
||||
})
|
||||
return User.findById(
|
||||
owner_id,
|
||||
'ace.spellCheckLanguage',
|
||||
function (err, user) {
|
||||
project.spellCheckLanguage = user.ace.spellCheckLanguage
|
||||
return project.save(function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(err, project)
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
createProjectFromSnippet(owner_id, projectName, docLines, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, project) {}
|
||||
callback = function (error, project) {}
|
||||
}
|
||||
return ProjectCreationHandler.createBlankProject(
|
||||
owner_id,
|
||||
projectName,
|
||||
function(error, project) {
|
||||
function (error, project) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -150,12 +152,12 @@ const ProjectCreationHandler = {
|
||||
|
||||
createBasicProject(owner_id, projectName, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, project) {}
|
||||
callback = function (error, project) {}
|
||||
}
|
||||
return ProjectCreationHandler.createBlankProject(
|
||||
owner_id,
|
||||
projectName,
|
||||
function(error, project) {
|
||||
function (error, project) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -163,7 +165,7 @@ const ProjectCreationHandler = {
|
||||
'mainbasic.tex',
|
||||
owner_id,
|
||||
projectName,
|
||||
function(error, docLines) {
|
||||
function (error, docLines) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -181,12 +183,12 @@ const ProjectCreationHandler = {
|
||||
|
||||
createExampleProject(owner_id, projectName, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, project) {}
|
||||
callback = function (error, project) {}
|
||||
}
|
||||
return ProjectCreationHandler.createBlankProject(
|
||||
owner_id,
|
||||
projectName,
|
||||
function(error, project) {
|
||||
function (error, project) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -197,7 +199,7 @@ const ProjectCreationHandler = {
|
||||
'main.tex',
|
||||
owner_id,
|
||||
projectName,
|
||||
function(error, docLines) {
|
||||
function (error, docLines) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -214,7 +216,7 @@ const ProjectCreationHandler = {
|
||||
'references.bib',
|
||||
owner_id,
|
||||
projectName,
|
||||
function(error, docLines) {
|
||||
function (error, docLines) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -228,7 +230,7 @@ const ProjectCreationHandler = {
|
||||
)
|
||||
}
|
||||
),
|
||||
function(callback) {
|
||||
function (callback) {
|
||||
const universePath = Path.resolve(
|
||||
__dirname + '/../../../templates/project_files/universe.jpg'
|
||||
)
|
||||
@@ -251,7 +253,7 @@ const ProjectCreationHandler = {
|
||||
|
||||
_createRootDoc(project, owner_id, docLines, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, project) {}
|
||||
callback = function (error, project) {}
|
||||
}
|
||||
return ProjectEntityUpdateHandler.addDoc(
|
||||
project._id,
|
||||
@@ -259,7 +261,7 @@ const ProjectCreationHandler = {
|
||||
'main.tex',
|
||||
docLines,
|
||||
owner_id,
|
||||
function(error, doc) {
|
||||
function (error, doc) {
|
||||
if (error != null) {
|
||||
OError.tag(error, 'error adding root doc when creating project')
|
||||
return callback(error)
|
||||
@@ -275,47 +277,48 @@ const ProjectCreationHandler = {
|
||||
|
||||
_buildTemplate(template_name, user_id, project_name, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, output) {}
|
||||
callback = function (error, output) {}
|
||||
}
|
||||
return User.findById(user_id, 'first_name last_name', function(
|
||||
error,
|
||||
user
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
const monthNames = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December'
|
||||
]
|
||||
|
||||
const templatePath = Path.resolve(
|
||||
__dirname + `/../../../templates/project_files/${template_name}`
|
||||
)
|
||||
return fs.readFile(templatePath, function(error, template) {
|
||||
return User.findById(
|
||||
user_id,
|
||||
'first_name last_name',
|
||||
function (error, user) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
const data = {
|
||||
project_name,
|
||||
user,
|
||||
year: new Date().getUTCFullYear(),
|
||||
month: monthNames[new Date().getUTCMonth()]
|
||||
}
|
||||
const output = _.template(template.toString(), data)
|
||||
return callback(null, output.split('\n'))
|
||||
})
|
||||
})
|
||||
const monthNames = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December'
|
||||
]
|
||||
|
||||
const templatePath = Path.resolve(
|
||||
__dirname + `/../../../templates/project_files/${template_name}`
|
||||
)
|
||||
return fs.readFile(templatePath, function (error, template) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
const data = {
|
||||
project_name,
|
||||
user,
|
||||
year: new Date().getUTCFullYear(),
|
||||
month: monthNames[new Date().getUTCMonth()]
|
||||
}
|
||||
const output = _.template(template.toString(), data)
|
||||
return callback(null, output.split('\n'))
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ const ProjectEntityUpdateHandler = {
|
||||
|
||||
addDocWithRanges: wrapWithLock({
|
||||
beforeLock(next) {
|
||||
return function(
|
||||
return function (
|
||||
projectId,
|
||||
folderId,
|
||||
docName,
|
||||
@@ -457,7 +457,7 @@ const ProjectEntityUpdateHandler = {
|
||||
|
||||
addFile: wrapWithLock({
|
||||
beforeLock(next) {
|
||||
return function(
|
||||
return function (
|
||||
projectId,
|
||||
folderId,
|
||||
fileName,
|
||||
@@ -544,7 +544,7 @@ const ProjectEntityUpdateHandler = {
|
||||
|
||||
replaceFile: wrapWithLock({
|
||||
beforeLock(next) {
|
||||
return function(
|
||||
return function (
|
||||
projectId,
|
||||
fileId,
|
||||
fsPath,
|
||||
@@ -648,7 +648,7 @@ const ProjectEntityUpdateHandler = {
|
||||
}
|
||||
}),
|
||||
|
||||
upsertDoc: wrapWithLock(function(
|
||||
upsertDoc: wrapWithLock(function (
|
||||
projectId,
|
||||
folderId,
|
||||
docName,
|
||||
@@ -796,7 +796,7 @@ const ProjectEntityUpdateHandler = {
|
||||
|
||||
upsertFile: wrapWithLock({
|
||||
beforeLock(next) {
|
||||
return function(
|
||||
return function (
|
||||
projectId,
|
||||
folderId,
|
||||
fileName,
|
||||
@@ -974,7 +974,7 @@ const ProjectEntityUpdateHandler = {
|
||||
}
|
||||
}),
|
||||
|
||||
upsertDocWithPath: wrapWithLock(function(
|
||||
upsertDocWithPath: wrapWithLock(function (
|
||||
projectId,
|
||||
elementPath,
|
||||
docLines,
|
||||
@@ -1014,7 +1014,7 @@ const ProjectEntityUpdateHandler = {
|
||||
|
||||
upsertFileWithPath: wrapWithLock({
|
||||
beforeLock(next) {
|
||||
return function(
|
||||
return function (
|
||||
projectId,
|
||||
elementPath,
|
||||
fsPath,
|
||||
@@ -1102,7 +1102,7 @@ const ProjectEntityUpdateHandler = {
|
||||
}
|
||||
}),
|
||||
|
||||
deleteEntity: wrapWithLock(function(
|
||||
deleteEntity: wrapWithLock(function (
|
||||
projectId,
|
||||
entityId,
|
||||
entityType,
|
||||
@@ -1174,7 +1174,7 @@ const ProjectEntityUpdateHandler = {
|
||||
)
|
||||
),
|
||||
|
||||
mkdirp: wrapWithLock(function(projectId, path, callback) {
|
||||
mkdirp: wrapWithLock(function (projectId, path, callback) {
|
||||
for (let folder of path.split('/')) {
|
||||
if (folder.length > 0 && !SafePath.isCleanFilename(folder)) {
|
||||
return callback(new Errors.InvalidNameError('invalid element name'))
|
||||
@@ -1188,7 +1188,7 @@ const ProjectEntityUpdateHandler = {
|
||||
)
|
||||
}),
|
||||
|
||||
mkdirpWithExactCase: wrapWithLock(function(projectId, path, callback) {
|
||||
mkdirpWithExactCase: wrapWithLock(function (projectId, path, callback) {
|
||||
for (let folder of path.split('/')) {
|
||||
if (folder.length > 0 && !SafePath.isCleanFilename(folder)) {
|
||||
return callback(new Errors.InvalidNameError('invalid element name'))
|
||||
@@ -1202,7 +1202,7 @@ const ProjectEntityUpdateHandler = {
|
||||
)
|
||||
}),
|
||||
|
||||
addFolder: wrapWithLock(function(
|
||||
addFolder: wrapWithLock(function (
|
||||
projectId,
|
||||
parentFolderId,
|
||||
folderName,
|
||||
@@ -1219,7 +1219,7 @@ const ProjectEntityUpdateHandler = {
|
||||
)
|
||||
}),
|
||||
|
||||
moveEntity: wrapWithLock(function(
|
||||
moveEntity: wrapWithLock(function (
|
||||
projectId,
|
||||
entityId,
|
||||
destFolderId,
|
||||
@@ -1272,7 +1272,7 @@ const ProjectEntityUpdateHandler = {
|
||||
)
|
||||
}),
|
||||
|
||||
renameEntity: wrapWithLock(function(
|
||||
renameEntity: wrapWithLock(function (
|
||||
projectId,
|
||||
entityId,
|
||||
entityType,
|
||||
@@ -1572,7 +1572,7 @@ const ProjectEntityUpdateHandler = {
|
||||
|
||||
convertDocToFile: wrapWithLock({
|
||||
beforeLock(next) {
|
||||
return function(projectId, docId, userId, callback) {
|
||||
return function (projectId, docId, userId, callback) {
|
||||
DocumentUpdaterHandler.flushDocToMongo(projectId, docId, err => {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
|
||||
@@ -72,7 +72,7 @@ const ProjectGetter = {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
db.projects.findOne(query, { projection }, function(err, project) {
|
||||
db.projects.findOne(query, { projection }, function (err, project) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error getting project', {
|
||||
query,
|
||||
@@ -85,43 +85,49 @@ const ProjectGetter = {
|
||||
},
|
||||
|
||||
getProjectIdByReadAndWriteToken(token, callback) {
|
||||
Project.findOne({ 'tokens.readAndWrite': token }, { _id: 1 }, function(
|
||||
err,
|
||||
project
|
||||
) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
Project.findOne(
|
||||
{ 'tokens.readAndWrite': token },
|
||||
{ _id: 1 },
|
||||
function (err, project) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
if (project == null) {
|
||||
return callback()
|
||||
}
|
||||
callback(null, project._id)
|
||||
}
|
||||
if (project == null) {
|
||||
return callback()
|
||||
}
|
||||
callback(null, project._id)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
findAllUsersProjects(userId, fields, callback) {
|
||||
const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
|
||||
Project.find({ owner_ref: userId }, fields, function(error, ownedProjects) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
CollaboratorsGetter.getProjectsUserIsMemberOf(userId, fields, function(
|
||||
error,
|
||||
projects
|
||||
) {
|
||||
Project.find(
|
||||
{ owner_ref: userId },
|
||||
fields,
|
||||
function (error, ownedProjects) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
const result = {
|
||||
owned: ownedProjects || [],
|
||||
readAndWrite: projects.readAndWrite || [],
|
||||
readOnly: projects.readOnly || [],
|
||||
tokenReadAndWrite: projects.tokenReadAndWrite || [],
|
||||
tokenReadOnly: projects.tokenReadOnly || []
|
||||
}
|
||||
callback(null, result)
|
||||
})
|
||||
})
|
||||
CollaboratorsGetter.getProjectsUserIsMemberOf(
|
||||
userId,
|
||||
fields,
|
||||
function (error, projects) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
const result = {
|
||||
owned: ownedProjects || [],
|
||||
readAndWrite: projects.readAndWrite || [],
|
||||
readOnly: projects.readOnly || [],
|
||||
tokenReadAndWrite: projects.tokenReadAndWrite || [],
|
||||
tokenReadOnly: projects.tokenReadOnly || []
|
||||
}
|
||||
callback(null, result)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -126,7 +126,7 @@ function _addSuffixToProjectName(name, suffix, maxLength) {
|
||||
|
||||
function _addNumericSuffixToProjectName(name, allProjectNames, maxLength) {
|
||||
const NUMERIC_SUFFIX_MATCH = / \((\d+)\)$/
|
||||
const suffixedName = function(basename, number) {
|
||||
const suffixedName = function (basename, number) {
|
||||
const suffix = ` (${number})`
|
||||
return basename.substr(0, maxLength - suffix.length) + suffix
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ const ProjectHistoryHandler = {
|
||||
setHistoryId(project_id, history_id, callback) {
|
||||
// reject invalid history ids
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
if (!history_id || typeof history_id !== 'number') {
|
||||
return callback(new Error('invalid history id'))
|
||||
@@ -34,7 +34,7 @@ const ProjectHistoryHandler = {
|
||||
return Project.updateOne(
|
||||
{ _id: project_id, 'overleaf.history.id': { $exists: false } },
|
||||
{ 'overleaf.history.id': history_id },
|
||||
function(err, result) {
|
||||
function (err, result) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -48,29 +48,32 @@ const ProjectHistoryHandler = {
|
||||
|
||||
getHistoryId(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, result) {}
|
||||
callback = function (err, result) {}
|
||||
}
|
||||
return ProjectDetailsHandler.getDetails(project_id, function(err, project) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
} // n.b. getDetails returns an error if the project doesn't exist
|
||||
return callback(
|
||||
null,
|
||||
__guard__(
|
||||
return ProjectDetailsHandler.getDetails(
|
||||
project_id,
|
||||
function (err, project) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
} // n.b. getDetails returns an error if the project doesn't exist
|
||||
return callback(
|
||||
null,
|
||||
__guard__(
|
||||
project != null ? project.overleaf : undefined,
|
||||
x1 => x1.history
|
||||
),
|
||||
x => x.id
|
||||
__guard__(
|
||||
project != null ? project.overleaf : undefined,
|
||||
x1 => x1.history
|
||||
),
|
||||
x => x.id
|
||||
)
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
upgradeHistory(project_id, callback) {
|
||||
// project must have an overleaf.history.id before allowing display of new history
|
||||
if (callback == null) {
|
||||
callback = function(err, result) {}
|
||||
callback = function (err, result) {}
|
||||
}
|
||||
return Project.updateOne(
|
||||
{ _id: project_id, 'overleaf.history.id': { $exists: true } },
|
||||
@@ -78,7 +81,7 @@ const ProjectHistoryHandler = {
|
||||
'overleaf.history.display': true,
|
||||
'overleaf.history.upgradedAt': new Date()
|
||||
},
|
||||
function(err, result) {
|
||||
function (err, result) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -93,7 +96,7 @@ const ProjectHistoryHandler = {
|
||||
|
||||
downgradeHistory(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, result) {}
|
||||
callback = function (err, result) {}
|
||||
}
|
||||
return Project.updateOne(
|
||||
{ _id: project_id, 'overleaf.history.upgradedAt': { $exists: true } },
|
||||
@@ -101,7 +104,7 @@ const ProjectHistoryHandler = {
|
||||
'overleaf.history.display': false,
|
||||
$unset: { 'overleaf.history.upgradedAt': 1 }
|
||||
},
|
||||
function(err, result) {
|
||||
function (err, result) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -120,45 +123,45 @@ const ProjectHistoryHandler = {
|
||||
// state. Setting a history id when one wasn't present before is ok,
|
||||
// because undefined history ids aren't cached.
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
return ProjectHistoryHandler.getHistoryId(project_id, function(
|
||||
err,
|
||||
history_id
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
if (history_id != null) {
|
||||
return callback()
|
||||
} // history already exists, success
|
||||
return HistoryManager.initializeProject(function(err, history) {
|
||||
return ProjectHistoryHandler.getHistoryId(
|
||||
project_id,
|
||||
function (err, history_id) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
if (!(history != null ? history.overleaf_id : undefined)) {
|
||||
return callback(new Error('failed to initialize history id'))
|
||||
}
|
||||
return ProjectHistoryHandler.setHistoryId(
|
||||
project_id,
|
||||
history.overleaf_id,
|
||||
function(err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return ProjectEntityUpdateHandler.resyncProjectHistory(
|
||||
project_id,
|
||||
function(err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return HistoryManager.flushProject(project_id, callback)
|
||||
}
|
||||
)
|
||||
if (history_id != null) {
|
||||
return callback()
|
||||
} // history already exists, success
|
||||
return HistoryManager.initializeProject(function (err, history) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
if (!(history != null ? history.overleaf_id : undefined)) {
|
||||
return callback(new Error('failed to initialize history id'))
|
||||
}
|
||||
return ProjectHistoryHandler.setHistoryId(
|
||||
project_id,
|
||||
history.overleaf_id,
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return ProjectEntityUpdateHandler.resyncProjectHistory(
|
||||
project_id,
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return HistoryManager.flushProject(project_id, callback)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,12 @@ function findElement(options, _callback) {
|
||||
const elementType = sanitizeTypeOfElement(type)
|
||||
|
||||
let count = 0
|
||||
const endOfBranch = function() {
|
||||
const endOfBranch = function () {
|
||||
if (--count === 0) {
|
||||
logger.warn(
|
||||
`element ${elementId} could not be found for project ${projectId ||
|
||||
project._id}`
|
||||
`element ${elementId} could not be found for project ${
|
||||
projectId || project._id
|
||||
}`
|
||||
)
|
||||
callback(new Errors.NotFoundError('entity not found'))
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ const _ = require('underscore')
|
||||
module.exports = ProjectRootDocManager = {
|
||||
setRootDocAutomatically(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ProjectEntityHandler.getAllDocs(project_id, function(error, docs) {
|
||||
return ProjectEntityHandler.getAllDocs(project_id, function (error, docs) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -38,23 +38,23 @@ module.exports = ProjectRootDocManager = {
|
||||
const jobs = _.map(
|
||||
docs,
|
||||
(doc, path) =>
|
||||
function(cb) {
|
||||
function (cb) {
|
||||
if (
|
||||
ProjectEntityUpdateHandler.isPathValidForRootDoc(path) &&
|
||||
DocumentHelper.contentHasDocumentclass(doc.lines)
|
||||
) {
|
||||
async.setImmediate(function() {
|
||||
async.setImmediate(function () {
|
||||
cb(doc._id)
|
||||
})
|
||||
} else {
|
||||
async.setImmediate(function() {
|
||||
async.setImmediate(function () {
|
||||
cb(null)
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return async.series(jobs, function(root_doc_id) {
|
||||
return async.series(jobs, function (root_doc_id) {
|
||||
if (root_doc_id != null) {
|
||||
return ProjectEntityUpdateHandler.setRootDoc(
|
||||
project_id,
|
||||
@@ -70,7 +70,7 @@ module.exports = ProjectRootDocManager = {
|
||||
|
||||
findRootDocFileFromDirectory(directoryPath, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, path, content) {}
|
||||
callback = function (error, path, content) {}
|
||||
}
|
||||
const filePathsPromise = globby(['**/*.{tex,Rtex}'], {
|
||||
cwd: directoryPath,
|
||||
@@ -88,7 +88,7 @@ module.exports = ProjectRootDocManager = {
|
||||
ProjectRootDocManager._sortFileList(
|
||||
unsortedFiles,
|
||||
directoryPath,
|
||||
function(err, files) {
|
||||
function (err, files) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -96,12 +96,12 @@ module.exports = ProjectRootDocManager = {
|
||||
|
||||
return async.until(
|
||||
() => doc != null || files.length === 0,
|
||||
function(cb) {
|
||||
function (cb) {
|
||||
const file = files.shift()
|
||||
return fs.readFile(
|
||||
Path.join(directoryPath, file),
|
||||
'utf8',
|
||||
function(error, content) {
|
||||
function (error, content) {
|
||||
if (error != null) {
|
||||
return cb(error)
|
||||
}
|
||||
@@ -131,11 +131,11 @@ module.exports = ProjectRootDocManager = {
|
||||
|
||||
setRootDocFromName(project_id, rootDocName, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ProjectEntityHandler.getAllDocPathsFromProjectById(
|
||||
project_id,
|
||||
function(error, docPaths) {
|
||||
function (error, docPaths) {
|
||||
let doc_id, path
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
@@ -180,89 +180,91 @@ module.exports = ProjectRootDocManager = {
|
||||
|
||||
ensureRootDocumentIsSet(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ProjectGetter.getProject(project_id, { rootDoc_id: 1 }, function(
|
||||
error,
|
||||
project
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
if (project == null) {
|
||||
return callback(new Error('project not found'))
|
||||
}
|
||||
return ProjectGetter.getProject(
|
||||
project_id,
|
||||
{ rootDoc_id: 1 },
|
||||
function (error, project) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
if (project == null) {
|
||||
return callback(new Error('project not found'))
|
||||
}
|
||||
|
||||
if (project.rootDoc_id != null) {
|
||||
return callback()
|
||||
} else {
|
||||
return ProjectRootDocManager.setRootDocAutomatically(
|
||||
project_id,
|
||||
callback
|
||||
)
|
||||
if (project.rootDoc_id != null) {
|
||||
return callback()
|
||||
} else {
|
||||
return ProjectRootDocManager.setRootDocAutomatically(
|
||||
project_id,
|
||||
callback
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
ensureRootDocumentIsValid(project_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return ProjectGetter.getProject(project_id, { rootDoc_id: 1 }, function(
|
||||
error,
|
||||
project
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
if (project == null) {
|
||||
return callback(new Error('project not found'))
|
||||
}
|
||||
return ProjectGetter.getProject(
|
||||
project_id,
|
||||
{ rootDoc_id: 1 },
|
||||
function (error, project) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
if (project == null) {
|
||||
return callback(new Error('project not found'))
|
||||
}
|
||||
|
||||
if (project.rootDoc_id != null) {
|
||||
return ProjectEntityHandler.getAllDocPathsFromProjectById(
|
||||
project_id,
|
||||
function(error, docPaths) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
let rootDocValid = false
|
||||
for (let doc_id in docPaths) {
|
||||
const _path = docPaths[doc_id]
|
||||
if (doc_id === project.rootDoc_id) {
|
||||
rootDocValid = true
|
||||
if (project.rootDoc_id != null) {
|
||||
return ProjectEntityHandler.getAllDocPathsFromProjectById(
|
||||
project_id,
|
||||
function (error, docPaths) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
let rootDocValid = false
|
||||
for (let doc_id in docPaths) {
|
||||
const _path = docPaths[doc_id]
|
||||
if (doc_id === project.rootDoc_id) {
|
||||
rootDocValid = true
|
||||
}
|
||||
}
|
||||
if (rootDocValid) {
|
||||
return callback()
|
||||
} else {
|
||||
return ProjectEntityUpdateHandler.unsetRootDoc(project_id, () =>
|
||||
ProjectRootDocManager.setRootDocAutomatically(
|
||||
project_id,
|
||||
callback
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (rootDocValid) {
|
||||
return callback()
|
||||
} else {
|
||||
return ProjectEntityUpdateHandler.unsetRootDoc(project_id, () =>
|
||||
ProjectRootDocManager.setRootDocAutomatically(
|
||||
project_id,
|
||||
callback
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
return ProjectRootDocManager.setRootDocAutomatically(
|
||||
project_id,
|
||||
callback
|
||||
)
|
||||
)
|
||||
} else {
|
||||
return ProjectRootDocManager.setRootDocAutomatically(
|
||||
project_id,
|
||||
callback
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
_sortFileList(listToSort, rootDirectory, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, result) {}
|
||||
callback = function (error, result) {}
|
||||
}
|
||||
return async.mapLimit(
|
||||
listToSort,
|
||||
5,
|
||||
(filePath, cb) =>
|
||||
fs.stat(Path.join(rootDirectory, filePath), function(err, stat) {
|
||||
fs.stat(Path.join(rootDirectory, filePath), function (err, stat) {
|
||||
if (err != null) {
|
||||
return cb(err)
|
||||
}
|
||||
@@ -273,7 +275,7 @@ module.exports = ProjectRootDocManager = {
|
||||
name: Path.basename(filePath)
|
||||
})
|
||||
}),
|
||||
function(err, files) {
|
||||
function (err, files) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ const logger = require('logger-sharelatex')
|
||||
module.exports = {
|
||||
markAsUpdated(projectId, lastUpdatedAt, lastUpdatedBy, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
if (lastUpdatedAt == null) {
|
||||
lastUpdatedAt = new Date()
|
||||
@@ -38,7 +38,7 @@ module.exports = {
|
||||
markAsOpened(project_id, callback) {
|
||||
const conditions = { _id: project_id }
|
||||
const update = { lastOpened: Date.now() }
|
||||
return Project.updateOne(conditions, update, {}, function(err) {
|
||||
return Project.updateOne(conditions, update, {}, function (err) {
|
||||
if (callback != null) {
|
||||
return callback()
|
||||
}
|
||||
@@ -48,7 +48,7 @@ module.exports = {
|
||||
markAsInactive(project_id, callback) {
|
||||
const conditions = { _id: project_id }
|
||||
const update = { active: false }
|
||||
return Project.updateOne(conditions, update, {}, function(err) {
|
||||
return Project.updateOne(conditions, update, {}, function (err) {
|
||||
if (callback != null) {
|
||||
return callback()
|
||||
}
|
||||
@@ -58,7 +58,7 @@ module.exports = {
|
||||
markAsActive(project_id, callback) {
|
||||
const conditions = { _id: project_id }
|
||||
const update = { active: true }
|
||||
return Project.updateOne(conditions, update, {}, function(err) {
|
||||
return Project.updateOne(conditions, update, {}, function (err) {
|
||||
if (callback != null) {
|
||||
return callback()
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// frontend/js/ide/directives/SafePath.js
|
||||
// frontend/js/features/file-tree/util/safe-path.js
|
||||
|
||||
const load = function() {
|
||||
const load = function () {
|
||||
let SafePath
|
||||
const BADCHAR_RX = new RegExp(
|
||||
`\
|
||||
|
||||
@@ -21,7 +21,7 @@ const _ = require('underscore')
|
||||
module.exports = PublishersGetter = {
|
||||
getManagedPublishers(user_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, managedPublishers) {}
|
||||
callback = function (error, managedPublishers) {}
|
||||
}
|
||||
return UserMembershipsHandler.getEntitiesByUser(
|
||||
UserMembershipEntityConfigs.publisher,
|
||||
|
||||
@@ -5,14 +5,14 @@ const FeaturesUpdater = require('../Subscription/FeaturesUpdater')
|
||||
module.exports = {
|
||||
allocate(referalId, newUserId, referalSource, referalMedium, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
if (referalId == null) {
|
||||
return callback(null)
|
||||
}
|
||||
|
||||
const query = { referal_id: referalId }
|
||||
return User.findOne(query, { _id: 1 }, function(error, user) {
|
||||
return User.findOne(query, { _id: 1 }, function (error, user) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -32,7 +32,7 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
{},
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'something went wrong allocating referal', {
|
||||
referalId,
|
||||
|
||||
@@ -7,10 +7,10 @@ let ReferalFeatures
|
||||
module.exports = ReferalFeatures = {
|
||||
getBonusFeatures(userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
const query = { _id: userId }
|
||||
User.findOne(query, { refered_user_count: 1 }, function(error, user) {
|
||||
User.findOne(query, { refered_user_count: 1 }, function (error, user) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -37,7 +37,7 @@ module.exports = ReferalFeatures = {
|
||||
|
||||
_getBonusLevel(user) {
|
||||
let highestBonusLevel = 0
|
||||
_.each(_.keys(Settings.bonus_features), function(level) {
|
||||
_.each(_.keys(Settings.bonus_features), function (level) {
|
||||
const levelIsLessThanUser = level <= user.refered_user_count
|
||||
const levelIsMoreThanCurrentHighest = level >= highestBonusLevel
|
||||
if (levelIsLessThanUser && levelIsMoreThanCurrentHighest) {
|
||||
|
||||
@@ -3,7 +3,7 @@ const { User } = require('../../models/User')
|
||||
module.exports = {
|
||||
getReferedUsers(userId, callback) {
|
||||
const projection = { refered_users: 1, refered_user_count: 1 }
|
||||
User.findById(userId, projection, function(err, user) {
|
||||
User.findById(userId, projection, function (err, user) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ module.exports = ReferencesController = {
|
||||
)
|
||||
return res.sendStatus(400)
|
||||
}
|
||||
return ReferencesHandler.index(projectId, docIds, function(err, data) {
|
||||
return ReferencesHandler.index(projectId, docIds, function (err, data) {
|
||||
if (err != null) {
|
||||
logger.err({ err, projectId }, 'error indexing all references')
|
||||
return res.sendStatus(500)
|
||||
@@ -46,7 +46,7 @@ module.exports = ReferencesController = {
|
||||
indexAll(req, res) {
|
||||
const projectId = req.params.Project_id
|
||||
const { shouldBroadcast } = req.body
|
||||
return ReferencesHandler.indexAll(projectId, function(err, data) {
|
||||
return ReferencesHandler.indexAll(projectId, function (err, data) {
|
||||
if (err != null) {
|
||||
logger.err({ err, projectId }, 'error indexing all references')
|
||||
return res.sendStatus(500)
|
||||
|
||||
@@ -42,8 +42,8 @@ module.exports = ReferencesHandler = {
|
||||
|
||||
_findBibFileIds(project) {
|
||||
const ids = []
|
||||
var _process = function(folder) {
|
||||
_.each(folder.fileRefs || [], function(file) {
|
||||
var _process = function (folder) {
|
||||
_.each(folder.fileRefs || [], function (file) {
|
||||
if (
|
||||
__guard__(file != null ? file.name : undefined, x1 =>
|
||||
x1.match(/^.*\.bib$/)
|
||||
@@ -60,8 +60,8 @@ module.exports = ReferencesHandler = {
|
||||
|
||||
_findBibDocIds(project) {
|
||||
const ids = []
|
||||
var _process = function(folder) {
|
||||
_.each(folder.docs || [], function(doc) {
|
||||
var _process = function (folder) {
|
||||
_.each(folder.docs || [], function (doc) {
|
||||
if (
|
||||
__guard__(doc != null ? doc.name : undefined, x1 =>
|
||||
x1.match(/^.*\.bib$/)
|
||||
@@ -78,32 +78,33 @@ module.exports = ReferencesHandler = {
|
||||
|
||||
_isFullIndex(project, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, result) {}
|
||||
callback = function (err, result) {}
|
||||
}
|
||||
return UserGetter.getUser(project.owner_ref, { features: true }, function(
|
||||
err,
|
||||
owner
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
return UserGetter.getUser(
|
||||
project.owner_ref,
|
||||
{ features: true },
|
||||
function (err, owner) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
const features = owner != null ? owner.features : undefined
|
||||
return callback(
|
||||
null,
|
||||
(features != null ? features.references : undefined) === true ||
|
||||
(features != null ? features.referencesSearch : undefined) === true
|
||||
)
|
||||
}
|
||||
const features = owner != null ? owner.features : undefined
|
||||
return callback(
|
||||
null,
|
||||
(features != null ? features.references : undefined) === true ||
|
||||
(features != null ? features.referencesSearch : undefined) === true
|
||||
)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
indexAll(projectId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, data) {}
|
||||
callback = function (err, data) {}
|
||||
}
|
||||
return ProjectGetter.getProject(
|
||||
projectId,
|
||||
{ rootFolder: true, owner_ref: 1 },
|
||||
function(err, project) {
|
||||
function (err, project) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error finding project', {
|
||||
projectId
|
||||
@@ -126,12 +127,12 @@ module.exports = ReferencesHandler = {
|
||||
|
||||
index(projectId, docIds, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, data) {}
|
||||
callback = function (err, data) {}
|
||||
}
|
||||
return ProjectGetter.getProject(
|
||||
projectId,
|
||||
{ rootFolder: true, owner_ref: 1 },
|
||||
function(err, project) {
|
||||
function (err, project) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error finding project', {
|
||||
projectId
|
||||
@@ -153,7 +154,7 @@ module.exports = ReferencesHandler = {
|
||||
if (!Features.hasFeature('references')) {
|
||||
return callback()
|
||||
}
|
||||
return ReferencesHandler._isFullIndex(project, function(err, isFullIndex) {
|
||||
return ReferencesHandler._isFullIndex(project, function (err, isFullIndex) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error checking whether to do full index', {
|
||||
projectId
|
||||
@@ -168,7 +169,7 @@ module.exports = ReferencesHandler = {
|
||||
docIds.map(docId => cb =>
|
||||
DocumentUpdaterHandler.flushDocToMongo(projectId, docId, cb)
|
||||
),
|
||||
function(err) {
|
||||
function (err) {
|
||||
// continue
|
||||
if (err) {
|
||||
OError.tag(err, 'error flushing docs to mongo', {
|
||||
@@ -192,7 +193,7 @@ module.exports = ReferencesHandler = {
|
||||
fullIndex: isFullIndex
|
||||
}
|
||||
},
|
||||
function(err, res, data) {
|
||||
function (err, res, data) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error communicating with references api', {
|
||||
projectId
|
||||
|
||||
@@ -16,7 +16,7 @@ function processLoginRequest(email, callback) {
|
||||
|
||||
function recordSuccessfulLogin(email, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
RateLimiter.clearRateLimit('login', email, callback)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ module.exports = {
|
||||
options = {}
|
||||
}
|
||||
if (callback == null) {
|
||||
callback = function(error, data) {}
|
||||
callback = function (error, data) {}
|
||||
}
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
@@ -44,7 +44,7 @@ module.exports = {
|
||||
createdAt,
|
||||
expiresAt
|
||||
},
|
||||
function(error) {
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -55,7 +55,7 @@ module.exports = {
|
||||
|
||||
getValueFromTokenAndExpire(use, token, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, data) {}
|
||||
callback = function (error, data) {}
|
||||
}
|
||||
const now = new Date()
|
||||
return db.tokens.findOneAndUpdate(
|
||||
@@ -70,7 +70,7 @@ module.exports = {
|
||||
usedAt: now
|
||||
}
|
||||
},
|
||||
function(error, result) {
|
||||
function (error, result) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ const settings = require('settings-sharelatex')
|
||||
Unique clients are identified by user_id if logged in, and IP address if not.
|
||||
*/
|
||||
function rateLimit(opts) {
|
||||
return function(req, res, next) {
|
||||
return function (req, res, next) {
|
||||
const userId = AuthenticationController.getLoggedInUserId(req) || req.ip
|
||||
if (
|
||||
settings.smokeTest &&
|
||||
@@ -41,7 +41,7 @@ function rateLimit(opts) {
|
||||
subjectName,
|
||||
throttle: opts.maxRequests || 6
|
||||
}
|
||||
return RateLimiter.addCount(options, function(error, canContinue) {
|
||||
return RateLimiter.addCount(options, function (error, canContinue) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -62,7 +62,7 @@ function loginRateLimit(req, res, next) {
|
||||
if (!email) {
|
||||
return next()
|
||||
}
|
||||
LoginRateLimiter.processLoginRequest(email, function(err, isAllowed) {
|
||||
LoginRateLimiter.processLoginRequest(email, function (err, isAllowed) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ const SystemMessageManager = require('../SystemMessages/SystemMessageManager')
|
||||
|
||||
const oneMinInMs = 60 * 1000
|
||||
|
||||
var updateOpenConnetionsMetrics = function() {
|
||||
var updateOpenConnetionsMetrics = function () {
|
||||
metrics.gauge(
|
||||
'open_connections.socketio',
|
||||
__guard__(
|
||||
@@ -79,7 +79,7 @@ const AdminController = {
|
||||
})()
|
||||
}
|
||||
|
||||
return SystemMessageManager.getMessagesFromDB(function(
|
||||
return SystemMessageManager.getMessagesFromDB(function (
|
||||
error,
|
||||
systemMessages
|
||||
) {
|
||||
@@ -124,7 +124,7 @@ const AdminController = {
|
||||
writeAllToMongo(req, res) {
|
||||
logger.log('writing all docs to mongo')
|
||||
Settings.mongo.writeAll = true
|
||||
return DocumentUpdaterHandler.flushAllDocsToMongo(function() {
|
||||
return DocumentUpdaterHandler.flushAllDocsToMongo(function () {
|
||||
logger.log('all docs have been saved to mongo')
|
||||
return res.sendStatus(200)
|
||||
})
|
||||
@@ -144,18 +144,19 @@ const AdminController = {
|
||||
},
|
||||
|
||||
createMessage(req, res, next) {
|
||||
return SystemMessageManager.createMessage(req.body.content, function(
|
||||
error
|
||||
) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
return SystemMessageManager.createMessage(
|
||||
req.body.content,
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return res.sendStatus(200)
|
||||
}
|
||||
return res.sendStatus(200)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
clearMessages(req, res, next) {
|
||||
return SystemMessageManager.clearMessages(function(error) {
|
||||
return SystemMessageManager.clearMessages(function (error) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ module.exports = {
|
||||
json: req.body,
|
||||
timeout: TEN_SECONDS
|
||||
})
|
||||
.on('error', function(error) {
|
||||
.on('error', function (error) {
|
||||
logger.error({ err: error }, 'Spelling API error')
|
||||
return res.status(500).end()
|
||||
})
|
||||
|
||||
@@ -48,14 +48,14 @@ module.exports = HomeController = {
|
||||
},
|
||||
|
||||
externalPage(page, title) {
|
||||
return function(req, res, next) {
|
||||
return function (req, res, next) {
|
||||
if (next == null) {
|
||||
next = function(error) {}
|
||||
next = function (error) {}
|
||||
}
|
||||
const path = Path.resolve(
|
||||
__dirname + `/../../../views/external/${page}.pug`
|
||||
)
|
||||
return fs.exists(path, function(exists) {
|
||||
return fs.exists(path, function (exists) {
|
||||
// No error in this callback - old method in Node.js!
|
||||
if (exists) {
|
||||
return res.render(`external/${page}.pug`, { title })
|
||||
|
||||
@@ -67,7 +67,7 @@ const FeaturesUpdater = {
|
||||
FeaturesUpdater._getFeaturesOverrides(userId, cb)
|
||||
}
|
||||
}
|
||||
async.series(jobs, function(err, results) {
|
||||
async.series(jobs, function (err, results) {
|
||||
if (err) {
|
||||
OError.tag(
|
||||
err,
|
||||
@@ -158,26 +158,25 @@ const FeaturesUpdater = {
|
||||
},
|
||||
|
||||
_getV1Features(userId, callback) {
|
||||
V1SubscriptionManager.getPlanCodeFromV1(userId, function(
|
||||
err,
|
||||
planCode,
|
||||
v1Id
|
||||
) {
|
||||
if (err) {
|
||||
if ((err ? err.name : undefined) === 'NotFoundError') {
|
||||
return callback(null, [])
|
||||
V1SubscriptionManager.getPlanCodeFromV1(
|
||||
userId,
|
||||
function (err, planCode, v1Id) {
|
||||
if (err) {
|
||||
if ((err ? err.name : undefined) === 'NotFoundError') {
|
||||
return callback(null, [])
|
||||
}
|
||||
return callback(err)
|
||||
}
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
callback(
|
||||
err,
|
||||
FeaturesUpdater._mergeFeatures(
|
||||
V1SubscriptionManager.getGrandfatheredFeaturesForV1User(v1Id) || {},
|
||||
FeaturesUpdater._planCodeToFeatures(planCode)
|
||||
callback(
|
||||
err,
|
||||
FeaturesUpdater._mergeFeatures(
|
||||
V1SubscriptionManager.getGrandfatheredFeaturesForV1User(v1Id) || {},
|
||||
FeaturesUpdater._planCodeToFeatures(planCode)
|
||||
)
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
_mergeFeatures(featuresA, featuresB) {
|
||||
@@ -277,31 +276,32 @@ const FeaturesUpdater = {
|
||||
|
||||
doSyncFromV1(v1UserId, callback) {
|
||||
logger.log({ v1UserId }, '[AccountSync] starting account sync')
|
||||
return UserGetter.getUser({ 'overleaf.id': v1UserId }, { _id: 1 }, function(
|
||||
err,
|
||||
user
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(err, '[AccountSync] error getting user', {
|
||||
v1UserId
|
||||
})
|
||||
return callback(err)
|
||||
return UserGetter.getUser(
|
||||
{ 'overleaf.id': v1UserId },
|
||||
{ _id: 1 },
|
||||
function (err, user) {
|
||||
if (err != null) {
|
||||
OError.tag(err, '[AccountSync] error getting user', {
|
||||
v1UserId
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
if ((user != null ? user._id : undefined) == null) {
|
||||
logger.warn({ v1UserId }, '[AccountSync] no user found for v1 id')
|
||||
return callback(null)
|
||||
}
|
||||
logger.log(
|
||||
{ v1UserId, userId: user._id },
|
||||
'[AccountSync] updating user subscription and features'
|
||||
)
|
||||
return FeaturesUpdater.refreshFeatures(user._id, callback)
|
||||
}
|
||||
if ((user != null ? user._id : undefined) == null) {
|
||||
logger.warn({ v1UserId }, '[AccountSync] no user found for v1 id')
|
||||
return callback(null)
|
||||
}
|
||||
logger.log(
|
||||
{ v1UserId, userId: user._id },
|
||||
'[AccountSync] updating user subscription and features'
|
||||
)
|
||||
return FeaturesUpdater.refreshFeatures(user._id, callback)
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const refreshFeaturesPromise = userId =>
|
||||
new Promise(function(resolve, reject) {
|
||||
new Promise(function (resolve, reject) {
|
||||
FeaturesUpdater.refreshFeatures(
|
||||
userId,
|
||||
(error, features, featuresChanged) => {
|
||||
|
||||
@@ -41,7 +41,7 @@ module.exports = LimitationsManager = {
|
||||
},
|
||||
|
||||
allowedNumberOfCollaboratorsForUser(user_id, callback) {
|
||||
return UserGetter.getUser(user_id, { features: 1 }, function(error, user) {
|
||||
return UserGetter.getUser(user_id, { features: 1 }, function (error, user) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -55,7 +55,7 @@ module.exports = LimitationsManager = {
|
||||
|
||||
canAddXCollaborators(project_id, x_collaborators, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, allowed) {}
|
||||
callback = function (error, allowed) {}
|
||||
}
|
||||
return this.allowedNumberOfCollaboratorsInProject(
|
||||
project_id,
|
||||
@@ -94,7 +94,7 @@ module.exports = LimitationsManager = {
|
||||
|
||||
hasPaidSubscription(user, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, hasSubscriptionOrIsMember) {}
|
||||
callback = function (err, hasSubscriptionOrIsMember) {}
|
||||
}
|
||||
return this.userHasV2Subscription(
|
||||
user,
|
||||
@@ -132,27 +132,27 @@ module.exports = LimitationsManager = {
|
||||
|
||||
userHasV2Subscription(user, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, hasSubscription, subscription) {}
|
||||
callback = function (err, hasSubscription, subscription) {}
|
||||
}
|
||||
return SubscriptionLocator.getUsersSubscription(user._id, function(
|
||||
err,
|
||||
subscription
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
return SubscriptionLocator.getUsersSubscription(
|
||||
user._id,
|
||||
function (err, subscription) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
const hasValidSubscription =
|
||||
subscription != null &&
|
||||
(subscription.recurlySubscription_id != null ||
|
||||
(subscription != null ? subscription.customAccount : undefined) ===
|
||||
true)
|
||||
return callback(err, hasValidSubscription, subscription)
|
||||
}
|
||||
const hasValidSubscription =
|
||||
subscription != null &&
|
||||
(subscription.recurlySubscription_id != null ||
|
||||
(subscription != null ? subscription.customAccount : undefined) ===
|
||||
true)
|
||||
return callback(err, hasValidSubscription, subscription)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
userHasV1OrV2Subscription(user, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, hasSubscription) {}
|
||||
callback = function (err, hasSubscription) {}
|
||||
}
|
||||
return this.userHasV2Subscription(user, (err, hasV2Subscription) => {
|
||||
if (err != null) {
|
||||
@@ -175,35 +175,37 @@ module.exports = LimitationsManager = {
|
||||
|
||||
userIsMemberOfGroupSubscription(user, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, isMember, subscriptions) {}
|
||||
callback = function (error, isMember, subscriptions) {}
|
||||
}
|
||||
return SubscriptionLocator.getMemberSubscriptions(user._id, function(
|
||||
err,
|
||||
subscriptions
|
||||
) {
|
||||
if (subscriptions == null) {
|
||||
subscriptions = []
|
||||
return SubscriptionLocator.getMemberSubscriptions(
|
||||
user._id,
|
||||
function (err, subscriptions) {
|
||||
if (subscriptions == null) {
|
||||
subscriptions = []
|
||||
}
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(err, subscriptions.length > 0, subscriptions)
|
||||
}
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return callback(err, subscriptions.length > 0, subscriptions)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
userHasV1Subscription(user, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, hasV1Subscription) {}
|
||||
callback = function (error, hasV1Subscription) {}
|
||||
}
|
||||
return V1SubscriptionManager.getSubscriptionsFromV1(user._id, function(
|
||||
err,
|
||||
v1Subscription
|
||||
) {
|
||||
return callback(
|
||||
err,
|
||||
!!(v1Subscription != null ? v1Subscription.has_subscription : undefined)
|
||||
)
|
||||
})
|
||||
return V1SubscriptionManager.getSubscriptionsFromV1(
|
||||
user._id,
|
||||
function (err, v1Subscription) {
|
||||
return callback(
|
||||
err,
|
||||
!!(v1Subscription != null
|
||||
? v1Subscription.has_subscription
|
||||
: undefined)
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
teamHasReachedMemberLimit(subscription) {
|
||||
@@ -217,27 +219,27 @@ module.exports = LimitationsManager = {
|
||||
|
||||
hasGroupMembersLimitReached(subscriptionId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, limitReached, subscription) {}
|
||||
callback = function (err, limitReached, subscription) {}
|
||||
}
|
||||
return SubscriptionLocator.getSubscription(subscriptionId, function(
|
||||
err,
|
||||
subscription
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting subscription', {
|
||||
subscriptionId
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
if (subscription == null) {
|
||||
logger.warn({ subscriptionId }, 'no subscription found')
|
||||
return callback(new Error('no subscription found'))
|
||||
}
|
||||
return SubscriptionLocator.getSubscription(
|
||||
subscriptionId,
|
||||
function (err, subscription) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error getting subscription', {
|
||||
subscriptionId
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
if (subscription == null) {
|
||||
logger.warn({ subscriptionId }, 'no subscription found')
|
||||
return callback(new Error('no subscription found'))
|
||||
}
|
||||
|
||||
const limitReached = LimitationsManager.teamHasReachedMemberLimit(
|
||||
subscription
|
||||
)
|
||||
return callback(err, limitReached, subscription)
|
||||
})
|
||||
const limitReached = LimitationsManager.teamHasReachedMemberLimit(
|
||||
subscription
|
||||
)
|
||||
return callback(err, limitReached, subscription)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ const RecurlyWrapper = {
|
||||
method: 'GET',
|
||||
expect404: true
|
||||
},
|
||||
function(error, response, responseBody) {
|
||||
function (error, response, responseBody) {
|
||||
if (error) {
|
||||
OError.tag(
|
||||
error,
|
||||
@@ -86,20 +86,20 @@ const RecurlyWrapper = {
|
||||
return next(null, cache)
|
||||
}
|
||||
logger.log({ user_id: user._id }, 'user appears to exist in recurly')
|
||||
return RecurlyWrapper._parseAccountXml(responseBody, function(
|
||||
err,
|
||||
account
|
||||
) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error parsing account', {
|
||||
user_id: user._id
|
||||
})
|
||||
return next(err)
|
||||
return RecurlyWrapper._parseAccountXml(
|
||||
responseBody,
|
||||
function (err, account) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error parsing account', {
|
||||
user_id: user._id
|
||||
})
|
||||
return next(err)
|
||||
}
|
||||
cache.userExists = true
|
||||
cache.account = account
|
||||
return next(null, cache)
|
||||
}
|
||||
cache.userExists = true
|
||||
cache.account = account
|
||||
return next(null, cache)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
@@ -142,19 +142,19 @@ const RecurlyWrapper = {
|
||||
)
|
||||
return next(error)
|
||||
}
|
||||
return RecurlyWrapper._parseAccountXml(responseBody, function(
|
||||
err,
|
||||
account
|
||||
) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error creating account', {
|
||||
user_id: user._id
|
||||
})
|
||||
return next(err)
|
||||
return RecurlyWrapper._parseAccountXml(
|
||||
responseBody,
|
||||
function (err, account) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error creating account', {
|
||||
user_id: user._id
|
||||
})
|
||||
return next(err)
|
||||
}
|
||||
cache.account = account
|
||||
return next(null, cache)
|
||||
}
|
||||
cache.account = account
|
||||
return next(null, cache)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
@@ -189,20 +189,20 @@ const RecurlyWrapper = {
|
||||
)
|
||||
return next(error)
|
||||
}
|
||||
return RecurlyWrapper._parseBillingInfoXml(responseBody, function(
|
||||
err,
|
||||
billingInfo
|
||||
) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error creating billing info', {
|
||||
user_id: user._id,
|
||||
accountCode
|
||||
})
|
||||
return next(err)
|
||||
return RecurlyWrapper._parseBillingInfoXml(
|
||||
responseBody,
|
||||
function (err, billingInfo) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error creating billing info', {
|
||||
user_id: user._id,
|
||||
accountCode
|
||||
})
|
||||
return next(err)
|
||||
}
|
||||
cache.billingInfo = billingInfo
|
||||
return next(null, cache)
|
||||
}
|
||||
cache.billingInfo = billingInfo
|
||||
return next(null, cache)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
@@ -255,19 +255,19 @@ const RecurlyWrapper = {
|
||||
)
|
||||
return next(error)
|
||||
}
|
||||
return RecurlyWrapper._parseBillingInfoXml(responseBody, function(
|
||||
err,
|
||||
billingInfo
|
||||
) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error updating billing info', {
|
||||
user_id: user._id
|
||||
})
|
||||
return next(err)
|
||||
return RecurlyWrapper._parseBillingInfoXml(
|
||||
responseBody,
|
||||
function (err, billingInfo) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error updating billing info', {
|
||||
user_id: user._id
|
||||
})
|
||||
return next(err)
|
||||
}
|
||||
cache.billingInfo = billingInfo
|
||||
return next(null, cache)
|
||||
}
|
||||
cache.billingInfo = billingInfo
|
||||
return next(null, cache)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
@@ -308,19 +308,19 @@ const RecurlyWrapper = {
|
||||
)
|
||||
return next(error)
|
||||
}
|
||||
return RecurlyWrapper._parseSubscriptionXml(responseBody, function(
|
||||
err,
|
||||
subscription
|
||||
) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error creating subscription', {
|
||||
user_id: user._id
|
||||
})
|
||||
return next(err)
|
||||
return RecurlyWrapper._parseSubscriptionXml(
|
||||
responseBody,
|
||||
function (err, subscription) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error creating subscription', {
|
||||
user_id: user._id
|
||||
})
|
||||
return next(err)
|
||||
}
|
||||
cache.subscription = subscription
|
||||
return next(null, cache)
|
||||
}
|
||||
cache.subscription = subscription
|
||||
return next(null, cache)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -348,7 +348,7 @@ const RecurlyWrapper = {
|
||||
RecurlyWrapper._paypal.setAddressAndCompanyBillingInfo,
|
||||
RecurlyWrapper._paypal.createSubscription
|
||||
],
|
||||
function(err, result) {
|
||||
function (err, result) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error in paypal subscription creation process', {
|
||||
user_id: user._id
|
||||
@@ -449,7 +449,7 @@ const RecurlyWrapper = {
|
||||
const { expect404, expect422 } = options
|
||||
delete options.expect404
|
||||
delete options.expect422
|
||||
return request(options, function(error, response, body) {
|
||||
return request(options, function (error, response, body) {
|
||||
if (
|
||||
error == null &&
|
||||
response.statusCode !== 200 &&
|
||||
@@ -532,16 +532,16 @@ const RecurlyWrapper = {
|
||||
)
|
||||
}
|
||||
|
||||
return RecurlyWrapper.getAccount(accountId, function(
|
||||
error,
|
||||
account
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
return RecurlyWrapper.getAccount(
|
||||
accountId,
|
||||
function (error, account) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
recurlySubscription.account = account
|
||||
return callback(null, recurlySubscription)
|
||||
}
|
||||
recurlySubscription.account = account
|
||||
return callback(null, recurlySubscription)
|
||||
})
|
||||
)
|
||||
} else {
|
||||
return callback(null, recurlySubscription)
|
||||
}
|
||||
@@ -566,7 +566,7 @@ const RecurlyWrapper = {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return RecurlyWrapper._parseXml(body, function(err, data) {
|
||||
return RecurlyWrapper._parseXml(body, function (err, data) {
|
||||
if (err != null) {
|
||||
logger.warn({ err }, 'could not get accoutns')
|
||||
callback(err)
|
||||
@@ -620,29 +620,30 @@ const RecurlyWrapper = {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return RecurlyWrapper._parseRedemptionsXml(body, function(
|
||||
error,
|
||||
redemptions
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
const activeRedemptions = redemptions.filter(
|
||||
redemption => redemption.state === 'active'
|
||||
)
|
||||
const couponCodes = activeRedemptions.map(
|
||||
redemption => redemption.coupon_code
|
||||
)
|
||||
return Async.map(couponCodes, RecurlyWrapper.getCoupon, function(
|
||||
error,
|
||||
coupons
|
||||
) {
|
||||
return RecurlyWrapper._parseRedemptionsXml(
|
||||
body,
|
||||
function (error, redemptions) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return callback(null, coupons)
|
||||
})
|
||||
})
|
||||
const activeRedemptions = redemptions.filter(
|
||||
redemption => redemption.state === 'active'
|
||||
)
|
||||
const couponCodes = activeRedemptions.map(
|
||||
redemption => redemption.coupon_code
|
||||
)
|
||||
return Async.map(
|
||||
couponCodes,
|
||||
RecurlyWrapper.getCoupon,
|
||||
function (error, coupons) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return callback(null, coupons)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
@@ -776,9 +777,9 @@ const RecurlyWrapper = {
|
||||
url: `subscriptions/${subscriptionId}/cancel`,
|
||||
method: 'put'
|
||||
},
|
||||
function(error, response, body) {
|
||||
function (error, response, body) {
|
||||
if (error != null) {
|
||||
return RecurlyWrapper._parseXml(body, function(_err, parsed) {
|
||||
return RecurlyWrapper._parseXml(body, function (_err, parsed) {
|
||||
if (
|
||||
__guard__(
|
||||
parsed != null ? parsed.error : undefined,
|
||||
@@ -870,7 +871,7 @@ const RecurlyWrapper = {
|
||||
|
||||
listAccountActiveSubscriptions(account_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, subscriptions) {}
|
||||
callback = function (error, subscriptions) {}
|
||||
}
|
||||
return RecurlyWrapper.apiRequest(
|
||||
{
|
||||
@@ -880,7 +881,7 @@ const RecurlyWrapper = {
|
||||
},
|
||||
expect404: true
|
||||
},
|
||||
function(error, response, body) {
|
||||
function (error, response, body) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -975,7 +976,7 @@ const RecurlyWrapper = {
|
||||
},
|
||||
|
||||
_parseXmlAndGetAttribute(xml, attribute, callback) {
|
||||
return RecurlyWrapper._parseXml(xml, function(error, data) {
|
||||
return RecurlyWrapper._parseXml(xml, function (error, data) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -990,7 +991,7 @@ const RecurlyWrapper = {
|
||||
},
|
||||
|
||||
_parseXml(xml, callback) {
|
||||
var convertDataTypes = function(data) {
|
||||
var convertDataTypes = function (data) {
|
||||
let key, value
|
||||
if (data != null && data.$ != null) {
|
||||
if (data.$.nil === 'nil') {
|
||||
@@ -1033,7 +1034,7 @@ const RecurlyWrapper = {
|
||||
explicitArray: false,
|
||||
emptyTag: ''
|
||||
})
|
||||
return parser.parseString(xml, function(error, data) {
|
||||
return parser.parseString(xml, function (error, data) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ module.exports = SubscriptionController = {
|
||||
|
||||
return GeoIpLookup.getCurrencyCode(
|
||||
(req.query != null ? req.query.ip : undefined) || req.ip,
|
||||
function(err, recomendedCurrency) {
|
||||
function (err, recomendedCurrency) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -57,16 +57,17 @@ module.exports = SubscriptionController = {
|
||||
})
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
if (user_id != null) {
|
||||
return UserGetter.getUser(user_id, { signUpDate: 1 }, function(
|
||||
err,
|
||||
user
|
||||
) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
return UserGetter.getUser(
|
||||
user_id,
|
||||
{ signUpDate: 1 },
|
||||
function (err, user) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
currentUser = user
|
||||
return render()
|
||||
}
|
||||
currentUser = user
|
||||
return render()
|
||||
})
|
||||
)
|
||||
} else {
|
||||
return render()
|
||||
}
|
||||
@@ -81,68 +82,68 @@ module.exports = SubscriptionController = {
|
||||
if (!plan) {
|
||||
return HttpErrorHandler.unprocessableEntity(req, res, 'Plan not found')
|
||||
}
|
||||
return LimitationsManager.userHasV1OrV2Subscription(user, function(
|
||||
err,
|
||||
hasSubscription
|
||||
) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
if (hasSubscription) {
|
||||
return res.redirect('/user/subscription?hasSubscription=true')
|
||||
} else {
|
||||
// LimitationsManager.userHasV2Subscription only checks Mongo. Double check with
|
||||
// Recurly as well at this point (we don't do this most places for speed).
|
||||
return SubscriptionHandler.validateNoSubscriptionInRecurly(
|
||||
user._id,
|
||||
function(error, valid) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
if (!valid) {
|
||||
res.redirect('/user/subscription?hasSubscription=true')
|
||||
} else {
|
||||
let currency =
|
||||
req.query.currency != null
|
||||
? req.query.currency.toUpperCase()
|
||||
: undefined
|
||||
return GeoIpLookup.getCurrencyCode(
|
||||
(req.query != null ? req.query.ip : undefined) || req.ip,
|
||||
function(err, recomendedCurrency, countryCode) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
if (recomendedCurrency != null && currency == null) {
|
||||
currency = recomendedCurrency
|
||||
}
|
||||
return res.render('subscriptions/new', {
|
||||
title: 'subscribe',
|
||||
currency,
|
||||
countryCode,
|
||||
plan,
|
||||
showStudentPlan: req.query.ssp === 'true',
|
||||
recurlyConfig: JSON.stringify({
|
||||
return LimitationsManager.userHasV1OrV2Subscription(
|
||||
user,
|
||||
function (err, hasSubscription) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
if (hasSubscription) {
|
||||
return res.redirect('/user/subscription?hasSubscription=true')
|
||||
} else {
|
||||
// LimitationsManager.userHasV2Subscription only checks Mongo. Double check with
|
||||
// Recurly as well at this point (we don't do this most places for speed).
|
||||
return SubscriptionHandler.validateNoSubscriptionInRecurly(
|
||||
user._id,
|
||||
function (error, valid) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
if (!valid) {
|
||||
res.redirect('/user/subscription?hasSubscription=true')
|
||||
} else {
|
||||
let currency =
|
||||
req.query.currency != null
|
||||
? req.query.currency.toUpperCase()
|
||||
: undefined
|
||||
return GeoIpLookup.getCurrencyCode(
|
||||
(req.query != null ? req.query.ip : undefined) || req.ip,
|
||||
function (err, recomendedCurrency, countryCode) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
if (recomendedCurrency != null && currency == null) {
|
||||
currency = recomendedCurrency
|
||||
}
|
||||
return res.render('subscriptions/new', {
|
||||
title: 'subscribe',
|
||||
currency,
|
||||
subdomain: Settings.apis.recurly.subdomain
|
||||
}),
|
||||
showCouponField: !!req.query.scf,
|
||||
showVatField: !!req.query.svf,
|
||||
gaOptimize: true
|
||||
})
|
||||
}
|
||||
)
|
||||
countryCode,
|
||||
plan,
|
||||
showStudentPlan: req.query.ssp === 'true',
|
||||
recurlyConfig: JSON.stringify({
|
||||
currency,
|
||||
subdomain: Settings.apis.recurly.subdomain
|
||||
}),
|
||||
showCouponField: !!req.query.scf,
|
||||
showVatField: !!req.query.svf,
|
||||
gaOptimize: true
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
userSubscriptionPage(req, res, next) {
|
||||
const user = AuthenticationController.getSessionUser(req)
|
||||
return SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel(
|
||||
user,
|
||||
function(error, results) {
|
||||
function (error, results) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -155,31 +156,31 @@ module.exports = SubscriptionController = {
|
||||
managedPublishers,
|
||||
v1SubscriptionStatus
|
||||
} = results
|
||||
return LimitationsManager.userHasV1OrV2Subscription(user, function(
|
||||
err,
|
||||
hasSubscription
|
||||
) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
return LimitationsManager.userHasV1OrV2Subscription(
|
||||
user,
|
||||
function (err, hasSubscription) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
const fromPlansPage = req.query.hasSubscription
|
||||
const plans = SubscriptionViewModelBuilder.buildPlansList()
|
||||
const data = {
|
||||
title: 'your_subscription',
|
||||
plans,
|
||||
user,
|
||||
hasSubscription,
|
||||
fromPlansPage,
|
||||
personalSubscription,
|
||||
memberGroupSubscriptions,
|
||||
managedGroupSubscriptions,
|
||||
confirmedMemberAffiliations,
|
||||
managedInstitutions,
|
||||
managedPublishers,
|
||||
v1SubscriptionStatus
|
||||
}
|
||||
return res.render('subscriptions/dashboard', data)
|
||||
}
|
||||
const fromPlansPage = req.query.hasSubscription
|
||||
const plans = SubscriptionViewModelBuilder.buildPlansList()
|
||||
const data = {
|
||||
title: 'your_subscription',
|
||||
plans,
|
||||
user,
|
||||
hasSubscription,
|
||||
fromPlansPage,
|
||||
personalSubscription,
|
||||
memberGroupSubscriptions,
|
||||
managedGroupSubscriptions,
|
||||
confirmedMemberAffiliations,
|
||||
managedInstitutions,
|
||||
managedPublishers,
|
||||
v1SubscriptionStatus
|
||||
}
|
||||
return res.render('subscriptions/dashboard', data)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
@@ -193,54 +194,54 @@ module.exports = SubscriptionController = {
|
||||
}
|
||||
const { subscriptionDetails } = req.body
|
||||
|
||||
return LimitationsManager.userHasV1OrV2Subscription(user, function(
|
||||
err,
|
||||
hasSubscription
|
||||
) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
if (hasSubscription) {
|
||||
logger.warn({ user_id: user._id }, 'user already has subscription')
|
||||
return res.sendStatus(409) // conflict
|
||||
}
|
||||
return SubscriptionHandler.createSubscription(
|
||||
user,
|
||||
subscriptionDetails,
|
||||
recurlyTokenIds,
|
||||
function(err) {
|
||||
if (!err) {
|
||||
return res.sendStatus(201)
|
||||
}
|
||||
|
||||
if (
|
||||
err instanceof SubscriptionErrors.RecurlyTransactionError ||
|
||||
err instanceof Errors.InvalidError
|
||||
) {
|
||||
logger.error({ err }, 'recurly transaction error, potential 422')
|
||||
return HttpErrorHandler.unprocessableEntity(
|
||||
req,
|
||||
res,
|
||||
err.message,
|
||||
OError.getFullInfo(err).public
|
||||
)
|
||||
}
|
||||
|
||||
logger.warn(
|
||||
{ err, user_id: user._id },
|
||||
'something went wrong creating subscription'
|
||||
)
|
||||
next(err)
|
||||
return LimitationsManager.userHasV1OrV2Subscription(
|
||||
user,
|
||||
function (err, hasSubscription) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
)
|
||||
})
|
||||
if (hasSubscription) {
|
||||
logger.warn({ user_id: user._id }, 'user already has subscription')
|
||||
return res.sendStatus(409) // conflict
|
||||
}
|
||||
return SubscriptionHandler.createSubscription(
|
||||
user,
|
||||
subscriptionDetails,
|
||||
recurlyTokenIds,
|
||||
function (err) {
|
||||
if (!err) {
|
||||
return res.sendStatus(201)
|
||||
}
|
||||
|
||||
if (
|
||||
err instanceof SubscriptionErrors.RecurlyTransactionError ||
|
||||
err instanceof Errors.InvalidError
|
||||
) {
|
||||
logger.error({ err }, 'recurly transaction error, potential 422')
|
||||
return HttpErrorHandler.unprocessableEntity(
|
||||
req,
|
||||
res,
|
||||
err.message,
|
||||
OError.getFullInfo(err).public
|
||||
)
|
||||
}
|
||||
|
||||
logger.warn(
|
||||
{ err, user_id: user._id },
|
||||
'something went wrong creating subscription'
|
||||
)
|
||||
next(err)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
successful_subscription(req, res, next) {
|
||||
const user = AuthenticationController.getSessionUser(req)
|
||||
return SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel(
|
||||
user,
|
||||
function(error, { personalSubscription }) {
|
||||
function (error, { personalSubscription }) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -258,7 +259,7 @@ module.exports = SubscriptionController = {
|
||||
cancelSubscription(req, res, next) {
|
||||
const user = AuthenticationController.getSessionUser(req)
|
||||
logger.log({ user_id: user._id }, 'canceling subscription')
|
||||
return SubscriptionHandler.cancelSubscription(user, function(err) {
|
||||
return SubscriptionHandler.cancelSubscription(user, function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'something went wrong canceling subscription', {
|
||||
user_id: user._id
|
||||
@@ -281,7 +282,7 @@ module.exports = SubscriptionController = {
|
||||
cancelV1Subscription(req, res, next) {
|
||||
const user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
logger.log({ user_id }, 'canceling v1 subscription')
|
||||
return V1SubscriptionManager.cancelV1Subscription(user_id, function(err) {
|
||||
return V1SubscriptionManager.cancelV1Subscription(user_id, function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'something went wrong canceling v1 subscription', {
|
||||
user_id
|
||||
@@ -310,7 +311,7 @@ module.exports = SubscriptionController = {
|
||||
user,
|
||||
planCode,
|
||||
null,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'something went wrong updating subscription', {
|
||||
user_id: user._id
|
||||
@@ -324,20 +325,22 @@ module.exports = SubscriptionController = {
|
||||
|
||||
updateAccountEmailAddress(req, res, next) {
|
||||
const user = AuthenticationController.getSessionUser(req)
|
||||
RecurlyWrapper.updateAccountEmailAddress(user._id, user.email, function(
|
||||
error
|
||||
) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
RecurlyWrapper.updateAccountEmailAddress(
|
||||
user._id,
|
||||
user.email,
|
||||
function (error) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
res.sendStatus(200)
|
||||
}
|
||||
res.sendStatus(200)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
reactivateSubscription(req, res, next) {
|
||||
const user = AuthenticationController.getSessionUser(req)
|
||||
logger.log({ user_id: user._id }, 'reactivating subscription')
|
||||
return SubscriptionHandler.reactivateSubscription(user, function(err) {
|
||||
return SubscriptionHandler.reactivateSubscription(user, function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'something went wrong reactivating subscription', {
|
||||
user_id: user._id
|
||||
@@ -363,7 +366,7 @@ module.exports = SubscriptionController = {
|
||||
return SubscriptionHandler.syncSubscription(
|
||||
recurlySubscription,
|
||||
{ ip: req.ip },
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -374,7 +377,7 @@ module.exports = SubscriptionController = {
|
||||
const recurlyAccountCode = eventData.account.account_code
|
||||
return SubscriptionHandler.attemptPaypalInvoiceCollection(
|
||||
recurlyAccountCode,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
@@ -388,36 +391,38 @@ module.exports = SubscriptionController = {
|
||||
|
||||
renderUpgradeToAnnualPlanPage(req, res, next) {
|
||||
const user = AuthenticationController.getSessionUser(req)
|
||||
return LimitationsManager.userHasV2Subscription(user, function(
|
||||
err,
|
||||
hasSubscription,
|
||||
subscription
|
||||
) {
|
||||
let planName
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
return LimitationsManager.userHasV2Subscription(
|
||||
user,
|
||||
function (err, hasSubscription, subscription) {
|
||||
let planName
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
const planCode =
|
||||
subscription != null ? subscription.planCode.toLowerCase() : undefined
|
||||
if (
|
||||
(planCode != null ? planCode.indexOf('annual') : undefined) !== -1
|
||||
) {
|
||||
planName = 'annual'
|
||||
} else if (
|
||||
(planCode != null ? planCode.indexOf('student') : undefined) !== -1
|
||||
) {
|
||||
planName = 'student'
|
||||
} else if (
|
||||
(planCode != null ? planCode.indexOf('collaborator') : undefined) !==
|
||||
-1
|
||||
) {
|
||||
planName = 'collaborator'
|
||||
}
|
||||
if (!hasSubscription) {
|
||||
return res.redirect('/user/subscription/plans')
|
||||
}
|
||||
return res.render('subscriptions/upgradeToAnnual', {
|
||||
title: 'Upgrade to annual',
|
||||
planName
|
||||
})
|
||||
}
|
||||
const planCode =
|
||||
subscription != null ? subscription.planCode.toLowerCase() : undefined
|
||||
if ((planCode != null ? planCode.indexOf('annual') : undefined) !== -1) {
|
||||
planName = 'annual'
|
||||
} else if (
|
||||
(planCode != null ? planCode.indexOf('student') : undefined) !== -1
|
||||
) {
|
||||
planName = 'student'
|
||||
} else if (
|
||||
(planCode != null ? planCode.indexOf('collaborator') : undefined) !== -1
|
||||
) {
|
||||
planName = 'collaborator'
|
||||
}
|
||||
if (!hasSubscription) {
|
||||
return res.redirect('/user/subscription/plans')
|
||||
}
|
||||
return res.render('subscriptions/upgradeToAnnual', {
|
||||
title: 'Upgrade to annual',
|
||||
planName
|
||||
})
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
processUpgradeToAnnualPlan(req, res, next) {
|
||||
@@ -433,7 +438,7 @@ module.exports = SubscriptionController = {
|
||||
user,
|
||||
annualPlanName,
|
||||
coupon_code,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error updating subscription', {
|
||||
user_id: user._id
|
||||
@@ -447,29 +452,32 @@ module.exports = SubscriptionController = {
|
||||
|
||||
extendTrial(req, res, next) {
|
||||
const user = AuthenticationController.getSessionUser(req)
|
||||
return LimitationsManager.userHasV2Subscription(user, function(
|
||||
err,
|
||||
hasSubscription,
|
||||
subscription
|
||||
) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
return SubscriptionHandler.extendTrial(subscription, 14, function(err) {
|
||||
return LimitationsManager.userHasV2Subscription(
|
||||
user,
|
||||
function (err, hasSubscription, subscription) {
|
||||
if (err != null) {
|
||||
return res.sendStatus(500)
|
||||
} else {
|
||||
return res.sendStatus(200)
|
||||
return next(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
return SubscriptionHandler.extendTrial(
|
||||
subscription,
|
||||
14,
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return res.sendStatus(500)
|
||||
} else {
|
||||
return res.sendStatus(200)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
recurlyNotificationParser(req, res, next) {
|
||||
let xml = ''
|
||||
req.on('data', chunk => (xml += chunk))
|
||||
return req.on('end', () =>
|
||||
RecurlyWrapper._parseXml(xml, function(error, body) {
|
||||
RecurlyWrapper._parseXml(xml, function (error, body) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -481,7 +489,7 @@ module.exports = SubscriptionController = {
|
||||
|
||||
refreshUserFeatures(req, res, next) {
|
||||
const { user_id } = req.params
|
||||
return FeaturesUpdater.refreshFeatures(user_id, function(error) {
|
||||
return FeaturesUpdater.refreshFeatures(user_id, function (error) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ module.exports = {
|
||||
return SubscriptionGroupHandler.removeUserFromGroup(
|
||||
subscription._id,
|
||||
userToRemove_id,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error removing user from group', {
|
||||
subscriptionId: subscription._id,
|
||||
@@ -46,28 +46,28 @@ module.exports = {
|
||||
removeSelfFromGroup(req, res, next) {
|
||||
const subscriptionId = req.query.subscriptionId
|
||||
const userToRemove_id = AuthenticationController.getLoggedInUserId(req)
|
||||
return SubscriptionLocator.getSubscription(subscriptionId, function(
|
||||
error,
|
||||
subscription
|
||||
) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
|
||||
return SubscriptionGroupHandler.removeUserFromGroup(
|
||||
subscription._id,
|
||||
userToRemove_id,
|
||||
function(err) {
|
||||
if (err != null) {
|
||||
logger.err(
|
||||
{ err, userToRemove_id, subscriptionId },
|
||||
'error removing self from group'
|
||||
)
|
||||
return res.sendStatus(500)
|
||||
}
|
||||
return res.sendStatus(200)
|
||||
return SubscriptionLocator.getSubscription(
|
||||
subscriptionId,
|
||||
function (error, subscription) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
return SubscriptionGroupHandler.removeUserFromGroup(
|
||||
subscription._id,
|
||||
userToRemove_id,
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
logger.err(
|
||||
{ err, userToRemove_id, subscriptionId },
|
||||
'error removing self from group'
|
||||
)
|
||||
return res.sendStatus(500)
|
||||
}
|
||||
return res.sendStatus(200)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ const SubscriptionGroupHandler = {
|
||||
return Subscription.updateOne(
|
||||
{ admin_id: oldId },
|
||||
{ admin_id: newId },
|
||||
function(error) {
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -51,7 +51,7 @@ const SubscriptionGroupHandler = {
|
||||
'manager_ids',
|
||||
oldId,
|
||||
newId,
|
||||
function(error) {
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -71,12 +71,12 @@ const SubscriptionGroupHandler = {
|
||||
|
||||
isUserPartOfGroup(user_id, subscription_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, partOfGroup) {}
|
||||
callback = function (err, partOfGroup) {}
|
||||
}
|
||||
return SubscriptionLocator.getSubscriptionByMemberIdAndId(
|
||||
user_id,
|
||||
subscription_id,
|
||||
function(err, subscription) {
|
||||
function (err, subscription) {
|
||||
let partOfGroup
|
||||
if (subscription != null) {
|
||||
partOfGroup = true
|
||||
@@ -90,7 +90,7 @@ const SubscriptionGroupHandler = {
|
||||
|
||||
getTotalConfirmedUsersInGroup(subscription_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, totalUsers) {}
|
||||
callback = function (err, totalUsers) {}
|
||||
}
|
||||
return SubscriptionLocator.getSubscription(
|
||||
subscription_id,
|
||||
@@ -106,7 +106,7 @@ const SubscriptionGroupHandler = {
|
||||
}
|
||||
}
|
||||
|
||||
var replaceInArray = function(model, property, oldValue, newValue, callback) {
|
||||
var replaceInArray = function (model, property, oldValue, newValue, callback) {
|
||||
// Mongo won't let us pull and addToSet in the same query, so do it in
|
||||
// two. Note we need to add first, since the query is based on the old user.
|
||||
const query = {}
|
||||
@@ -118,7 +118,7 @@ var replaceInArray = function(model, property, oldValue, newValue, callback) {
|
||||
const setOldValue = {}
|
||||
setOldValue[property] = oldValue
|
||||
|
||||
model.updateMany(query, { $addToSet: setNewValue }, function(error) {
|
||||
model.updateMany(query, { $addToSet: setNewValue }, function (error) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
@@ -11,228 +11,227 @@ const Analytics = require('../Analytics/AnalyticsManager')
|
||||
const SubscriptionHandler = {
|
||||
validateNoSubscriptionInRecurly(userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
RecurlyWrapper.listAccountActiveSubscriptions(userId, function(
|
||||
error,
|
||||
subscriptions
|
||||
) {
|
||||
if (subscriptions == null) {
|
||||
subscriptions = []
|
||||
}
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
if (subscriptions.length > 0) {
|
||||
SubscriptionUpdater.syncSubscription(subscriptions[0], userId, function(
|
||||
error
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
callback(null, false)
|
||||
})
|
||||
} else {
|
||||
callback(null, true)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
createSubscription(user, subscriptionDetails, recurlyTokenIds, callback) {
|
||||
SubscriptionHandler.validateNoSubscriptionInRecurly(user._id, function(
|
||||
error,
|
||||
valid
|
||||
) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
if (!valid) {
|
||||
return callback(new Error('user already has subscription in recurly'))
|
||||
}
|
||||
RecurlyWrapper.createSubscription(
|
||||
user,
|
||||
subscriptionDetails,
|
||||
recurlyTokenIds,
|
||||
function(error, recurlySubscription) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return SubscriptionUpdater.syncSubscription(
|
||||
recurlySubscription,
|
||||
user._id,
|
||||
function(error) {
|
||||
RecurlyWrapper.listAccountActiveSubscriptions(
|
||||
userId,
|
||||
function (error, subscriptions) {
|
||||
if (subscriptions == null) {
|
||||
subscriptions = []
|
||||
}
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
if (subscriptions.length > 0) {
|
||||
SubscriptionUpdater.syncSubscription(
|
||||
subscriptions[0],
|
||||
userId,
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return callback()
|
||||
callback(null, false)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
callback(null, true)
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
createSubscription(user, subscriptionDetails, recurlyTokenIds, callback) {
|
||||
SubscriptionHandler.validateNoSubscriptionInRecurly(
|
||||
user._id,
|
||||
function (error, valid) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
if (!valid) {
|
||||
return callback(new Error('user already has subscription in recurly'))
|
||||
}
|
||||
RecurlyWrapper.createSubscription(
|
||||
user,
|
||||
subscriptionDetails,
|
||||
recurlyTokenIds,
|
||||
function (error, recurlySubscription) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return SubscriptionUpdater.syncSubscription(
|
||||
recurlySubscription,
|
||||
user._id,
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
return callback()
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
updateSubscription(user, planCode, couponCode, callback) {
|
||||
LimitationsManager.userHasV2Subscription(user, function(
|
||||
err,
|
||||
hasSubscription,
|
||||
subscription
|
||||
) {
|
||||
if (err) {
|
||||
logger.warn(
|
||||
{ err, user_id: user._id, hasSubscription },
|
||||
'there was an error checking user v2 subscription'
|
||||
)
|
||||
}
|
||||
if (!hasSubscription) {
|
||||
return callback()
|
||||
} else {
|
||||
return async.series(
|
||||
[
|
||||
function(cb) {
|
||||
if (couponCode == null) {
|
||||
return cb()
|
||||
}
|
||||
RecurlyWrapper.getSubscription(
|
||||
subscription.recurlySubscription_id,
|
||||
{ includeAccount: true },
|
||||
function(err, usersSubscription) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
RecurlyWrapper.redeemCoupon(
|
||||
usersSubscription.account.account_code,
|
||||
couponCode,
|
||||
cb
|
||||
)
|
||||
LimitationsManager.userHasV2Subscription(
|
||||
user,
|
||||
function (err, hasSubscription, subscription) {
|
||||
if (err) {
|
||||
logger.warn(
|
||||
{ err, user_id: user._id, hasSubscription },
|
||||
'there was an error checking user v2 subscription'
|
||||
)
|
||||
}
|
||||
if (!hasSubscription) {
|
||||
return callback()
|
||||
} else {
|
||||
return async.series(
|
||||
[
|
||||
function (cb) {
|
||||
if (couponCode == null) {
|
||||
return cb()
|
||||
}
|
||||
)
|
||||
},
|
||||
cb =>
|
||||
RecurlyWrapper.updateSubscription(
|
||||
subscription.recurlySubscription_id,
|
||||
{ plan_code: planCode, timeframe: 'now' },
|
||||
function(error, recurlySubscription) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
RecurlyWrapper.getSubscription(
|
||||
subscription.recurlySubscription_id,
|
||||
{ includeAccount: true },
|
||||
function (err, usersSubscription) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
RecurlyWrapper.redeemCoupon(
|
||||
usersSubscription.account.account_code,
|
||||
couponCode,
|
||||
cb
|
||||
)
|
||||
}
|
||||
SubscriptionUpdater.syncSubscription(
|
||||
recurlySubscription,
|
||||
user._id,
|
||||
cb
|
||||
)
|
||||
}
|
||||
)
|
||||
],
|
||||
callback
|
||||
)
|
||||
)
|
||||
},
|
||||
cb =>
|
||||
RecurlyWrapper.updateSubscription(
|
||||
subscription.recurlySubscription_id,
|
||||
{ plan_code: planCode, timeframe: 'now' },
|
||||
function (error, recurlySubscription) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
SubscriptionUpdater.syncSubscription(
|
||||
recurlySubscription,
|
||||
user._id,
|
||||
cb
|
||||
)
|
||||
}
|
||||
)
|
||||
],
|
||||
callback
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
cancelSubscription(user, callback) {
|
||||
LimitationsManager.userHasV2Subscription(user, function(
|
||||
err,
|
||||
hasSubscription,
|
||||
subscription
|
||||
) {
|
||||
if (err) {
|
||||
logger.warn(
|
||||
{ err, user_id: user._id, hasSubscription },
|
||||
'there was an error checking user v2 subscription'
|
||||
)
|
||||
}
|
||||
if (hasSubscription) {
|
||||
RecurlyWrapper.cancelSubscription(
|
||||
subscription.recurlySubscription_id,
|
||||
function(error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
const emailOpts = {
|
||||
to: user.email,
|
||||
first_name: user.first_name
|
||||
}
|
||||
const ONE_HOUR_IN_MS = 1000 * 60 * 60
|
||||
setTimeout(
|
||||
() =>
|
||||
EmailHandler.sendEmail(
|
||||
'canceledSubscription',
|
||||
emailOpts,
|
||||
err => {
|
||||
if (err != null) {
|
||||
logger.warn(
|
||||
{ err },
|
||||
'failed to send confirmation email for subscription cancellation'
|
||||
)
|
||||
LimitationsManager.userHasV2Subscription(
|
||||
user,
|
||||
function (err, hasSubscription, subscription) {
|
||||
if (err) {
|
||||
logger.warn(
|
||||
{ err, user_id: user._id, hasSubscription },
|
||||
'there was an error checking user v2 subscription'
|
||||
)
|
||||
}
|
||||
if (hasSubscription) {
|
||||
RecurlyWrapper.cancelSubscription(
|
||||
subscription.recurlySubscription_id,
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
const emailOpts = {
|
||||
to: user.email,
|
||||
first_name: user.first_name
|
||||
}
|
||||
const ONE_HOUR_IN_MS = 1000 * 60 * 60
|
||||
setTimeout(
|
||||
() =>
|
||||
EmailHandler.sendEmail(
|
||||
'canceledSubscription',
|
||||
emailOpts,
|
||||
err => {
|
||||
if (err != null) {
|
||||
logger.warn(
|
||||
{ err },
|
||||
'failed to send confirmation email for subscription cancellation'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
ONE_HOUR_IN_MS
|
||||
)
|
||||
Analytics.recordEvent(user._id, 'subscription-canceled')
|
||||
callback()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
callback()
|
||||
),
|
||||
ONE_HOUR_IN_MS
|
||||
)
|
||||
Analytics.recordEvent(user._id, 'subscription-canceled')
|
||||
callback()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
reactivateSubscription(user, callback) {
|
||||
LimitationsManager.userHasV2Subscription(user, function(
|
||||
err,
|
||||
hasSubscription,
|
||||
subscription
|
||||
) {
|
||||
if (err) {
|
||||
logger.warn(
|
||||
{ err, user_id: user._id, hasSubscription },
|
||||
'there was an error checking user v2 subscription'
|
||||
)
|
||||
}
|
||||
if (hasSubscription) {
|
||||
RecurlyWrapper.reactivateSubscription(
|
||||
subscription.recurlySubscription_id,
|
||||
function(error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
EmailHandler.sendEmail(
|
||||
'reactivatedSubscription',
|
||||
{ to: user.email },
|
||||
err => {
|
||||
if (err != null) {
|
||||
logger.warn(
|
||||
{ err },
|
||||
'failed to send reactivation confirmation email'
|
||||
)
|
||||
}
|
||||
LimitationsManager.userHasV2Subscription(
|
||||
user,
|
||||
function (err, hasSubscription, subscription) {
|
||||
if (err) {
|
||||
logger.warn(
|
||||
{ err, user_id: user._id, hasSubscription },
|
||||
'there was an error checking user v2 subscription'
|
||||
)
|
||||
}
|
||||
if (hasSubscription) {
|
||||
RecurlyWrapper.reactivateSubscription(
|
||||
subscription.recurlySubscription_id,
|
||||
function (error) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
)
|
||||
Analytics.recordEvent(user._id, 'subscription-reactivated')
|
||||
callback()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
callback()
|
||||
EmailHandler.sendEmail(
|
||||
'reactivatedSubscription',
|
||||
{ to: user.email },
|
||||
err => {
|
||||
if (err != null) {
|
||||
logger.warn(
|
||||
{ err },
|
||||
'failed to send reactivation confirmation email'
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
Analytics.recordEvent(user._id, 'subscription-reactivated')
|
||||
callback()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
syncSubscription(recurlySubscription, requesterData, callback) {
|
||||
RecurlyWrapper.getSubscription(
|
||||
recurlySubscription.uuid,
|
||||
{ includeAccount: true },
|
||||
function(error, recurlySubscription) {
|
||||
function (error, recurlySubscription) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
User.findById(
|
||||
recurlySubscription.account.account_code,
|
||||
{ _id: 1 },
|
||||
function(error, user) {
|
||||
function (error, user) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
@@ -21,20 +21,20 @@ require('./GroupPlansData') // make sure dynamic group plans are loaded
|
||||
const SubscriptionLocator = {
|
||||
getUsersSubscription(user_or_id, callback) {
|
||||
const user_id = SubscriptionLocator._getUserId(user_or_id)
|
||||
return Subscription.findOne({ admin_id: user_id }, function(
|
||||
err,
|
||||
subscription
|
||||
) {
|
||||
logger.log({ user_id }, 'got users subscription')
|
||||
return callback(err, subscription)
|
||||
})
|
||||
return Subscription.findOne(
|
||||
{ admin_id: user_id },
|
||||
function (err, subscription) {
|
||||
logger.log({ user_id }, 'got users subscription')
|
||||
return callback(err, subscription)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
getUserIndividualSubscription(user_or_id, callback) {
|
||||
const user_id = SubscriptionLocator._getUserId(user_or_id)
|
||||
return Subscription.findOne(
|
||||
{ admin_id: user_id, groupPlan: false },
|
||||
function(err, subscription) {
|
||||
function (err, subscription) {
|
||||
logger.log({ user_id }, 'got users individual subscription')
|
||||
return callback(err, subscription)
|
||||
}
|
||||
@@ -43,7 +43,7 @@ const SubscriptionLocator = {
|
||||
|
||||
getManagedGroupSubscriptions(user_or_id, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, managedSubscriptions) {}
|
||||
callback = function (error, managedSubscriptions) {}
|
||||
}
|
||||
const user_id = SubscriptionLocator._getUserId(user_or_id)
|
||||
return Subscription.find({
|
||||
|
||||
@@ -45,37 +45,37 @@ const SubscriptionUpdater = {
|
||||
callback = requesterData
|
||||
requesterData = {}
|
||||
}
|
||||
SubscriptionLocator.getUsersSubscription(adminUserId, function(
|
||||
err,
|
||||
subscription
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
if (subscription != null) {
|
||||
SubscriptionUpdater._updateSubscriptionFromRecurly(
|
||||
recurlySubscription,
|
||||
subscription,
|
||||
requesterData,
|
||||
callback
|
||||
)
|
||||
} else {
|
||||
SubscriptionUpdater._createNewSubscription(adminUserId, function(
|
||||
err,
|
||||
subscription
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
SubscriptionLocator.getUsersSubscription(
|
||||
adminUserId,
|
||||
function (err, subscription) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
if (subscription != null) {
|
||||
SubscriptionUpdater._updateSubscriptionFromRecurly(
|
||||
recurlySubscription,
|
||||
subscription,
|
||||
requesterData,
|
||||
callback
|
||||
)
|
||||
})
|
||||
} else {
|
||||
SubscriptionUpdater._createNewSubscription(
|
||||
adminUserId,
|
||||
function (err, subscription) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
SubscriptionUpdater._updateSubscriptionFromRecurly(
|
||||
recurlySubscription,
|
||||
subscription,
|
||||
requesterData,
|
||||
callback
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
addUserToGroup(subscriptionId, userId, callback) {
|
||||
@@ -86,7 +86,7 @@ const SubscriptionUpdater = {
|
||||
SubscriptionUpdater.addUsersToGroupWithoutFeaturesRefresh(
|
||||
subscriptionId,
|
||||
memberIds,
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -104,7 +104,7 @@ const SubscriptionUpdater = {
|
||||
|
||||
removeUserFromGroups(filter, userId, callback) {
|
||||
const removeOperation = { $pull: { member_ids: userId } }
|
||||
Subscription.updateMany(filter, removeOperation, function(err) {
|
||||
Subscription.updateMany(filter, removeOperation, function (err) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'error removing user from groups', {
|
||||
filter,
|
||||
@@ -112,7 +112,7 @@ const SubscriptionUpdater = {
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
UserGetter.getUser(userId, function(error, user) {
|
||||
UserGetter.getUser(userId, function (error, user) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -130,23 +130,23 @@ const SubscriptionUpdater = {
|
||||
},
|
||||
|
||||
removeUserFromAllGroups(userId, callback) {
|
||||
SubscriptionLocator.getMemberSubscriptions(userId, function(
|
||||
error,
|
||||
subscriptions
|
||||
) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
SubscriptionLocator.getMemberSubscriptions(
|
||||
userId,
|
||||
function (error, subscriptions) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
if (!subscriptions) {
|
||||
return callback()
|
||||
}
|
||||
const subscriptionIds = subscriptions.map(sub => sub._id)
|
||||
SubscriptionUpdater.removeUserFromGroups(
|
||||
{ _id: subscriptionIds },
|
||||
userId,
|
||||
callback
|
||||
)
|
||||
}
|
||||
if (!subscriptions) {
|
||||
return callback()
|
||||
}
|
||||
const subscriptionIds = subscriptions.map(sub => sub._id)
|
||||
SubscriptionUpdater.removeUserFromGroups(
|
||||
{ _id: subscriptionIds },
|
||||
userId,
|
||||
callback
|
||||
)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
deleteWithV1Id(v1TeamId, callback) {
|
||||
@@ -155,7 +155,7 @@ const SubscriptionUpdater = {
|
||||
|
||||
deleteSubscription(subscription, deleterData, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
async.series(
|
||||
[
|
||||
@@ -178,38 +178,38 @@ const SubscriptionUpdater = {
|
||||
},
|
||||
|
||||
restoreSubscription(subscriptionId, callback) {
|
||||
SubscriptionLocator.getDeletedSubscription(subscriptionId, function(
|
||||
err,
|
||||
deletedSubscription
|
||||
) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
SubscriptionLocator.getDeletedSubscription(
|
||||
subscriptionId,
|
||||
function (err, deletedSubscription) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
let subscription = deletedSubscription.subscription
|
||||
async.series(
|
||||
[
|
||||
cb =>
|
||||
// 1. upsert subscription
|
||||
db.subscriptions.updateOne(
|
||||
{ _id: subscription._id },
|
||||
subscription,
|
||||
{ upsert: true },
|
||||
cb
|
||||
),
|
||||
cb =>
|
||||
// 2. refresh users features. Do this before removing the
|
||||
// subscription so the restore can be retried if this fails
|
||||
SubscriptionUpdater._refreshUsersFeatures(subscription, cb),
|
||||
cb =>
|
||||
// 3. remove deleted subscription
|
||||
DeletedSubscription.deleteOne(
|
||||
{ 'subscription._id': subscription._id },
|
||||
callback
|
||||
)
|
||||
],
|
||||
callback
|
||||
)
|
||||
}
|
||||
let subscription = deletedSubscription.subscription
|
||||
async.series(
|
||||
[
|
||||
cb =>
|
||||
// 1. upsert subscription
|
||||
db.subscriptions.updateOne(
|
||||
{ _id: subscription._id },
|
||||
subscription,
|
||||
{ upsert: true },
|
||||
cb
|
||||
),
|
||||
cb =>
|
||||
// 2. refresh users features. Do this before removing the
|
||||
// subscription so the restore can be retried if this fails
|
||||
SubscriptionUpdater._refreshUsersFeatures(subscription, cb),
|
||||
cb =>
|
||||
// 3. remove deleted subscription
|
||||
DeletedSubscription.deleteOne(
|
||||
{ 'subscription._id': subscription._id },
|
||||
callback
|
||||
)
|
||||
],
|
||||
callback
|
||||
)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
_refreshUsersFeatures(subscription, callback) {
|
||||
@@ -284,7 +284,7 @@ const SubscriptionUpdater = {
|
||||
})
|
||||
}
|
||||
}
|
||||
subscription.save(function(error) {
|
||||
subscription.save(function (error) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ module.exports = {
|
||||
teamManagerId,
|
||||
subscription,
|
||||
email,
|
||||
function(err, inviteUserData) {
|
||||
function (err, inviteUserData) {
|
||||
if (err != null) {
|
||||
if (err.alreadyInTeam) {
|
||||
return res.status(400).json({
|
||||
@@ -66,58 +66,58 @@ module.exports = {
|
||||
const { token } = req.params
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
|
||||
return TeamInvitesHandler.getInvite(token, function(
|
||||
err,
|
||||
invite,
|
||||
teamSubscription
|
||||
) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
|
||||
if (!invite) {
|
||||
return ErrorController.notFound(req, res, next)
|
||||
}
|
||||
|
||||
return SubscriptionLocator.getUsersSubscription(userId, function(
|
||||
err,
|
||||
personalSubscription
|
||||
) {
|
||||
return TeamInvitesHandler.getInvite(
|
||||
token,
|
||||
function (err, invite, teamSubscription) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
|
||||
const hasIndividualRecurlySubscription =
|
||||
personalSubscription != null &&
|
||||
personalSubscription.planCode.match(/(free|trial)/) == null &&
|
||||
personalSubscription.groupPlan === false &&
|
||||
personalSubscription.recurlySubscription_id != null &&
|
||||
personalSubscription.recurlySubscription_id !== ''
|
||||
if (!invite) {
|
||||
return ErrorController.notFound(req, res, next)
|
||||
}
|
||||
|
||||
return res.render('subscriptions/team/invite', {
|
||||
inviterName: invite.inviterName,
|
||||
inviteToken: invite.token,
|
||||
hasIndividualRecurlySubscription,
|
||||
appName: settings.appName,
|
||||
expired: req.query.expired
|
||||
})
|
||||
})
|
||||
})
|
||||
return SubscriptionLocator.getUsersSubscription(
|
||||
userId,
|
||||
function (err, personalSubscription) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
|
||||
const hasIndividualRecurlySubscription =
|
||||
personalSubscription != null &&
|
||||
personalSubscription.planCode.match(/(free|trial)/) == null &&
|
||||
personalSubscription.groupPlan === false &&
|
||||
personalSubscription.recurlySubscription_id != null &&
|
||||
personalSubscription.recurlySubscription_id !== ''
|
||||
|
||||
return res.render('subscriptions/team/invite', {
|
||||
inviterName: invite.inviterName,
|
||||
inviteToken: invite.token,
|
||||
hasIndividualRecurlySubscription,
|
||||
appName: settings.appName,
|
||||
expired: req.query.expired
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
acceptInvite(req, res, next) {
|
||||
const { token } = req.params
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
|
||||
return TeamInvitesHandler.acceptInvite(token, userId, function(
|
||||
err,
|
||||
results
|
||||
) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
return TeamInvitesHandler.acceptInvite(
|
||||
token,
|
||||
userId,
|
||||
function (err, results) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
return res.sendStatus(204)
|
||||
}
|
||||
return res.sendStatus(204)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
revokeInvite(req, res) {
|
||||
@@ -132,7 +132,7 @@ module.exports = {
|
||||
teamManagerId,
|
||||
subscription,
|
||||
email,
|
||||
function(err, results) {
|
||||
function (err, results) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
|
||||
@@ -20,20 +20,20 @@ const Errors = require('../Errors/Errors')
|
||||
|
||||
module.exports = TeamInvitesHandler = {
|
||||
getInvite(token, callback) {
|
||||
return Subscription.findOne({ 'teamInvites.token': token }, function(
|
||||
err,
|
||||
subscription
|
||||
) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
if (!subscription) {
|
||||
return callback(new Errors.NotFoundError('team not found'))
|
||||
}
|
||||
return Subscription.findOne(
|
||||
{ 'teamInvites.token': token },
|
||||
function (err, subscription) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
if (!subscription) {
|
||||
return callback(new Errors.NotFoundError('team not found'))
|
||||
}
|
||||
|
||||
const invite = subscription.teamInvites.find(i => i.token === token)
|
||||
callback(null, invite, subscription)
|
||||
})
|
||||
const invite = subscription.teamInvites.find(i => i.token === token)
|
||||
callback(null, invite, subscription)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
createInvite(teamManagerId, subscription, email, callback) {
|
||||
@@ -41,12 +41,12 @@ module.exports = TeamInvitesHandler = {
|
||||
if (!email) {
|
||||
return callback(new Error('invalid email'))
|
||||
}
|
||||
return UserGetter.getUser(teamManagerId, function(error, teamManager) {
|
||||
return UserGetter.getUser(teamManagerId, function (error, teamManager) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
removeLegacyInvite(subscription.id, email, function(error) {
|
||||
removeLegacyInvite(subscription.id, email, function (error) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -56,31 +56,31 @@ module.exports = TeamInvitesHandler = {
|
||||
},
|
||||
|
||||
importInvite(subscription, inviterName, email, token, sentAt, callback) {
|
||||
checkIfInviteIsPossible(subscription, email, function(
|
||||
error,
|
||||
possible,
|
||||
reason
|
||||
) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
if (!possible) {
|
||||
return callback(reason)
|
||||
}
|
||||
checkIfInviteIsPossible(
|
||||
subscription,
|
||||
email,
|
||||
function (error, possible, reason) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
if (!possible) {
|
||||
return callback(reason)
|
||||
}
|
||||
|
||||
subscription.teamInvites.push({
|
||||
email,
|
||||
inviterName,
|
||||
token,
|
||||
sentAt
|
||||
})
|
||||
subscription.teamInvites.push({
|
||||
email,
|
||||
inviterName,
|
||||
token,
|
||||
sentAt
|
||||
})
|
||||
|
||||
subscription.save(callback)
|
||||
})
|
||||
subscription.save(callback)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
acceptInvite(token, userId, callback) {
|
||||
TeamInvitesHandler.getInvite(token, function(err, invite, subscription) {
|
||||
TeamInvitesHandler.getInvite(token, function (err, invite, subscription) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -88,15 +88,17 @@ module.exports = TeamInvitesHandler = {
|
||||
return callback(new Errors.NotFoundError('invite not found'))
|
||||
}
|
||||
|
||||
SubscriptionUpdater.addUserToGroup(subscription._id, userId, function(
|
||||
err
|
||||
) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
SubscriptionUpdater.addUserToGroup(
|
||||
subscription._id,
|
||||
userId,
|
||||
function (err) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
removeInviteFromTeam(subscription.id, invite.email, callback)
|
||||
})
|
||||
removeInviteFromTeam(subscription.id, invite.email, callback)
|
||||
}
|
||||
)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -112,7 +114,7 @@ module.exports = TeamInvitesHandler = {
|
||||
// email is in Subscription.invited_emails when they join. We'll remove this
|
||||
// after a short while.
|
||||
createTeamInvitesForLegacyInvitedEmail(email, callback) {
|
||||
SubscriptionLocator.getGroupsWithEmailInvite(email, function(err, teams) {
|
||||
SubscriptionLocator.getGroupsWithEmailInvite(email, function (err, teams) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -127,81 +129,83 @@ module.exports = TeamInvitesHandler = {
|
||||
}
|
||||
}
|
||||
|
||||
var createInvite = function(subscription, email, inviter, callback) {
|
||||
checkIfInviteIsPossible(subscription, email, function(
|
||||
error,
|
||||
possible,
|
||||
reason
|
||||
) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
if (!possible) {
|
||||
return callback(reason)
|
||||
}
|
||||
|
||||
// don't send invites when inviting self; add user directly to the group
|
||||
const isInvitingSelf = inviter.emails.some(
|
||||
emailData => emailData.email === email
|
||||
)
|
||||
if (isInvitingSelf) {
|
||||
return SubscriptionUpdater.addUserToGroup(
|
||||
subscription._id,
|
||||
inviter._id,
|
||||
err => {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
// legacy: remove any invite that might have been created in the past
|
||||
removeInviteFromTeam(subscription._id, email, error => {
|
||||
const inviteUserData = {
|
||||
email: inviter.email,
|
||||
first_name: inviter.first_name,
|
||||
last_name: inviter.last_name,
|
||||
invite: false
|
||||
}
|
||||
callback(error, inviteUserData)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const inviterName = getInviterName(inviter)
|
||||
let invite = subscription.teamInvites.find(invite => invite.email === email)
|
||||
|
||||
if (invite) {
|
||||
invite.sentAt = new Date()
|
||||
} else {
|
||||
invite = {
|
||||
email,
|
||||
inviterName,
|
||||
token: crypto.randomBytes(32).toString('hex'),
|
||||
sentAt: new Date()
|
||||
}
|
||||
subscription.teamInvites.push(invite)
|
||||
}
|
||||
|
||||
subscription.save(function(error) {
|
||||
var createInvite = function (subscription, email, inviter, callback) {
|
||||
checkIfInviteIsPossible(
|
||||
subscription,
|
||||
email,
|
||||
function (error, possible, reason) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
const opts = {
|
||||
to: email,
|
||||
inviter,
|
||||
acceptInviteUrl: `${settings.siteUrl}/subscription/invites/${invite.token}/`,
|
||||
appName: settings.appName
|
||||
if (!possible) {
|
||||
return callback(reason)
|
||||
}
|
||||
EmailHandler.sendEmail('verifyEmailToJoinTeam', opts, error => {
|
||||
Object.assign(invite, { invite: true })
|
||||
callback(error, invite)
|
||||
|
||||
// don't send invites when inviting self; add user directly to the group
|
||||
const isInvitingSelf = inviter.emails.some(
|
||||
emailData => emailData.email === email
|
||||
)
|
||||
if (isInvitingSelf) {
|
||||
return SubscriptionUpdater.addUserToGroup(
|
||||
subscription._id,
|
||||
inviter._id,
|
||||
err => {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
// legacy: remove any invite that might have been created in the past
|
||||
removeInviteFromTeam(subscription._id, email, error => {
|
||||
const inviteUserData = {
|
||||
email: inviter.email,
|
||||
first_name: inviter.first_name,
|
||||
last_name: inviter.last_name,
|
||||
invite: false
|
||||
}
|
||||
callback(error, inviteUserData)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const inviterName = getInviterName(inviter)
|
||||
let invite = subscription.teamInvites.find(
|
||||
invite => invite.email === email
|
||||
)
|
||||
|
||||
if (invite) {
|
||||
invite.sentAt = new Date()
|
||||
} else {
|
||||
invite = {
|
||||
email,
|
||||
inviterName,
|
||||
token: crypto.randomBytes(32).toString('hex'),
|
||||
sentAt: new Date()
|
||||
}
|
||||
subscription.teamInvites.push(invite)
|
||||
}
|
||||
|
||||
subscription.save(function (error) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
|
||||
const opts = {
|
||||
to: email,
|
||||
inviter,
|
||||
acceptInviteUrl: `${settings.siteUrl}/subscription/invites/${invite.token}/`,
|
||||
appName: settings.appName
|
||||
}
|
||||
EmailHandler.sendEmail('verifyEmailToJoinTeam', opts, error => {
|
||||
Object.assign(invite, { invite: true })
|
||||
callback(error, invite)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var removeInviteFromTeam = function(subscriptionId, email, callback) {
|
||||
var removeInviteFromTeam = function (subscriptionId, email, callback) {
|
||||
const searchConditions = { _id: new ObjectId(subscriptionId.toString()) }
|
||||
const removeInvite = { $pull: { teamInvites: { email } } }
|
||||
|
||||
@@ -227,7 +231,7 @@ var removeLegacyInvite = (subscriptionId, email, callback) =>
|
||||
callback
|
||||
)
|
||||
|
||||
var checkIfInviteIsPossible = function(subscription, email, callback) {
|
||||
var checkIfInviteIsPossible = function (subscription, email, callback) {
|
||||
if (!subscription.groupPlan) {
|
||||
logger.log(
|
||||
{ subscriptionId: subscription.id },
|
||||
@@ -244,7 +248,7 @@ var checkIfInviteIsPossible = function(subscription, email, callback) {
|
||||
return callback(null, false, { limitReached: true })
|
||||
}
|
||||
|
||||
UserGetter.getUserByAnyEmail(email, function(error, existingUser) {
|
||||
UserGetter.getUserByAnyEmail(email, function (error, existingUser) {
|
||||
if (error) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -268,7 +272,7 @@ var checkIfInviteIsPossible = function(subscription, email, callback) {
|
||||
})
|
||||
}
|
||||
|
||||
var getInviterName = function(inviter) {
|
||||
var getInviterName = function (inviter) {
|
||||
let inviterName
|
||||
if (inviter.first_name && inviter.last_name) {
|
||||
inviterName = `${inviter.first_name} ${inviter.last_name} (${inviter.email})`
|
||||
|
||||
@@ -26,7 +26,7 @@ module.exports = V1SubscriptionManager = {
|
||||
// - 'v1_free'
|
||||
getPlanCodeFromV1(userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, planCode, v1Id) {}
|
||||
callback = function (err, planCode, v1Id) {}
|
||||
}
|
||||
return V1SubscriptionManager._v1Request(
|
||||
userId,
|
||||
@@ -36,7 +36,7 @@ module.exports = V1SubscriptionManager = {
|
||||
return `/api/v1/sharelatex/users/${v1Id}/plan_code`
|
||||
}
|
||||
},
|
||||
function(error, body, v1Id) {
|
||||
function (error, body, v1Id) {
|
||||
if (error != null) {
|
||||
return callback(error)
|
||||
}
|
||||
@@ -54,7 +54,7 @@ module.exports = V1SubscriptionManager = {
|
||||
|
||||
getSubscriptionsFromV1(userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, subscriptions, v1Id) {}
|
||||
callback = function (err, subscriptions, v1Id) {}
|
||||
}
|
||||
return V1SubscriptionManager._v1Request(
|
||||
userId,
|
||||
@@ -70,7 +70,7 @@ module.exports = V1SubscriptionManager = {
|
||||
|
||||
getSubscriptionStatusFromV1(userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, status) {}
|
||||
callback = function (err, status) {}
|
||||
}
|
||||
return V1SubscriptionManager._v1Request(
|
||||
userId,
|
||||
@@ -86,7 +86,7 @@ module.exports = V1SubscriptionManager = {
|
||||
|
||||
cancelV1Subscription(userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err) {}
|
||||
callback = function (err) {}
|
||||
}
|
||||
return V1SubscriptionManager._v1Request(
|
||||
userId,
|
||||
@@ -102,22 +102,23 @@ module.exports = V1SubscriptionManager = {
|
||||
|
||||
v1IdForUser(userId, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, v1Id) {}
|
||||
callback = function (err, v1Id) {}
|
||||
}
|
||||
return UserGetter.getUser(userId, { 'overleaf.id': 1 }, function(
|
||||
err,
|
||||
user
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
const v1Id = __guard__(
|
||||
user != null ? user.overleaf : undefined,
|
||||
x => x.id
|
||||
)
|
||||
return UserGetter.getUser(
|
||||
userId,
|
||||
{ 'overleaf.id': 1 },
|
||||
function (err, user) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
const v1Id = __guard__(
|
||||
user != null ? user.overleaf : undefined,
|
||||
x => x.id
|
||||
)
|
||||
|
||||
return callback(null, v1Id)
|
||||
})
|
||||
return callback(null, v1Id)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
// v1 accounts created before migration to v2 had github and mendeley for free
|
||||
@@ -140,13 +141,13 @@ module.exports = V1SubscriptionManager = {
|
||||
|
||||
_v1Request(userId, options, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, body, v1Id) {}
|
||||
callback = function (err, body, v1Id) {}
|
||||
}
|
||||
if (!settings.apis.v1.url) {
|
||||
return callback(null, null)
|
||||
}
|
||||
|
||||
return V1SubscriptionManager.v1IdForUser(userId, function(err, v1Id) {
|
||||
return V1SubscriptionManager.v1IdForUser(userId, function (err, v1Id) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -167,7 +168,7 @@ module.exports = V1SubscriptionManager = {
|
||||
json: true,
|
||||
timeout: 15 * 1000
|
||||
},
|
||||
function(error, response, body) {
|
||||
function (error, response, body) {
|
||||
if (error != null) {
|
||||
return callback(
|
||||
new V1ConnectionError({
|
||||
|
||||
@@ -15,28 +15,28 @@ const { SystemMessage } = require('../../models/SystemMessage')
|
||||
module.exports = SystemMessageManager = {
|
||||
getMessages(callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, messages) {}
|
||||
callback = function (error, messages) {}
|
||||
}
|
||||
callback(null, this._cachedMessages)
|
||||
},
|
||||
|
||||
getMessagesFromDB(callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error, messages) {}
|
||||
callback = function (error, messages) {}
|
||||
}
|
||||
return SystemMessage.find({}, callback)
|
||||
},
|
||||
|
||||
clearMessages(callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return SystemMessage.deleteMany({}, callback)
|
||||
},
|
||||
|
||||
createMessage(content, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
const message = new SystemMessage({ content })
|
||||
return message.save(callback)
|
||||
|
||||
@@ -7,7 +7,7 @@ const TagsController = {
|
||||
if (!userId) {
|
||||
return next(new Errors.NotFoundError())
|
||||
}
|
||||
TagsHandler.getAllTags(userId, function(error, allTags) {
|
||||
TagsHandler.getAllTags(userId, function (error, allTags) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -28,7 +28,7 @@ const TagsController = {
|
||||
createTag(req, res, next) {
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
const { name } = req.body
|
||||
TagsHandler.createTag(userId, name, function(error, tag) {
|
||||
TagsHandler.createTag(userId, name, function (error, tag) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -39,7 +39,7 @@ const TagsController = {
|
||||
addProjectToTag(req, res, next) {
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
const { tagId, projectId } = req.params
|
||||
TagsHandler.addProjectToTag(userId, tagId, projectId, function(error) {
|
||||
TagsHandler.addProjectToTag(userId, tagId, projectId, function (error) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -50,18 +50,23 @@ const TagsController = {
|
||||
removeProjectFromTag(req, res, next) {
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
const { tagId, projectId } = req.params
|
||||
TagsHandler.removeProjectFromTag(userId, tagId, projectId, function(error) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
TagsHandler.removeProjectFromTag(
|
||||
userId,
|
||||
tagId,
|
||||
projectId,
|
||||
function (error) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
res.status(204).end()
|
||||
}
|
||||
res.status(204).end()
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
deleteTag(req, res, next) {
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
const { tagId } = req.params
|
||||
TagsHandler.deleteTag(userId, tagId, function(error) {
|
||||
TagsHandler.deleteTag(userId, tagId, function (error) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
@@ -76,7 +81,7 @@ const TagsController = {
|
||||
if (!name) {
|
||||
return res.status(400).end()
|
||||
}
|
||||
TagsHandler.renameTag(userId, tagId, name, function(error) {
|
||||
TagsHandler.renameTag(userId, tagId, name, function (error) {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ function getAllTags(userId, callback) {
|
||||
|
||||
function createTag(userId, name, callback) {
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
Tag.create({ user_id: userId, name }, function(err, tag) {
|
||||
Tag.create({ user_id: userId, name }, function (err, tag) {
|
||||
// on duplicate key error return existing tag
|
||||
if (err && err.code === 11000) {
|
||||
return Tag.findOne({ user_id: userId, name }, callback)
|
||||
@@ -20,7 +20,7 @@ function createTag(userId, name, callback) {
|
||||
|
||||
function renameTag(userId, tagId, name, callback) {
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
Tag.updateOne(
|
||||
{
|
||||
@@ -38,7 +38,7 @@ function renameTag(userId, tagId, name, callback) {
|
||||
|
||||
function deleteTag(userId, tagId, callback) {
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
Tag.deleteOne(
|
||||
{
|
||||
@@ -52,7 +52,7 @@ function deleteTag(userId, tagId, callback) {
|
||||
// TODO: unused?
|
||||
function updateTagUserIds(oldUserId, newUserId, callback) {
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
const searchOps = { user_id: oldUserId }
|
||||
const updateOperation = { $set: { user_id: newUserId } }
|
||||
@@ -61,7 +61,7 @@ function updateTagUserIds(oldUserId, newUserId, callback) {
|
||||
|
||||
function removeProjectFromTag(userId, tagId, projectId, callback) {
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
const searchOps = {
|
||||
_id: tagId,
|
||||
@@ -73,7 +73,7 @@ function removeProjectFromTag(userId, tagId, projectId, callback) {
|
||||
|
||||
function addProjectToTag(userId, tagId, projectId, callback) {
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
const searchOps = {
|
||||
_id: tagId,
|
||||
@@ -85,7 +85,7 @@ function addProjectToTag(userId, tagId, projectId, callback) {
|
||||
|
||||
function addProjectToTagName(userId, name, projectId, callback) {
|
||||
if (!callback) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
const searchOps = {
|
||||
name,
|
||||
|
||||
@@ -57,7 +57,7 @@ module.exports = TemplatesController = {
|
||||
req.body.templateVersionId,
|
||||
user_id,
|
||||
req.body.imageName,
|
||||
function(err, project) {
|
||||
function (err, project) {
|
||||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
|
||||
@@ -49,11 +49,11 @@ const TemplatesManager = {
|
||||
},
|
||||
timeout: 60 * 1000
|
||||
})
|
||||
zipReq.on('error', function(err) {
|
||||
zipReq.on('error', function (err) {
|
||||
logger.warn({ err }, 'error getting zip from template API')
|
||||
return callback(err)
|
||||
})
|
||||
return FileWriter.ensureDumpFolderExists(function(err) {
|
||||
return FileWriter.ensureDumpFolderExists(function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -65,7 +65,7 @@ const TemplatesManager = {
|
||||
fromV1TemplateId: templateId,
|
||||
fromV1TemplateVersionId: templateVersionId
|
||||
}
|
||||
writeStream.on('close', function() {
|
||||
writeStream.on('close', function () {
|
||||
if (zipReq.response.statusCode !== 200) {
|
||||
logger.warn(
|
||||
{ uri: zipUrl, statusCode: zipReq.response.statusCode },
|
||||
@@ -78,7 +78,7 @@ const TemplatesManager = {
|
||||
projectName,
|
||||
dumpPath,
|
||||
attributes,
|
||||
function(err, project) {
|
||||
function (err, project) {
|
||||
if (err != null) {
|
||||
OError.tag(err, 'problem building project from zip', {
|
||||
zipReq
|
||||
@@ -97,11 +97,11 @@ const TemplatesManager = {
|
||||
cb
|
||||
)
|
||||
],
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
fs.unlink(dumpPath, function(err) {
|
||||
fs.unlink(dumpPath, function (err) {
|
||||
if (err != null) {
|
||||
return logger.err({ err }, 'error unlinking template zip')
|
||||
}
|
||||
@@ -114,7 +114,7 @@ const TemplatesManager = {
|
||||
{ _id: project._id },
|
||||
update,
|
||||
{},
|
||||
function(err) {
|
||||
function (err) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
parseParams: (parseParams = function(req) {
|
||||
parseParams: (parseParams = function (req) {
|
||||
let filePath, projectName
|
||||
let path = req.params[0]
|
||||
const userId = req.params.user_id
|
||||
|
||||
@@ -25,166 +25,173 @@ const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
|
||||
module.exports = UpdateMerger = {
|
||||
mergeUpdate(user_id, project_id, path, updateRequest, source, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return FileWriter.writeStreamToDisk(project_id, updateRequest, function(
|
||||
err,
|
||||
fsPath
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
return FileWriter.writeStreamToDisk(
|
||||
project_id,
|
||||
updateRequest,
|
||||
function (err, fsPath) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
return UpdateMerger._mergeUpdate(
|
||||
user_id,
|
||||
project_id,
|
||||
path,
|
||||
fsPath,
|
||||
source,
|
||||
mergeErr =>
|
||||
fs.unlink(fsPath, function (deleteErr) {
|
||||
if (deleteErr != null) {
|
||||
logger.err({ project_id, fsPath }, 'error deleting file')
|
||||
}
|
||||
return callback(mergeErr)
|
||||
})
|
||||
)
|
||||
}
|
||||
return UpdateMerger._mergeUpdate(
|
||||
user_id,
|
||||
project_id,
|
||||
path,
|
||||
fsPath,
|
||||
source,
|
||||
mergeErr =>
|
||||
fs.unlink(fsPath, function(deleteErr) {
|
||||
if (deleteErr != null) {
|
||||
logger.err({ project_id, fsPath }, 'error deleting file')
|
||||
}
|
||||
return callback(mergeErr)
|
||||
})
|
||||
)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
_findExistingFileType(project_id, path, callback) {
|
||||
ProjectEntityHandler.getAllEntities(project_id, function(err, docs, files) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
ProjectEntityHandler.getAllEntities(
|
||||
project_id,
|
||||
function (err, docs, files) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
var existingFileType = null
|
||||
if (_.some(files, f => f.path === path)) {
|
||||
existingFileType = 'file'
|
||||
}
|
||||
if (_.some(docs, d => d.path === path)) {
|
||||
existingFileType = 'doc'
|
||||
}
|
||||
callback(null, existingFileType)
|
||||
}
|
||||
var existingFileType = null
|
||||
if (_.some(files, f => f.path === path)) {
|
||||
existingFileType = 'file'
|
||||
}
|
||||
if (_.some(docs, d => d.path === path)) {
|
||||
existingFileType = 'doc'
|
||||
}
|
||||
callback(null, existingFileType)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
_determineFileType(project_id, path, fsPath, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(err, fileType) {}
|
||||
callback = function (err, fileType) {}
|
||||
}
|
||||
// check if there is an existing file with the same path (we either need
|
||||
// to overwrite it or delete it)
|
||||
UpdateMerger._findExistingFileType(project_id, path, function(
|
||||
err,
|
||||
existingFileType
|
||||
) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
// determine whether the update should create a doc or binary file
|
||||
FileTypeManager.getType(path, fsPath, function(
|
||||
err,
|
||||
{ binary, encoding }
|
||||
) {
|
||||
if (err != null) {
|
||||
UpdateMerger._findExistingFileType(
|
||||
project_id,
|
||||
path,
|
||||
function (err, existingFileType) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
// determine whether the update should create a doc or binary file
|
||||
FileTypeManager.getType(
|
||||
path,
|
||||
fsPath,
|
||||
function (err, { binary, encoding }) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
// If we receive a non-utf8 encoding, we won't be able to keep things in
|
||||
// sync, so we'll treat non-utf8 files as binary
|
||||
const isBinary = binary || encoding !== 'utf-8'
|
||||
// If we receive a non-utf8 encoding, we won't be able to keep things in
|
||||
// sync, so we'll treat non-utf8 files as binary
|
||||
const isBinary = binary || encoding !== 'utf-8'
|
||||
|
||||
// Existing | Update | Action
|
||||
// ---------|-----------|-------
|
||||
// file | isBinary | existing-file
|
||||
// file | !isBinary | existing-file
|
||||
// doc | isBinary | new-file, delete-existing-doc
|
||||
// doc | !isBinary | existing-doc
|
||||
// null | isBinary | new-file
|
||||
// null | !isBinary | new-doc
|
||||
// Existing | Update | Action
|
||||
// ---------|-----------|-------
|
||||
// file | isBinary | existing-file
|
||||
// file | !isBinary | existing-file
|
||||
// doc | isBinary | new-file, delete-existing-doc
|
||||
// doc | !isBinary | existing-doc
|
||||
// null | isBinary | new-file
|
||||
// null | !isBinary | new-doc
|
||||
|
||||
// if a binary file already exists, always keep it as a binary file
|
||||
// even if the update looks like a text file
|
||||
if (existingFileType === 'file') {
|
||||
return callback(null, 'existing-file')
|
||||
}
|
||||
// if a binary file already exists, always keep it as a binary file
|
||||
// even if the update looks like a text file
|
||||
if (existingFileType === 'file') {
|
||||
return callback(null, 'existing-file')
|
||||
}
|
||||
|
||||
// if there is an existing doc, keep it as a doc except when the
|
||||
// incoming update is binary. In that case delete the doc and replace
|
||||
// it with a new file.
|
||||
if (existingFileType === 'doc') {
|
||||
if (isBinary) {
|
||||
return callback(null, 'new-file', 'delete-existing-doc')
|
||||
} else {
|
||||
return callback(null, 'existing-doc')
|
||||
// if there is an existing doc, keep it as a doc except when the
|
||||
// incoming update is binary. In that case delete the doc and replace
|
||||
// it with a new file.
|
||||
if (existingFileType === 'doc') {
|
||||
if (isBinary) {
|
||||
return callback(null, 'new-file', 'delete-existing-doc')
|
||||
} else {
|
||||
return callback(null, 'existing-doc')
|
||||
}
|
||||
}
|
||||
// if there no existing file, create a file or doc as needed
|
||||
return callback(null, isBinary ? 'new-file' : 'new-doc')
|
||||
}
|
||||
}
|
||||
// if there no existing file, create a file or doc as needed
|
||||
return callback(null, isBinary ? 'new-file' : 'new-doc')
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
_mergeUpdate(user_id, project_id, path, fsPath, source, callback) {
|
||||
if (callback == null) {
|
||||
callback = function(error) {}
|
||||
callback = function (error) {}
|
||||
}
|
||||
return UpdateMerger._determineFileType(project_id, path, fsPath, function(
|
||||
err,
|
||||
fileType,
|
||||
deleteOriginalEntity
|
||||
) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
return UpdateMerger._determineFileType(
|
||||
project_id,
|
||||
path,
|
||||
fsPath,
|
||||
function (err, fileType, deleteOriginalEntity) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
async.series(
|
||||
[
|
||||
function (cb) {
|
||||
if (deleteOriginalEntity) {
|
||||
// currently we only delete docs
|
||||
UpdateMerger.deleteUpdate(user_id, project_id, path, source, cb)
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
},
|
||||
function (cb) {
|
||||
if (['existing-file', 'new-file'].includes(fileType)) {
|
||||
return UpdateMerger.p.processFile(
|
||||
project_id,
|
||||
fsPath,
|
||||
path,
|
||||
source,
|
||||
user_id,
|
||||
cb
|
||||
)
|
||||
} else if (['existing-doc', 'new-doc'].includes(fileType)) {
|
||||
return UpdateMerger.p.processDoc(
|
||||
project_id,
|
||||
user_id,
|
||||
fsPath,
|
||||
path,
|
||||
source,
|
||||
cb
|
||||
)
|
||||
} else {
|
||||
return cb(new Error('unrecognized file'))
|
||||
}
|
||||
}
|
||||
],
|
||||
callback
|
||||
)
|
||||
}
|
||||
async.series(
|
||||
[
|
||||
function(cb) {
|
||||
if (deleteOriginalEntity) {
|
||||
// currently we only delete docs
|
||||
UpdateMerger.deleteUpdate(user_id, project_id, path, source, cb)
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
},
|
||||
function(cb) {
|
||||
if (['existing-file', 'new-file'].includes(fileType)) {
|
||||
return UpdateMerger.p.processFile(
|
||||
project_id,
|
||||
fsPath,
|
||||
path,
|
||||
source,
|
||||
user_id,
|
||||
cb
|
||||
)
|
||||
} else if (['existing-doc', 'new-doc'].includes(fileType)) {
|
||||
return UpdateMerger.p.processDoc(
|
||||
project_id,
|
||||
user_id,
|
||||
fsPath,
|
||||
path,
|
||||
source,
|
||||
cb
|
||||
)
|
||||
} else {
|
||||
return cb(new Error('unrecognized file'))
|
||||
}
|
||||
}
|
||||
],
|
||||
callback
|
||||
)
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
deleteUpdate(user_id, project_id, path, source, callback) {
|
||||
if (callback == null) {
|
||||
callback = function() {}
|
||||
callback = function () {}
|
||||
}
|
||||
return EditorController.deleteEntityWithPath(
|
||||
project_id,
|
||||
path,
|
||||
source,
|
||||
user_id,
|
||||
function() {
|
||||
function () {
|
||||
return callback()
|
||||
}
|
||||
)
|
||||
@@ -192,32 +199,32 @@ module.exports = UpdateMerger = {
|
||||
|
||||
p: {
|
||||
processDoc(project_id, user_id, fsPath, path, source, callback) {
|
||||
return UpdateMerger.p.readFileIntoTextArray(fsPath, function(
|
||||
err,
|
||||
docLines
|
||||
) {
|
||||
if (err != null) {
|
||||
OError.tag(
|
||||
err,
|
||||
'error reading file into text array for process doc update',
|
||||
{
|
||||
project_id
|
||||
}
|
||||
)
|
||||
return callback(err)
|
||||
}
|
||||
logger.log({ docLines }, 'processing doc update from tpds')
|
||||
return EditorController.upsertDocWithPath(
|
||||
project_id,
|
||||
path,
|
||||
docLines,
|
||||
source,
|
||||
user_id,
|
||||
function(err) {
|
||||
return UpdateMerger.p.readFileIntoTextArray(
|
||||
fsPath,
|
||||
function (err, docLines) {
|
||||
if (err != null) {
|
||||
OError.tag(
|
||||
err,
|
||||
'error reading file into text array for process doc update',
|
||||
{
|
||||
project_id
|
||||
}
|
||||
)
|
||||
return callback(err)
|
||||
}
|
||||
)
|
||||
})
|
||||
logger.log({ docLines }, 'processing doc update from tpds')
|
||||
return EditorController.upsertDocWithPath(
|
||||
project_id,
|
||||
path,
|
||||
docLines,
|
||||
source,
|
||||
user_id,
|
||||
function (err) {
|
||||
return callback(err)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
processFile(project_id, fsPath, path, source, user_id, callback) {
|
||||
@@ -228,14 +235,14 @@ module.exports = UpdateMerger = {
|
||||
null,
|
||||
source,
|
||||
user_id,
|
||||
function(err) {
|
||||
function (err) {
|
||||
return callback(err)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
readFileIntoTextArray(path, callback) {
|
||||
return fs.readFile(path, 'utf8', function(error, content) {
|
||||
return fs.readFile(path, 'utf8', function (error, content) {
|
||||
if (content == null) {
|
||||
content = ''
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ const TokenAccessHandler = {
|
||||
{
|
||||
'tokens.readAndWritePrefix': numerics
|
||||
},
|
||||
function(err, project) {
|
||||
function (err, project) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -263,7 +263,7 @@ const TokenAccessHandler = {
|
||||
}
|
||||
V1Api.request(
|
||||
{ url: `/api/v1/sharelatex/docs/${token}/is_published` },
|
||||
function(err, response, body) {
|
||||
function (err, response, body) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -279,7 +279,7 @@ const TokenAccessHandler = {
|
||||
exported: false
|
||||
})
|
||||
}
|
||||
UserGetter.getUser(v2UserId, { overleaf: 1 }, function(err, user) {
|
||||
UserGetter.getUser(v2UserId, { overleaf: 1 }, function (err, user) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
@@ -289,7 +289,7 @@ const TokenAccessHandler = {
|
||||
}
|
||||
V1Api.request(
|
||||
{ url: `/api/v1/sharelatex/users/${v1UserId}/docs/${token}/info` },
|
||||
function(err, response, body) {
|
||||
function (err, response, body) {
|
||||
if (err != null) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user