Merge pull request #3495 from overleaf/ae-prettier-2

Upgrade Prettier to v2

GitOrigin-RevId: 85aa3fa1acb6332c4f58c46165a43d1a51471f33
This commit is contained in:
Alf Eaton
2021-04-14 14:17:21 +01:00
committed by Copybot
parent 930d7ba028
commit 1ebc8a79cb
582 changed files with 20382 additions and 20374 deletions

View File

@@ -5,3 +5,4 @@ frontend/js/vendor
modules/**/frontend/js/vendor modules/**/frontend/js/vendor
public/js public/js
public/minjs public/minjs
frontend/stylesheets/components/nvd3.less

View File

@@ -45,7 +45,7 @@ if (!module.parent) {
} }
Promise.all([mongodb.waitForDb(), mongoose.connectionPromise]) Promise.all([mongodb.waitForDb(), mongoose.connectionPromise])
.then(() => { .then(() => {
Server.server.listen(port, host, function() { Server.server.listen(port, host, function () {
logger.info(`web starting up, listening on ${host}:${port}`) logger.info(`web starting up, listening on ${host}:${port}`)
logger.info(`${require('http').globalAgent.maxSockets} sockets enabled`) logger.info(`${require('http').globalAgent.maxSockets} sockets enabled`)
// wait until the process is ready before monitoring the event loop // 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 // 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') logger.warn({ signal: signal }, 'received signal, shutting down')
Settings.shuttingDown = true Settings.shuttingDown = true
}) })

View File

@@ -15,7 +15,7 @@ module.exports = {
let countryCode = null let countryCode = null
if (userId) { if (userId) {
GeoIpLookup.getDetails(req.ip, function(err, geoDetails) { GeoIpLookup.getDetails(req.ip, function (err, geoDetails) {
if (err) { if (err) {
metrics.inc('analytics_geo_ip_lookup_errors') metrics.inc('analytics_geo_ip_lookup_errors')
} else if (geoDetails && geoDetails.country_code) { } else if (geoDetails && geoDetails.country_code) {
@@ -43,7 +43,7 @@ module.exports = {
req.query.start_date, req.query.start_date,
req.query.end_date, req.query.end_date,
req.query.lag, req.query.lag,
function(error, licences) { function (error, licences) {
if (error) { if (error) {
return next(error) return next(error)
} }
@@ -58,7 +58,7 @@ module.exports = {
req.query.start_date, req.query.start_date,
req.query.end_date, req.query.end_date,
req.query.lag, req.query.lag,
function(error, licences) { function (error, licences) {
if (error) { if (error) {
return next(error) return next(error)
} }

View File

@@ -58,7 +58,7 @@ const AuthenticationController = {
// This function is middleware which wraps the passport.authenticate middleware, // This function is middleware which wraps the passport.authenticate middleware,
// so we can send back our custom `{message: {text: "", type: ""}}` responses on failure, // so we can send back our custom `{message: {text: "", type: ""}}` responses on failure,
// and send a `{redir: ""}` response on success // and send a `{redir: ""}` response on success
passport.authenticate('local', function(err, user, info) { passport.authenticate('local', function (err, user, info) {
if (err) { if (err) {
return next(err) return next(err)
} }
@@ -81,86 +81,96 @@ const AuthenticationController = {
} // OAuth2 'state' mismatch } // OAuth2 'state' mismatch
const Modules = require('../../infrastructure/Modules') const Modules = require('../../infrastructure/Modules')
Modules.hooks.fire('preFinishLogin', req, res, user, function( Modules.hooks.fire(
error, 'preFinishLogin',
results req,
) { res,
if (error) { user,
return next(error) function (error, results) {
} if (error) {
if (results.some(result => result && result.doNotFinish)) { return next(error)
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)
} }
_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) { if (err) {
return next(err) return next(err)
} }
AuthenticationController._clearRedirectFromSession(req) _afterLoginSessionSetup(req, user, function (err) {
AsyncFormHelper.redirect(req, res, redir) if (err) {
return next(err)
}
AuthenticationController._clearRedirectFromSession(req)
AsyncFormHelper.redirect(req, res, redir)
})
}) })
}) }
}) )
}, },
doPassportLogin(req, username, password, done) { doPassportLogin(req, username, password, done) {
const email = username.toLowerCase() const email = username.toLowerCase()
const Modules = require('../../infrastructure/Modules') const Modules = require('../../infrastructure/Modules')
Modules.hooks.fire('preDoPassportLogin', req, email, function( Modules.hooks.fire(
err, 'preDoPassportLogin',
infoList req,
) { email,
if (err) { function (err, infoList) {
return done(err)
}
const info = infoList.find(i => i != null)
if (info != null) {
return done(null, false, info)
}
LoginRateLimiter.processLoginRequest(email, function(err, isAllowed) {
if (err) { if (err) {
return done(err) return done(err)
} }
if (!isAllowed) { const info = infoList.find(i => i != null)
logger.log({ email }, 'too many login requests') if (info != null) {
return done(null, null, { return done(null, false, info)
text: req.i18n.translate('to_many_login_requests_2_mins'),
type: 'error'
})
} }
AuthenticationManager.authenticate({ email }, password, function( LoginRateLimiter.processLoginRequest(email, function (err, isAllowed) {
error, if (err) {
user return done(err)
) {
if (error != null) {
return done(error)
} }
if (user != null) { if (!isAllowed) {
// async actions logger.log({ email }, 'too many login requests')
done(null, user) return done(null, null, {
} else { text: req.i18n.translate('to_many_login_requests_2_mins'),
AuthenticationController._recordFailedLogin()
logger.log({ email }, 'failed log in')
done(null, false, {
text: req.i18n.translate('email_or_password_wrong_try_again'),
type: 'error' 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) { ipMatchCheck(req, user) {
@@ -215,9 +225,9 @@ const AuthenticationController = {
}, },
requireLogin() { requireLogin() {
const doRequest = function(req, res, next) { const doRequest = function (req, res, next) {
if (next == null) { if (next == null) {
next = function() {} next = function () {}
} }
if (!AuthenticationController.isUserLoggedIn(req)) { if (!AuthenticationController.isUserLoggedIn(req)) {
if (acceptsJson(req)) return send401WithChallenge(res) if (acceptsJson(req)) return send401WithChallenge(res)
@@ -234,45 +244,47 @@ const AuthenticationController = {
requireOauth() { requireOauth() {
// require this here because module may not be included in some versions // require this here because module may not be included in some versions
const Oauth2Server = require('../../../../modules/oauth2-server/app/src/Oauth2Server') const Oauth2Server = require('../../../../modules/oauth2-server/app/src/Oauth2Server')
return function(req, res, next) { return function (req, res, next) {
if (next == null) { if (next == null) {
next = function() {} next = function () {}
} }
const request = new Oauth2Server.Request(req) const request = new Oauth2Server.Request(req)
const response = new Oauth2Server.Response(res) const response = new Oauth2Server.Response(res)
return Oauth2Server.server.authenticate(request, response, {}, function( return Oauth2Server.server.authenticate(
err, request,
token response,
) { {},
if (err) { function (err, token) {
// use a 401 status code for malformed header for git-bridge if (err) {
if ( // use a 401 status code for malformed header for git-bridge
err.code === 400 && if (
err.message === 'Invalid request: malformed authorization header' err.code === 400 &&
) { err.message === 'Invalid request: malformed authorization header'
err.code = 401 ) {
err.code = 401
}
// send all other errors
return res
.status(err.code)
.json({ error: err.name, error_description: err.message })
} }
// send all other errors req.oauth = { access_token: token.accessToken }
return res req.oauth_token = token
.status(err.code) req.oauth_user = token.user
.json({ error: err.name, error_description: err.message }) 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, // 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 // 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 // exceeded a maximum lifetime (req.session.session_created), or for session
// hijacking checks (e.g. change of ip address, req.session.ip_address). For // 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 // now, just check that the session has been loaded from the session store
// correctly. // correctly.
return function(req, res, next) { return function (req, res, next) {
// check that the session store is returning valid results // check that the session store is returning valid results
if (req.session && !SessionStoreManager.hasValidationToken(req)) { if (req.session && !SessionStoreManager.hasValidationToken(req)) {
// force user to update session // force user to update session
@@ -349,7 +361,7 @@ const AuthenticationController = {
return next() return next()
}, },
httpAuth: basicAuth(function(user, pass) { httpAuth: basicAuth(function (user, pass) {
let expectedPassword = Settings.httpAuthUsers[user] let expectedPassword = Settings.httpAuthUsers[user]
const isValid = const isValid =
expectedPassword && expectedPassword &&
@@ -424,7 +436,7 @@ const AuthenticationController = {
_recordSuccessfulLogin(userId, callback) { _recordSuccessfulLogin(userId, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
UserUpdater.updateUser( UserUpdater.updateUser(
userId.toString(), userId.toString(),
@@ -432,7 +444,7 @@ const AuthenticationController = {
$set: { lastLoggedIn: new Date() }, $set: { lastLoggedIn: new Date() },
$inc: { loginCount: 1 } $inc: { loginCount: 1 }
}, },
function(error) { function (error) {
if (error != null) { if (error != null) {
callback(error) callback(error)
} }
@@ -465,9 +477,9 @@ const AuthenticationController = {
function _afterLoginSessionSetup(req, user, callback) { function _afterLoginSessionSetup(req, user, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
req.login(user, function(err) { req.login(user, function (err) {
if (err) { if (err) {
OError.tag(err, 'error from req.login', { OError.tag(err, 'error from req.login', {
user_id: user._id user_id: user._id
@@ -477,7 +489,7 @@ function _afterLoginSessionSetup(req, user, callback) {
// Regenerate the session to get a new sessionID (cookie value) to // Regenerate the session to get a new sessionID (cookie value) to
// protect against session fixation attacks // protect against session fixation attacks
const oldSession = req.session const oldSession = req.session
req.session.destroy(function(err) { req.session.destroy(function (err) {
if (err) { if (err) {
OError.tag(err, 'error when trying to destroy old session', { OError.tag(err, 'error when trying to destroy old session', {
user_id: user._id user_id: user._id
@@ -493,14 +505,14 @@ function _afterLoginSessionSetup(req, user, callback) {
req.session[key] = value req.session[key] = value
} }
} }
req.session.save(function(err) { req.session.save(function (err) {
if (err) { if (err) {
OError.tag(err, 'error saving regenerated session after login', { OError.tag(err, 'error saving regenerated session after login', {
user_id: user._id user_id: user._id
}) })
return callback(err) return callback(err)
} }
UserSessionsManager.trackSession(user, req.sessionID, function() {}) UserSessionsManager.trackSession(user, req.sessionID, function () {})
callback(null) callback(null)
}) })
}) })

View File

@@ -12,7 +12,7 @@ const util = require('util')
const BCRYPT_ROUNDS = Settings.security.bcryptRounds || 12 const BCRYPT_ROUNDS = Settings.security.bcryptRounds || 12
const BCRYPT_MINOR_VERSION = Settings.security.bcryptMinorVersion || 'a' const BCRYPT_MINOR_VERSION = Settings.security.bcryptMinorVersion || 'a'
const _checkWriteResult = function(result, callback) { const _checkWriteResult = function (result, callback) {
// for MongoDB // for MongoDB
if (result && result.modifiedCount === 1) { if (result && result.modifiedCount === 1) {
callback(null, true) callback(null, true)
@@ -33,7 +33,7 @@ const AuthenticationManager = {
if (!user || !user.hashedPassword) { if (!user || !user.hashedPassword) {
return callback(null, null) return callback(null, null)
} }
bcrypt.compare(password, user.hashedPassword, function(error, match) { bcrypt.compare(password, user.hashedPassword, function (error, match) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -44,7 +44,7 @@ const AuthenticationManager = {
user, user,
user.hashedPassword, user.hashedPassword,
password, password,
function(err) { function (err) {
if (err) { if (err) {
return callback(err) return callback(err)
} }
@@ -146,7 +146,7 @@ const AuthenticationManager = {
}, },
hashPassword(password, callback) { 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) { if (error) {
return callback(error) return callback(error)
} }
@@ -162,7 +162,7 @@ const AuthenticationManager = {
if (validationError) { if (validationError) {
return callback(validationError) return callback(validationError)
} }
this.hashPassword(password, function(error, hash) { this.hashPassword(password, function (error, hash) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -178,7 +178,7 @@ const AuthenticationManager = {
password: true password: true
} }
}, },
function(updateError, result) { function (updateError, result) {
if (updateError) { if (updateError) {
return callback(updateError) return callback(updateError)
} }

View File

@@ -54,20 +54,21 @@ const AuthorizationManager = {
return callback(new Error('invalid project id')) return callback(new Error('invalid project id'))
} }
// Note, the Project property in the DB is `publicAccesLevel`, without the second `s` // Note, the Project property in the DB is `publicAccesLevel`, without the second `s`
ProjectGetter.getProject(projectId, { publicAccesLevel: 1 }, function( ProjectGetter.getProject(
error, projectId,
project { publicAccesLevel: 1 },
) { function (error, project) {
if (error) { if (error) {
return callback(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 // 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 // User is present, get their privilege level from database
getPrivilegeLevelForProjectWithUser(userId, projectId, token, callback) { getPrivilegeLevelForProjectWithUser(userId, projectId, token, callback) {
CollaboratorsGetter.getMemberIdPrivilegeLevel(userId, projectId, function( CollaboratorsGetter.getMemberIdPrivilegeLevel(
error, userId,
privilegeLevel 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) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
if (isAdmin) { if (privilegeLevel && privilegeLevel !== PrivilegeLevels.NONE) {
return callback(null, PrivilegeLevels.OWNER, false, true) // The user has direct access
return callback(null, privilegeLevel, false, false)
} }
// Legacy public-access system AuthorizationManager.isUserSiteAdmin(userId, function (error, isAdmin) {
// User is present (not anonymous), but does not have direct access if (error) {
AuthorizationManager.getPublicAccessLevel(projectId, function( return callback(error)
err,
publicAccessLevel
) {
if (err) {
return callback(err)
} }
if (publicAccessLevel === PublicAccessLevels.READ_ONLY) { if (isAdmin) {
return callback(null, PrivilegeLevels.READ_ONLY, true, false) return callback(null, PrivilegeLevels.OWNER, false, true)
} }
if (publicAccessLevel === PublicAccessLevels.READ_AND_WRITE) { // Legacy public-access system
return callback(null, PrivilegeLevels.READ_AND_WRITE, true, false) // User is present (not anonymous), but does not have direct access
} AuthorizationManager.getPublicAccessLevel(
callback(null, PrivilegeLevels.NONE, false, false) 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 // User is Anonymous, Try Token-based access
getPrivilegeLevelForProjectWithoutUser(projectId, token, callback) { getPrivilegeLevelForProjectWithoutUser(projectId, token, callback) {
AuthorizationManager.getPublicAccessLevel(projectId, function( AuthorizationManager.getPublicAccessLevel(
err, projectId,
publicAccessLevel function (err, publicAccessLevel) {
) { if (err) {
if (err) { return callback(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) { getPrivilegeLevelForProjectWithToken(projectId, token, callback) {
@@ -170,7 +177,7 @@ const AuthorizationManager = {
TokenAccessHandler.validateTokenForAnonymousAccess( TokenAccessHandler.validateTokenForAnonymousAccess(
projectId, projectId,
token, token,
function(err, isValidReadAndWrite, isValidReadOnly) { function (err, isValidReadAndWrite, isValidReadOnly) {
if (err) { if (err) {
return callback(err) return callback(err)
} }
@@ -193,7 +200,7 @@ const AuthorizationManager = {
userId, userId,
projectId, projectId,
token, token,
function(error, privilegeLevel) { function (error, privilegeLevel) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -214,7 +221,7 @@ const AuthorizationManager = {
userId, userId,
projectId, projectId,
token, token,
function(error, privilegeLevel) { function (error, privilegeLevel) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -233,7 +240,7 @@ const AuthorizationManager = {
userId, userId,
projectId, projectId,
token, token,
function(error, privilegeLevel, becausePublic) { function (error, privilegeLevel, becausePublic) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -256,7 +263,7 @@ const AuthorizationManager = {
userId, userId,
projectId, projectId,
token, token,
function(error, privilegeLevel, becausePublic, becauseSiteAdmin) { function (error, privilegeLevel, becausePublic, becauseSiteAdmin) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -273,7 +280,7 @@ const AuthorizationManager = {
if (!userId) { if (!userId) {
return callback(null, false) return callback(null, false)
} }
User.findOne({ _id: userId }, { isAdmin: 1 }, function(error, user) { User.findOne({ _id: userId }, { isAdmin: 1 }, function (error, user) {
if (error) { if (error) {
return callback(error) return callback(error)
} }

View File

@@ -11,7 +11,7 @@ const TokenAccessHandler = require('../TokenAccess/TokenAccessHandler')
module.exports = AuthorizationMiddleware = { module.exports = AuthorizationMiddleware = {
ensureUserCanReadMultipleProjects(req, res, next) { ensureUserCanReadMultipleProjects(req, res, next) {
const projectIds = (req.query.project_ids || '').split(',') const projectIds = (req.query.project_ids || '').split(',')
AuthorizationMiddleware._getUserId(req, function(error, userId) { AuthorizationMiddleware._getUserId(req, function (error, userId) {
if (error) { if (error) {
return next(error) return next(error)
} }
@@ -19,13 +19,13 @@ module.exports = AuthorizationMiddleware = {
// errors in callbacks // errors in callbacks
async.rejectSeries( async.rejectSeries(
projectIds, projectIds,
function(projectId, cb) { function (projectId, cb) {
const token = TokenAccessHandler.getRequestToken(req, projectId) const token = TokenAccessHandler.getRequestToken(req, projectId)
AuthorizationManager.canUserReadProject( AuthorizationManager.canUserReadProject(
userId, userId,
projectId, projectId,
token, token,
function(error, canRead) { function (error, canRead) {
if (error) { if (error) {
return next(error) return next(error)
} }
@@ -33,7 +33,7 @@ module.exports = AuthorizationMiddleware = {
} }
) )
}, },
function(unauthorizedProjectIds) { function (unauthorizedProjectIds) {
if (unauthorizedProjectIds.length > 0) { if (unauthorizedProjectIds.length > 0) {
return AuthorizationMiddleware.redirectToRestricted(req, res, next) return AuthorizationMiddleware.redirectToRestricted(req, res, next)
} }
@@ -44,178 +44,173 @@ module.exports = AuthorizationMiddleware = {
}, },
blockRestrictedUserFromProject(req, res, next) { blockRestrictedUserFromProject(req, res, next) {
AuthorizationMiddleware._getUserAndProjectId(req, function( AuthorizationMiddleware._getUserAndProjectId(
error, req,
userId, function (error, userId, projectId) {
projectId if (error) {
) { return next(error)
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()
} }
) 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) { ensureUserCanReadProject(req, res, next) {
AuthorizationMiddleware._getUserAndProjectId(req, function( AuthorizationMiddleware._getUserAndProjectId(
error, req,
userId, function (error, userId, projectId) {
projectId if (error) {
) { return next(error)
if (error) { }
return next(error) const token = TokenAccessHandler.getRequestToken(req, projectId)
} AuthorizationManager.canUserReadProject(
const token = TokenAccessHandler.getRequestToken(req, projectId) userId,
AuthorizationManager.canUserReadProject( projectId,
userId, token,
projectId, function (error, canRead) {
token, if (error) {
function(error, canRead) { return next(error)
if (error) { }
return next(error) if (canRead) {
} logger.log(
if (canRead) { { userId, projectId },
'allowing user read access to project'
)
return next()
}
logger.log( logger.log(
{ userId, projectId }, { 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) { ensureUserCanWriteProjectSettings(req, res, next) {
AuthorizationMiddleware._getUserAndProjectId(req, function( AuthorizationMiddleware._getUserAndProjectId(
error, req,
userId, function (error, userId, projectId) {
projectId if (error) {
) { return next(error)
if (error) { }
return next(error) const token = TokenAccessHandler.getRequestToken(req, projectId)
} AuthorizationManager.canUserWriteProjectSettings(
const token = TokenAccessHandler.getRequestToken(req, projectId) userId,
AuthorizationManager.canUserWriteProjectSettings( projectId,
userId, token,
projectId, function (error, canWrite) {
token, if (error) {
function(error, canWrite) { return next(error)
if (error) { }
return next(error) if (canWrite) {
} logger.log(
if (canWrite) { { userId, projectId },
'allowing user write access to project settings'
)
return next()
}
logger.log( logger.log(
{ userId, projectId }, { 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) { ensureUserCanWriteProjectContent(req, res, next) {
AuthorizationMiddleware._getUserAndProjectId(req, function( AuthorizationMiddleware._getUserAndProjectId(
error, req,
userId, function (error, userId, projectId) {
projectId if (error) {
) { return next(error)
if (error) { }
return next(error) const token = TokenAccessHandler.getRequestToken(req, projectId)
} AuthorizationManager.canUserWriteProjectContent(
const token = TokenAccessHandler.getRequestToken(req, projectId) userId,
AuthorizationManager.canUserWriteProjectContent( projectId,
userId, token,
projectId, function (error, canWrite) {
token, if (error) {
function(error, canWrite) { return next(error)
if (error) { }
return next(error) if (canWrite) {
} logger.log(
if (canWrite) { { userId, projectId },
'allowing user write access to project content'
)
return next()
}
logger.log( logger.log(
{ userId, projectId }, { 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) { ensureUserCanAdminProject(req, res, next) {
AuthorizationMiddleware._getUserAndProjectId(req, function( AuthorizationMiddleware._getUserAndProjectId(
error, req,
userId, function (error, userId, projectId) {
projectId if (error) {
) { return next(error)
if (error) { }
return next(error) const token = TokenAccessHandler.getRequestToken(req, projectId)
} AuthorizationManager.canUserAdminProject(
const token = TokenAccessHandler.getRequestToken(req, projectId) userId,
AuthorizationManager.canUserAdminProject( projectId,
userId, token,
projectId, function (error, canAdmin) {
token, if (error) {
function(error, canAdmin) { return next(error)
if (error) { }
return next(error) if (canAdmin) {
} logger.log(
if (canAdmin) { { userId, projectId },
'allowing user admin access to project'
)
return next()
}
logger.log( logger.log(
{ userId, projectId }, { 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) { ensureUserIsSiteAdmin(req, res, next) {
AuthorizationMiddleware._getUserId(req, function(error, userId) { AuthorizationMiddleware._getUserId(req, function (error, userId) {
if (error) { if (error) {
return next(error) return next(error)
} }
AuthorizationManager.isUserSiteAdmin(userId, function(error, isAdmin) { AuthorizationManager.isUserSiteAdmin(userId, function (error, isAdmin) {
if (error) { if (error) {
return next(error) return next(error)
} }
@@ -239,7 +234,7 @@ module.exports = AuthorizationMiddleware = {
new Errors.NotFoundError(`invalid projectId: ${projectId}`) new Errors.NotFoundError(`invalid projectId: ${projectId}`)
) )
} }
AuthorizationMiddleware._getUserId(req, function(error, userId) { AuthorizationMiddleware._getUserId(req, function (error, userId) {
if (error) { if (error) {
return callback(error) return callback(error)
} }

View File

@@ -12,7 +12,7 @@ const BetaProgramController = {
if (userId == null) { if (userId == null) {
return next(new Error('no user id in session')) return next(new Error('no user id in session'))
} }
BetaProgramHandler.optIn(userId, function(err) { BetaProgramHandler.optIn(userId, function (err) {
if (err) { if (err) {
return next(err) return next(err)
} }
@@ -26,7 +26,7 @@ const BetaProgramController = {
if (userId == null) { if (userId == null) {
return next(new Error('no user id in session')) return next(new Error('no user id in session'))
} }
BetaProgramHandler.optOut(userId, function(err) { BetaProgramHandler.optOut(userId, function (err) {
if (err) { if (err) {
return next(err) return next(err)
} }
@@ -37,7 +37,7 @@ const BetaProgramController = {
optInPage(req, res, next) { optInPage(req, res, next) {
const userId = AuthenticationController.getLoggedInUserId(req) const userId = AuthenticationController.getLoggedInUserId(req)
logger.log({ user_id: userId }, 'showing beta participation page for user') 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) { if (err) {
OError.tag(err, 'error fetching user', { OError.tag(err, 'error fetching user', {
userId userId

View File

@@ -22,7 +22,7 @@ const V1Api = require('../V1/V1Api')
module.exports = BrandVariationsHandler = { module.exports = BrandVariationsHandler = {
getBrandVariationById(brandVariationId, callback) { getBrandVariationById(brandVariationId, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, brandVariationDetails) {} callback = function (error, brandVariationDetails) {}
} }
if (brandVariationId == null || brandVariationId === '') { if (brandVariationId == null || brandVariationId === '') {
return callback(new Error('Branding variation id not provided')) return callback(new Error('Branding variation id not provided'))
@@ -32,7 +32,7 @@ module.exports = BrandVariationsHandler = {
{ {
uri: `/api/v2/brand_variations/${brandVariationId}` uri: `/api/v2/brand_variations/${brandVariationId}`
}, },
function(error, response, brandVariationDetails) { function (error, response, brandVariationDetails) {
if (error != null) { if (error != null) {
OError.tag(error, 'error getting brand variation details', { OError.tag(error, 'error getting brand variation details', {
brandVariationId brandVariationId
@@ -46,7 +46,7 @@ module.exports = BrandVariationsHandler = {
} }
} }
var _formatBrandVariationDetails = function(details) { var _formatBrandVariationDetails = function (details) {
if (details.export_url != null) { if (details.export_url != null) {
details.export_url = _setV1AsHostIfRelativeURL(details.export_url) details.export_url = _setV1AsHostIfRelativeURL(details.export_url)
} }

View File

@@ -17,7 +17,7 @@ const Settings = require('settings-sharelatex')
module.exports = CaptchaMiddleware = { module.exports = CaptchaMiddleware = {
validateCaptcha(action) { validateCaptcha(action) {
return function(req, res, next) { return function (req, res, next) {
if ( if (
(Settings.recaptcha != null ? Settings.recaptcha.siteKey : undefined) == (Settings.recaptcha != null ? Settings.recaptcha.siteKey : undefined) ==
null null
@@ -42,7 +42,7 @@ module.exports = CaptchaMiddleware = {
return request.post( return request.post(
'https://www.google.com/recaptcha/api/siteverify', 'https://www.google.com/recaptcha/api/siteverify',
options, options,
function(error, response, body) { function (error, response, body) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }

View File

@@ -19,9 +19,9 @@ const settings = require('settings-sharelatex')
module.exports = ChatApiHandler = { module.exports = ChatApiHandler = {
_apiRequest(opts, callback) { _apiRequest(opts, callback) {
if (callback == null) { 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) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -71,7 +71,7 @@ module.exports = ChatApiHandler = {
sendComment(project_id, thread_id, user_id, content, callback) { sendComment(project_id, thread_id, user_id, content, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return ChatApiHandler._apiRequest( return ChatApiHandler._apiRequest(
{ {
@@ -85,7 +85,7 @@ module.exports = ChatApiHandler = {
getThreads(project_id, callback) { getThreads(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return ChatApiHandler._apiRequest( return ChatApiHandler._apiRequest(
{ {
@@ -99,7 +99,7 @@ module.exports = ChatApiHandler = {
resolveThread(project_id, thread_id, user_id, callback) { resolveThread(project_id, thread_id, user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return ChatApiHandler._apiRequest( return ChatApiHandler._apiRequest(
{ {
@@ -113,7 +113,7 @@ module.exports = ChatApiHandler = {
reopenThread(project_id, thread_id, callback) { reopenThread(project_id, thread_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return ChatApiHandler._apiRequest( return ChatApiHandler._apiRequest(
{ {
@@ -126,7 +126,7 @@ module.exports = ChatApiHandler = {
deleteThread(project_id, thread_id, callback) { deleteThread(project_id, thread_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return ChatApiHandler._apiRequest( return ChatApiHandler._apiRequest(
{ {
@@ -139,7 +139,7 @@ module.exports = ChatApiHandler = {
editMessage(project_id, thread_id, message_id, content, callback) { editMessage(project_id, thread_id, message_id, content, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return ChatApiHandler._apiRequest( return ChatApiHandler._apiRequest(
{ {
@@ -155,7 +155,7 @@ module.exports = ChatApiHandler = {
deleteMessage(project_id, thread_id, message_id, callback) { deleteMessage(project_id, thread_id, message_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return ChatApiHandler._apiRequest( return ChatApiHandler._apiRequest(
{ {

View File

@@ -36,25 +36,25 @@ module.exports = ChatController = {
project_id, project_id,
user_id, user_id,
content, content,
function(err, message) { function (err, message) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} }
return UserInfoManager.getPersonalInfo(message.user_id, function( return UserInfoManager.getPersonalInfo(
err, message.user_id,
user function (err, user) {
) { if (err != null) {
if (err != null) { return next(err)
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, project_id,
query.limit, query.limit,
query.before, query.before,
function(err, messages) { function (err, messages) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} }
return ChatController._injectUserInfoIntoThreads( return ChatController._injectUserInfoIntoThreads(
{ global: { messages } }, { global: { messages } },
function(err) { function (err) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} }
@@ -89,7 +89,7 @@ module.exports = ChatController = {
// user fields // user fields
let message, thread, thread_id, user_id let message, thread, thread_id, user_id
if (callback == null) { if (callback == null) {
callback = function(error, threads) {} callback = function (error, threads) {}
} }
const user_ids = {} const user_ids = {}
for (thread_id in threads) { for (thread_id in threads) {
@@ -108,7 +108,7 @@ module.exports = ChatController = {
const _ = user_ids[user_id] const _ = user_ids[user_id]
;(user_id => ;(user_id =>
jobs.push(cb => jobs.push(cb =>
UserInfoManager.getPersonalInfo(user_id, function(error, user) { UserInfoManager.getPersonalInfo(user_id, function (error, user) {
if (error != null) return cb(error) if (error != null) return cb(error)
user = UserInfoController.formatPersonalInfo(user) user = UserInfoController.formatPersonalInfo(user)
users[user_id] = user users[user_id] = user
@@ -117,7 +117,7 @@ module.exports = ChatController = {
))(user_id) ))(user_id)
} }
return async.series(jobs, function(error) { return async.series(jobs, function (error) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }

View File

@@ -30,7 +30,7 @@ module.exports = CollaboratorsEmailHandler = {
return Project.findOne({ _id: project_id }) return Project.findOne({ _id: project_id })
.select('name owner_ref') .select('name owner_ref')
.populate('owner_ref') .populate('owner_ref')
.exec(function(err, project) { .exec(function (err, project) {
const emailOptions = { const emailOptions = {
to: email, to: email,
replyTo: project.owner_ref.email, replyTo: project.owner_ref.email,

View File

@@ -31,37 +31,38 @@ module.exports = CollaboratorsInviteController = {
getAllInvites(req, res, next) { getAllInvites(req, res, next) {
const projectId = req.params.Project_id const projectId = req.params.Project_id
logger.log({ projectId }, 'getting all active invites for project') logger.log({ projectId }, 'getting all active invites for project')
return CollaboratorsInviteHandler.getAllInvites(projectId, function( return CollaboratorsInviteHandler.getAllInvites(
err, projectId,
invites function (err, invites) {
) { if (err != null) {
if (err != null) { OError.tag(err, 'error getting invites for project', {
OError.tag(err, 'error getting invites for project', { projectId
projectId })
}) return next(err)
return next(err) }
return res.json({ invites })
} }
return res.json({ invites }) )
})
}, },
_checkShouldInviteEmail(email, callback) { _checkShouldInviteEmail(email, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, shouldAllowInvite) {} callback = function (err, shouldAllowInvite) {}
} }
if (Settings.restrictInvitesToExistingAccounts === true) { if (Settings.restrictInvitesToExistingAccounts === true) {
logger.log({ email }, 'checking if user exists with this email') logger.log({ email }, 'checking if user exists with this email')
return UserGetter.getUserByAnyEmail(email, { _id: 1 }, function( return UserGetter.getUserByAnyEmail(
err, email,
user { _id: 1 },
) { function (err, user) {
if (err != null) { if (err != null) {
return callback(err) 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 { } else {
return callback(null, true) return callback(null, true)
} }
@@ -69,11 +70,11 @@ module.exports = CollaboratorsInviteController = {
_checkRateLimit(user_id, callback) { _checkRateLimit(user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return LimitationsManager.allowedNumberOfCollaboratorsForUser( return LimitationsManager.allowedNumberOfCollaboratorsForUser(
user_id, user_id,
function(err, collabLimit) { function (err, collabLimit) {
if (collabLimit == null) { if (collabLimit == null) {
collabLimit = 1 collabLimit = 1
} }
@@ -134,7 +135,7 @@ module.exports = CollaboratorsInviteController = {
} }
return CollaboratorsInviteController._checkRateLimit( return CollaboratorsInviteController._checkRateLimit(
sendingUserId, sendingUserId,
function(error, underRateLimit) { function (error, underRateLimit) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
@@ -143,7 +144,7 @@ module.exports = CollaboratorsInviteController = {
} }
return CollaboratorsInviteController._checkShouldInviteEmail( return CollaboratorsInviteController._checkShouldInviteEmail(
email, email,
function(err, shouldAllowInvite) { function (err, shouldAllowInvite) {
if (err != null) { if (err != null) {
OError.tag( OError.tag(
err, err,
@@ -171,7 +172,7 @@ module.exports = CollaboratorsInviteController = {
sendingUser, sendingUser,
email, email,
privileges, privileges,
function(err, invite) { function (err, invite) {
if (err != null) { if (err != null) {
OError.tag(err, 'error creating project invite', { OError.tag(err, 'error creating project invite', {
projectId, projectId,
@@ -207,7 +208,7 @@ module.exports = CollaboratorsInviteController = {
return CollaboratorsInviteHandler.revokeInvite( return CollaboratorsInviteHandler.revokeInvite(
projectId, projectId,
inviteId, inviteId,
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'error revoking invite', { OError.tag(err, 'error revoking invite', {
projectId, projectId,
@@ -232,7 +233,7 @@ module.exports = CollaboratorsInviteController = {
const sendingUser = AuthenticationController.getSessionUser(req) const sendingUser = AuthenticationController.getSessionUser(req)
return CollaboratorsInviteController._checkRateLimit( return CollaboratorsInviteController._checkRateLimit(
sendingUser._id, sendingUser._id,
function(error, underRateLimit) { function (error, underRateLimit) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
@@ -243,7 +244,7 @@ module.exports = CollaboratorsInviteController = {
projectId, projectId,
sendingUser, sendingUser,
inviteId, inviteId,
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'error resending invite', { OError.tag(err, 'error resending invite', {
projectId, projectId,
@@ -261,7 +262,7 @@ module.exports = CollaboratorsInviteController = {
viewInvite(req, res, next) { viewInvite(req, res, next) {
const projectId = req.params.Project_id const projectId = req.params.Project_id
const { token } = req.params const { token } = req.params
const _renderInvalidPage = function() { const _renderInvalidPage = function () {
logger.log( logger.log(
{ projectId, token }, { projectId, token },
'invite not valid, rendering not-valid page' 'invite not valid, rendering not-valid page'
@@ -273,7 +274,7 @@ module.exports = CollaboratorsInviteController = {
return CollaboratorsGetter.isUserInvitedMemberOfProject( return CollaboratorsGetter.isUserInvitedMemberOfProject(
currentUser._id, currentUser._id,
projectId, projectId,
function(err, isMember) { function (err, isMember) {
if (err != null) { if (err != null) {
OError.tag(err, 'error checking if user is member of project', { OError.tag(err, 'error checking if user is member of project', {
projectId projectId
@@ -291,7 +292,7 @@ module.exports = CollaboratorsInviteController = {
return CollaboratorsInviteHandler.getInviteByToken( return CollaboratorsInviteHandler.getInviteByToken(
projectId, projectId,
token, token,
function(err, invite) { function (err, invite) {
if (err != null) { if (err != null) {
OError.tag(err, 'error getting invite by token', { OError.tag(err, 'error getting invite by token', {
projectId, projectId,
@@ -308,7 +309,7 @@ module.exports = CollaboratorsInviteController = {
return UserGetter.getUser( return UserGetter.getUser(
{ _id: invite.sendingUserId }, { _id: invite.sendingUserId },
{ email: 1, first_name: 1, last_name: 1 }, { email: 1, first_name: 1, last_name: 1 },
function(err, owner) { function (err, owner) {
if (err != null) { if (err != null) {
OError.tag(err, 'error getting project owner', { OError.tag(err, 'error getting project owner', {
projectId projectId
@@ -320,28 +321,29 @@ module.exports = CollaboratorsInviteController = {
return _renderInvalidPage() return _renderInvalidPage()
} }
// fetch the project name // fetch the project name
return ProjectGetter.getProject(projectId, {}, function( return ProjectGetter.getProject(
err, projectId,
project {},
) { function (err, project) {
if (err != null) { if (err != null) {
OError.tag(err, 'error getting project', { OError.tag(err, 'error getting project', {
projectId 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, projectId,
token, token,
currentUser, currentUser,
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'error accepting invite by token', { OError.tag(err, 'error accepting invite by token', {
projectId, projectId,

View File

@@ -26,10 +26,10 @@ const { promisifyAll } = require('../../util/promises')
const CollaboratorsInviteHandler = { const CollaboratorsInviteHandler = {
getAllInvites(projectId, callback) { getAllInvites(projectId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, invites) {} callback = function (err, invites) {}
} }
logger.log({ projectId }, 'fetching invites for project') logger.log({ projectId }, 'fetching invites for project')
return ProjectInvite.find({ projectId }, function(err, invites) { return ProjectInvite.find({ projectId }, function (err, invites) {
if (err != null) { if (err != null) {
OError.tag(err, 'error getting invites from mongo', { OError.tag(err, 'error getting invites from mongo', {
projectId projectId
@@ -46,10 +46,10 @@ const CollaboratorsInviteHandler = {
getInviteCount(projectId, callback) { getInviteCount(projectId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, count) {} callback = function (err, count) {}
} }
logger.log({ projectId }, 'counting invites for project') logger.log({ projectId }, 'counting invites for project')
return ProjectInvite.countDocuments({ projectId }, function(err, count) { return ProjectInvite.countDocuments({ projectId }, function (err, count) {
if (err != null) { if (err != null) {
OError.tag(err, 'error getting invites from mongo', { OError.tag(err, 'error getting invites from mongo', {
projectId projectId
@@ -62,55 +62,57 @@ const CollaboratorsInviteHandler = {
_trySendInviteNotification(projectId, sendingUser, invite, callback) { _trySendInviteNotification(projectId, sendingUser, invite, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
const { email } = invite const { email } = invite
return UserGetter.getUserByAnyEmail(email, { _id: 1 }, function( return UserGetter.getUserByAnyEmail(
err, email,
existingUser { _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
) {
if (err != null) { if (err != null) {
OError.tag(err, 'error getting project', { OError.tag(err, 'error checking if user exists', {
projectId, projectId,
email email
}) })
return callback(err) return callback(err)
} }
if (project == null) { if (existingUser == null) {
logger.log( logger.log({ projectId, email }, 'no existing user found, returning')
{ projectId },
'no project found while sending notification, returning'
)
return callback(null) return callback(null)
} }
return NotificationsBuilder.projectInvite( return ProjectGetter.getProject(
invite, projectId,
project, { _id: 1, name: 1 },
sendingUser, function (err, project) {
existingUser if (err != null) {
).create(callback) 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) { _tryCancelInviteNotification(inviteId, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
return NotificationsBuilder.projectInvite( return NotificationsBuilder.projectInvite(
{ _id: inviteId }, { _id: inviteId },
@@ -122,7 +124,7 @@ const CollaboratorsInviteHandler = {
_sendMessages(projectId, sendingUser, invite, callback) { _sendMessages(projectId, sendingUser, invite, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
logger.log( logger.log(
{ projectId, inviteId: invite._id }, { projectId, inviteId: invite._id },
@@ -133,7 +135,7 @@ const CollaboratorsInviteHandler = {
invite.email, invite.email,
invite, invite,
sendingUser, sendingUser,
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -141,7 +143,7 @@ const CollaboratorsInviteHandler = {
projectId, projectId,
sendingUser, sendingUser,
invite, invite,
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -154,13 +156,13 @@ const CollaboratorsInviteHandler = {
inviteToProject(projectId, sendingUser, email, privileges, callback) { inviteToProject(projectId, sendingUser, email, privileges, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, invite) {} callback = function (err, invite) {}
} }
logger.log( logger.log(
{ projectId, sendingUserId: sendingUser._id, email, privileges }, { projectId, sendingUserId: sendingUser._id, email, privileges },
'adding invite' 'adding invite'
) )
return Crypto.randomBytes(24, function(err, buffer) { return Crypto.randomBytes(24, function (err, buffer) {
if (err != null) { if (err != null) {
OError.tag(err, 'error generating random token', { OError.tag(err, 'error generating random token', {
projectId, projectId,
@@ -177,7 +179,7 @@ const CollaboratorsInviteHandler = {
projectId, projectId,
privileges privileges
}) })
return invite.save(function(err, invite) { return invite.save(function (err, invite) {
if (err != null) { if (err != null) {
OError.tag(err, 'error saving token', { OError.tag(err, 'error saving token', {
projectId, projectId,
@@ -191,7 +193,7 @@ const CollaboratorsInviteHandler = {
projectId, projectId,
sendingUser, sendingUser,
invite, invite,
function(err) { function (err) {
if (err != null) { if (err != null) {
return logger.err( return logger.err(
{ err, projectId, email }, { err, projectId, email },
@@ -207,98 +209,101 @@ const CollaboratorsInviteHandler = {
revokeInvite(projectId, inviteId, callback) { revokeInvite(projectId, inviteId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
logger.log({ projectId, inviteId }, 'removing invite') logger.log({ projectId, inviteId }, 'removing invite')
return ProjectInvite.deleteOne({ projectId, _id: inviteId }, function(err) { return ProjectInvite.deleteOne(
if (err != null) { { projectId, _id: inviteId },
OError.tag(err, 'error removing invite', { function (err) {
projectId, if (err != null) {
inviteId OError.tag(err, 'error removing invite', {
}) projectId,
return callback(err) inviteId
})
return callback(err)
}
CollaboratorsInviteHandler._tryCancelInviteNotification(
inviteId,
function () {}
)
return callback(null)
} }
CollaboratorsInviteHandler._tryCancelInviteNotification( )
inviteId,
function() {}
)
return callback(null)
})
}, },
resendInvite(projectId, sendingUser, inviteId, callback) { resendInvite(projectId, sendingUser, inviteId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
logger.log({ projectId, inviteId }, 'resending invite email') logger.log({ projectId, inviteId }, 'resending invite email')
return ProjectInvite.findOne({ _id: inviteId, projectId }, function( return ProjectInvite.findOne(
err, { _id: inviteId, projectId },
invite function (err, invite) {
) { if (err != null) {
if (err != null) { OError.tag(err, 'error finding invite', {
OError.tag(err, 'error finding invite', { projectId,
projectId, inviteId
inviteId })
}) return callback(err)
return callback(err) }
} if (invite == null) {
if (invite == null) { logger.err(
logger.err( { err, projectId, inviteId },
{ err, projectId, inviteId }, 'no invite found, nothing to resend'
'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) 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) { getInviteByToken(projectId, tokenString, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, invite) {} callback = function (err, invite) {}
} }
logger.log({ projectId, tokenString }, 'fetching invite by token') logger.log({ projectId, tokenString }, 'fetching invite by token')
return ProjectInvite.findOne({ projectId, token: tokenString }, function( return ProjectInvite.findOne(
err, { projectId, token: tokenString },
invite function (err, invite) {
) { if (err != null) {
if (err != null) { OError.tag(err, 'error fetching invite', {
OError.tag(err, 'error fetching invite', { projectId
projectId })
}) return callback(err)
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) { acceptInvite(projectId, tokenString, user, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
logger.log({ projectId, userId: user._id, tokenString }, 'accepting invite') logger.log({ projectId, userId: user._id, tokenString }, 'accepting invite')
return CollaboratorsInviteHandler.getInviteByToken( return CollaboratorsInviteHandler.getInviteByToken(
projectId, projectId,
tokenString, tokenString,
function(err, invite) { function (err, invite) {
if (err != null) { if (err != null) {
OError.tag(err, 'error finding invite', { OError.tag(err, 'error finding invite', {
projectId, projectId,
@@ -320,7 +325,7 @@ const CollaboratorsInviteHandler = {
invite.sendingUserId, invite.sendingUserId,
user._id, user._id,
invite.privileges, invite.privileges,
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'error adding user to project', { OError.tag(err, 'error adding user to project', {
projectId, projectId,
@@ -331,7 +336,7 @@ const CollaboratorsInviteHandler = {
} }
// Remove invite // Remove invite
logger.log({ projectId, inviteId }, 'removing invite') logger.log({ projectId, inviteId }, 'removing invite')
return ProjectInvite.deleteOne({ _id: inviteId }, function(err) { return ProjectInvite.deleteOne({ _id: inviteId }, function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'error removing invite', { OError.tag(err, 'error removing invite', {
projectId, projectId,
@@ -341,7 +346,7 @@ const CollaboratorsInviteHandler = {
} }
CollaboratorsInviteHandler._tryCancelInviteNotification( CollaboratorsInviteHandler._tryCancelInviteNotification(
inviteId, inviteId,
function() {} function () {}
) )
return callback() return callback()
}) })

View File

@@ -27,7 +27,7 @@ const clsiCookiesEnabled =
(Settings.clsiCookie != null ? Settings.clsiCookie.key : undefined) != null && (Settings.clsiCookie != null ? Settings.clsiCookie.key : undefined) != null &&
Settings.clsiCookie.key.length !== 0 Settings.clsiCookie.key.length !== 0
module.exports = function(backendGroup) { module.exports = function (backendGroup) {
return { return {
buildKey(project_id) { buildKey(project_id) {
if (backendGroup != null) { if (backendGroup != null) {
@@ -39,7 +39,7 @@ module.exports = function(backendGroup) {
_getServerId(project_id, callback) { _getServerId(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, serverId) {} callback = function (err, serverId) {}
} }
return rclient.get(this.buildKey(project_id), (err, serverId) => { return rclient.get(this.buildKey(project_id), (err, serverId) => {
if (err != null) { if (err != null) {
@@ -55,7 +55,7 @@ module.exports = function(backendGroup) {
_populateServerIdViaRequest(project_id, callback) { _populateServerIdViaRequest(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, serverId) {} callback = function (err, serverId) {}
} }
const url = `${Settings.apis.clsi.url}/project/${project_id}/status` const url = `${Settings.apis.clsi.url}/project/${project_id}/status`
return request.post(url, (err, res, body) => { return request.post(url, (err, res, body) => {
@@ -65,7 +65,7 @@ module.exports = function(backendGroup) {
}) })
return callback(err) return callback(err)
} }
return this.setServerId(project_id, res, function(err, serverId) { return this.setServerId(project_id, res, function (err, serverId) {
if (err != null) { if (err != null) {
logger.warn( logger.warn(
{ err, project_id }, { err, project_id },
@@ -88,7 +88,7 @@ module.exports = function(backendGroup) {
setServerId(project_id, response, callback) { setServerId(project_id, response, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, serverId) {} callback = function (err, serverId) {}
} }
if (!clsiCookiesEnabled) { if (!clsiCookiesEnabled) {
return callback() return callback()
@@ -112,7 +112,7 @@ module.exports = function(backendGroup) {
_setServerIdInRedis(rclient, project_id, serverId, callback) { _setServerIdInRedis(rclient, project_id, serverId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
rclient.setex( rclient.setex(
this.buildKey(project_id), this.buildKey(project_id),
@@ -124,7 +124,7 @@ module.exports = function(backendGroup) {
clearServerId(project_id, callback) { clearServerId(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
if (!clsiCookiesEnabled) { if (!clsiCookiesEnabled) {
return callback() return callback()
@@ -134,7 +134,7 @@ module.exports = function(backendGroup) {
getCookieJar(project_id, callback) { getCookieJar(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, jar) {} callback = function (err, jar) {}
} }
if (!clsiCookiesEnabled) { if (!clsiCookiesEnabled) {
return callback(null, request.jar()) return callback(null, request.jar())

View File

@@ -26,7 +26,7 @@ module.exports = ClsiFormatChecker = {
} }
} }
return async.series(jobs, function(err, problems) { return async.series(jobs, function (err, problems) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -44,7 +44,7 @@ module.exports = ClsiFormatChecker = {
_checkForConflictingPaths(resources, callback) { _checkForConflictingPaths(resources, callback) {
const paths = resources.map(resource => resource.path) const paths = resources.map(resource => resource.path)
const conflicts = _.filter(paths, function(path) { const conflicts = _.filter(paths, function (path) {
const matchingPaths = _.filter( const matchingPaths = _.filter(
paths, paths,
checkPath => checkPath.indexOf(path + '/') !== -1 checkPath => checkPath.indexOf(path + '/') !== -1
@@ -63,7 +63,7 @@ module.exports = ClsiFormatChecker = {
let totalSize = 0 let totalSize = 0
let sizedResources = resources.map(function(resource) { let sizedResources = resources.map(function (resource) {
const result = { path: resource.path } const result = { path: resource.path }
if (resource.content != null) { if (resource.content != null) {
result.size = resource.content.replace(/\n/g, '').length result.size = resource.content.replace(/\n/g, '').length
@@ -79,9 +79,7 @@ module.exports = ClsiFormatChecker = {
if (!tooLarge) { if (!tooLarge) {
return callback() return callback()
} else { } else {
sizedResources = _.sortBy(sizedResources, 'size') sizedResources = _.sortBy(sizedResources, 'size').reverse().slice(0, 10)
.reverse()
.slice(0, 10)
return callback(null, { resources: sizedResources, totalSize }) return callback(null, { resources: sizedResources, totalSize })
} }
} }

View File

@@ -34,50 +34,48 @@ const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
// unsetting it if it removes any documents from the doc updater. // unsetting it if it removes any documents from the doc updater.
const buildState = s => const buildState = s =>
crypto crypto.createHash('sha1').update(s, 'utf8').digest('hex')
.createHash('sha1')
.update(s, 'utf8')
.digest('hex')
module.exports = ClsiStateManager = { module.exports = ClsiStateManager = {
computeHash(project, options, callback) { computeHash(project, options, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, hash) {} callback = function (err, hash) {}
} }
return ProjectEntityHandler.getAllEntitiesFromProject(project, function( return ProjectEntityHandler.getAllEntitiesFromProject(
err, project,
docs, function (err, docs, files) {
files const fileList = Array.from(files || []).map(
) { f => `${f.file._id}:${f.file.rev}:${f.file.created}:${f.path}`
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 docList = Array.from(docs || []).map(d => `${d.doc._id}:${d.path}`) )
const sortedEntityList = [ const sortedEntityList = [
...Array.from(docList), ...Array.from(docList),
...Array.from(fileList) ...Array.from(fileList)
].sort() ].sort()
// ignore the isAutoCompile options as it doesn't affect the // ignore the isAutoCompile options as it doesn't affect the
// output, but include all other options e.g. draft // output, but include all other options e.g. draft
const optionsList = (() => { const optionsList = (() => {
const result = [] const result = []
const object = options || {} const object = options || {}
for (let key in object) { for (let key in object) {
const value = object[key] const value = object[key]
if (!['isAutoCompile'].includes(key)) { if (!['isAutoCompile'].includes(key)) {
result.push(`option ${key}:${value}`) result.push(`option ${key}:${value}`)
}
} }
} return result
return result })()
})() const sortedOptionsList = optionsList.sort()
const sortedOptionsList = optionsList.sort() const hash = buildState(
const hash = buildState( [
[ ...Array.from(sortedEntityList),
...Array.from(sortedEntityList), ...Array.from(sortedOptionsList)
...Array.from(sortedOptionsList) ].join('\n')
].join('\n') )
) return callback(null, hash)
return callback(null, hash) }
}) )
} }
} }

View File

@@ -104,11 +104,11 @@ module.exports = CompileController = {
stopCompile(req, res, next) { stopCompile(req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
const project_id = req.params.Project_id const project_id = req.params.Project_id
const user_id = AuthenticationController.getLoggedInUserId(req) 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) { if (error != null) {
return next(error) return next(error)
} }
@@ -119,7 +119,7 @@ module.exports = CompileController = {
// Used for submissions through the public API // Used for submissions through the public API
compileSubmission(req, res, next) { compileSubmission(req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
res.setTimeout(COMPILE_TIMEOUT_MS) res.setTimeout(COMPILE_TIMEOUT_MS)
const { submission_id } = req.params const { submission_id } = req.params
@@ -150,7 +150,7 @@ module.exports = CompileController = {
submission_id, submission_id,
req.body, req.body,
options, options,
function(error, status, outputFiles, clsiServerId, validationProblems) { function (error, status, outputFiles, clsiServerId, validationProblems) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
@@ -189,13 +189,13 @@ module.exports = CompileController = {
downloadPdf(req, res, next) { downloadPdf(req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
Metrics.inc('pdf-downloads') Metrics.inc('pdf-downloads')
const project_id = req.params.Project_id const project_id = req.params.Project_id
const isPdfjsPartialDownload = const isPdfjsPartialDownload =
req.query != null ? req.query.pdfng : undefined req.query != null ? req.query.pdfng : undefined
const rateLimit = function(callback) { const rateLimit = function (callback) {
if (isPdfjsPartialDownload) { if (isPdfjsPartialDownload) {
return callback(null, true) return callback(null, true)
} else { } else {
@@ -209,51 +209,52 @@ module.exports = CompileController = {
} }
} }
return ProjectGetter.getProject(project_id, { name: 1 }, function( return ProjectGetter.getProject(
err, project_id,
project { name: 1 },
) { function (err, project) {
res.contentType('application/pdf') res.contentType('application/pdf')
const filename = `${CompileController._getSafeProjectName(project)}.pdf` const filename = `${CompileController._getSafeProjectName(project)}.pdf`
if (req.query.popupDownload) { if (req.query.popupDownload) {
res.setContentDisposition('attachment', { filename }) 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)
} else { } else {
return CompileController._downloadAsUser(req, function( res.setContentDisposition('', { filename })
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
)
})
} }
})
}) 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) { _getSafeProjectName(project) {
@@ -264,18 +265,21 @@ module.exports = CompileController = {
deleteAuxFiles(req, res, next) { deleteAuxFiles(req, res, next) {
const project_id = req.params.Project_id const project_id = req.params.Project_id
const { clsiserverid } = req.query const { clsiserverid } = req.query
return CompileController._compileAsUser(req, function(error, user_id) { return CompileController._compileAsUser(req, function (error, user_id) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
CompileManager.deleteAuxFiles(project_id, user_id, clsiserverid, function( CompileManager.deleteAuxFiles(
error project_id,
) { user_id,
if (error != null) { clsiserverid,
return next(error) 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) { compileAndDownloadPdf(req, res, next) {
const { project_id } = req.params const { project_id } = req.params
// pass user_id as null, since templates are an "anonymous" compile // 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) { if (err != null) {
logger.err( logger.err(
{ err, project_id }, { err, project_id },
@@ -298,10 +302,10 @@ module.exports = CompileController = {
getFileFromClsi(req, res, next) { getFileFromClsi(req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
const project_id = req.params.Project_id 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) { if (error != null) {
return next(error) return next(error)
} }
@@ -317,7 +321,7 @@ module.exports = CompileController = {
getFileFromClsiWithoutUser(req, res, next) { getFileFromClsiWithoutUser(req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
const { submission_id } = req.params const { submission_id } = req.params
const url = CompileController._getFileUrl( const url = CompileController._getFileUrl(
@@ -367,7 +371,7 @@ module.exports = CompileController = {
proxySyncPdf(req, res, next) { proxySyncPdf(req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
const project_id = req.params.Project_id const project_id = req.params.Project_id
const { page, h, v } = req.query const { page, h, v } = req.query
@@ -381,7 +385,7 @@ module.exports = CompileController = {
return next(new Error('invalid v parameter')) return next(new Error('invalid v parameter'))
} }
// whether this request is going to a per-user container // 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) { if (error != null) {
return next(error) return next(error)
} }
@@ -403,7 +407,7 @@ module.exports = CompileController = {
proxySyncCode(req, res, next) { proxySyncCode(req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
const project_id = req.params.Project_id const project_id = req.params.Project_id
const { file, line, column } = req.query const { file, line, column } = req.query
@@ -425,7 +429,7 @@ module.exports = CompileController = {
if (!(column != null ? column.match(/^\d+$/) : undefined)) { if (!(column != null ? column.match(/^\d+$/) : undefined)) {
return next(new Error('invalid column parameter')) 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) { if (error != null) {
return next(error) return next(error)
} }
@@ -447,7 +451,7 @@ module.exports = CompileController = {
proxyToClsi(project_id, url, req, res, next) { proxyToClsi(project_id, url, req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
if (req.query != null ? req.query.compileGroup : undefined) { if (req.query != null ? req.query.compileGroup : undefined) {
return CompileController.proxyToClsiWithLimits( return CompileController.proxyToClsiWithLimits(
@@ -459,28 +463,28 @@ module.exports = CompileController = {
next next
) )
} else { } else {
return CompileManager.getProjectCompileLimits(project_id, function( return CompileManager.getProjectCompileLimits(
error, project_id,
limits function (error, limits) {
) { if (error != null) {
if (error != null) { return next(error)
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) { proxyToClsiWithLimits(project_id, url, limits, req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
_getPersistenceOptions(req, project_id, (err, persistenceOptions) => { _getPersistenceOptions(req, project_id, (err, persistenceOptions) => {
let qs let qs
@@ -541,7 +545,7 @@ module.exports = CompileController = {
const project_id = req.params.Project_id const project_id = req.params.Project_id
const file = req.query.file || false const file = req.query.file || false
const { clsiserverid } = req.query const { clsiserverid } = req.query
return CompileController._compileAsUser(req, function(error, user_id) { return CompileController._compileAsUser(req, function (error, user_id) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
@@ -550,7 +554,7 @@ module.exports = CompileController = {
user_id, user_id,
file, file,
clsiserverid, clsiserverid,
function(error, body) { function (error, body) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }

View File

@@ -30,10 +30,10 @@ module.exports = CompileManager = {
options = {} options = {}
} }
if (_callback == null) { if (_callback == null) {
_callback = function(error) {} _callback = function (error) {}
} }
const timer = new Metrics.Timer('editor.compile') const timer = new Metrics.Timer('editor.compile')
const callback = function(...args) { const callback = function (...args) {
timer.done() timer.done()
return _callback(...Array.from(args || [])) return _callback(...Array.from(args || []))
} }
@@ -41,7 +41,7 @@ module.exports = CompileManager = {
return CompileManager._checkIfRecentlyCompiled( return CompileManager._checkIfRecentlyCompiled(
project_id, project_id,
user_id, user_id,
function(error, recentlyCompiled) { function (error, recentlyCompiled) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -52,20 +52,20 @@ module.exports = CompileManager = {
return CompileManager._checkIfAutoCompileLimitHasBeenHit( return CompileManager._checkIfAutoCompileLimitHasBeenHit(
options.isAutoCompile, options.isAutoCompile,
'everyone', 'everyone',
function(err, canCompile) { function (err, canCompile) {
if (!canCompile) { if (!canCompile) {
return callback(null, 'autocompile-backoff', []) return callback(null, 'autocompile-backoff', [])
} }
return ProjectRootDocManager.ensureRootDocumentIsSet( return ProjectRootDocManager.ensureRootDocumentIsSet(
project_id, project_id,
function(error) { function (error) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
return CompileManager.getProjectCompileLimits( return CompileManager.getProjectCompileLimits(
project_id, project_id,
function(error, limits) { function (error, limits) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -77,7 +77,7 @@ module.exports = CompileManager = {
return CompileManager._checkCompileGroupAutoCompileLimit( return CompileManager._checkCompileGroupAutoCompileLimit(
options.isAutoCompile, options.isAutoCompile,
limits.compileGroup, limits.compileGroup,
function(err, canCompile) { function (err, canCompile) {
if (!canCompile) { if (!canCompile) {
return callback(null, 'autocompile-backoff', []) return callback(null, 'autocompile-backoff', [])
} }
@@ -89,7 +89,7 @@ module.exports = CompileManager = {
project_id, project_id,
compileAsUser, compileAsUser,
options, options,
function( function (
error, error,
status, status,
outputFiles, outputFiles,
@@ -123,100 +123,105 @@ module.exports = CompileManager = {
stopCompile(project_id, user_id, callback) { stopCompile(project_id, user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return CompileManager.getProjectCompileLimits(project_id, function( return CompileManager.getProjectCompileLimits(
error, project_id,
limits function (error, limits) {
) { if (error != null) {
if (error != null) { return callback(error)
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) { deleteAuxFiles(project_id, user_id, clsiserverid, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return CompileManager.getProjectCompileLimits(project_id, function( return CompileManager.getProjectCompileLimits(
error, project_id,
limits function (error, limits) {
) { if (error != null) {
if (error != null) { return callback(error)
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) { getProjectCompileLimits(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, limits) {} callback = function (error, limits) {}
} }
return ProjectGetter.getProject(project_id, { owner_ref: 1 }, function( return ProjectGetter.getProject(
error, project_id,
project { owner_ref: 1 },
) { function (error, project) {
if (error != null) { if (error != null) {
return callback(error) 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 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 COMPILE_DELAY: 1, // seconds
_checkIfRecentlyCompiled(project_id, user_id, callback) { _checkIfRecentlyCompiled(project_id, user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, recentlyCompiled) {} callback = function (error, recentlyCompiled) {}
} }
const key = `compile:${project_id}:${user_id}` const key = `compile:${project_id}:${user_id}`
return rclient.set(key, true, 'EX', this.COMPILE_DELAY, 'NX', function( return rclient.set(
error, key,
ok true,
) { 'EX',
if (error != null) { this.COMPILE_DELAY,
return callback(error) '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) { _checkCompileGroupAutoCompileLimit(isAutoCompile, compileGroup, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, canCompile) {} callback = function (err, canCompile) {}
} }
if (!isAutoCompile) { if (!isAutoCompile) {
return callback(null, true) return callback(null, true)
@@ -236,7 +241,7 @@ module.exports = CompileManager = {
_checkIfAutoCompileLimitHasBeenHit(isAutoCompile, compileGroup, callback) { _checkIfAutoCompileLimitHasBeenHit(isAutoCompile, compileGroup, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, canCompile) {} callback = function (err, canCompile) {}
} }
if (!isAutoCompile) { if (!isAutoCompile) {
return callback(null, true) return callback(null, true)
@@ -248,7 +253,7 @@ module.exports = CompileManager = {
subjectName: compileGroup, subjectName: compileGroup,
throttle: Settings.rateLimit.autoCompile[compileGroup] || 25 throttle: Settings.rateLimit.autoCompile[compileGroup] || 25
} }
return rateLimiter.addCount(opts, function(err, canCompile) { return rateLimiter.addCount(opts, function (err, canCompile) {
if (err != null) { if (err != null) {
canCompile = false canCompile = false
} }
@@ -261,23 +266,23 @@ module.exports = CompileManager = {
wordCount(project_id, user_id, file, clsiserverid, callback) { wordCount(project_id, user_id, file, clsiserverid, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return CompileManager.getProjectCompileLimits(project_id, function( return CompileManager.getProjectCompileLimits(
error, project_id,
limits function (error, limits) {
) { if (error != null) {
if (error != null) { return callback(error)
return callback(error) }
ClsiManager.wordCount(
project_id,
user_id,
file,
limits,
clsiserverid,
callback
)
} }
ClsiManager.wordCount( )
project_id,
user_id,
file,
limits,
clsiserverid,
callback
)
})
} }
} }

View File

@@ -22,58 +22,63 @@ const Modules = require('../../infrastructure/Modules')
module.exports = ContactsController = { module.exports = ContactsController = {
getContacts(req, res, next) { getContacts(req, res, next) {
const user_id = AuthenticationController.getLoggedInUserId(req) const user_id = AuthenticationController.getLoggedInUserId(req)
return ContactManager.getContactIds(user_id, { limit: 50 }, function( return ContactManager.getContactIds(
error, user_id,
contact_ids { limit: 50 },
) { function (error, contact_ids) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
return UserGetter.getUsers( return UserGetter.getUsers(
contact_ids, contact_ids,
{ {
email: 1, email: 1,
first_name: 1, first_name: 1,
last_name: 1, last_name: 1,
holdingAccount: 1 holdingAccount: 1
}, },
function(error, contacts) { 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
) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
contacts = contacts.concat(...Array.from(additional_contacts || []))
return res.send({ // UserGetter.getUsers may not preserve order so put them back in order
contacts 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) { _formatContact(contact) {

View File

@@ -23,7 +23,7 @@ module.exports = ContactManager = {
options = { limits: 50 } options = { limits: 50 }
} }
if (callback == null) { if (callback == null) {
callback = function(error, contacts) {} callback = function (error, contacts) {}
} }
const url = `${settings.apis.contacts.url}/user/${user_id}/contacts` const url = `${settings.apis.contacts.url}/user/${user_id}/contacts`
return request.get( return request.get(
@@ -33,7 +33,7 @@ module.exports = ContactManager = {
json: true, json: true,
jar: false jar: false
}, },
function(error, res, data) { function (error, res, data) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -55,7 +55,7 @@ module.exports = ContactManager = {
addContact(user_id, contact_id, callback) { addContact(user_id, contact_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
const url = `${settings.apis.contacts.url}/user/${user_id}/contacts` const url = `${settings.apis.contacts.url}/user/${user_id}/contacts`
return request.post( return request.post(
@@ -66,7 +66,7 @@ module.exports = ContactManager = {
}, },
jar: false jar: false
}, },
function(error, res, data) { function (error, res, data) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }

View File

@@ -24,7 +24,7 @@ module.exports = CooldownManager = {
putProjectOnCooldown(projectId, callback) { putProjectOnCooldown(projectId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
logger.log( logger.log(
{ projectId }, { projectId },
@@ -41,16 +41,16 @@ module.exports = CooldownManager = {
isProjectOnCooldown(projectId, callback) { isProjectOnCooldown(projectId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, isOnCooldown) {} callback = function (err, isOnCooldown) {}
} }
return rclient.get(CooldownManager._buildKey(projectId), function( return rclient.get(
err, CooldownManager._buildKey(projectId),
result function (err, result) {
) { if (err != null) {
if (err != null) { return callback(err)
return callback(err) }
return callback(null, result === '1')
} }
return callback(null, result === '1') )
})
} }
} }

View File

@@ -20,21 +20,21 @@ module.exports = CooldownMiddleware = {
if (projectId == null) { if (projectId == null) {
return next(new Error('[Cooldown] No projectId parameter on route')) return next(new Error('[Cooldown] No projectId parameter on route'))
} }
return CooldownManager.isProjectOnCooldown(projectId, function( return CooldownManager.isProjectOnCooldown(
err, projectId,
projectIsOnCooldown function (err, projectIsOnCooldown) {
) { if (err != null) {
if (err != null) { return next(err)
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()
})
} }
} }

View File

@@ -24,12 +24,12 @@ const TIMEOUT = 30 * 1000 // request timeout
const DocstoreManager = { const DocstoreManager = {
deleteDoc(project_id, doc_id, name, deletedAt, callback) { deleteDoc(project_id, doc_id, name, deletedAt, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}` const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}`
const docMetaData = { deleted: true, deletedAt, name } const docMetaData = { deleted: true, deletedAt, name }
const options = { url, json: docMetaData, timeout: TIMEOUT } const options = { url, json: docMetaData, timeout: TIMEOUT }
request.patch(options, function(error, res) { request.patch(options, function (error, res) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -59,7 +59,7 @@ const DocstoreManager = {
getAllDocs(project_id, callback) { getAllDocs(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
const url = `${settings.apis.docstore.url}/project/${project_id}/doc` const url = `${settings.apis.docstore.url}/project/${project_id}/doc`
return request.get( return request.get(
@@ -68,7 +68,7 @@ const DocstoreManager = {
timeout: TIMEOUT, timeout: TIMEOUT,
json: true json: true
}, },
function(error, res, docs) { function (error, res, docs) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -87,29 +87,30 @@ const DocstoreManager = {
getAllDeletedDocs(project_id, callback) { getAllDeletedDocs(project_id, callback) {
const url = `${settings.apis.docstore.url}/project/${project_id}/doc-deleted` const url = `${settings.apis.docstore.url}/project/${project_id}/doc-deleted`
request.get({ url, timeout: TIMEOUT, json: true }, function( request.get(
error, { url, timeout: TIMEOUT, json: true },
res, function (error, res, docs) {
docs if (error) {
) { callback(
if (error) { OError.tag(error, 'could not get deleted docs from docstore')
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 }
) )
) } 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) { getAllRanges(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
const url = `${settings.apis.docstore.url}/project/${project_id}/ranges` const url = `${settings.apis.docstore.url}/project/${project_id}/ranges`
return request.get( return request.get(
@@ -118,7 +119,7 @@ const DocstoreManager = {
timeout: TIMEOUT, timeout: TIMEOUT,
json: true json: true
}, },
function(error, res, docs) { function (error, res, docs) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -140,7 +141,7 @@ const DocstoreManager = {
options = {} options = {}
} }
if (callback == null) { if (callback == null) {
callback = function(error, lines, rev, version) {} callback = function (error, lines, rev, version) {}
} }
if (typeof options === 'function') { if (typeof options === 'function') {
callback = options callback = options
@@ -156,7 +157,7 @@ const DocstoreManager = {
timeout: TIMEOUT, timeout: TIMEOUT,
json: true json: true
}, },
function(error, res, doc) { function (error, res, doc) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -191,36 +192,35 @@ const DocstoreManager = {
isDocDeleted(project_id, doc_id, callback) { isDocDeleted(project_id, doc_id, callback) {
const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}/deleted` const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}/deleted`
request.get({ url, timeout: TIMEOUT, json: true }, function( request.get(
err, { url, timeout: TIMEOUT, json: true },
res, function (err, res, body) {
body if (err) {
) { callback(err)
if (err) { } else if (res.statusCode === 200) {
callback(err) callback(null, body.deleted)
} else if (res.statusCode === 200) { } else if (res.statusCode === 404) {
callback(null, body.deleted) callback(
} else if (res.statusCode === 404) { new Errors.NotFoundError({
callback( message: 'doc does not exist in project',
new Errors.NotFoundError({ info: { project_id, doc_id }
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 }
) )
) } 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) { updateDoc(project_id, doc_id, lines, version, ranges, callback) {
if (callback == null) { 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}` const url = `${settings.apis.docstore.url}/project/${project_id}/doc/${doc_id}`
return request.post( return request.post(
@@ -233,7 +233,7 @@ const DocstoreManager = {
ranges ranges
} }
}, },
function(error, res, result) { function (error, res, result) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -270,7 +270,7 @@ const DocstoreManager = {
const url = `${settings.apis.docstore.url}/project/${project_id}/${method}` const url = `${settings.apis.docstore.url}/project/${project_id}/${method}`
logger.log({ project_id }, `calling ${method} for project in docstore`) logger.log({ project_id }, `calling ${method} for project in docstore`)
// use default timeout for archiving/unarchiving/destroying // use default timeout for archiving/unarchiving/destroying
request.post(url, function(err, res, docs) { request.post(url, function (err, res, docs) {
if (err != null) { if (err != null) {
OError.tag(err, `error calling ${method} project in docstore`, { OError.tag(err, `error calling ${method} project in docstore`, {
project_id project_id

View File

@@ -101,7 +101,7 @@ function getDocument(projectId, docId, fromVersion, callback) {
}, },
projectId, projectId,
'get-document', 'get-document',
function(error, doc) { function (error, doc) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -133,7 +133,7 @@ function getProjectDocsIfMatch(projectId, projectStateHash, callback) {
// fall back to getting them from mongo. // fall back to getting them from mongo.
const timer = new metrics.Timer('get-project-docs') const timer = new metrics.Timer('get-project-docs')
const url = `${settings.apis.documentupdater.url}/project/${projectId}/get_and_flush_if_old?state=${projectStateHash}` 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() timer.done()
if (error) { if (error) {
OError.tag(error, 'error getting project docs from doc updater', { OError.tag(error, 'error getting project docs from doc updater', {
@@ -300,7 +300,7 @@ function _makeRequest(options, projectId, metricsKey, callback) {
json: options.json, json: options.json,
method: options.method || 'GET' method: options.method || 'GET'
}, },
function(error, res, body) { function (error, res, body) {
timer.done() timer.done()
if (error) { if (error) {
logger.warn( logger.warn(

View File

@@ -23,7 +23,7 @@ const _ = require('lodash')
module.exports = { module.exports = {
getDocument(req, res, next) { getDocument(req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
const project_id = req.params.Project_id const project_id = req.params.Project_id
const { doc_id } = req.params const { doc_id } = req.params
@@ -32,7 +32,7 @@ module.exports = {
return ProjectGetter.getProject( return ProjectGetter.getProject(
project_id, project_id,
{ rootFolder: true, overleaf: true }, { rootFolder: true, overleaf: true },
function(error, project) { function (error, project) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
@@ -41,7 +41,7 @@ module.exports = {
} }
return ProjectLocator.findElement( return ProjectLocator.findElement(
{ project, element_id: doc_id, type: 'doc' }, { project, element_id: doc_id, type: 'doc' },
function(error, doc, path) { function (error, doc, path) {
if (error != null) { if (error != null) {
OError.tag(error, 'error finding element for getDocument', { OError.tag(error, 'error finding element for getDocument', {
doc_id, doc_id,
@@ -49,45 +49,43 @@ module.exports = {
}) })
return next(error) return next(error)
} }
return ProjectEntityHandler.getDoc(project_id, doc_id, function( return ProjectEntityHandler.getDoc(
error, project_id,
lines, doc_id,
rev, function (error, lines, rev, version, ranges) {
version, if (error != null) {
ranges OError.tag(
) { error,
if (error != null) { 'error finding doc contents for getDocument',
OError.tag( {
error, doc_id,
'error finding doc contents for getDocument', project_id
{ }
doc_id, )
project_id return next(error)
} }
) if (plain) {
return next(error) 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) { setDocument(req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
const project_id = req.params.Project_id const project_id = req.params.Project_id
const { doc_id } = req.params const { doc_id } = req.params
@@ -109,7 +107,7 @@ module.exports = {
ranges, ranges,
lastUpdatedAt, lastUpdatedAt,
lastUpdatedBy, lastUpdatedBy,
function(error) { function (error) {
if (error != null) { if (error != null) {
OError.tag(error, 'error finding element for getDocument', { OError.tag(error, 'error finding element for getDocument', {
doc_id, doc_id,

View File

@@ -22,34 +22,36 @@ module.exports = ProjectDownloadsController = {
downloadProject(req, res, next) { downloadProject(req, res, next) {
const project_id = req.params.Project_id const project_id = req.params.Project_id
Metrics.inc('zip-downloads') Metrics.inc('zip-downloads')
return DocumentUpdaterHandler.flushProjectToMongo(project_id, function( return DocumentUpdaterHandler.flushProjectToMongo(
error project_id,
) { function (error) {
if (error != null) {
return next(error)
}
return ProjectGetter.getProject(project_id, { name: true }, function(
error,
project
) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
return ProjectZipStreamManager.createZipStreamForProject( return ProjectGetter.getProject(
project_id, project_id,
function(error, stream) { { name: true },
function (error, project) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
res.setContentDisposition('attachment', { return ProjectZipStreamManager.createZipStreamForProject(
filename: `${project.name}.zip` project_id,
}) function (error, stream) {
res.contentType('application/zip') if (error != null) {
return stream.pipe(res) return next(error)
}
res.setContentDisposition('attachment', {
filename: `${project.name}.zip`
})
res.contentType('application/zip')
return stream.pipe(res)
}
)
} }
) )
}) }
}) )
}, },
downloadMultipleProjects(req, res, next) { downloadMultipleProjects(req, res, next) {
@@ -57,13 +59,13 @@ module.exports = ProjectDownloadsController = {
Metrics.inc('zip-downloads-multiple') Metrics.inc('zip-downloads-multiple')
return DocumentUpdaterHandler.flushMultipleProjectsToMongo( return DocumentUpdaterHandler.flushMultipleProjectsToMongo(
project_ids, project_ids,
function(error) { function (error) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
return ProjectZipStreamManager.createZipStreamForMultipleProjects( return ProjectZipStreamManager.createZipStreamForMultipleProjects(
project_ids, project_ids,
function(error, stream) { function (error, stream) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }

View File

@@ -26,7 +26,7 @@ module.exports = ProjectZipStreamManager = {
// We'll build up a zip file that contains multiple zip files // We'll build up a zip file that contains multiple zip files
if (callback == null) { if (callback == null) {
callback = function(error, stream) {} callback = function (error, stream) {}
} }
const archive = archiver('zip') const archive = archiver('zip')
archive.on('error', err => archive.on('error', err =>
@@ -41,38 +41,39 @@ module.exports = ProjectZipStreamManager = {
for (let project_id of Array.from(project_ids || [])) { for (let project_id of Array.from(project_ids || [])) {
;(project_id => ;(project_id =>
jobs.push(callback => jobs.push(callback =>
ProjectGetter.getProject(project_id, { name: true }, function( ProjectGetter.getProject(
error, project_id,
project { name: true },
) { function (error, project) {
if (error != null) { if (error != null) {
return callback(error) 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()
})
} }
) 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) ))(project_id)
} }
return async.series(jobs, function() { return async.series(jobs, function () {
logger.log( logger.log(
{ project_ids }, { project_ids },
'finished creating zip stream of multiple projects' 'finished creating zip stream of multiple projects'
@@ -83,7 +84,7 @@ module.exports = ProjectZipStreamManager = {
createZipStreamForProject(project_id, callback) { createZipStreamForProject(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, stream) {} callback = function (error, stream) {}
} }
const archive = archiver('zip') const archive = archiver('zip')
// return stream immediately before we start adding things to it // return stream immediately before we start adding things to it
@@ -115,20 +116,20 @@ module.exports = ProjectZipStreamManager = {
addAllDocsToArchive(project_id, archive, callback) { addAllDocsToArchive(project_id, archive, callback) {
if (callback == null) { 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) { if (error != null) {
return callback(error) return callback(error)
} }
const jobs = [] const jobs = []
for (let path in docs) { for (let path in docs) {
const doc = docs[path] const doc = docs[path]
;(function(path, doc) { ;(function (path, doc) {
if (path[0] === '/') { if (path[0] === '/') {
path = path.slice(1) path = path.slice(1)
} }
return jobs.push(function(callback) { return jobs.push(function (callback) {
logger.log({ project_id }, 'Adding doc') logger.log({ project_id }, 'Adding doc')
archive.append(doc.lines.join('\n'), { name: path }) archive.append(doc.lines.join('\n'), { name: path })
return callback() return callback()
@@ -141,37 +142,42 @@ module.exports = ProjectZipStreamManager = {
addAllFilesToArchive(project_id, archive, callback) { addAllFilesToArchive(project_id, archive, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return ProjectEntityHandler.getAllFiles(project_id, function(error, files) { return ProjectEntityHandler.getAllFiles(
if (error != null) { project_id,
return callback(error) 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)
})
} }
} }

View File

@@ -31,7 +31,7 @@ const { promisifyAll } = require('../../util/promises')
const EditorController = { const EditorController = {
addDoc(project_id, folder_id, docName, docLines, source, user_id, callback) { addDoc(project_id, folder_id, docName, docLines, source, user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, doc) {} callback = function (error, doc) {}
} }
return EditorController.addDocWithRanges( return EditorController.addDocWithRanges(
project_id, project_id,
@@ -56,7 +56,7 @@ const EditorController = {
callback callback
) { ) {
if (callback == null) { if (callback == null) {
callback = function(error, doc) {} callback = function (error, doc) {}
} }
docName = docName.trim() docName = docName.trim()
Metrics.inc('editor.add-doc') Metrics.inc('editor.add-doc')
@@ -99,7 +99,7 @@ const EditorController = {
callback callback
) { ) {
if (callback == null) { if (callback == null) {
callback = function(error, file) {} callback = function (error, file) {}
} }
fileName = fileName.trim() fileName = fileName.trim()
Metrics.inc('editor.add-file') Metrics.inc('editor.add-file')
@@ -143,7 +143,7 @@ const EditorController = {
callback callback
) { ) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
return ProjectEntityUpdateHandler.upsertDoc( return ProjectEntityUpdateHandler.upsertDoc(
project_id, project_id,
@@ -152,7 +152,7 @@ const EditorController = {
docLines, docLines,
source, source,
user_id, user_id,
function(err, doc, didAddNewDoc) { function (err, doc, didAddNewDoc) {
if (didAddNewDoc) { if (didAddNewDoc) {
EditorRealTimeController.emitToRoom( EditorRealTimeController.emitToRoom(
project_id, project_id,
@@ -179,7 +179,7 @@ const EditorController = {
callback callback
) { ) {
if (callback == null) { if (callback == null) {
callback = function(err, file) {} callback = function (err, file) {}
} }
return ProjectEntityUpdateHandler.upsertFile( return ProjectEntityUpdateHandler.upsertFile(
project_id, project_id,
@@ -188,7 +188,7 @@ const EditorController = {
fsPath, fsPath,
linkedFileData, linkedFileData,
user_id, user_id,
function(err, newFile, didAddFile, existingFile) { function (err, newFile, didAddFile, existingFile) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -230,14 +230,14 @@ const EditorController = {
docLines, docLines,
source, source,
user_id, user_id,
function(err, doc, didAddNewDoc, newFolders, lastFolder) { function (err, doc, didAddNewDoc, newFolders, lastFolder) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
return EditorController._notifyProjectUsersOfNewFolders( return EditorController._notifyProjectUsersOfNewFolders(
project_id, project_id,
newFolders, newFolders,
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -273,14 +273,21 @@ const EditorController = {
fsPath, fsPath,
linkedFileData, linkedFileData,
user_id, user_id,
function(err, newFile, didAddFile, existingFile, newFolders, lastFolder) { function (
err,
newFile,
didAddFile,
existingFile,
newFolders,
lastFolder
) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
return EditorController._notifyProjectUsersOfNewFolders( return EditorController._notifyProjectUsersOfNewFolders(
project_id, project_id,
newFolders, newFolders,
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -312,7 +319,7 @@ const EditorController = {
addFolder(project_id, folder_id, folderName, source, userId, callback) { addFolder(project_id, folder_id, folderName, source, userId, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, folder) {} callback = function (error, folder) {}
} }
folderName = folderName.trim() folderName = folderName.trim()
Metrics.inc('editor.add-folder') Metrics.inc('editor.add-folder')
@@ -335,7 +342,7 @@ const EditorController = {
folder_id, folder_id,
folder, folder,
userId, userId,
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -348,7 +355,7 @@ const EditorController = {
mkdirp(project_id, path, callback) { mkdirp(project_id, path, callback) {
if (callback == null) { 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") logger.log({ project_id, path }, "making directories if they don't exist")
return ProjectEntityUpdateHandler.mkdirp( return ProjectEntityUpdateHandler.mkdirp(
@@ -366,7 +373,7 @@ const EditorController = {
return EditorController._notifyProjectUsersOfNewFolders( return EditorController._notifyProjectUsersOfNewFolders(
project_id, project_id,
newFolders, newFolders,
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -379,7 +386,7 @@ const EditorController = {
deleteEntity(project_id, entity_id, entityType, source, userId, callback) { deleteEntity(project_id, entity_id, entityType, source, userId, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
Metrics.inc('editor.delete-entity') Metrics.inc('editor.delete-entity')
return ProjectEntityUpdateHandler.deleteEntity( return ProjectEntityUpdateHandler.deleteEntity(
@@ -387,7 +394,7 @@ const EditorController = {
entity_id, entity_id,
entityType, entityType,
userId, userId,
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'could not delete entity', { OError.tag(err, 'could not delete entity', {
project_id, project_id,
@@ -416,7 +423,7 @@ const EditorController = {
project_id, project_id,
path, path,
user_id, user_id,
function(err, entity_id) { function (err, entity_id) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -433,13 +440,13 @@ const EditorController = {
updateProjectDescription(project_id, description, callback) { updateProjectDescription(project_id, description, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
logger.log({ project_id, description }, 'updating project description') logger.log({ project_id, description }, 'updating project description')
return ProjectDetailsHandler.setProjectDescription( return ProjectDetailsHandler.setProjectDescription(
project_id, project_id,
description, description,
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag( OError.tag(
err, err,
@@ -468,7 +475,7 @@ const EditorController = {
renameEntity(project_id, entity_id, entityType, newName, userId, callback) { renameEntity(project_id, entity_id, entityType, newName, userId, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
newName = sanitize.escape(newName) newName = sanitize.escape(newName)
Metrics.inc('editor.rename-entity') Metrics.inc('editor.rename-entity')
@@ -478,7 +485,7 @@ const EditorController = {
entityType, entityType,
newName, newName,
userId, userId,
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'error renaming entity', { OError.tag(err, 'error renaming entity', {
project_id, project_id,
@@ -503,7 +510,7 @@ const EditorController = {
moveEntity(project_id, entity_id, folder_id, entityType, userId, callback) { moveEntity(project_id, entity_id, folder_id, entityType, userId, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
Metrics.inc('editor.move-entity') Metrics.inc('editor.move-entity')
return ProjectEntityUpdateHandler.moveEntity( return ProjectEntityUpdateHandler.moveEntity(
@@ -512,7 +519,7 @@ const EditorController = {
folder_id, folder_id,
entityType, entityType,
userId, userId,
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'error moving entity', { OError.tag(err, 'error moving entity', {
project_id, project_id,
@@ -534,73 +541,79 @@ const EditorController = {
renameProject(project_id, newName, callback) { renameProject(project_id, newName, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
return ProjectDetailsHandler.renameProject(project_id, newName, function( return ProjectDetailsHandler.renameProject(
err project_id,
) { newName,
if (err != null) { function (err) {
OError.tag(err, 'error renaming project', { if (err != null) {
OError.tag(err, 'error renaming project', {
project_id,
newName
})
return callback(err)
}
EditorRealTimeController.emitToRoom(
project_id, project_id,
'projectNameUpdated',
newName newName
}) )
return callback(err) return callback()
} }
EditorRealTimeController.emitToRoom( )
project_id,
'projectNameUpdated',
newName
)
return callback()
})
}, },
setCompiler(project_id, compiler, callback) { setCompiler(project_id, compiler, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
return ProjectOptionsHandler.setCompiler(project_id, compiler, function( return ProjectOptionsHandler.setCompiler(
err project_id,
) { compiler,
if (err != null) { function (err) {
return callback(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) { setImageName(project_id, imageName, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
return ProjectOptionsHandler.setImageName(project_id, imageName, function( return ProjectOptionsHandler.setImageName(
err project_id,
) { imageName,
if (err != null) { function (err) {
return callback(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) { setSpellCheckLanguage(project_id, languageCode, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
return ProjectOptionsHandler.setSpellCheckLanguage( return ProjectOptionsHandler.setSpellCheckLanguage(
project_id, project_id,
languageCode, languageCode,
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -616,12 +629,12 @@ const EditorController = {
setPublicAccessLevel(project_id, newAccessLevel, callback) { setPublicAccessLevel(project_id, newAccessLevel, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
return ProjectDetailsHandler.setPublicAccessLevel( return ProjectDetailsHandler.setPublicAccessLevel(
project_id, project_id,
newAccessLevel, newAccessLevel,
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -633,7 +646,7 @@ const EditorController = {
if (newAccessLevel === PublicAccessLevels.TOKEN_BASED) { if (newAccessLevel === PublicAccessLevels.TOKEN_BASED) {
return ProjectDetailsHandler.ensureTokensArePresent( return ProjectDetailsHandler.ensureTokensArePresent(
project_id, project_id,
function(err, tokens) { function (err, tokens) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -654,12 +667,12 @@ const EditorController = {
setRootDoc(project_id, newRootDocID, callback) { setRootDoc(project_id, newRootDocID, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
return ProjectEntityUpdateHandler.setRootDoc( return ProjectEntityUpdateHandler.setRootDoc(
project_id, project_id,
newRootDocID, newRootDocID,
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -675,7 +688,7 @@ const EditorController = {
_notifyProjectUsersOfNewFolders(project_id, folders, callback) { _notifyProjectUsersOfNewFolders(project_id, folders, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return async.eachSeries( return async.eachSeries(
folders, folders,
@@ -699,7 +712,7 @@ const EditorController = {
callback callback
) { ) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
EditorRealTimeController.emitToRoom( EditorRealTimeController.emitToRoom(
project_id, project_id,

View File

@@ -49,41 +49,41 @@ module.exports = {
} }
} }
return ExportsHandler.exportProject(export_params, function( return ExportsHandler.exportProject(
err, export_params,
export_data function (err, export_data) {
) { if (err != null) {
if (err != null) { if (err.forwardResponse != null) {
if (err.forwardResponse != null) { logger.log(
logger.log( { responseError: err.forwardResponse },
{ responseError: err.forwardResponse }, 'forwarding response'
'forwarding response' )
) const statusCode = err.forwardResponse.status || 500
const statusCode = err.forwardResponse.status || 500 return res.status(statusCode).json(err.forwardResponse)
return res.status(statusCode).json(err.forwardResponse) } else {
} else { return next(err)
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) { exportStatus(req, res) {
const { export_id } = req.params 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 let json
if (err != null) { if (err != null) {
json = { json = {
@@ -112,15 +112,16 @@ module.exports = {
const { type, export_id } = req.params const { type, export_id } = req.params
AuthenticationController.getLoggedInUserId(req) AuthenticationController.getLoggedInUserId(req)
return ExportsHandler.fetchDownload(export_id, type, function( return ExportsHandler.fetchDownload(
err, export_id,
export_file_url type,
) { function (err, export_file_url) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} }
return res.redirect(export_file_url) return res.redirect(export_file_url)
}) }
)
} }
} }

View File

@@ -30,13 +30,13 @@ settings = require('settings-sharelatex')
module.exports = ExportsHandler = self = { module.exports = ExportsHandler = self = {
exportProject(export_params, callback) { exportProject(export_params, callback) {
if (callback == null) { 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) { if (err != null) {
return callback(err) return callback(err)
} }
return self._requestExport(export_data, function(err, body) { return self._requestExport(export_data, function (err, body) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -50,7 +50,7 @@ module.exports = ExportsHandler = self = {
_buildExport(export_params, callback) { _buildExport(export_params, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, export_data) {} callback = function (err, export_data) {}
} }
const { const {
project_id, project_id,
@@ -70,17 +70,18 @@ module.exports = ExportsHandler = self = {
rootDoc: [ rootDoc: [
'project', 'project',
(cb, results) => (cb, results) =>
ProjectRootDocManager.ensureRootDocumentIsValid(project_id, function( ProjectRootDocManager.ensureRootDocumentIsValid(
error project_id,
) { function (error) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
}
return ProjectLocator.findRootDoc(
{ project: results.project, project_id },
cb
)
} }
return ProjectLocator.findRootDoc( )
{ project: results.project, project_id },
cb
)
})
], ],
user(cb) { user(cb) {
return UserGetter.getUser( return UserGetter.getUser(
@@ -92,7 +93,7 @@ module.exports = ExportsHandler = self = {
historyVersion(cb) { historyVersion(cb) {
return ProjectHistoryHandler.ensureHistoryExistsForProject( return ProjectHistoryHandler.ensureHistoryExistsForProject(
project_id, project_id,
function(error) { function (error) {
if (error != null) { if (error != null) {
return callback(error) 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) { if (err != null) {
OError.tag(err, 'error building project export', { OError.tag(err, 'error building project export', {
project_id, project_id,
@@ -167,7 +168,7 @@ module.exports = ExportsHandler = self = {
_requestExport(export_data, callback) { _requestExport(export_data, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, export_v1_id) {} callback = function (err, export_v1_id) {}
} }
return request.post( return request.post(
{ {
@@ -175,7 +176,7 @@ module.exports = ExportsHandler = self = {
auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass }, auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass },
json: export_data json: export_data
}, },
function(err, res, body) { function (err, res, body) {
if (err != null) { if (err != null) {
OError.tag(err, 'error making request to v1 export', { OError.tag(err, 'error making request to v1 export', {
export: export_data export: export_data
@@ -197,14 +198,14 @@ module.exports = ExportsHandler = self = {
_requestVersion(project_id, callback) { _requestVersion(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, export_v1_id) {} callback = function (err, export_v1_id) {}
} }
return request.get( return request.get(
{ {
url: `${settings.apis.project_history.url}/project/${project_id}/version`, url: `${settings.apis.project_history.url}/project/${project_id}/version`,
json: true json: true
}, },
function(err, res, body) { function (err, res, body) {
if (err != null) { if (err != null) {
OError.tag(err, 'error making request to project history', { OError.tag(err, 'error making request to project history', {
project_id project_id
@@ -225,14 +226,14 @@ module.exports = ExportsHandler = self = {
fetchExport(export_id, callback) { fetchExport(export_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, export_json) {} callback = function (err, export_json) {}
} }
return request.get( return request.get(
{ {
url: `${settings.apis.v1.url}/api/v1/sharelatex/exports/${export_id}`, url: `${settings.apis.v1.url}/api/v1/sharelatex/exports/${export_id}`,
auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass } auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass }
}, },
function(err, res, body) { function (err, res, body) {
if (err != null) { if (err != null) {
OError.tag(err, 'error making request to v1 export', { OError.tag(err, 'error making request to v1 export', {
export: export_id export: export_id
@@ -253,14 +254,14 @@ module.exports = ExportsHandler = self = {
fetchDownload(export_id, type, callback) { fetchDownload(export_id, type, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, file_url) {} callback = function (err, file_url) {}
} }
return request.get( return request.get(
{ {
url: `${settings.apis.v1.url}/api/v1/sharelatex/exports/${export_id}/${type}_url`, url: `${settings.apis.v1.url}/api/v1/sharelatex/exports/${export_id}/${type}_url`,
auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass } auth: { user: settings.apis.v1.user, pass: settings.apis.v1.pass }
}, },
function(err, res, body) { function (err, res, body) {
if (err != null) { if (err != null) {
OError.tag(err, 'error making request to v1 export', { OError.tag(err, 'error making request to v1 export', {
export: export_id export: export_id

View File

@@ -20,7 +20,7 @@ const _ = require('underscore')
module.exports = FileHashManager = { module.exports = FileHashManager = {
computeHash(filePath, callback) { computeHash(filePath, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, hashValue) {} callback = function (error, hashValue) {}
} }
callback = _.once(callback) // avoid double callbacks callback = _.once(callback) // avoid double callbacks
@@ -28,20 +28,20 @@ module.exports = FileHashManager = {
const getGitBlobHeader = byteLength => `blob ${byteLength}` + '\x00' const getGitBlobHeader = byteLength => `blob ${byteLength}` + '\x00'
const getByteLengthOfFile = cb => const getByteLengthOfFile = cb =>
fs.stat(filePath, function(err, stats) { fs.stat(filePath, function (err, stats) {
if (err != null) { if (err != null) {
return cb(err) return cb(err)
} }
return cb(null, stats.size) return cb(null, stats.size)
}) })
return getByteLengthOfFile(function(err, byteLength) { return getByteLengthOfFile(function (err, byteLength) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
const input = fs.createReadStream(filePath) const input = fs.createReadStream(filePath)
input.on('error', function(err) { input.on('error', function (err) {
logger.warn({ filePath, err }, 'error opening file in computeHash') logger.warn({ filePath, err }, 'error opening file in computeHash')
return callback(err) return callback(err)
}) })
@@ -49,7 +49,7 @@ module.exports = FileHashManager = {
const hash = crypto.createHash('sha1') const hash = crypto.createHash('sha1')
hash.setEncoding('hex') hash.setEncoding('hex')
hash.update(getGitBlobHeader(byteLength)) hash.update(getGitBlobHeader(byteLength))
hash.on('readable', function() { hash.on('readable', function () {
const result = hash.read() const result = hash.read()
if (result != null) { if (result != null) {
return callback(null, result.toString('hex')) return callback(null, result.toString('hex'))

View File

@@ -12,7 +12,7 @@ module.exports = {
const userAgent = req.get('User-Agent') const userAgent = req.get('User-Agent')
ProjectLocator.findElement( ProjectLocator.findElement(
{ project_id: projectId, element_id: fileId, type: 'file' }, { project_id: projectId, element_id: fileId, type: 'file' },
function(err, file) { function (err, file) {
if (err) { if (err) {
logger.err( logger.err(
{ err, projectId, fileId, queryString }, { err, projectId, fileId, queryString },
@@ -20,24 +20,26 @@ module.exports = {
) )
return res.sendStatus(500) return res.sendStatus(500)
} }
FileStoreHandler.getFileStream(projectId, fileId, queryString, function( FileStoreHandler.getFileStream(
err, projectId,
stream fileId,
) { queryString,
if (err) { function (err, stream) {
logger.err( if (err) {
{ err, projectId, fileId, queryString }, logger.err(
'error getting file stream for downloading file' { err, projectId, fileId, queryString },
) 'error getting file stream for downloading file'
return res.sendStatus(500) )
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)
})
} }
) )
}, },

View File

@@ -17,7 +17,7 @@ const FileStoreHandler = {
RETRY_ATTEMPTS: 3, RETRY_ATTEMPTS: 3,
uploadFileFromDisk(projectId, fileArgs, fsPath, callback) { uploadFileFromDisk(projectId, fileArgs, fsPath, callback) {
fs.lstat(fsPath, function(err, stat) { fs.lstat(fsPath, function (err, stat) {
if (err) { if (err) {
logger.warn({ err, projectId, fileArgs, fsPath }, 'error stating file') logger.warn({ err, projectId, fileArgs, fsPath }, 'error stating file')
callback(err) callback(err)
@@ -45,7 +45,7 @@ const FileStoreHandler = {
fsPath, fsPath,
cb cb
), ),
function(err, result) { function (err, result) {
if (err) { if (err) {
OError.tag(err, 'Error uploading file, retries failed', { OError.tag(err, 'Error uploading file, retries failed', {
projectId, projectId,
@@ -62,21 +62,21 @@ const FileStoreHandler = {
_doUploadFileFromDisk(projectId, fileArgs, fsPath, callback) { _doUploadFileFromDisk(projectId, fileArgs, fsPath, callback) {
const callbackOnce = _.once(callback) const callbackOnce = _.once(callback)
FileHashManager.computeHash(fsPath, function(err, hashValue) { FileHashManager.computeHash(fsPath, function (err, hashValue) {
if (err) { if (err) {
return callbackOnce(err) return callbackOnce(err)
} }
const fileRef = new File(Object.assign({}, fileArgs, { hash: hashValue })) const fileRef = new File(Object.assign({}, fileArgs, { hash: hashValue }))
const fileId = fileRef._id const fileId = fileRef._id
const readStream = fs.createReadStream(fsPath) const readStream = fs.createReadStream(fsPath)
readStream.on('error', function(err) { readStream.on('error', function (err) {
logger.warn( logger.warn(
{ err, projectId, fileId, fsPath }, { err, projectId, fileId, fsPath },
'something went wrong on the read stream of uploadFileFromDisk' 'something went wrong on the read stream of uploadFileFromDisk'
) )
callbackOnce(err) callbackOnce(err)
}) })
readStream.on('open', function() { readStream.on('open', function () {
const url = FileStoreHandler._buildUrl(projectId, fileId) const url = FileStoreHandler._buildUrl(projectId, fileId)
const opts = { const opts = {
method: 'post', method: 'post',
@@ -87,14 +87,14 @@ const FileStoreHandler = {
} // send the hash to the filestore as a custom header so it can be checked } // send the hash to the filestore as a custom header so it can be checked
} }
const writeStream = request(opts) const writeStream = request(opts)
writeStream.on('error', function(err) { writeStream.on('error', function (err) {
logger.warn( logger.warn(
{ err, projectId, fileId, fsPath }, { err, projectId, fileId, fsPath },
'something went wrong on the write stream of uploadFileFromDisk' 'something went wrong on the write stream of uploadFileFromDisk'
) )
callbackOnce(err) callbackOnce(err)
}) })
writeStream.on('response', function(response) { writeStream.on('response', function (response) {
if (![200, 201].includes(response.statusCode)) { if (![200, 201].includes(response.statusCode)) {
err = new OError( err = new OError(
`non-ok response from filestore for upload: ${response.statusCode}`, `non-ok response from filestore for upload: ${response.statusCode}`,
@@ -168,7 +168,7 @@ const FileStoreHandler = {
uri: this._buildUrl(projectId, fileId), uri: this._buildUrl(projectId, fileId),
timeout: FIVE_MINS_IN_MS timeout: FIVE_MINS_IN_MS
} }
return request(opts, function(err, response) { return request(opts, function (err, response) {
if (err) { if (err) {
logger.warn( logger.warn(
{ err, projectId, fileId }, { err, projectId, fileId },
@@ -217,7 +217,7 @@ const FileStoreHandler = {
uri: this._buildUrl(newProjectId, newFileId), uri: this._buildUrl(newProjectId, newFileId),
timeout: FIVE_MINS_IN_MS timeout: FIVE_MINS_IN_MS
} }
return request(opts, function(err, response) { return request(opts, function (err, response) {
if (err) { if (err) {
OError.tag( OError.tag(
err, err,

View File

@@ -61,7 +61,7 @@ module.exports = {
}, },
checkRedis(req, res, next) { checkRedis(req, res, next) {
return rclient.healthCheck(function(error) { return rclient.healthCheck(function (error) {
if (error != null) { if (error != null) {
logger.err({ err: error }, 'failed redis health check') logger.err({ err: error }, 'failed redis health check')
return res.sendStatus(500) return res.sendStatus(500)
@@ -72,23 +72,23 @@ module.exports = {
}, },
checkMongo(req, res, next) { checkMongo(req, res, next) {
return UserGetter.getUserEmail(settings.smokeTest.userId, function( return UserGetter.getUserEmail(
err, settings.smokeTest.userId,
email function (err, email) {
) { if (err != null) {
if (err != null) { logger.err({ err }, 'mongo health check failed, error present')
logger.err({ err }, 'mongo health check failed, error present') return res.sendStatus(500)
return res.sendStatus(500) } else if (email == null) {
} else if (email == null) { logger.err(
logger.err( { err },
{ err }, 'mongo health check failed, no emai present in find result'
'mongo health check failed, no emai present in find result' )
) return res.sendStatus(500)
return res.sendStatus(500) } else {
} else { return res.sendStatus(200)
return res.sendStatus(200) }
} }
}) )
} }
} }

View File

@@ -17,7 +17,7 @@ module.exports = HistoryController = {
selectHistoryApi(req, res, next) { selectHistoryApi(req, res, next) {
const { Project_id: projectId } = req.params const { Project_id: projectId } = req.params
// find out which type of history service this project uses // find out which type of history service this project uses
ProjectDetailsHandler.getDetails(projectId, function(err, project) { ProjectDetailsHandler.getDetails(projectId, function (err, project) {
if (err) { if (err) {
return next(err) return next(err)
} }
@@ -52,7 +52,7 @@ module.exports = HistoryController = {
} }
}) })
getReq.pipe(res) getReq.pipe(res)
getReq.on('error', function(err) { getReq.on('error', function (err) {
logger.warn({ url, err }, 'history API error') logger.warn({ url, err }, 'history API error')
next(err) next(err)
}) })
@@ -71,11 +71,11 @@ module.exports = HistoryController = {
'X-User-Id': userId 'X-User-Id': userId
} }
}, },
function(err, body) { function (err, body) {
if (err) { if (err) {
return next(err) return next(err)
} }
HistoryManager.injectUserDetails(body, function(err, data) { HistoryManager.injectUserDetails(body, function (err, data) {
if (err) { if (err) {
return next(err) return next(err)
} }
@@ -97,7 +97,7 @@ module.exports = HistoryController = {
resyncProjectHistory(req, res, next) { resyncProjectHistory(req, res, next) {
const projectId = req.params.Project_id const projectId = req.params.Project_id
ProjectEntityUpdateHandler.resyncProjectHistory(projectId, function(err) { ProjectEntityUpdateHandler.resyncProjectHistory(projectId, function (err) {
if (err instanceof Errors.ProjectHistoryDisabledError) { if (err instanceof Errors.ProjectHistoryDisabledError) {
return res.sendStatus(404) return res.sendStatus(404)
} }
@@ -117,7 +117,7 @@ module.exports = HistoryController = {
projectId, projectId,
version, version,
pathname, pathname,
function(err, entity) { function (err, entity) {
if (err) { if (err) {
return next(err) return next(err)
} }
@@ -158,7 +158,7 @@ module.exports = HistoryController = {
url: `${settings.apis.project_history.url}/project/${projectId}/labels`, url: `${settings.apis.project_history.url}/project/${projectId}/labels`,
json: true json: true
}, },
function(err, labels) { function (err, labels) {
if (err) { if (err) {
return next(err) return next(err)
} }
@@ -182,7 +182,7 @@ module.exports = HistoryController = {
url: `${settings.apis.project_history.url}/project/${projectId}/user/${userId}/labels`, url: `${settings.apis.project_history.url}/project/${projectId}/user/${userId}/labels`,
json: { comment, version } json: { comment, version }
}, },
function(err, label) { function (err, label) {
if (err) { if (err) {
return next(err) return next(err)
} }
@@ -230,7 +230,7 @@ module.exports = HistoryController = {
UserGetter.getUsers( UserGetter.getUsers(
Array.from(uniqueUsers), Array.from(uniqueUsers),
{ first_name: 1, last_name: 1, email: 1 }, { first_name: 1, last_name: 1, email: 1 },
function(err, rawUsers) { function (err, rawUsers) {
if (err) { if (err) {
return callback(err) return callback(err)
} }
@@ -274,7 +274,7 @@ module.exports = HistoryController = {
method: 'DELETE', method: 'DELETE',
url: `${settings.apis.project_history.url}/project/${projectId}/user/${userId}/labels/${labelId}` url: `${settings.apis.project_history.url}/project/${projectId}/user/${userId}/labels/${labelId}`
}, },
function(err) { function (err) {
if (err) { if (err) {
return next(err) return next(err)
} }
@@ -284,7 +284,7 @@ module.exports = HistoryController = {
}, },
_makeRequest(options, callback) { _makeRequest(options, callback) {
return request(options, function(err, response, body) { return request(options, function (err, response, body) {
if (err) { if (err) {
return callback(err) return callback(err)
} }
@@ -301,7 +301,7 @@ module.exports = HistoryController = {
downloadZipOfVersion(req, res, next) { downloadZipOfVersion(req, res, next) {
const { project_id: projectId, version } = req.params const { project_id: projectId, version } = req.params
ProjectDetailsHandler.getDetails(projectId, function(err, project) { ProjectDetailsHandler.getDetails(projectId, function (err, project) {
if (err) { if (err) {
return next(err) return next(err)
} }
@@ -344,7 +344,7 @@ module.exports = HistoryController = {
method: 'post', method: 'post',
url url
} }
request(options, function(err, response, body) { request(options, function (err, response, body) {
if (err) { if (err) {
OError.tag(err, 'history API error', { OError.tag(err, 'history API error', {
v1ProjectId, v1ProjectId,
@@ -362,7 +362,7 @@ module.exports = HistoryController = {
async.retry( async.retry(
40, 40,
callback => callback =>
setTimeout(function() { setTimeout(function () {
if (req.aborted) { if (req.aborted) {
// client has disconnected -- skip s3 download // client has disconnected -- skip s3 download
return callback() // stop async.retry loop return callback() // stop async.retry loop
@@ -384,7 +384,7 @@ module.exports = HistoryController = {
req.off('aborted', abortS3Request) req.off('aborted', abortS3Request)
res.off('timeout', abortS3Request) res.off('timeout', abortS3Request)
} }
getReq.on('response', function(response) { getReq.on('response', function (response) {
if (response.statusCode !== 200) { if (response.statusCode !== 200) {
cleanupAbortTrigger() cleanupAbortTrigger()
return callback(new Error('invalid response')) return callback(new Error('invalid response'))
@@ -407,7 +407,7 @@ module.exports = HistoryController = {
}) })
callback() callback()
}) })
getReq.on('error', function(err) { getReq.on('error', function (err) {
logger.warn( logger.warn(
{ err, v1ProjectId, version, retryAttempt }, { err, v1ProjectId, version, retryAttempt },
'history s3 download error' 'history s3 download error'
@@ -416,7 +416,7 @@ module.exports = HistoryController = {
callback(err) callback(err)
}) })
}, retryDelay), }, retryDelay),
function(err) { function (err) {
if (err) { if (err) {
OError.tag(err, 'history s3 download failed', { OError.tag(err, 'history s3 download failed', {
v1ProjectId, v1ProjectId,

View File

@@ -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. // 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. // We don't actually remove the deleted doc entry, just create a new one from its lines.
if (callback == null) { if (callback == null) {
callback = function(error, doc, folder_id) {} callback = function (error, doc, folder_id) {}
} }
return ProjectEntityHandler.getDoc( return ProjectEntityHandler.getDoc(
project_id, project_id,
doc_id, doc_id,
{ include_deleted: true }, { include_deleted: true },
function(error, lines) { function (error, lines) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -59,13 +59,13 @@ module.exports = RestoreManager = {
restoreFileFromV2(user_id, project_id, version, pathname, callback) { restoreFileFromV2(user_id, project_id, version, pathname, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, entity) {} callback = function (error, entity) {}
} }
return RestoreManager._writeFileVersionToDisk( return RestoreManager._writeFileVersionToDisk(
project_id, project_id,
version, version,
pathname, pathname,
function(error, fsPath) { function (error, fsPath) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -75,54 +75,55 @@ module.exports = RestoreManager = {
// no directory // no directory
dirname = '' dirname = ''
} }
return RestoreManager._findOrCreateFolder(project_id, dirname, function( return RestoreManager._findOrCreateFolder(
error, project_id,
parent_folder_id dirname,
) { function (error, parent_folder_id) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
const addEntityWithName = (name, callback) => const addEntityWithName = (name, callback) =>
FileSystemImportManager.addEntity( FileSystemImportManager.addEntity(
user_id, user_id,
project_id, project_id,
parent_folder_id, parent_folder_id,
name, name,
fsPath, fsPath,
false, false,
callback
)
return RestoreManager._addEntityWithUniqueName(
addEntityWithName,
basename,
callback callback
) )
return RestoreManager._addEntityWithUniqueName( }
addEntityWithName, )
basename,
callback
)
})
} }
) )
}, },
_findOrCreateFolder(project_id, dirname, callback) { _findOrCreateFolder(project_id, dirname, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, folder_id) {} callback = function (error, folder_id) {}
} }
return EditorController.mkdirp(project_id, dirname, function( return EditorController.mkdirp(
error, project_id,
newFolders, dirname,
lastFolder function (error, newFolders, lastFolder) {
) { if (error != null) {
if (error != null) { return callback(error)
return callback(error) }
return callback(null, lastFolder != null ? lastFolder._id : undefined)
} }
return callback(null, lastFolder != null ? lastFolder._id : undefined) )
})
}, },
_addEntityWithUniqueName(addEntityWithName, basename, callback) { _addEntityWithUniqueName(addEntityWithName, basename, callback) {
if (callback == null) { 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 != null) {
if (error instanceof Errors.InvalidNameError) { if (error instanceof Errors.InvalidNameError) {
// likely a duplicate name, so try with a prefix // likely a duplicate name, so try with a prefix
@@ -146,7 +147,7 @@ module.exports = RestoreManager = {
_writeFileVersionToDisk(project_id, version, pathname, callback) { _writeFileVersionToDisk(project_id, version, pathname, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, fsPath) {} callback = function (error, fsPath) {}
} }
const url = `${ const url = `${
Settings.apis.project_history.url Settings.apis.project_history.url

View File

@@ -22,7 +22,7 @@ module.exports = {
return InactiveProjectManager.deactivateOldProjects( return InactiveProjectManager.deactivateOldProjects(
numberOfProjectsToArchive, numberOfProjectsToArchive,
ageOfProjects, ageOfProjects,
function(err, projectsDeactivated) { function (err, projectsDeactivated) {
if (err != null) { if (err != null) {
return res.sendStatus(500) return res.sendStatus(500)
} else { } else {
@@ -34,7 +34,7 @@ module.exports = {
deactivateProject(req, res) { deactivateProject(req, res) {
const { project_id } = req.params const { project_id } = req.params
return InactiveProjectManager.deactivateProject(project_id, function(err) { return InactiveProjectManager.deactivateProject(project_id, function (err) {
if (err != null) { if (err != null) {
return res.sendStatus(500) return res.sendStatus(500)
} else { } else {

View File

@@ -24,35 +24,36 @@ const { ObjectId } = require('mongodb')
const MILISECONDS_IN_DAY = 86400000 const MILISECONDS_IN_DAY = 86400000
module.exports = InactiveProjectManager = { module.exports = InactiveProjectManager = {
reactivateProjectIfRequired(project_id, callback) { reactivateProjectIfRequired(project_id, callback) {
return ProjectGetter.getProject(project_id, { active: true }, function( return ProjectGetter.getProject(
err, project_id,
project { 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) {
if (err != null) { if (err != null) {
OError.tag(err, 'error reactivating project in docstore', { OError.tag(err, 'error getting project', {
project_id project_id
}) })
return callback(err) 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) { deactivateOldProjects(limit, daysOld, callback) {
@@ -73,12 +74,12 @@ module.exports = InactiveProjectManager = {
.sort({ _id: 1 }) .sort({ _id: 1 })
.limit(limit) .limit(limit)
.read('secondary') .read('secondary')
.exec(function(err, projects) { .exec(function (err, projects) {
if (err != null) { if (err != null) {
logger.err({ err }, 'could not get projects for deactivating') logger.err({ err }, 'could not get projects for deactivating')
} }
const jobs = _.map(projects, project => cb => const jobs = _.map(projects, project => cb =>
InactiveProjectManager.deactivateProject(project._id, function(err) { InactiveProjectManager.deactivateProject(project._id, function (err) {
if (err) { if (err) {
logger.err( logger.err(
{ project_id: project._id, err: err }, { project_id: project._id, err: err },
@@ -92,7 +93,7 @@ module.exports = InactiveProjectManager = {
{ numberOfProjects: projects && projects.length }, { numberOfProjects: projects && projects.length },
'deactivating projects' 'deactivating projects'
) )
async.series(jobs, function(err) { async.series(jobs, function (err) {
if (err != null) { if (err != null) {
logger.warn({ err }, 'error deactivating projects') logger.warn({ err }, 'error deactivating projects')
} }
@@ -107,7 +108,7 @@ module.exports = InactiveProjectManager = {
cb => DocstoreManager.archiveProject(project_id, cb), cb => DocstoreManager.archiveProject(project_id, cb),
cb => ProjectUpdateHandler.markAsInactive(project_id, cb) cb => ProjectUpdateHandler.markAsInactive(project_id, cb)
] ]
return async.series(jobs, function(err) { return async.series(jobs, function (err) {
if (err != null) { if (err != null) {
logger.warn({ err, project_id }, 'error deactivating project') logger.warn({ err, project_id }, 'error deactivating project')
} }

View File

@@ -99,7 +99,7 @@ const InstitutionsAPI = {
}, },
defaultErrorMessage: "Couldn't create affiliation" defaultErrorMessage: "Couldn't create affiliation"
}, },
function(error, body) { function (error, body) {
if (error) { if (error) {
if (error.info && error.info.statusCode === 422) { if (error.info && error.info.statusCode === 422) {
return callback( return callback(
@@ -115,7 +115,7 @@ const InstitutionsAPI = {
// have notifications delete any ip matcher notifications for this university // have notifications delete any ip matcher notifications for this university
NotificationsBuilder.ipMatcherAffiliation(userId).read( NotificationsBuilder.ipMatcherAffiliation(userId).read(
university.id, university.id,
function(err) { function (err) {
if (err) { if (err) {
// log and ignore error // log and ignore error
logger.err( logger.err(
@@ -191,7 +191,7 @@ const InstitutionsAPI = {
} }
} }
var makeAffiliationRequest = function(requestOptions, callback) { var makeAffiliationRequest = function (requestOptions, callback) {
if (!settings.apis.v1.url) { if (!settings.apis.v1.url) {
return callback(null) return callback(null)
} // service is not configured } // service is not configured
@@ -207,7 +207,7 @@ var makeAffiliationRequest = function(requestOptions, callback) {
json: true, json: true,
timeout: 20 * 1000 timeout: 20 * 1000
}, },
function(error, response, body) { function (error, response, body) {
if (error) { if (error) {
return callback( return callback(
new V1ConnectionError('error getting affiliations from v1').withCause( new V1ConnectionError('error getting affiliations from v1').withCause(

View File

@@ -8,7 +8,7 @@ const ASYNC_AFFILIATIONS_LIMIT = 10
module.exports = { module.exports = {
confirmDomain(req, res, next) { confirmDomain(req, res, next) {
const { hostname } = req.body const { hostname } = req.body
affiliateUsers(hostname, function(error) { affiliateUsers(hostname, function (error) {
if (error) { if (error) {
return next(error) return next(error)
} }
@@ -17,13 +17,9 @@ module.exports = {
} }
} }
var affiliateUsers = function(hostname, callback) { var affiliateUsers = function (hostname, callback) {
const reversedHostname = hostname const reversedHostname = hostname.trim().split('').reverse().join('')
.trim() UserGetter.getUsersByHostname(hostname, { _id: 1 }, function (error, users) {
.split('')
.reverse()
.join('')
UserGetter.getUsersByHostname(hostname, { _id: 1 }, function(error, users) {
if (error) { if (error) {
OError.tag(error, 'problem fetching users by hostname') OError.tag(error, 'problem fetching users by hostname')
return callback(error) return callback(error)
@@ -44,7 +40,7 @@ var affiliateUsers = function(hostname, callback) {
}) })
} }
var affiliateUserByReversedHostname = function( var affiliateUserByReversedHostname = function (
user, user,
reversedHostname, reversedHostname,
callback callback

View File

@@ -5,18 +5,21 @@ const Settings = require('settings-sharelatex')
module.exports = InstitutionsFeatures = { module.exports = InstitutionsFeatures = {
getInstitutionsFeatures(userId, callback) { getInstitutionsFeatures(userId, callback) {
InstitutionsFeatures.getInstitutionsPlan(userId, function(error, planCode) { InstitutionsFeatures.getInstitutionsPlan(
if (error) { userId,
return callback(error) 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) { getInstitutionsPlan(userId, callback) {
InstitutionsFeatures.hasLicence(userId, function(error, hasLicence) { InstitutionsFeatures.hasLicence(userId, function (error, hasLicence) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -28,7 +31,7 @@ module.exports = InstitutionsFeatures = {
}, },
hasLicence(userId, callback) { hasLicence(userId, callback) {
UserGetter.getUserFullEmails(userId, function(error, emailsData) { UserGetter.getUserFullEmails(userId, function (error, emailsData) {
if (error) { if (error) {
return callback(error) return callback(error)
} }

View File

@@ -5,7 +5,7 @@ const UserMembershipEntityConfigs = require('../UserMembership/UserMembershipEnt
module.exports = InstitutionsGetter = { module.exports = InstitutionsGetter = {
getConfirmedAffiliations(userId, callback) { getConfirmedAffiliations(userId, callback) {
UserGetter.getUserFullEmails(userId, function(error, emailsData) { UserGetter.getUserFullEmails(userId, function (error, emailsData) {
if (error) { if (error) {
return callback(error) return callback(error)
} }

View File

@@ -18,8 +18,8 @@ module.exports = {
async.waterfall( async.waterfall(
[ [
cb => fetchInstitutionAndAffiliations(institutionId, cb), cb => fetchInstitutionAndAffiliations(institutionId, cb),
function(institution, affiliations, cb) { function (institution, affiliations, cb) {
affiliations = _.map(affiliations, function(affiliation) { affiliations = _.map(affiliations, function (affiliation) {
affiliation.institutionName = institution.name affiliation.institutionName = institution.name
affiliation.institutionId = institutionId affiliation.institutionId = institutionId
return affiliation return affiliation
@@ -50,7 +50,7 @@ module.exports = {
}, },
getInstitutionUsersSubscriptions(institutionId, callback) { getInstitutionUsersSubscriptions(institutionId, callback) {
getInstitutionAffiliations(institutionId, function(error, affiliations) { getInstitutionAffiliations(institutionId, function (error, affiliations) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -84,12 +84,12 @@ var fetchInstitutionAndAffiliations = (institutionId, callback) =>
callback callback
) )
var refreshFeatures = function(affiliation, callback) { var refreshFeatures = function (affiliation, callback) {
const userId = ObjectId(affiliation.user_id) const userId = ObjectId(affiliation.user_id)
FeaturesUpdater.refreshFeatures(userId, callback) FeaturesUpdater.refreshFeatures(userId, callback)
} }
var refreshFeaturesAndNotify = function(affiliation, callback) { var refreshFeaturesAndNotify = function (affiliation, callback) {
const userId = ObjectId(affiliation.user_id) const userId = ObjectId(affiliation.user_id)
async.waterfall( async.waterfall(
[ [
@@ -124,7 +124,7 @@ var getUserInfo = (userId, callback) =>
var notifyUser = (user, affiliation, subscription, featuresChanged, callback) => var notifyUser = (user, affiliation, subscription, featuresChanged, callback) =>
async.parallel( async.parallel(
[ [
function(cb) { function (cb) {
if (featuresChanged) { if (featuresChanged) {
NotificationsBuilder.featuresUpgradedByAffiliation( NotificationsBuilder.featuresUpgradedByAffiliation(
affiliation, affiliation,
@@ -134,7 +134,7 @@ var notifyUser = (user, affiliation, subscription, featuresChanged, callback) =>
cb() cb()
} }
}, },
function(cb) { function (cb) {
if ( if (
subscription && subscription &&
!subscription.planCode.match(/(free|trial)/) && !subscription.planCode.match(/(free|trial)/) &&
@@ -152,7 +152,7 @@ var notifyUser = (user, affiliation, subscription, featuresChanged, callback) =>
callback callback
) )
var checkFeatures = function(institutionId, users) { var checkFeatures = function (institutionId, users) {
const usersSummary = { const usersSummary = {
confirmedEmailUsers: { confirmedEmailUsers: {
total: users.length, // all users are confirmed email users total: users.length, // all users are confirmed email users
@@ -167,7 +167,7 @@ var checkFeatures = function(institutionId, users) {
nonProUsers: [] nonProUsers: []
} }
} }
users.forEach(function(user) { users.forEach(function (user) {
let isSSOEntitled = SAMLIdentityManager.userHasEntitlement( let isSSOEntitled = SAMLIdentityManager.userHasEntitlement(
user, user,
institutionId institutionId

View File

@@ -75,7 +75,7 @@ module.exports = LinkedFilesController = {
name, name,
parent_folder_id, parent_folder_id,
user_id, user_id,
function(err, newFileId) { function (err, newFileId) {
if (err != null) { if (err != null) {
return LinkedFilesController.handleError(err, req, res, next) return LinkedFilesController.handleError(err, req, res, next)
} }
@@ -88,47 +88,46 @@ module.exports = LinkedFilesController = {
const { project_id, file_id } = req.params const { project_id, file_id } = req.params
const user_id = AuthenticationController.getLoggedInUserId(req) const user_id = AuthenticationController.getLoggedInUserId(req)
return LinkedFilesHandler.getFileById(project_id, file_id, function( return LinkedFilesHandler.getFileById(
err, project_id,
file, file_id,
path, function (err, file, path, parentFolder) {
parentFolder if (err != null) {
) { return next(err)
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 })
} }
) 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) { handleError(error, req, res, next) {

View File

@@ -28,7 +28,7 @@ const {
module.exports = LinkedFilesHandler = { module.exports = LinkedFilesHandler = {
getFileById(project_id, file_id, callback) { getFileById(project_id, file_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, file) {} callback = function (err, file) {}
} }
return ProjectLocator.findElement( return ProjectLocator.findElement(
{ {
@@ -36,7 +36,7 @@ module.exports = LinkedFilesHandler = {
element_id: file_id, element_id: file_id,
type: 'file' type: 'file'
}, },
function(err, file, path, parentFolder) { function (err, file, path, parentFolder) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -47,14 +47,14 @@ module.exports = LinkedFilesHandler = {
getSourceProject(data, callback) { getSourceProject(data, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, project) {} callback = function (err, project) {}
} }
const projection = { _id: 1, name: 1 } const projection = { _id: 1, name: 1 }
if (data.v1_source_doc_id != null) { if (data.v1_source_doc_id != null) {
return Project.findOne( return Project.findOne(
{ 'overleaf.id': data.v1_source_doc_id }, { 'overleaf.id': data.v1_source_doc_id },
projection, projection,
function(err, project) { function (err, project) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -68,7 +68,7 @@ module.exports = LinkedFilesHandler = {
return ProjectGetter.getProject( return ProjectGetter.getProject(
data.source_project_id, data.source_project_id,
projection, projection,
function(err, project) { function (err, project) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -93,32 +93,33 @@ module.exports = LinkedFilesHandler = {
callback callback
) { ) {
if (callback == null) { if (callback == null) {
callback = function(err, file) {} callback = function (err, file) {}
} }
callback = _.once(callback) callback = _.once(callback)
return FileWriter.writeStreamToDisk(project_id, readStream, function( return FileWriter.writeStreamToDisk(
err, project_id,
fsPath readStream,
) { function (err, fsPath) {
if (err != null) { if (err != null) {
return callback(err) 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 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( importContent(
@@ -131,31 +132,32 @@ module.exports = LinkedFilesHandler = {
callback callback
) { ) {
if (callback == null) { if (callback == null) {
callback = function(err, file) {} callback = function (err, file) {}
} }
callback = _.once(callback) callback = _.once(callback)
return FileWriter.writeContentToDisk(project_id, content, function( return FileWriter.writeContentToDisk(
err, project_id,
fsPath content,
) { function (err, fsPath) {
if (err != null) { if (err != null) {
return callback(err) 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 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)
}
)
}
)
} }
} }

View File

@@ -73,7 +73,7 @@ module.exports = ProjectFileAgent = {
_prepare(project_id, linkedFileData, user_id, callback) { _prepare(project_id, linkedFileData, user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, linkedFileData) {} callback = function (err, linkedFileData) {}
} }
return this._checkAuth( return this._checkAuth(
project_id, project_id,
@@ -118,7 +118,7 @@ module.exports = ProjectFileAgent = {
return DocstoreManager.getDoc( return DocstoreManager.getDoc(
source_project._id, source_project._id,
entity._id, entity._id,
function(err, lines) { function (err, lines) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -129,7 +129,7 @@ module.exports = ProjectFileAgent = {
name, name,
parent_folder_id, parent_folder_id,
user_id, user_id,
function(err, file) { function (err, file) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -143,7 +143,7 @@ module.exports = ProjectFileAgent = {
source_project._id, source_project._id,
entity._id, entity._id,
null, null,
function(err, fileStream) { function (err, fileStream) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -154,7 +154,7 @@ module.exports = ProjectFileAgent = {
name, name,
parent_folder_id, parent_folder_id,
user_id, user_id,
function(err, file) { function (err, file) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -174,18 +174,18 @@ module.exports = ProjectFileAgent = {
_getEntity(linkedFileData, current_user_id, callback) { _getEntity(linkedFileData, current_user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, entity, type) {} callback = function (err, entity, type) {}
} }
callback = _.once(callback) callback = _.once(callback)
const { source_entity_path } = linkedFileData const { source_entity_path } = linkedFileData
return this._getSourceProject(linkedFileData, function(err, project) { return this._getSourceProject(linkedFileData, function (err, project) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
const source_project_id = project._id const source_project_id = project._id
return DocumentUpdaterHandler.flushProjectToMongo( return DocumentUpdaterHandler.flushProjectToMongo(
source_project_id, source_project_id,
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -195,7 +195,7 @@ module.exports = ProjectFileAgent = {
path: source_entity_path, path: source_entity_path,
exactCaseMatch: true exactCaseMatch: true
}, },
function(err, entity, type) { function (err, entity, type) {
if (err != null) { if (err != null) {
if (/^not found.*/.test(err.toString())) { if (/^not found.*/.test(err.toString())) {
err = new SourceFileNotFoundError() err = new SourceFileNotFoundError()
@@ -236,13 +236,13 @@ module.exports = ProjectFileAgent = {
_checkAuth(project_id, data, current_user_id, callback) { _checkAuth(project_id, data, current_user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, allowed) {} callback = function (error, allowed) {}
} }
callback = _.once(callback) callback = _.once(callback)
if (!ProjectFileAgent._validate(data)) { if (!ProjectFileAgent._validate(data)) {
return callback(new BadDataError()) return callback(new BadDataError())
} }
return this._getSourceProject(data, function(err, project) { return this._getSourceProject(data, function (err, project) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -250,7 +250,7 @@ module.exports = ProjectFileAgent = {
current_user_id, current_user_id,
project._id, project._id,
null, null,
function(err, canRead) { function (err, canRead) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }

View File

@@ -32,7 +32,7 @@ const logger = require('logger-sharelatex')
module.exports = ProjectOutputFileAgent = { module.exports = ProjectOutputFileAgent = {
_prepare(project_id, linkedFileData, user_id, callback) { _prepare(project_id, linkedFileData, user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, linkedFileData) {} callback = function (err, linkedFileData) {}
} }
return this._checkAuth( return this._checkAuth(
project_id, project_id,
@@ -91,7 +91,7 @@ module.exports = ProjectOutputFileAgent = {
name, name,
parent_folder_id, parent_folder_id,
user_id, user_id,
function(err, file) { function (err, file) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -147,7 +147,7 @@ module.exports = ProjectOutputFileAgent = {
name, name,
parent_folder_id, parent_folder_id,
user_id, user_id,
function(err, file) { function (err, file) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -197,13 +197,13 @@ module.exports = ProjectOutputFileAgent = {
_checkAuth(project_id, data, current_user_id, callback) { _checkAuth(project_id, data, current_user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, allowed) {} callback = function (err, allowed) {}
} }
callback = _.once(callback) callback = _.once(callback)
if (!this._validate(data)) { if (!this._validate(data)) {
return callback(new BadDataError()) return callback(new BadDataError())
} }
return this._getSourceProject(data, function(err, project) { return this._getSourceProject(data, function (err, project) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -211,7 +211,7 @@ module.exports = ProjectOutputFileAgent = {
current_user_id, current_user_id,
project._id, project._id,
null, null,
function(err, canRead) { function (err, canRead) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -223,11 +223,11 @@ module.exports = ProjectOutputFileAgent = {
_getFileStream(linkedFileData, user_id, callback) { _getFileStream(linkedFileData, user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, fileStream) {} callback = function (err, fileStream) {}
} }
callback = _.once(callback) callback = _.once(callback)
const { source_output_file_path, build_id } = linkedFileData 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) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -237,7 +237,7 @@ module.exports = ProjectOutputFileAgent = {
user_id, user_id,
build_id, build_id,
source_output_file_path, source_output_file_path,
function(err, readStream) { function (err, readStream) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -250,48 +250,49 @@ module.exports = ProjectOutputFileAgent = {
_compileAndGetFileStream(linkedFileData, user_id, callback) { _compileAndGetFileStream(linkedFileData, user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, stream, build_id) {} callback = function (err, stream, build_id) {}
} }
callback = _.once(callback) callback = _.once(callback)
const { source_output_file_path } = linkedFileData const { source_output_file_path } = linkedFileData
return this._getSourceProject(linkedFileData, function(err, project) { return this._getSourceProject(linkedFileData, function (err, project) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
const source_project_id = project._id const source_project_id = project._id
return CompileManager.compile(source_project_id, user_id, {}, function( return CompileManager.compile(
err, source_project_id,
status, user_id,
outputFiles {},
) { function (err, status, outputFiles) {
if (err != null) { if (err != null) {
return callback(err) 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)
} }
) 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)
}
)
}
)
}) })
} }
} }

View File

@@ -30,40 +30,42 @@ module.exports = UrlAgent = {
callback callback
) { ) {
linkedFileData = this._sanitizeData(linkedFileData) linkedFileData = this._sanitizeData(linkedFileData)
return this._getUrlStream(project_id, linkedFileData, user_id, function( return this._getUrlStream(
err, project_id,
readStream linkedFileData,
) { user_id,
if (err != null) { function (err, readStream) {
return callback(err) 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)
} }
}) 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( refreshLinkedFile(
@@ -93,7 +95,7 @@ module.exports = UrlAgent = {
_getUrlStream(project_id, data, current_user_id, callback) { _getUrlStream(project_id, data, current_user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, fsPath) {} callback = function (error, fsPath) {}
} }
callback = _.once(callback) callback = _.once(callback)
let { url } = data let { url } = data

View File

@@ -21,22 +21,22 @@ module.exports = MetaController = {
getMetadata(req, res, next) { getMetadata(req, res, next) {
const { project_id } = req.params const { project_id } = req.params
logger.log({ project_id }, 'getting all labels for project') logger.log({ project_id }, 'getting all labels for project')
return MetaHandler.getAllMetaForProject(project_id, function( return MetaHandler.getAllMetaForProject(
err, project_id,
projectMeta function (err, projectMeta) {
) { if (err != null) {
if (err != null) { OError.tag(
OError.tag( err,
err, '[MetaController] error getting all labels from project',
'[MetaController] error getting all labels from project', {
{ project_id
project_id }
} )
) return next(err)
return next(err) }
return res.json({ projectId: project_id, projectMeta })
} }
return res.json({ projectId: project_id, projectMeta }) )
})
}, },
broadcastMetadataForDoc(req, res, next) { broadcastMetadataForDoc(req, res, next) {
@@ -44,27 +44,28 @@ module.exports = MetaController = {
const { doc_id } = req.params const { doc_id } = req.params
const { broadcast } = req.body const { broadcast } = req.body
logger.log({ project_id, doc_id, broadcast }, 'getting labels for doc') logger.log({ project_id, doc_id, broadcast }, 'getting labels for doc')
return MetaHandler.getMetaForDoc(project_id, doc_id, function( return MetaHandler.getMetaForDoc(
err, project_id,
docMeta doc_id,
) { function (err, docMeta) {
if (err != null) { if (err != null) {
OError.tag(err, '[MetaController] error getting labels from doc', { OError.tag(err, '[MetaController] error getting labels from doc', {
project_id, project_id,
doc_id doc_id
}) })
return next(err) 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 })
}
})
} }
} }

View File

@@ -33,43 +33,49 @@ module.exports = MetaHandler = {
getAllMetaForProject(projectId, callback) { getAllMetaForProject(projectId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, projectMeta) {} callback = function (err, projectMeta) {}
} }
return DocumentUpdaterHandler.flushProjectToMongo(projectId, function(err) { return DocumentUpdaterHandler.flushProjectToMongo(
if (err != null) { projectId,
return callback(err) function (err) {
}
return ProjectEntityHandler.getAllDocs(projectId, function(err, docs) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
const projectMeta = MetaHandler.extractMetaFromProjectDocs(docs) return ProjectEntityHandler.getAllDocs(projectId, function (err, docs) {
return callback(null, projectMeta) if (err != null) {
}) return callback(err)
}) }
const projectMeta = MetaHandler.extractMetaFromProjectDocs(docs)
return callback(null, projectMeta)
})
}
)
}, },
getMetaForDoc(projectId, docId, callback) { getMetaForDoc(projectId, docId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, docMeta) {} callback = function (err, docMeta) {}
} }
return DocumentUpdaterHandler.flushDocToMongo(projectId, docId, function( return DocumentUpdaterHandler.flushDocToMongo(
err projectId,
) { docId,
if (err != null) { function (err) {
return callback(err)
}
return ProjectEntityHandler.getDoc(projectId, docId, function(
err,
lines
) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
const docMeta = MetaHandler.extractMetaFromDoc(lines) return ProjectEntityHandler.getDoc(
return callback(null, docMeta) projectId,
}) docId,
}) function (err, lines) {
if (err != null) {
return callback(err)
}
const docMeta = MetaHandler.extractMetaFromDoc(lines)
return callback(null, docMeta)
}
)
}
)
}, },
extractMetaFromDoc(lines) { extractMetaFromDoc(lines) {

View File

@@ -180,10 +180,7 @@ function makeMailchimpProvider() {
} }
function hashEmail(email) { function hashEmail(email) {
return crypto return crypto.createHash('md5').update(email.toLowerCase()).digest('hex')
.createHash('md5')
.update(email.toLowerCase())
.digest('hex')
} }
function getMergeFields(user) { function getMergeFields(user) {

View File

@@ -8,7 +8,7 @@ function dropboxDuplicateProjectNames(userId) {
key: `dropboxDuplicateProjectNames-${userId}`, key: `dropboxDuplicateProjectNames-${userId}`,
create(projectName, callback) { create(projectName, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
NotificationsHandler.createNotification( NotificationsHandler.createNotification(
userId, userId,
@@ -22,7 +22,7 @@ function dropboxDuplicateProjectNames(userId) {
}, },
read(callback) { read(callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
NotificationsHandler.markAsReadWithKey(userId, this.key, callback) NotificationsHandler.markAsReadWithKey(userId, this.key, callback)
} }
@@ -34,7 +34,7 @@ function featuresUpgradedByAffiliation(affiliation, user) {
key: `features-updated-by=${affiliation.institutionId}`, key: `features-updated-by=${affiliation.institutionId}`,
create(callback) { create(callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
const messageOpts = { institutionName: affiliation.institutionName } const messageOpts = { institutionName: affiliation.institutionName }
NotificationsHandler.createNotification( NotificationsHandler.createNotification(
@@ -49,7 +49,7 @@ function featuresUpgradedByAffiliation(affiliation, user) {
}, },
read(callback) { read(callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
NotificationsHandler.markAsReadByKeyOnly(this.key, callback) NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
} }
@@ -61,7 +61,7 @@ function redundantPersonalSubscription(affiliation, user) {
key: `redundant-personal-subscription-${affiliation.institutionId}`, key: `redundant-personal-subscription-${affiliation.institutionId}`,
create(callback) { create(callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
const messageOpts = { institutionName: affiliation.institutionName } const messageOpts = { institutionName: affiliation.institutionName }
NotificationsHandler.createNotification( NotificationsHandler.createNotification(
@@ -76,7 +76,7 @@ function redundantPersonalSubscription(affiliation, user) {
}, },
read(callback) { read(callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
NotificationsHandler.markAsReadByKeyOnly(this.key, callback) NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
} }
@@ -88,7 +88,7 @@ function projectInvite(invite, project, sendingUser, user) {
key: `project-invite-${invite._id}`, key: `project-invite-${invite._id}`,
create(callback) { create(callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
const messageOpts = { const messageOpts = {
userName: sendingUser.first_name, userName: sendingUser.first_name,
@@ -107,7 +107,7 @@ function projectInvite(invite, project, sendingUser, user) {
}, },
read(callback) { read(callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
NotificationsHandler.markAsReadByKeyOnly(this.key, callback) NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
} }
@@ -118,7 +118,7 @@ function ipMatcherAffiliation(userId) {
return { return {
create(ip, callback) { create(ip, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
if (!settings.apis.v1.url) { if (!settings.apis.v1.url) {
// service is not configured // service is not configured
@@ -133,7 +133,7 @@ function ipMatcherAffiliation(userId) {
json: true, json: true,
timeout: 20 * 1000 timeout: 20 * 1000
}, },
function(error, response, body) { function (error, response, body) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -167,7 +167,7 @@ function ipMatcherAffiliation(userId) {
read(universityId, callback) { read(universityId, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
const key = `ip-matched-affiliation-${universityId}` const key = `ip-matched-affiliation-${universityId}`
NotificationsHandler.markAsReadWithKey(userId, key, callback) NotificationsHandler.markAsReadWithKey(userId, key, callback)
@@ -180,7 +180,7 @@ function tpdsFileLimit(userId) {
key: `tpdsFileLimit-${userId}`, key: `tpdsFileLimit-${userId}`,
create(projectName, callback) { create(projectName, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
const messageOpts = { const messageOpts = {
projectName: projectName projectName: projectName
@@ -197,7 +197,7 @@ function tpdsFileLimit(userId) {
}, },
read(callback) { read(callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
NotificationsHandler.markAsReadByKeyOnly(this.key, callback) NotificationsHandler.markAsReadByKeyOnly(this.key, callback)
} }
@@ -215,7 +215,7 @@ const NotificationsBuilder = {
} }
NotificationsBuilder.promises = { NotificationsBuilder.promises = {
redundantPersonalSubscription: function(affiliation, user) { redundantPersonalSubscription: function (affiliation, user) {
return promisifyAll(redundantPersonalSubscription(affiliation, user)) return promisifyAll(redundantPersonalSubscription(affiliation, user))
} }
} }

View File

@@ -17,19 +17,22 @@ const _ = require('underscore')
module.exports = { module.exports = {
getAllUnreadNotifications(req, res) { getAllUnreadNotifications(req, res) {
const user_id = AuthenticationController.getLoggedInUserId(req) const user_id = AuthenticationController.getLoggedInUserId(req)
return NotificationsHandler.getUserNotifications(user_id, function( return NotificationsHandler.getUserNotifications(
err, user_id,
unreadNotifications function (err, unreadNotifications) {
) { unreadNotifications = _.map(
unreadNotifications = _.map(unreadNotifications, function(notification) { unreadNotifications,
notification.html = req.i18n.translate( function (notification) {
notification.templateKey, notification.html = req.i18n.translate(
notification.messageOpts notification.templateKey,
notification.messageOpts
)
return notification
}
) )
return notification return res.send(unreadNotifications)
}) }
return res.send(unreadNotifications) )
})
}, },
markNotificationAsRead(req, res) { markNotificationAsRead(req, res) {

View File

@@ -17,7 +17,7 @@ const logger = require('logger-sharelatex')
const oneSecond = 1000 const oneSecond = 1000
const makeRequest = function(opts, callback) { const makeRequest = function (opts, callback) {
if ( if (
(settings.apis.notifications != null (settings.apis.notifications != null
? settings.apis.notifications.url ? settings.apis.notifications.url
@@ -41,7 +41,7 @@ module.exports = {
timeout: oneSecond, timeout: oneSecond,
method: 'GET' method: 'GET'
} }
return makeRequest(opts, function(err, res, unreadNotifications) { return makeRequest(opts, function (err, res, unreadNotifications) {
const statusCode = res != null ? res.statusCode : 500 const statusCode = res != null ? res.statusCode : 500
if (err != null || statusCode !== 200) { if (err != null || statusCode !== 200) {
const e = new Error( const e = new Error(

View File

@@ -17,14 +17,14 @@ const logger = require('logger-sharelatex')
module.exports = { module.exports = {
getProjectDetails(req, res, next) { getProjectDetails(req, res, next) {
const { project_id } = req.params const { project_id } = req.params
return ProjectDetailsHandler.getDetails(project_id, function( return ProjectDetailsHandler.getDetails(
err, project_id,
projDetails function (err, projDetails) {
) { if (err != null) {
if (err != null) { return next(err)
return next(err) }
return res.json(projDetails)
} }
return res.json(projDetails) )
})
} }
} }

View File

@@ -25,7 +25,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
callback callback
) { ) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
return ProjectCollabratecDetailsHandler.setCollabratecUsers( return ProjectCollabratecDetailsHandler.setCollabratecUsers(
project_id, project_id,
@@ -36,7 +36,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
isLinkedCollabratecUserProject(project_id, user_id, callback) { isLinkedCollabratecUserProject(project_id, user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, isLinked) {} callback = function (err, isLinked) {}
} }
try { try {
project_id = ObjectId(project_id) 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) { if (err != null) {
callback(err) callback(err)
} }
@@ -68,7 +68,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
callback callback
) { ) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
try { try {
project_id = ObjectId(project_id) project_id = ObjectId(project_id)
@@ -102,7 +102,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
setCollabratecUsers(project_id, collabratec_users, callback) { setCollabratecUsers(project_id, collabratec_users, callback) {
let err let err
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
try { try {
project_id = ObjectId(project_id) project_id = ObjectId(project_id)
@@ -127,7 +127,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
unlinkCollabratecUserProject(project_id, user_id, callback) { unlinkCollabratecUserProject(project_id, user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
try { try {
project_id = ObjectId(project_id) project_id = ObjectId(project_id)
@@ -149,7 +149,7 @@ module.exports = ProjectCollabratecDetailsHandler = {
updateCollabratecUserIds(old_user_id, new_user_id, callback) { updateCollabratecUserIds(old_user_id, new_user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
try { try {
old_user_id = ObjectId(old_user_id) old_user_id = ObjectId(old_user_id)

View File

@@ -64,10 +64,7 @@ const ProjectController = {
return true return true
} }
const data = `${rolloutName}:${objectId.toString()}` const data = `${rolloutName}:${objectId.toString()}`
const md5hash = crypto const md5hash = crypto.createHash('md5').update(data).digest('hex')
.createHash('md5')
.update(data)
.digest('hex')
const counter = parseInt(md5hash.slice(26, 32), 16) const counter = parseInt(md5hash.slice(26, 32), 16)
return counter % 100 < percentage return counter % 100 < percentage
}, },
@@ -162,7 +159,7 @@ const ProjectController = {
const projectId = req.params.Project_id const projectId = req.params.Project_id
const userId = AuthenticationController.getLoggedInUserId(req) const userId = AuthenticationController.getLoggedInUserId(req)
ProjectDeleter.archiveProject(projectId, userId, function(err) { ProjectDeleter.archiveProject(projectId, userId, function (err) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} else { } else {
@@ -175,7 +172,7 @@ const ProjectController = {
const projectId = req.params.Project_id const projectId = req.params.Project_id
const userId = AuthenticationController.getLoggedInUserId(req) const userId = AuthenticationController.getLoggedInUserId(req)
ProjectDeleter.unarchiveProject(projectId, userId, function(err) { ProjectDeleter.unarchiveProject(projectId, userId, function (err) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} else { } else {
@@ -188,7 +185,7 @@ const ProjectController = {
const projectId = req.params.project_id const projectId = req.params.project_id
const userId = AuthenticationController.getLoggedInUserId(req) const userId = AuthenticationController.getLoggedInUserId(req)
ProjectDeleter.trashProject(projectId, userId, function(err) { ProjectDeleter.trashProject(projectId, userId, function (err) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} else { } else {
@@ -201,7 +198,7 @@ const ProjectController = {
const projectId = req.params.project_id const projectId = req.params.project_id
const userId = AuthenticationController.getLoggedInUserId(req) const userId = AuthenticationController.getLoggedInUserId(req)
ProjectDeleter.untrashProject(projectId, userId, function(err) { ProjectDeleter.untrashProject(projectId, userId, function (err) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} else { } else {

View File

@@ -33,7 +33,7 @@ const AnalyticsManager = require('../Analytics/AnalyticsManager')
const ProjectCreationHandler = { const ProjectCreationHandler = {
createBlankProject(owner_id, projectName, attributes, callback) { createBlankProject(owner_id, projectName, attributes, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, project) {} callback = function (error, project) {}
} }
metrics.inc('project-creation') metrics.inc('project-creation')
if (arguments.length === 3) { if (arguments.length === 3) {
@@ -41,59 +41,60 @@ const ProjectCreationHandler = {
attributes = {} attributes = {}
} }
return ProjectDetailsHandler.validateProjectName(projectName, function( return ProjectDetailsHandler.validateProjectName(
error projectName,
) { function (error) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
if (attributes.overleaf !== undefined && attributes.overleaf != null) { 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 ProjectCreationHandler._createBlankProject( return ProjectCreationHandler._createBlankProject(
owner_id, owner_id,
projectName, projectName,
attributes, attributes,
function(error, project) { function (error, project) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
AnalyticsManager.recordEvent(owner_id, 'project-created', { AnalyticsManager.recordEvent(owner_id, 'project-imported', {
projectId: project._id, projectId: project._id,
attributes attributes
}) })
return callback(error, project) 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) { _createBlankProject(owner_id, projectName, attributes, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, project) {} callback = function (error, project) {}
} }
const rootFolder = new Folder({ name: 'rootFolder' }) const rootFolder = new Folder({ name: 'rootFolder' })
@@ -113,28 +114,29 @@ const ProjectCreationHandler = {
} }
} }
project.rootFolder[0] = rootFolder project.rootFolder[0] = rootFolder
return User.findById(owner_id, 'ace.spellCheckLanguage', function( return User.findById(
err, owner_id,
user 'ace.spellCheckLanguage',
) { function (err, user) {
project.spellCheckLanguage = user.ace.spellCheckLanguage project.spellCheckLanguage = user.ace.spellCheckLanguage
return project.save(function(err) { return project.save(function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
return callback(err, project) return callback(err, project)
}) })
}) }
)
}, },
createProjectFromSnippet(owner_id, projectName, docLines, callback) { createProjectFromSnippet(owner_id, projectName, docLines, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, project) {} callback = function (error, project) {}
} }
return ProjectCreationHandler.createBlankProject( return ProjectCreationHandler.createBlankProject(
owner_id, owner_id,
projectName, projectName,
function(error, project) { function (error, project) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -150,12 +152,12 @@ const ProjectCreationHandler = {
createBasicProject(owner_id, projectName, callback) { createBasicProject(owner_id, projectName, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, project) {} callback = function (error, project) {}
} }
return ProjectCreationHandler.createBlankProject( return ProjectCreationHandler.createBlankProject(
owner_id, owner_id,
projectName, projectName,
function(error, project) { function (error, project) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -163,7 +165,7 @@ const ProjectCreationHandler = {
'mainbasic.tex', 'mainbasic.tex',
owner_id, owner_id,
projectName, projectName,
function(error, docLines) { function (error, docLines) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -181,12 +183,12 @@ const ProjectCreationHandler = {
createExampleProject(owner_id, projectName, callback) { createExampleProject(owner_id, projectName, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, project) {} callback = function (error, project) {}
} }
return ProjectCreationHandler.createBlankProject( return ProjectCreationHandler.createBlankProject(
owner_id, owner_id,
projectName, projectName,
function(error, project) { function (error, project) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -197,7 +199,7 @@ const ProjectCreationHandler = {
'main.tex', 'main.tex',
owner_id, owner_id,
projectName, projectName,
function(error, docLines) { function (error, docLines) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -214,7 +216,7 @@ const ProjectCreationHandler = {
'references.bib', 'references.bib',
owner_id, owner_id,
projectName, projectName,
function(error, docLines) { function (error, docLines) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -228,7 +230,7 @@ const ProjectCreationHandler = {
) )
} }
), ),
function(callback) { function (callback) {
const universePath = Path.resolve( const universePath = Path.resolve(
__dirname + '/../../../templates/project_files/universe.jpg' __dirname + '/../../../templates/project_files/universe.jpg'
) )
@@ -251,7 +253,7 @@ const ProjectCreationHandler = {
_createRootDoc(project, owner_id, docLines, callback) { _createRootDoc(project, owner_id, docLines, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, project) {} callback = function (error, project) {}
} }
return ProjectEntityUpdateHandler.addDoc( return ProjectEntityUpdateHandler.addDoc(
project._id, project._id,
@@ -259,7 +261,7 @@ const ProjectCreationHandler = {
'main.tex', 'main.tex',
docLines, docLines,
owner_id, owner_id,
function(error, doc) { function (error, doc) {
if (error != null) { if (error != null) {
OError.tag(error, 'error adding root doc when creating project') OError.tag(error, 'error adding root doc when creating project')
return callback(error) return callback(error)
@@ -275,47 +277,48 @@ const ProjectCreationHandler = {
_buildTemplate(template_name, user_id, project_name, callback) { _buildTemplate(template_name, user_id, project_name, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, output) {} callback = function (error, output) {}
} }
return User.findById(user_id, 'first_name last_name', function( return User.findById(
error, user_id,
user '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) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
const data = { const monthNames = [
project_name, 'January',
user, 'February',
year: new Date().getUTCFullYear(), 'March',
month: monthNames[new Date().getUTCMonth()] 'April',
} 'May',
const output = _.template(template.toString(), data) 'June',
return callback(null, output.split('\n')) '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'))
})
}
)
} }
} }

View File

@@ -308,7 +308,7 @@ const ProjectEntityUpdateHandler = {
addDocWithRanges: wrapWithLock({ addDocWithRanges: wrapWithLock({
beforeLock(next) { beforeLock(next) {
return function( return function (
projectId, projectId,
folderId, folderId,
docName, docName,
@@ -457,7 +457,7 @@ const ProjectEntityUpdateHandler = {
addFile: wrapWithLock({ addFile: wrapWithLock({
beforeLock(next) { beforeLock(next) {
return function( return function (
projectId, projectId,
folderId, folderId,
fileName, fileName,
@@ -544,7 +544,7 @@ const ProjectEntityUpdateHandler = {
replaceFile: wrapWithLock({ replaceFile: wrapWithLock({
beforeLock(next) { beforeLock(next) {
return function( return function (
projectId, projectId,
fileId, fileId,
fsPath, fsPath,
@@ -648,7 +648,7 @@ const ProjectEntityUpdateHandler = {
} }
}), }),
upsertDoc: wrapWithLock(function( upsertDoc: wrapWithLock(function (
projectId, projectId,
folderId, folderId,
docName, docName,
@@ -796,7 +796,7 @@ const ProjectEntityUpdateHandler = {
upsertFile: wrapWithLock({ upsertFile: wrapWithLock({
beforeLock(next) { beforeLock(next) {
return function( return function (
projectId, projectId,
folderId, folderId,
fileName, fileName,
@@ -974,7 +974,7 @@ const ProjectEntityUpdateHandler = {
} }
}), }),
upsertDocWithPath: wrapWithLock(function( upsertDocWithPath: wrapWithLock(function (
projectId, projectId,
elementPath, elementPath,
docLines, docLines,
@@ -1014,7 +1014,7 @@ const ProjectEntityUpdateHandler = {
upsertFileWithPath: wrapWithLock({ upsertFileWithPath: wrapWithLock({
beforeLock(next) { beforeLock(next) {
return function( return function (
projectId, projectId,
elementPath, elementPath,
fsPath, fsPath,
@@ -1102,7 +1102,7 @@ const ProjectEntityUpdateHandler = {
} }
}), }),
deleteEntity: wrapWithLock(function( deleteEntity: wrapWithLock(function (
projectId, projectId,
entityId, entityId,
entityType, 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('/')) { for (let folder of path.split('/')) {
if (folder.length > 0 && !SafePath.isCleanFilename(folder)) { if (folder.length > 0 && !SafePath.isCleanFilename(folder)) {
return callback(new Errors.InvalidNameError('invalid element name')) 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('/')) { for (let folder of path.split('/')) {
if (folder.length > 0 && !SafePath.isCleanFilename(folder)) { if (folder.length > 0 && !SafePath.isCleanFilename(folder)) {
return callback(new Errors.InvalidNameError('invalid element name')) return callback(new Errors.InvalidNameError('invalid element name'))
@@ -1202,7 +1202,7 @@ const ProjectEntityUpdateHandler = {
) )
}), }),
addFolder: wrapWithLock(function( addFolder: wrapWithLock(function (
projectId, projectId,
parentFolderId, parentFolderId,
folderName, folderName,
@@ -1219,7 +1219,7 @@ const ProjectEntityUpdateHandler = {
) )
}), }),
moveEntity: wrapWithLock(function( moveEntity: wrapWithLock(function (
projectId, projectId,
entityId, entityId,
destFolderId, destFolderId,
@@ -1272,7 +1272,7 @@ const ProjectEntityUpdateHandler = {
) )
}), }),
renameEntity: wrapWithLock(function( renameEntity: wrapWithLock(function (
projectId, projectId,
entityId, entityId,
entityType, entityType,
@@ -1572,7 +1572,7 @@ const ProjectEntityUpdateHandler = {
convertDocToFile: wrapWithLock({ convertDocToFile: wrapWithLock({
beforeLock(next) { beforeLock(next) {
return function(projectId, docId, userId, callback) { return function (projectId, docId, userId, callback) {
DocumentUpdaterHandler.flushDocToMongo(projectId, docId, err => { DocumentUpdaterHandler.flushDocToMongo(projectId, docId, err => {
if (err) { if (err) {
return callback(err) return callback(err)

View File

@@ -72,7 +72,7 @@ const ProjectGetter = {
return callback(err) return callback(err)
} }
db.projects.findOne(query, { projection }, function(err, project) { db.projects.findOne(query, { projection }, function (err, project) {
if (err) { if (err) {
OError.tag(err, 'error getting project', { OError.tag(err, 'error getting project', {
query, query,
@@ -85,43 +85,49 @@ const ProjectGetter = {
}, },
getProjectIdByReadAndWriteToken(token, callback) { getProjectIdByReadAndWriteToken(token, callback) {
Project.findOne({ 'tokens.readAndWrite': token }, { _id: 1 }, function( Project.findOne(
err, { 'tokens.readAndWrite': token },
project { _id: 1 },
) { function (err, project) {
if (err) { if (err) {
return callback(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) { findAllUsersProjects(userId, fields, callback) {
const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter') const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
Project.find({ owner_ref: userId }, fields, function(error, ownedProjects) { Project.find(
if (error) { { owner_ref: userId },
return callback(error) fields,
} function (error, ownedProjects) {
CollaboratorsGetter.getProjectsUserIsMemberOf(userId, fields, function(
error,
projects
) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
const result = { CollaboratorsGetter.getProjectsUserIsMemberOf(
owned: ownedProjects || [], userId,
readAndWrite: projects.readAndWrite || [], fields,
readOnly: projects.readOnly || [], function (error, projects) {
tokenReadAndWrite: projects.tokenReadAndWrite || [], if (error) {
tokenReadOnly: projects.tokenReadOnly || [] return callback(error)
} }
callback(null, result) const result = {
}) owned: ownedProjects || [],
}) readAndWrite: projects.readAndWrite || [],
readOnly: projects.readOnly || [],
tokenReadAndWrite: projects.tokenReadAndWrite || [],
tokenReadOnly: projects.tokenReadOnly || []
}
callback(null, result)
}
)
}
)
}, },
/** /**

View File

@@ -126,7 +126,7 @@ function _addSuffixToProjectName(name, suffix, maxLength) {
function _addNumericSuffixToProjectName(name, allProjectNames, maxLength) { function _addNumericSuffixToProjectName(name, allProjectNames, maxLength) {
const NUMERIC_SUFFIX_MATCH = / \((\d+)\)$/ const NUMERIC_SUFFIX_MATCH = / \((\d+)\)$/
const suffixedName = function(basename, number) { const suffixedName = function (basename, number) {
const suffix = ` (${number})` const suffix = ` (${number})`
return basename.substr(0, maxLength - suffix.length) + suffix return basename.substr(0, maxLength - suffix.length) + suffix
} }

View File

@@ -25,7 +25,7 @@ const ProjectHistoryHandler = {
setHistoryId(project_id, history_id, callback) { setHistoryId(project_id, history_id, callback) {
// reject invalid history ids // reject invalid history ids
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
if (!history_id || typeof history_id !== 'number') { if (!history_id || typeof history_id !== 'number') {
return callback(new Error('invalid history id')) return callback(new Error('invalid history id'))
@@ -34,7 +34,7 @@ const ProjectHistoryHandler = {
return Project.updateOne( return Project.updateOne(
{ _id: project_id, 'overleaf.history.id': { $exists: false } }, { _id: project_id, 'overleaf.history.id': { $exists: false } },
{ 'overleaf.history.id': history_id }, { 'overleaf.history.id': history_id },
function(err, result) { function (err, result) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -48,29 +48,32 @@ const ProjectHistoryHandler = {
getHistoryId(project_id, callback) { getHistoryId(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, result) {} callback = function (err, result) {}
} }
return ProjectDetailsHandler.getDetails(project_id, function(err, project) { return ProjectDetailsHandler.getDetails(
if (err != null) { project_id,
return callback(err) function (err, project) {
} // n.b. getDetails returns an error if the project doesn't exist if (err != null) {
return callback( return callback(err)
null, } // n.b. getDetails returns an error if the project doesn't exist
__guard__( return callback(
null,
__guard__( __guard__(
project != null ? project.overleaf : undefined, __guard__(
x1 => x1.history project != null ? project.overleaf : undefined,
), x1 => x1.history
x => x.id ),
x => x.id
)
) )
) }
}) )
}, },
upgradeHistory(project_id, callback) { upgradeHistory(project_id, callback) {
// project must have an overleaf.history.id before allowing display of new history // project must have an overleaf.history.id before allowing display of new history
if (callback == null) { if (callback == null) {
callback = function(err, result) {} callback = function (err, result) {}
} }
return Project.updateOne( return Project.updateOne(
{ _id: project_id, 'overleaf.history.id': { $exists: true } }, { _id: project_id, 'overleaf.history.id': { $exists: true } },
@@ -78,7 +81,7 @@ const ProjectHistoryHandler = {
'overleaf.history.display': true, 'overleaf.history.display': true,
'overleaf.history.upgradedAt': new Date() 'overleaf.history.upgradedAt': new Date()
}, },
function(err, result) { function (err, result) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -93,7 +96,7 @@ const ProjectHistoryHandler = {
downgradeHistory(project_id, callback) { downgradeHistory(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, result) {} callback = function (err, result) {}
} }
return Project.updateOne( return Project.updateOne(
{ _id: project_id, 'overleaf.history.upgradedAt': { $exists: true } }, { _id: project_id, 'overleaf.history.upgradedAt': { $exists: true } },
@@ -101,7 +104,7 @@ const ProjectHistoryHandler = {
'overleaf.history.display': false, 'overleaf.history.display': false,
$unset: { 'overleaf.history.upgradedAt': 1 } $unset: { 'overleaf.history.upgradedAt': 1 }
}, },
function(err, result) { function (err, result) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -120,45 +123,45 @@ const ProjectHistoryHandler = {
// state. Setting a history id when one wasn't present before is ok, // state. Setting a history id when one wasn't present before is ok,
// because undefined history ids aren't cached. // because undefined history ids aren't cached.
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
return ProjectHistoryHandler.getHistoryId(project_id, function( return ProjectHistoryHandler.getHistoryId(
err, project_id,
history_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) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
if (!(history != null ? history.overleaf_id : undefined)) { if (history_id != null) {
return callback(new Error('failed to initialize history id')) return callback()
} } // history already exists, success
return ProjectHistoryHandler.setHistoryId( return HistoryManager.initializeProject(function (err, history) {
project_id, if (err != null) {
history.overleaf_id, return callback(err)
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 != 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)
}
)
}
)
})
}
)
} }
} }

View File

@@ -19,11 +19,12 @@ function findElement(options, _callback) {
const elementType = sanitizeTypeOfElement(type) const elementType = sanitizeTypeOfElement(type)
let count = 0 let count = 0
const endOfBranch = function() { const endOfBranch = function () {
if (--count === 0) { if (--count === 0) {
logger.warn( logger.warn(
`element ${elementId} could not be found for project ${projectId || `element ${elementId} could not be found for project ${
project._id}` projectId || project._id
}`
) )
callback(new Errors.NotFoundError('entity not found')) callback(new Errors.NotFoundError('entity not found'))
} }

View File

@@ -28,9 +28,9 @@ const _ = require('underscore')
module.exports = ProjectRootDocManager = { module.exports = ProjectRootDocManager = {
setRootDocAutomatically(project_id, callback) { setRootDocAutomatically(project_id, callback) {
if (callback == null) { 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) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -38,23 +38,23 @@ module.exports = ProjectRootDocManager = {
const jobs = _.map( const jobs = _.map(
docs, docs,
(doc, path) => (doc, path) =>
function(cb) { function (cb) {
if ( if (
ProjectEntityUpdateHandler.isPathValidForRootDoc(path) && ProjectEntityUpdateHandler.isPathValidForRootDoc(path) &&
DocumentHelper.contentHasDocumentclass(doc.lines) DocumentHelper.contentHasDocumentclass(doc.lines)
) { ) {
async.setImmediate(function() { async.setImmediate(function () {
cb(doc._id) cb(doc._id)
}) })
} else { } else {
async.setImmediate(function() { async.setImmediate(function () {
cb(null) cb(null)
}) })
} }
} }
) )
return async.series(jobs, function(root_doc_id) { return async.series(jobs, function (root_doc_id) {
if (root_doc_id != null) { if (root_doc_id != null) {
return ProjectEntityUpdateHandler.setRootDoc( return ProjectEntityUpdateHandler.setRootDoc(
project_id, project_id,
@@ -70,7 +70,7 @@ module.exports = ProjectRootDocManager = {
findRootDocFileFromDirectory(directoryPath, callback) { findRootDocFileFromDirectory(directoryPath, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, path, content) {} callback = function (error, path, content) {}
} }
const filePathsPromise = globby(['**/*.{tex,Rtex}'], { const filePathsPromise = globby(['**/*.{tex,Rtex}'], {
cwd: directoryPath, cwd: directoryPath,
@@ -88,7 +88,7 @@ module.exports = ProjectRootDocManager = {
ProjectRootDocManager._sortFileList( ProjectRootDocManager._sortFileList(
unsortedFiles, unsortedFiles,
directoryPath, directoryPath,
function(err, files) { function (err, files) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -96,12 +96,12 @@ module.exports = ProjectRootDocManager = {
return async.until( return async.until(
() => doc != null || files.length === 0, () => doc != null || files.length === 0,
function(cb) { function (cb) {
const file = files.shift() const file = files.shift()
return fs.readFile( return fs.readFile(
Path.join(directoryPath, file), Path.join(directoryPath, file),
'utf8', 'utf8',
function(error, content) { function (error, content) {
if (error != null) { if (error != null) {
return cb(error) return cb(error)
} }
@@ -131,11 +131,11 @@ module.exports = ProjectRootDocManager = {
setRootDocFromName(project_id, rootDocName, callback) { setRootDocFromName(project_id, rootDocName, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return ProjectEntityHandler.getAllDocPathsFromProjectById( return ProjectEntityHandler.getAllDocPathsFromProjectById(
project_id, project_id,
function(error, docPaths) { function (error, docPaths) {
let doc_id, path let doc_id, path
if (error != null) { if (error != null) {
return callback(error) return callback(error)
@@ -180,89 +180,91 @@ module.exports = ProjectRootDocManager = {
ensureRootDocumentIsSet(project_id, callback) { ensureRootDocumentIsSet(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return ProjectGetter.getProject(project_id, { rootDoc_id: 1 }, function( return ProjectGetter.getProject(
error, project_id,
project { rootDoc_id: 1 },
) { function (error, project) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
if (project == null) { if (project == null) {
return callback(new Error('project not found')) return callback(new Error('project not found'))
} }
if (project.rootDoc_id != null) { if (project.rootDoc_id != null) {
return callback() return callback()
} else { } else {
return ProjectRootDocManager.setRootDocAutomatically( return ProjectRootDocManager.setRootDocAutomatically(
project_id, project_id,
callback callback
) )
}
} }
}) )
}, },
ensureRootDocumentIsValid(project_id, callback) { ensureRootDocumentIsValid(project_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return ProjectGetter.getProject(project_id, { rootDoc_id: 1 }, function( return ProjectGetter.getProject(
error, project_id,
project { rootDoc_id: 1 },
) { function (error, project) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
if (project == null) { if (project == null) {
return callback(new Error('project not found')) return callback(new Error('project not found'))
} }
if (project.rootDoc_id != null) { if (project.rootDoc_id != null) {
return ProjectEntityHandler.getAllDocPathsFromProjectById( return ProjectEntityHandler.getAllDocPathsFromProjectById(
project_id, project_id,
function(error, docPaths) { function (error, docPaths) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
let rootDocValid = false let rootDocValid = false
for (let doc_id in docPaths) { for (let doc_id in docPaths) {
const _path = docPaths[doc_id] const _path = docPaths[doc_id]
if (doc_id === project.rootDoc_id) { if (doc_id === project.rootDoc_id) {
rootDocValid = true rootDocValid = true
}
}
if (rootDocValid) {
return callback()
} else {
return ProjectEntityUpdateHandler.unsetRootDoc(project_id, () =>
ProjectRootDocManager.setRootDocAutomatically(
project_id,
callback
)
)
} }
} }
if (rootDocValid) { )
return callback() } else {
} else { return ProjectRootDocManager.setRootDocAutomatically(
return ProjectEntityUpdateHandler.unsetRootDoc(project_id, () => project_id,
ProjectRootDocManager.setRootDocAutomatically( callback
project_id, )
callback }
)
)
}
}
)
} else {
return ProjectRootDocManager.setRootDocAutomatically(
project_id,
callback
)
} }
}) )
}, },
_sortFileList(listToSort, rootDirectory, callback) { _sortFileList(listToSort, rootDirectory, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, result) {} callback = function (error, result) {}
} }
return async.mapLimit( return async.mapLimit(
listToSort, listToSort,
5, 5,
(filePath, cb) => (filePath, cb) =>
fs.stat(Path.join(rootDirectory, filePath), function(err, stat) { fs.stat(Path.join(rootDirectory, filePath), function (err, stat) {
if (err != null) { if (err != null) {
return cb(err) return cb(err)
} }
@@ -273,7 +275,7 @@ module.exports = ProjectRootDocManager = {
name: Path.basename(filePath) name: Path.basename(filePath)
}) })
}), }),
function(err, files) { function (err, files) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }

View File

@@ -17,7 +17,7 @@ const logger = require('logger-sharelatex')
module.exports = { module.exports = {
markAsUpdated(projectId, lastUpdatedAt, lastUpdatedBy, callback) { markAsUpdated(projectId, lastUpdatedAt, lastUpdatedBy, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
if (lastUpdatedAt == null) { if (lastUpdatedAt == null) {
lastUpdatedAt = new Date() lastUpdatedAt = new Date()
@@ -38,7 +38,7 @@ module.exports = {
markAsOpened(project_id, callback) { markAsOpened(project_id, callback) {
const conditions = { _id: project_id } const conditions = { _id: project_id }
const update = { lastOpened: Date.now() } const update = { lastOpened: Date.now() }
return Project.updateOne(conditions, update, {}, function(err) { return Project.updateOne(conditions, update, {}, function (err) {
if (callback != null) { if (callback != null) {
return callback() return callback()
} }
@@ -48,7 +48,7 @@ module.exports = {
markAsInactive(project_id, callback) { markAsInactive(project_id, callback) {
const conditions = { _id: project_id } const conditions = { _id: project_id }
const update = { active: false } const update = { active: false }
return Project.updateOne(conditions, update, {}, function(err) { return Project.updateOne(conditions, update, {}, function (err) {
if (callback != null) { if (callback != null) {
return callback() return callback()
} }
@@ -58,7 +58,7 @@ module.exports = {
markAsActive(project_id, callback) { markAsActive(project_id, callback) {
const conditions = { _id: project_id } const conditions = { _id: project_id }
const update = { active: true } const update = { active: true }
return Project.updateOne(conditions, update, {}, function(err) { return Project.updateOne(conditions, update, {}, function (err) {
if (callback != null) { if (callback != null) {
return callback() return callback()
} }

View File

@@ -18,7 +18,7 @@
// frontend/js/ide/directives/SafePath.js // frontend/js/ide/directives/SafePath.js
// frontend/js/features/file-tree/util/safe-path.js // frontend/js/features/file-tree/util/safe-path.js
const load = function() { const load = function () {
let SafePath let SafePath
const BADCHAR_RX = new RegExp( const BADCHAR_RX = new RegExp(
`\ `\

View File

@@ -21,7 +21,7 @@ const _ = require('underscore')
module.exports = PublishersGetter = { module.exports = PublishersGetter = {
getManagedPublishers(user_id, callback) { getManagedPublishers(user_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, managedPublishers) {} callback = function (error, managedPublishers) {}
} }
return UserMembershipsHandler.getEntitiesByUser( return UserMembershipsHandler.getEntitiesByUser(
UserMembershipEntityConfigs.publisher, UserMembershipEntityConfigs.publisher,

View File

@@ -5,14 +5,14 @@ const FeaturesUpdater = require('../Subscription/FeaturesUpdater')
module.exports = { module.exports = {
allocate(referalId, newUserId, referalSource, referalMedium, callback) { allocate(referalId, newUserId, referalSource, referalMedium, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
if (referalId == null) { if (referalId == null) {
return callback(null) return callback(null)
} }
const query = { referal_id: referalId } 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) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -32,7 +32,7 @@ module.exports = {
} }
}, },
{}, {},
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'something went wrong allocating referal', { OError.tag(err, 'something went wrong allocating referal', {
referalId, referalId,

View File

@@ -7,10 +7,10 @@ let ReferalFeatures
module.exports = ReferalFeatures = { module.exports = ReferalFeatures = {
getBonusFeatures(userId, callback) { getBonusFeatures(userId, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
const query = { _id: userId } 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) { if (error) {
return callback(error) return callback(error)
} }
@@ -37,7 +37,7 @@ module.exports = ReferalFeatures = {
_getBonusLevel(user) { _getBonusLevel(user) {
let highestBonusLevel = 0 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 levelIsLessThanUser = level <= user.refered_user_count
const levelIsMoreThanCurrentHighest = level >= highestBonusLevel const levelIsMoreThanCurrentHighest = level >= highestBonusLevel
if (levelIsLessThanUser && levelIsMoreThanCurrentHighest) { if (levelIsLessThanUser && levelIsMoreThanCurrentHighest) {

View File

@@ -3,7 +3,7 @@ const { User } = require('../../models/User')
module.exports = { module.exports = {
getReferedUsers(userId, callback) { getReferedUsers(userId, callback) {
const projection = { refered_users: 1, refered_user_count: 1 } 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) { if (err) {
return callback(err) return callback(err)
} }

View File

@@ -28,7 +28,7 @@ module.exports = ReferencesController = {
) )
return res.sendStatus(400) return res.sendStatus(400)
} }
return ReferencesHandler.index(projectId, docIds, function(err, data) { return ReferencesHandler.index(projectId, docIds, function (err, data) {
if (err != null) { if (err != null) {
logger.err({ err, projectId }, 'error indexing all references') logger.err({ err, projectId }, 'error indexing all references')
return res.sendStatus(500) return res.sendStatus(500)
@@ -46,7 +46,7 @@ module.exports = ReferencesController = {
indexAll(req, res) { indexAll(req, res) {
const projectId = req.params.Project_id const projectId = req.params.Project_id
const { shouldBroadcast } = req.body const { shouldBroadcast } = req.body
return ReferencesHandler.indexAll(projectId, function(err, data) { return ReferencesHandler.indexAll(projectId, function (err, data) {
if (err != null) { if (err != null) {
logger.err({ err, projectId }, 'error indexing all references') logger.err({ err, projectId }, 'error indexing all references')
return res.sendStatus(500) return res.sendStatus(500)

View File

@@ -42,8 +42,8 @@ module.exports = ReferencesHandler = {
_findBibFileIds(project) { _findBibFileIds(project) {
const ids = [] const ids = []
var _process = function(folder) { var _process = function (folder) {
_.each(folder.fileRefs || [], function(file) { _.each(folder.fileRefs || [], function (file) {
if ( if (
__guard__(file != null ? file.name : undefined, x1 => __guard__(file != null ? file.name : undefined, x1 =>
x1.match(/^.*\.bib$/) x1.match(/^.*\.bib$/)
@@ -60,8 +60,8 @@ module.exports = ReferencesHandler = {
_findBibDocIds(project) { _findBibDocIds(project) {
const ids = [] const ids = []
var _process = function(folder) { var _process = function (folder) {
_.each(folder.docs || [], function(doc) { _.each(folder.docs || [], function (doc) {
if ( if (
__guard__(doc != null ? doc.name : undefined, x1 => __guard__(doc != null ? doc.name : undefined, x1 =>
x1.match(/^.*\.bib$/) x1.match(/^.*\.bib$/)
@@ -78,32 +78,33 @@ module.exports = ReferencesHandler = {
_isFullIndex(project, callback) { _isFullIndex(project, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, result) {} callback = function (err, result) {}
} }
return UserGetter.getUser(project.owner_ref, { features: true }, function( return UserGetter.getUser(
err, project.owner_ref,
owner { features: true },
) { function (err, owner) {
if (err != null) { if (err != null) {
return callback(err) 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) { indexAll(projectId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, data) {} callback = function (err, data) {}
} }
return ProjectGetter.getProject( return ProjectGetter.getProject(
projectId, projectId,
{ rootFolder: true, owner_ref: 1 }, { rootFolder: true, owner_ref: 1 },
function(err, project) { function (err, project) {
if (err) { if (err) {
OError.tag(err, 'error finding project', { OError.tag(err, 'error finding project', {
projectId projectId
@@ -126,12 +127,12 @@ module.exports = ReferencesHandler = {
index(projectId, docIds, callback) { index(projectId, docIds, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, data) {} callback = function (err, data) {}
} }
return ProjectGetter.getProject( return ProjectGetter.getProject(
projectId, projectId,
{ rootFolder: true, owner_ref: 1 }, { rootFolder: true, owner_ref: 1 },
function(err, project) { function (err, project) {
if (err) { if (err) {
OError.tag(err, 'error finding project', { OError.tag(err, 'error finding project', {
projectId projectId
@@ -153,7 +154,7 @@ module.exports = ReferencesHandler = {
if (!Features.hasFeature('references')) { if (!Features.hasFeature('references')) {
return callback() return callback()
} }
return ReferencesHandler._isFullIndex(project, function(err, isFullIndex) { return ReferencesHandler._isFullIndex(project, function (err, isFullIndex) {
if (err) { if (err) {
OError.tag(err, 'error checking whether to do full index', { OError.tag(err, 'error checking whether to do full index', {
projectId projectId
@@ -168,7 +169,7 @@ module.exports = ReferencesHandler = {
docIds.map(docId => cb => docIds.map(docId => cb =>
DocumentUpdaterHandler.flushDocToMongo(projectId, docId, cb) DocumentUpdaterHandler.flushDocToMongo(projectId, docId, cb)
), ),
function(err) { function (err) {
// continue // continue
if (err) { if (err) {
OError.tag(err, 'error flushing docs to mongo', { OError.tag(err, 'error flushing docs to mongo', {
@@ -192,7 +193,7 @@ module.exports = ReferencesHandler = {
fullIndex: isFullIndex fullIndex: isFullIndex
} }
}, },
function(err, res, data) { function (err, res, data) {
if (err) { if (err) {
OError.tag(err, 'error communicating with references api', { OError.tag(err, 'error communicating with references api', {
projectId projectId

View File

@@ -16,7 +16,7 @@ function processLoginRequest(email, callback) {
function recordSuccessfulLogin(email, callback) { function recordSuccessfulLogin(email, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
RateLimiter.clearRateLimit('login', email, callback) RateLimiter.clearRateLimit('login', email, callback)
} }

View File

@@ -26,7 +26,7 @@ module.exports = {
options = {} options = {}
} }
if (callback == null) { if (callback == null) {
callback = function(error, data) {} callback = function (error, data) {}
} }
if (typeof options === 'function') { if (typeof options === 'function') {
callback = options callback = options
@@ -44,7 +44,7 @@ module.exports = {
createdAt, createdAt,
expiresAt expiresAt
}, },
function(error) { function (error) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -55,7 +55,7 @@ module.exports = {
getValueFromTokenAndExpire(use, token, callback) { getValueFromTokenAndExpire(use, token, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, data) {} callback = function (error, data) {}
} }
const now = new Date() const now = new Date()
return db.tokens.findOneAndUpdate( return db.tokens.findOneAndUpdate(
@@ -70,7 +70,7 @@ module.exports = {
usedAt: now usedAt: now
} }
}, },
function(error, result) { function (error, result) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }

View File

@@ -16,7 +16,7 @@ const settings = require('settings-sharelatex')
Unique clients are identified by user_id if logged in, and IP address if not. Unique clients are identified by user_id if logged in, and IP address if not.
*/ */
function rateLimit(opts) { function rateLimit(opts) {
return function(req, res, next) { return function (req, res, next) {
const userId = AuthenticationController.getLoggedInUserId(req) || req.ip const userId = AuthenticationController.getLoggedInUserId(req) || req.ip
if ( if (
settings.smokeTest && settings.smokeTest &&
@@ -41,7 +41,7 @@ function rateLimit(opts) {
subjectName, subjectName,
throttle: opts.maxRequests || 6 throttle: opts.maxRequests || 6
} }
return RateLimiter.addCount(options, function(error, canContinue) { return RateLimiter.addCount(options, function (error, canContinue) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
@@ -62,7 +62,7 @@ function loginRateLimit(req, res, next) {
if (!email) { if (!email) {
return next() return next()
} }
LoginRateLimiter.processLoginRequest(email, function(err, isAllowed) { LoginRateLimiter.processLoginRequest(email, function (err, isAllowed) {
if (err) { if (err) {
return next(err) return next(err)
} }

View File

@@ -27,7 +27,7 @@ const SystemMessageManager = require('../SystemMessages/SystemMessageManager')
const oneMinInMs = 60 * 1000 const oneMinInMs = 60 * 1000
var updateOpenConnetionsMetrics = function() { var updateOpenConnetionsMetrics = function () {
metrics.gauge( metrics.gauge(
'open_connections.socketio', 'open_connections.socketio',
__guard__( __guard__(
@@ -79,7 +79,7 @@ const AdminController = {
})() })()
} }
return SystemMessageManager.getMessagesFromDB(function( return SystemMessageManager.getMessagesFromDB(function (
error, error,
systemMessages systemMessages
) { ) {
@@ -124,7 +124,7 @@ const AdminController = {
writeAllToMongo(req, res) { writeAllToMongo(req, res) {
logger.log('writing all docs to mongo') logger.log('writing all docs to mongo')
Settings.mongo.writeAll = true Settings.mongo.writeAll = true
return DocumentUpdaterHandler.flushAllDocsToMongo(function() { return DocumentUpdaterHandler.flushAllDocsToMongo(function () {
logger.log('all docs have been saved to mongo') logger.log('all docs have been saved to mongo')
return res.sendStatus(200) return res.sendStatus(200)
}) })
@@ -144,18 +144,19 @@ const AdminController = {
}, },
createMessage(req, res, next) { createMessage(req, res, next) {
return SystemMessageManager.createMessage(req.body.content, function( return SystemMessageManager.createMessage(
error req.body.content,
) { function (error) {
if (error != null) { if (error != null) {
return next(error) return next(error)
}
return res.sendStatus(200)
} }
return res.sendStatus(200) )
})
}, },
clearMessages(req, res, next) { clearMessages(req, res, next) {
return SystemMessageManager.clearMessages(function(error) { return SystemMessageManager.clearMessages(function (error) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }

View File

@@ -38,7 +38,7 @@ module.exports = {
json: req.body, json: req.body,
timeout: TEN_SECONDS timeout: TEN_SECONDS
}) })
.on('error', function(error) { .on('error', function (error) {
logger.error({ err: error }, 'Spelling API error') logger.error({ err: error }, 'Spelling API error')
return res.status(500).end() return res.status(500).end()
}) })

View File

@@ -48,14 +48,14 @@ module.exports = HomeController = {
}, },
externalPage(page, title) { externalPage(page, title) {
return function(req, res, next) { return function (req, res, next) {
if (next == null) { if (next == null) {
next = function(error) {} next = function (error) {}
} }
const path = Path.resolve( const path = Path.resolve(
__dirname + `/../../../views/external/${page}.pug` __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! // No error in this callback - old method in Node.js!
if (exists) { if (exists) {
return res.render(`external/${page}.pug`, { title }) return res.render(`external/${page}.pug`, { title })

View File

@@ -67,7 +67,7 @@ const FeaturesUpdater = {
FeaturesUpdater._getFeaturesOverrides(userId, cb) FeaturesUpdater._getFeaturesOverrides(userId, cb)
} }
} }
async.series(jobs, function(err, results) { async.series(jobs, function (err, results) {
if (err) { if (err) {
OError.tag( OError.tag(
err, err,
@@ -158,26 +158,25 @@ const FeaturesUpdater = {
}, },
_getV1Features(userId, callback) { _getV1Features(userId, callback) {
V1SubscriptionManager.getPlanCodeFromV1(userId, function( V1SubscriptionManager.getPlanCodeFromV1(
err, userId,
planCode, function (err, planCode, v1Id) {
v1Id if (err) {
) { if ((err ? err.name : undefined) === 'NotFoundError') {
if (err) { return callback(null, [])
if ((err ? err.name : undefined) === 'NotFoundError') { }
return callback(null, []) return callback(err)
} }
return callback(err)
}
callback( callback(
err, err,
FeaturesUpdater._mergeFeatures( FeaturesUpdater._mergeFeatures(
V1SubscriptionManager.getGrandfatheredFeaturesForV1User(v1Id) || {}, V1SubscriptionManager.getGrandfatheredFeaturesForV1User(v1Id) || {},
FeaturesUpdater._planCodeToFeatures(planCode) FeaturesUpdater._planCodeToFeatures(planCode)
)
) )
) }
}) )
}, },
_mergeFeatures(featuresA, featuresB) { _mergeFeatures(featuresA, featuresB) {
@@ -277,31 +276,32 @@ const FeaturesUpdater = {
doSyncFromV1(v1UserId, callback) { doSyncFromV1(v1UserId, callback) {
logger.log({ v1UserId }, '[AccountSync] starting account sync') logger.log({ v1UserId }, '[AccountSync] starting account sync')
return UserGetter.getUser({ 'overleaf.id': v1UserId }, { _id: 1 }, function( return UserGetter.getUser(
err, { 'overleaf.id': v1UserId },
user { _id: 1 },
) { function (err, user) {
if (err != null) { if (err != null) {
OError.tag(err, '[AccountSync] error getting user', { OError.tag(err, '[AccountSync] error getting user', {
v1UserId v1UserId
}) })
return callback(err) 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 => const refreshFeaturesPromise = userId =>
new Promise(function(resolve, reject) { new Promise(function (resolve, reject) {
FeaturesUpdater.refreshFeatures( FeaturesUpdater.refreshFeatures(
userId, userId,
(error, features, featuresChanged) => { (error, features, featuresChanged) => {

View File

@@ -41,7 +41,7 @@ module.exports = LimitationsManager = {
}, },
allowedNumberOfCollaboratorsForUser(user_id, callback) { 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) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -55,7 +55,7 @@ module.exports = LimitationsManager = {
canAddXCollaborators(project_id, x_collaborators, callback) { canAddXCollaborators(project_id, x_collaborators, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, allowed) {} callback = function (error, allowed) {}
} }
return this.allowedNumberOfCollaboratorsInProject( return this.allowedNumberOfCollaboratorsInProject(
project_id, project_id,
@@ -94,7 +94,7 @@ module.exports = LimitationsManager = {
hasPaidSubscription(user, callback) { hasPaidSubscription(user, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, hasSubscriptionOrIsMember) {} callback = function (err, hasSubscriptionOrIsMember) {}
} }
return this.userHasV2Subscription( return this.userHasV2Subscription(
user, user,
@@ -132,27 +132,27 @@ module.exports = LimitationsManager = {
userHasV2Subscription(user, callback) { userHasV2Subscription(user, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, hasSubscription, subscription) {} callback = function (err, hasSubscription, subscription) {}
} }
return SubscriptionLocator.getUsersSubscription(user._id, function( return SubscriptionLocator.getUsersSubscription(
err, user._id,
subscription function (err, subscription) {
) { if (err != null) {
if (err != null) { return callback(err)
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) { userHasV1OrV2Subscription(user, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, hasSubscription) {} callback = function (err, hasSubscription) {}
} }
return this.userHasV2Subscription(user, (err, hasV2Subscription) => { return this.userHasV2Subscription(user, (err, hasV2Subscription) => {
if (err != null) { if (err != null) {
@@ -175,35 +175,37 @@ module.exports = LimitationsManager = {
userIsMemberOfGroupSubscription(user, callback) { userIsMemberOfGroupSubscription(user, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, isMember, subscriptions) {} callback = function (error, isMember, subscriptions) {}
} }
return SubscriptionLocator.getMemberSubscriptions(user._id, function( return SubscriptionLocator.getMemberSubscriptions(
err, user._id,
subscriptions function (err, subscriptions) {
) { if (subscriptions == null) {
if (subscriptions == null) { subscriptions = []
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) { userHasV1Subscription(user, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, hasV1Subscription) {} callback = function (error, hasV1Subscription) {}
} }
return V1SubscriptionManager.getSubscriptionsFromV1(user._id, function( return V1SubscriptionManager.getSubscriptionsFromV1(
err, user._id,
v1Subscription function (err, v1Subscription) {
) { return callback(
return callback( err,
err, !!(v1Subscription != null
!!(v1Subscription != null ? v1Subscription.has_subscription : undefined) ? v1Subscription.has_subscription
) : undefined)
}) )
}
)
}, },
teamHasReachedMemberLimit(subscription) { teamHasReachedMemberLimit(subscription) {
@@ -217,27 +219,27 @@ module.exports = LimitationsManager = {
hasGroupMembersLimitReached(subscriptionId, callback) { hasGroupMembersLimitReached(subscriptionId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, limitReached, subscription) {} callback = function (err, limitReached, subscription) {}
} }
return SubscriptionLocator.getSubscription(subscriptionId, function( return SubscriptionLocator.getSubscription(
err, subscriptionId,
subscription function (err, subscription) {
) { if (err != null) {
if (err != null) { OError.tag(err, 'error getting subscription', {
OError.tag(err, 'error getting subscription', { subscriptionId
subscriptionId })
}) return callback(err)
return callback(err) }
} if (subscription == null) {
if (subscription == null) { logger.warn({ subscriptionId }, 'no subscription found')
logger.warn({ subscriptionId }, 'no subscription found') return callback(new Error('no subscription found'))
return callback(new Error('no subscription found')) }
}
const limitReached = LimitationsManager.teamHasReachedMemberLimit( const limitReached = LimitationsManager.teamHasReachedMemberLimit(
subscription subscription
) )
return callback(err, limitReached, subscription) return callback(err, limitReached, subscription)
}) }
)
} }
} }

View File

@@ -65,7 +65,7 @@ const RecurlyWrapper = {
method: 'GET', method: 'GET',
expect404: true expect404: true
}, },
function(error, response, responseBody) { function (error, response, responseBody) {
if (error) { if (error) {
OError.tag( OError.tag(
error, error,
@@ -86,20 +86,20 @@ const RecurlyWrapper = {
return next(null, cache) return next(null, cache)
} }
logger.log({ user_id: user._id }, 'user appears to exist in recurly') logger.log({ user_id: user._id }, 'user appears to exist in recurly')
return RecurlyWrapper._parseAccountXml(responseBody, function( return RecurlyWrapper._parseAccountXml(
err, responseBody,
account function (err, account) {
) { if (err) {
if (err) { OError.tag(err, 'error parsing account', {
OError.tag(err, 'error parsing account', { user_id: user._id
user_id: user._id })
}) return next(err)
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 next(error)
} }
return RecurlyWrapper._parseAccountXml(responseBody, function( return RecurlyWrapper._parseAccountXml(
err, responseBody,
account function (err, account) {
) { if (err) {
if (err) { OError.tag(err, 'error creating account', {
OError.tag(err, 'error creating account', { user_id: user._id
user_id: user._id })
}) return next(err)
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 next(error)
} }
return RecurlyWrapper._parseBillingInfoXml(responseBody, function( return RecurlyWrapper._parseBillingInfoXml(
err, responseBody,
billingInfo function (err, billingInfo) {
) { if (err) {
if (err) { OError.tag(err, 'error creating billing info', {
OError.tag(err, 'error creating billing info', { user_id: user._id,
user_id: user._id, accountCode
accountCode })
}) return next(err)
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 next(error)
} }
return RecurlyWrapper._parseBillingInfoXml(responseBody, function( return RecurlyWrapper._parseBillingInfoXml(
err, responseBody,
billingInfo function (err, billingInfo) {
) { if (err) {
if (err) { OError.tag(err, 'error updating billing info', {
OError.tag(err, 'error updating billing info', { user_id: user._id
user_id: user._id })
}) return next(err)
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 next(error)
} }
return RecurlyWrapper._parseSubscriptionXml(responseBody, function( return RecurlyWrapper._parseSubscriptionXml(
err, responseBody,
subscription function (err, subscription) {
) { if (err) {
if (err) { OError.tag(err, 'error creating subscription', {
OError.tag(err, 'error creating subscription', { user_id: user._id
user_id: user._id })
}) return next(err)
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.setAddressAndCompanyBillingInfo,
RecurlyWrapper._paypal.createSubscription RecurlyWrapper._paypal.createSubscription
], ],
function(err, result) { function (err, result) {
if (err) { if (err) {
OError.tag(err, 'error in paypal subscription creation process', { OError.tag(err, 'error in paypal subscription creation process', {
user_id: user._id user_id: user._id
@@ -449,7 +449,7 @@ const RecurlyWrapper = {
const { expect404, expect422 } = options const { expect404, expect422 } = options
delete options.expect404 delete options.expect404
delete options.expect422 delete options.expect422
return request(options, function(error, response, body) { return request(options, function (error, response, body) {
if ( if (
error == null && error == null &&
response.statusCode !== 200 && response.statusCode !== 200 &&
@@ -532,16 +532,16 @@ const RecurlyWrapper = {
) )
} }
return RecurlyWrapper.getAccount(accountId, function( return RecurlyWrapper.getAccount(
error, accountId,
account function (error, account) {
) { if (error != null) {
if (error != null) { return callback(error)
return callback(error) }
recurlySubscription.account = account
return callback(null, recurlySubscription)
} }
recurlySubscription.account = account )
return callback(null, recurlySubscription)
})
} else { } else {
return callback(null, recurlySubscription) return callback(null, recurlySubscription)
} }
@@ -566,7 +566,7 @@ const RecurlyWrapper = {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
return RecurlyWrapper._parseXml(body, function(err, data) { return RecurlyWrapper._parseXml(body, function (err, data) {
if (err != null) { if (err != null) {
logger.warn({ err }, 'could not get accoutns') logger.warn({ err }, 'could not get accoutns')
callback(err) callback(err)
@@ -620,29 +620,30 @@ const RecurlyWrapper = {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
return RecurlyWrapper._parseRedemptionsXml(body, function( return RecurlyWrapper._parseRedemptionsXml(
error, body,
redemptions 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
) {
if (error != null) { if (error != null) {
return callback(error) 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`, url: `subscriptions/${subscriptionId}/cancel`,
method: 'put' method: 'put'
}, },
function(error, response, body) { function (error, response, body) {
if (error != null) { if (error != null) {
return RecurlyWrapper._parseXml(body, function(_err, parsed) { return RecurlyWrapper._parseXml(body, function (_err, parsed) {
if ( if (
__guard__( __guard__(
parsed != null ? parsed.error : undefined, parsed != null ? parsed.error : undefined,
@@ -870,7 +871,7 @@ const RecurlyWrapper = {
listAccountActiveSubscriptions(account_id, callback) { listAccountActiveSubscriptions(account_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, subscriptions) {} callback = function (error, subscriptions) {}
} }
return RecurlyWrapper.apiRequest( return RecurlyWrapper.apiRequest(
{ {
@@ -880,7 +881,7 @@ const RecurlyWrapper = {
}, },
expect404: true expect404: true
}, },
function(error, response, body) { function (error, response, body) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -975,7 +976,7 @@ const RecurlyWrapper = {
}, },
_parseXmlAndGetAttribute(xml, attribute, callback) { _parseXmlAndGetAttribute(xml, attribute, callback) {
return RecurlyWrapper._parseXml(xml, function(error, data) { return RecurlyWrapper._parseXml(xml, function (error, data) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -990,7 +991,7 @@ const RecurlyWrapper = {
}, },
_parseXml(xml, callback) { _parseXml(xml, callback) {
var convertDataTypes = function(data) { var convertDataTypes = function (data) {
let key, value let key, value
if (data != null && data.$ != null) { if (data != null && data.$ != null) {
if (data.$.nil === 'nil') { if (data.$.nil === 'nil') {
@@ -1033,7 +1034,7 @@ const RecurlyWrapper = {
explicitArray: false, explicitArray: false,
emptyTag: '' emptyTag: ''
}) })
return parser.parseString(xml, function(error, data) { return parser.parseString(xml, function (error, data) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }

View File

@@ -41,7 +41,7 @@ module.exports = SubscriptionController = {
return GeoIpLookup.getCurrencyCode( return GeoIpLookup.getCurrencyCode(
(req.query != null ? req.query.ip : undefined) || req.ip, (req.query != null ? req.query.ip : undefined) || req.ip,
function(err, recomendedCurrency) { function (err, recomendedCurrency) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} }
@@ -57,16 +57,17 @@ module.exports = SubscriptionController = {
}) })
const user_id = AuthenticationController.getLoggedInUserId(req) const user_id = AuthenticationController.getLoggedInUserId(req)
if (user_id != null) { if (user_id != null) {
return UserGetter.getUser(user_id, { signUpDate: 1 }, function( return UserGetter.getUser(
err, user_id,
user { signUpDate: 1 },
) { function (err, user) {
if (err != null) { if (err != null) {
return next(err) return next(err)
}
currentUser = user
return render()
} }
currentUser = user )
return render()
})
} else { } else {
return render() return render()
} }
@@ -81,68 +82,68 @@ module.exports = SubscriptionController = {
if (!plan) { if (!plan) {
return HttpErrorHandler.unprocessableEntity(req, res, 'Plan not found') return HttpErrorHandler.unprocessableEntity(req, res, 'Plan not found')
} }
return LimitationsManager.userHasV1OrV2Subscription(user, function( return LimitationsManager.userHasV1OrV2Subscription(
err, user,
hasSubscription function (err, hasSubscription) {
) { if (err != null) {
if (err != null) { return next(err)
return next(err) }
} if (hasSubscription) {
if (hasSubscription) { return res.redirect('/user/subscription?hasSubscription=true')
return res.redirect('/user/subscription?hasSubscription=true') } else {
} else { // LimitationsManager.userHasV2Subscription only checks Mongo. Double check with
// LimitationsManager.userHasV2Subscription only checks Mongo. Double check with // Recurly as well at this point (we don't do this most places for speed).
// Recurly as well at this point (we don't do this most places for speed). return SubscriptionHandler.validateNoSubscriptionInRecurly(
return SubscriptionHandler.validateNoSubscriptionInRecurly( user._id,
user._id, function (error, valid) {
function(error, valid) { if (error != null) {
if (error != null) { return next(error)
return next(error) }
} if (!valid) {
if (!valid) { res.redirect('/user/subscription?hasSubscription=true')
res.redirect('/user/subscription?hasSubscription=true') } else {
} else { let currency =
let currency = req.query.currency != null
req.query.currency != null ? req.query.currency.toUpperCase()
? req.query.currency.toUpperCase() : undefined
: undefined return GeoIpLookup.getCurrencyCode(
return GeoIpLookup.getCurrencyCode( (req.query != null ? req.query.ip : undefined) || req.ip,
(req.query != null ? req.query.ip : undefined) || req.ip, function (err, recomendedCurrency, countryCode) {
function(err, recomendedCurrency, countryCode) { if (err != null) {
if (err != null) { return next(err)
return next(err) }
} if (recomendedCurrency != null && currency == null) {
if (recomendedCurrency != null && currency == null) { currency = recomendedCurrency
currency = recomendedCurrency }
} return res.render('subscriptions/new', {
return res.render('subscriptions/new', { title: 'subscribe',
title: 'subscribe',
currency,
countryCode,
plan,
showStudentPlan: req.query.ssp === 'true',
recurlyConfig: JSON.stringify({
currency, currency,
subdomain: Settings.apis.recurly.subdomain countryCode,
}), plan,
showCouponField: !!req.query.scf, showStudentPlan: req.query.ssp === 'true',
showVatField: !!req.query.svf, recurlyConfig: JSON.stringify({
gaOptimize: true currency,
}) subdomain: Settings.apis.recurly.subdomain
} }),
) showCouponField: !!req.query.scf,
showVatField: !!req.query.svf,
gaOptimize: true
})
}
)
}
} }
} )
) }
} }
}) )
}, },
userSubscriptionPage(req, res, next) { userSubscriptionPage(req, res, next) {
const user = AuthenticationController.getSessionUser(req) const user = AuthenticationController.getSessionUser(req)
return SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel( return SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel(
user, user,
function(error, results) { function (error, results) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
@@ -155,31 +156,31 @@ module.exports = SubscriptionController = {
managedPublishers, managedPublishers,
v1SubscriptionStatus v1SubscriptionStatus
} = results } = results
return LimitationsManager.userHasV1OrV2Subscription(user, function( return LimitationsManager.userHasV1OrV2Subscription(
err, user,
hasSubscription function (err, hasSubscription) {
) { if (error != null) {
if (error != null) { return next(error)
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 const { subscriptionDetails } = req.body
return LimitationsManager.userHasV1OrV2Subscription(user, function( return LimitationsManager.userHasV1OrV2Subscription(
err, user,
hasSubscription function (err, hasSubscription) {
) { if (err != null) {
if (err != null) { return next(err)
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)
} }
) 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) { successful_subscription(req, res, next) {
const user = AuthenticationController.getSessionUser(req) const user = AuthenticationController.getSessionUser(req)
return SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel( return SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel(
user, user,
function(error, { personalSubscription }) { function (error, { personalSubscription }) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
@@ -258,7 +259,7 @@ module.exports = SubscriptionController = {
cancelSubscription(req, res, next) { cancelSubscription(req, res, next) {
const user = AuthenticationController.getSessionUser(req) const user = AuthenticationController.getSessionUser(req)
logger.log({ user_id: user._id }, 'canceling subscription') logger.log({ user_id: user._id }, 'canceling subscription')
return SubscriptionHandler.cancelSubscription(user, function(err) { return SubscriptionHandler.cancelSubscription(user, function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'something went wrong canceling subscription', { OError.tag(err, 'something went wrong canceling subscription', {
user_id: user._id user_id: user._id
@@ -281,7 +282,7 @@ module.exports = SubscriptionController = {
cancelV1Subscription(req, res, next) { cancelV1Subscription(req, res, next) {
const user_id = AuthenticationController.getLoggedInUserId(req) const user_id = AuthenticationController.getLoggedInUserId(req)
logger.log({ user_id }, 'canceling v1 subscription') logger.log({ user_id }, 'canceling v1 subscription')
return V1SubscriptionManager.cancelV1Subscription(user_id, function(err) { return V1SubscriptionManager.cancelV1Subscription(user_id, function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'something went wrong canceling v1 subscription', { OError.tag(err, 'something went wrong canceling v1 subscription', {
user_id user_id
@@ -310,7 +311,7 @@ module.exports = SubscriptionController = {
user, user,
planCode, planCode,
null, null,
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'something went wrong updating subscription', { OError.tag(err, 'something went wrong updating subscription', {
user_id: user._id user_id: user._id
@@ -324,20 +325,22 @@ module.exports = SubscriptionController = {
updateAccountEmailAddress(req, res, next) { updateAccountEmailAddress(req, res, next) {
const user = AuthenticationController.getSessionUser(req) const user = AuthenticationController.getSessionUser(req)
RecurlyWrapper.updateAccountEmailAddress(user._id, user.email, function( RecurlyWrapper.updateAccountEmailAddress(
error user._id,
) { user.email,
if (error) { function (error) {
return next(error) if (error) {
return next(error)
}
res.sendStatus(200)
} }
res.sendStatus(200) )
})
}, },
reactivateSubscription(req, res, next) { reactivateSubscription(req, res, next) {
const user = AuthenticationController.getSessionUser(req) const user = AuthenticationController.getSessionUser(req)
logger.log({ user_id: user._id }, 'reactivating subscription') logger.log({ user_id: user._id }, 'reactivating subscription')
return SubscriptionHandler.reactivateSubscription(user, function(err) { return SubscriptionHandler.reactivateSubscription(user, function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'something went wrong reactivating subscription', { OError.tag(err, 'something went wrong reactivating subscription', {
user_id: user._id user_id: user._id
@@ -363,7 +366,7 @@ module.exports = SubscriptionController = {
return SubscriptionHandler.syncSubscription( return SubscriptionHandler.syncSubscription(
recurlySubscription, recurlySubscription,
{ ip: req.ip }, { ip: req.ip },
function(err) { function (err) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} }
@@ -374,7 +377,7 @@ module.exports = SubscriptionController = {
const recurlyAccountCode = eventData.account.account_code const recurlyAccountCode = eventData.account.account_code
return SubscriptionHandler.attemptPaypalInvoiceCollection( return SubscriptionHandler.attemptPaypalInvoiceCollection(
recurlyAccountCode, recurlyAccountCode,
function(err) { function (err) {
if (err) { if (err) {
return next(err) return next(err)
} }
@@ -388,36 +391,38 @@ module.exports = SubscriptionController = {
renderUpgradeToAnnualPlanPage(req, res, next) { renderUpgradeToAnnualPlanPage(req, res, next) {
const user = AuthenticationController.getSessionUser(req) const user = AuthenticationController.getSessionUser(req)
return LimitationsManager.userHasV2Subscription(user, function( return LimitationsManager.userHasV2Subscription(
err, user,
hasSubscription, function (err, hasSubscription, subscription) {
subscription let planName
) { if (err != null) {
let planName return next(err)
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) { processUpgradeToAnnualPlan(req, res, next) {
@@ -433,7 +438,7 @@ module.exports = SubscriptionController = {
user, user,
annualPlanName, annualPlanName,
coupon_code, coupon_code,
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'error updating subscription', { OError.tag(err, 'error updating subscription', {
user_id: user._id user_id: user._id
@@ -447,29 +452,32 @@ module.exports = SubscriptionController = {
extendTrial(req, res, next) { extendTrial(req, res, next) {
const user = AuthenticationController.getSessionUser(req) const user = AuthenticationController.getSessionUser(req)
return LimitationsManager.userHasV2Subscription(user, function( return LimitationsManager.userHasV2Subscription(
err, user,
hasSubscription, function (err, hasSubscription, subscription) {
subscription
) {
if (err != null) {
return next(err)
}
return SubscriptionHandler.extendTrial(subscription, 14, function(err) {
if (err != null) { if (err != null) {
return res.sendStatus(500) return next(err)
} else {
return res.sendStatus(200)
} }
}) return SubscriptionHandler.extendTrial(
}) subscription,
14,
function (err) {
if (err != null) {
return res.sendStatus(500)
} else {
return res.sendStatus(200)
}
}
)
}
)
}, },
recurlyNotificationParser(req, res, next) { recurlyNotificationParser(req, res, next) {
let xml = '' let xml = ''
req.on('data', chunk => (xml += chunk)) req.on('data', chunk => (xml += chunk))
return req.on('end', () => return req.on('end', () =>
RecurlyWrapper._parseXml(xml, function(error, body) { RecurlyWrapper._parseXml(xml, function (error, body) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
@@ -481,7 +489,7 @@ module.exports = SubscriptionController = {
refreshUserFeatures(req, res, next) { refreshUserFeatures(req, res, next) {
const { user_id } = req.params const { user_id } = req.params
return FeaturesUpdater.refreshFeatures(user_id, function(error) { return FeaturesUpdater.refreshFeatures(user_id, function (error) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }

View File

@@ -30,7 +30,7 @@ module.exports = {
return SubscriptionGroupHandler.removeUserFromGroup( return SubscriptionGroupHandler.removeUserFromGroup(
subscription._id, subscription._id,
userToRemove_id, userToRemove_id,
function(err) { function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'error removing user from group', { OError.tag(err, 'error removing user from group', {
subscriptionId: subscription._id, subscriptionId: subscription._id,
@@ -46,28 +46,28 @@ module.exports = {
removeSelfFromGroup(req, res, next) { removeSelfFromGroup(req, res, next) {
const subscriptionId = req.query.subscriptionId const subscriptionId = req.query.subscriptionId
const userToRemove_id = AuthenticationController.getLoggedInUserId(req) const userToRemove_id = AuthenticationController.getLoggedInUserId(req)
return SubscriptionLocator.getSubscription(subscriptionId, function( return SubscriptionLocator.getSubscription(
error, subscriptionId,
subscription function (error, subscription) {
) { if (error != null) {
if (error != null) { return next(error)
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 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)
}
)
}
)
} }
} }

View File

@@ -41,7 +41,7 @@ const SubscriptionGroupHandler = {
return Subscription.updateOne( return Subscription.updateOne(
{ admin_id: oldId }, { admin_id: oldId },
{ admin_id: newId }, { admin_id: newId },
function(error) { function (error) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -51,7 +51,7 @@ const SubscriptionGroupHandler = {
'manager_ids', 'manager_ids',
oldId, oldId,
newId, newId,
function(error) { function (error) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -71,12 +71,12 @@ const SubscriptionGroupHandler = {
isUserPartOfGroup(user_id, subscription_id, callback) { isUserPartOfGroup(user_id, subscription_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, partOfGroup) {} callback = function (err, partOfGroup) {}
} }
return SubscriptionLocator.getSubscriptionByMemberIdAndId( return SubscriptionLocator.getSubscriptionByMemberIdAndId(
user_id, user_id,
subscription_id, subscription_id,
function(err, subscription) { function (err, subscription) {
let partOfGroup let partOfGroup
if (subscription != null) { if (subscription != null) {
partOfGroup = true partOfGroup = true
@@ -90,7 +90,7 @@ const SubscriptionGroupHandler = {
getTotalConfirmedUsersInGroup(subscription_id, callback) { getTotalConfirmedUsersInGroup(subscription_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, totalUsers) {} callback = function (err, totalUsers) {}
} }
return SubscriptionLocator.getSubscription( return SubscriptionLocator.getSubscription(
subscription_id, 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 // 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. // two. Note we need to add first, since the query is based on the old user.
const query = {} const query = {}
@@ -118,7 +118,7 @@ var replaceInArray = function(model, property, oldValue, newValue, callback) {
const setOldValue = {} const setOldValue = {}
setOldValue[property] = oldValue setOldValue[property] = oldValue
model.updateMany(query, { $addToSet: setNewValue }, function(error) { model.updateMany(query, { $addToSet: setNewValue }, function (error) {
if (error) { if (error) {
return callback(error) return callback(error)
} }

View File

@@ -11,228 +11,227 @@ const Analytics = require('../Analytics/AnalyticsManager')
const SubscriptionHandler = { const SubscriptionHandler = {
validateNoSubscriptionInRecurly(userId, callback) { validateNoSubscriptionInRecurly(userId, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
RecurlyWrapper.listAccountActiveSubscriptions(userId, function( RecurlyWrapper.listAccountActiveSubscriptions(
error, userId,
subscriptions function (error, subscriptions) {
) { if (subscriptions == null) {
if (subscriptions == null) { subscriptions = []
subscriptions = [] }
} if (error != null) {
if (error != null) { return callback(error)
return callback(error) }
} if (subscriptions.length > 0) {
if (subscriptions.length > 0) { SubscriptionUpdater.syncSubscription(
SubscriptionUpdater.syncSubscription(subscriptions[0], userId, function( subscriptions[0],
error 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) {
if (error != null) { if (error != null) {
return callback(error) 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) { updateSubscription(user, planCode, couponCode, callback) {
LimitationsManager.userHasV2Subscription(user, function( LimitationsManager.userHasV2Subscription(
err, user,
hasSubscription, function (err, hasSubscription, subscription) {
subscription if (err) {
) { logger.warn(
if (err) { { err, user_id: user._id, hasSubscription },
logger.warn( 'there was an error checking user v2 subscription'
{ err, user_id: user._id, hasSubscription }, )
'there was an error checking user v2 subscription' }
) if (!hasSubscription) {
} return callback()
if (!hasSubscription) { } else {
return callback() return async.series(
} else { [
return async.series( function (cb) {
[ if (couponCode == null) {
function(cb) { return 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
)
} }
) RecurlyWrapper.getSubscription(
}, subscription.recurlySubscription_id,
cb => { includeAccount: true },
RecurlyWrapper.updateSubscription( function (err, usersSubscription) {
subscription.recurlySubscription_id, if (err != null) {
{ plan_code: planCode, timeframe: 'now' }, return callback(err)
function(error, recurlySubscription) { }
if (error != null) { RecurlyWrapper.redeemCoupon(
return callback(error) usersSubscription.account.account_code,
couponCode,
cb
)
} }
SubscriptionUpdater.syncSubscription( )
recurlySubscription, },
user._id, cb =>
cb RecurlyWrapper.updateSubscription(
) subscription.recurlySubscription_id,
} { plan_code: planCode, timeframe: 'now' },
) function (error, recurlySubscription) {
], if (error != null) {
callback return callback(error)
) }
SubscriptionUpdater.syncSubscription(
recurlySubscription,
user._id,
cb
)
}
)
],
callback
)
}
} }
}) )
}, },
cancelSubscription(user, callback) { cancelSubscription(user, callback) {
LimitationsManager.userHasV2Subscription(user, function( LimitationsManager.userHasV2Subscription(
err, user,
hasSubscription, function (err, hasSubscription, subscription) {
subscription if (err) {
) { logger.warn(
if (err) { { err, user_id: user._id, hasSubscription },
logger.warn( 'there was an error checking user v2 subscription'
{ err, user_id: user._id, hasSubscription }, )
'there was an error checking user v2 subscription' }
) if (hasSubscription) {
} RecurlyWrapper.cancelSubscription(
if (hasSubscription) { subscription.recurlySubscription_id,
RecurlyWrapper.cancelSubscription( function (error) {
subscription.recurlySubscription_id, if (error != null) {
function(error) { return callback(error)
if (error != null) { }
return callback(error) const emailOpts = {
} to: user.email,
const emailOpts = { first_name: user.first_name
to: user.email, }
first_name: user.first_name const ONE_HOUR_IN_MS = 1000 * 60 * 60
} setTimeout(
const ONE_HOUR_IN_MS = 1000 * 60 * 60 () =>
setTimeout( EmailHandler.sendEmail(
() => 'canceledSubscription',
EmailHandler.sendEmail( emailOpts,
'canceledSubscription', err => {
emailOpts, if (err != null) {
err => { logger.warn(
if (err != null) { { err },
logger.warn( 'failed to send confirmation email for subscription cancellation'
{ err }, )
'failed to send confirmation email for subscription cancellation' }
)
} }
} ),
), ONE_HOUR_IN_MS
ONE_HOUR_IN_MS )
) Analytics.recordEvent(user._id, 'subscription-canceled')
Analytics.recordEvent(user._id, 'subscription-canceled') callback()
callback() }
} )
) } else {
} else { callback()
callback() }
} }
}) )
}, },
reactivateSubscription(user, callback) { reactivateSubscription(user, callback) {
LimitationsManager.userHasV2Subscription(user, function( LimitationsManager.userHasV2Subscription(
err, user,
hasSubscription, function (err, hasSubscription, subscription) {
subscription if (err) {
) { logger.warn(
if (err) { { err, user_id: user._id, hasSubscription },
logger.warn( 'there was an error checking user v2 subscription'
{ err, user_id: user._id, hasSubscription }, )
'there was an error checking user v2 subscription' }
) if (hasSubscription) {
} RecurlyWrapper.reactivateSubscription(
if (hasSubscription) { subscription.recurlySubscription_id,
RecurlyWrapper.reactivateSubscription( function (error) {
subscription.recurlySubscription_id, if (error != null) {
function(error) { return callback(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'
)
}
} }
) EmailHandler.sendEmail(
Analytics.recordEvent(user._id, 'subscription-reactivated') 'reactivatedSubscription',
callback() { to: user.email },
} err => {
) if (err != null) {
} else { logger.warn(
callback() { err },
'failed to send reactivation confirmation email'
)
}
}
)
Analytics.recordEvent(user._id, 'subscription-reactivated')
callback()
}
)
} else {
callback()
}
} }
}) )
}, },
syncSubscription(recurlySubscription, requesterData, callback) { syncSubscription(recurlySubscription, requesterData, callback) {
RecurlyWrapper.getSubscription( RecurlyWrapper.getSubscription(
recurlySubscription.uuid, recurlySubscription.uuid,
{ includeAccount: true }, { includeAccount: true },
function(error, recurlySubscription) { function (error, recurlySubscription) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
User.findById( User.findById(
recurlySubscription.account.account_code, recurlySubscription.account.account_code,
{ _id: 1 }, { _id: 1 },
function(error, user) { function (error, user) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }

View File

@@ -21,20 +21,20 @@ require('./GroupPlansData') // make sure dynamic group plans are loaded
const SubscriptionLocator = { const SubscriptionLocator = {
getUsersSubscription(user_or_id, callback) { getUsersSubscription(user_or_id, callback) {
const user_id = SubscriptionLocator._getUserId(user_or_id) const user_id = SubscriptionLocator._getUserId(user_or_id)
return Subscription.findOne({ admin_id: user_id }, function( return Subscription.findOne(
err, { admin_id: user_id },
subscription function (err, subscription) {
) { logger.log({ user_id }, 'got users subscription')
logger.log({ user_id }, 'got users subscription') return callback(err, subscription)
return callback(err, subscription) }
}) )
}, },
getUserIndividualSubscription(user_or_id, callback) { getUserIndividualSubscription(user_or_id, callback) {
const user_id = SubscriptionLocator._getUserId(user_or_id) const user_id = SubscriptionLocator._getUserId(user_or_id)
return Subscription.findOne( return Subscription.findOne(
{ admin_id: user_id, groupPlan: false }, { admin_id: user_id, groupPlan: false },
function(err, subscription) { function (err, subscription) {
logger.log({ user_id }, 'got users individual subscription') logger.log({ user_id }, 'got users individual subscription')
return callback(err, subscription) return callback(err, subscription)
} }
@@ -43,7 +43,7 @@ const SubscriptionLocator = {
getManagedGroupSubscriptions(user_or_id, callback) { getManagedGroupSubscriptions(user_or_id, callback) {
if (callback == null) { if (callback == null) {
callback = function(error, managedSubscriptions) {} callback = function (error, managedSubscriptions) {}
} }
const user_id = SubscriptionLocator._getUserId(user_or_id) const user_id = SubscriptionLocator._getUserId(user_or_id)
return Subscription.find({ return Subscription.find({

View File

@@ -45,37 +45,37 @@ const SubscriptionUpdater = {
callback = requesterData callback = requesterData
requesterData = {} requesterData = {}
} }
SubscriptionLocator.getUsersSubscription(adminUserId, function( SubscriptionLocator.getUsersSubscription(
err, adminUserId,
subscription function (err, subscription) {
) { if (err != null) {
if (err != null) { return callback(err)
return callback(err) }
} if (subscription != null) {
if (subscription != null) {
SubscriptionUpdater._updateSubscriptionFromRecurly(
recurlySubscription,
subscription,
requesterData,
callback
)
} else {
SubscriptionUpdater._createNewSubscription(adminUserId, function(
err,
subscription
) {
if (err != null) {
return callback(err)
}
SubscriptionUpdater._updateSubscriptionFromRecurly( SubscriptionUpdater._updateSubscriptionFromRecurly(
recurlySubscription, recurlySubscription,
subscription, subscription,
requesterData, requesterData,
callback callback
) )
}) } else {
SubscriptionUpdater._createNewSubscription(
adminUserId,
function (err, subscription) {
if (err != null) {
return callback(err)
}
SubscriptionUpdater._updateSubscriptionFromRecurly(
recurlySubscription,
subscription,
requesterData,
callback
)
}
)
}
} }
}) )
}, },
addUserToGroup(subscriptionId, userId, callback) { addUserToGroup(subscriptionId, userId, callback) {
@@ -86,7 +86,7 @@ const SubscriptionUpdater = {
SubscriptionUpdater.addUsersToGroupWithoutFeaturesRefresh( SubscriptionUpdater.addUsersToGroupWithoutFeaturesRefresh(
subscriptionId, subscriptionId,
memberIds, memberIds,
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -104,7 +104,7 @@ const SubscriptionUpdater = {
removeUserFromGroups(filter, userId, callback) { removeUserFromGroups(filter, userId, callback) {
const removeOperation = { $pull: { member_ids: userId } } const removeOperation = { $pull: { member_ids: userId } }
Subscription.updateMany(filter, removeOperation, function(err) { Subscription.updateMany(filter, removeOperation, function (err) {
if (err != null) { if (err != null) {
OError.tag(err, 'error removing user from groups', { OError.tag(err, 'error removing user from groups', {
filter, filter,
@@ -112,7 +112,7 @@ const SubscriptionUpdater = {
}) })
return callback(err) return callback(err)
} }
UserGetter.getUser(userId, function(error, user) { UserGetter.getUser(userId, function (error, user) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -130,23 +130,23 @@ const SubscriptionUpdater = {
}, },
removeUserFromAllGroups(userId, callback) { removeUserFromAllGroups(userId, callback) {
SubscriptionLocator.getMemberSubscriptions(userId, function( SubscriptionLocator.getMemberSubscriptions(
error, userId,
subscriptions function (error, subscriptions) {
) { if (error) {
if (error) { return callback(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) { deleteWithV1Id(v1TeamId, callback) {
@@ -155,7 +155,7 @@ const SubscriptionUpdater = {
deleteSubscription(subscription, deleterData, callback) { deleteSubscription(subscription, deleterData, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
async.series( async.series(
[ [
@@ -178,38 +178,38 @@ const SubscriptionUpdater = {
}, },
restoreSubscription(subscriptionId, callback) { restoreSubscription(subscriptionId, callback) {
SubscriptionLocator.getDeletedSubscription(subscriptionId, function( SubscriptionLocator.getDeletedSubscription(
err, subscriptionId,
deletedSubscription function (err, deletedSubscription) {
) { if (err) {
if (err) { return callback(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) { _refreshUsersFeatures(subscription, callback) {
@@ -284,7 +284,7 @@ const SubscriptionUpdater = {
}) })
} }
} }
subscription.save(function(error) { subscription.save(function (error) {
if (error) { if (error) {
return callback(error) return callback(error)
} }

View File

@@ -37,7 +37,7 @@ module.exports = {
teamManagerId, teamManagerId,
subscription, subscription,
email, email,
function(err, inviteUserData) { function (err, inviteUserData) {
if (err != null) { if (err != null) {
if (err.alreadyInTeam) { if (err.alreadyInTeam) {
return res.status(400).json({ return res.status(400).json({
@@ -66,58 +66,58 @@ module.exports = {
const { token } = req.params const { token } = req.params
const userId = AuthenticationController.getLoggedInUserId(req) const userId = AuthenticationController.getLoggedInUserId(req)
return TeamInvitesHandler.getInvite(token, function( return TeamInvitesHandler.getInvite(
err, token,
invite, function (err, invite, teamSubscription) {
teamSubscription
) {
if (err != null) {
return next(err)
}
if (!invite) {
return ErrorController.notFound(req, res, next)
}
return SubscriptionLocator.getUsersSubscription(userId, function(
err,
personalSubscription
) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} }
const hasIndividualRecurlySubscription = if (!invite) {
personalSubscription != null && return ErrorController.notFound(req, res, next)
personalSubscription.planCode.match(/(free|trial)/) == null && }
personalSubscription.groupPlan === false &&
personalSubscription.recurlySubscription_id != null &&
personalSubscription.recurlySubscription_id !== ''
return res.render('subscriptions/team/invite', { return SubscriptionLocator.getUsersSubscription(
inviterName: invite.inviterName, userId,
inviteToken: invite.token, function (err, personalSubscription) {
hasIndividualRecurlySubscription, if (err != null) {
appName: settings.appName, return next(err)
expired: req.query.expired }
})
}) 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) { acceptInvite(req, res, next) {
const { token } = req.params const { token } = req.params
const userId = AuthenticationController.getLoggedInUserId(req) const userId = AuthenticationController.getLoggedInUserId(req)
return TeamInvitesHandler.acceptInvite(token, userId, function( return TeamInvitesHandler.acceptInvite(
err, token,
results userId,
) { function (err, results) {
if (err != null) { if (err != null) {
return next(err) return next(err)
}
return res.sendStatus(204)
} }
return res.sendStatus(204) )
})
}, },
revokeInvite(req, res) { revokeInvite(req, res) {
@@ -132,7 +132,7 @@ module.exports = {
teamManagerId, teamManagerId,
subscription, subscription,
email, email,
function(err, results) { function (err, results) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} }

View File

@@ -20,20 +20,20 @@ const Errors = require('../Errors/Errors')
module.exports = TeamInvitesHandler = { module.exports = TeamInvitesHandler = {
getInvite(token, callback) { getInvite(token, callback) {
return Subscription.findOne({ 'teamInvites.token': token }, function( return Subscription.findOne(
err, { 'teamInvites.token': token },
subscription function (err, subscription) {
) { if (err) {
if (err) { return callback(err)
return callback(err) }
} if (!subscription) {
if (!subscription) { return callback(new Errors.NotFoundError('team not found'))
return callback(new Errors.NotFoundError('team not found')) }
}
const invite = subscription.teamInvites.find(i => i.token === token) const invite = subscription.teamInvites.find(i => i.token === token)
callback(null, invite, subscription) callback(null, invite, subscription)
}) }
)
}, },
createInvite(teamManagerId, subscription, email, callback) { createInvite(teamManagerId, subscription, email, callback) {
@@ -41,12 +41,12 @@ module.exports = TeamInvitesHandler = {
if (!email) { if (!email) {
return callback(new Error('invalid email')) return callback(new Error('invalid email'))
} }
return UserGetter.getUser(teamManagerId, function(error, teamManager) { return UserGetter.getUser(teamManagerId, function (error, teamManager) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
removeLegacyInvite(subscription.id, email, function(error) { removeLegacyInvite(subscription.id, email, function (error) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -56,31 +56,31 @@ module.exports = TeamInvitesHandler = {
}, },
importInvite(subscription, inviterName, email, token, sentAt, callback) { importInvite(subscription, inviterName, email, token, sentAt, callback) {
checkIfInviteIsPossible(subscription, email, function( checkIfInviteIsPossible(
error, subscription,
possible, email,
reason function (error, possible, reason) {
) { if (error) {
if (error) { return callback(error)
return callback(error) }
} if (!possible) {
if (!possible) { return callback(reason)
return callback(reason) }
}
subscription.teamInvites.push({ subscription.teamInvites.push({
email, email,
inviterName, inviterName,
token, token,
sentAt sentAt
}) })
subscription.save(callback) subscription.save(callback)
}) }
)
}, },
acceptInvite(token, userId, callback) { acceptInvite(token, userId, callback) {
TeamInvitesHandler.getInvite(token, function(err, invite, subscription) { TeamInvitesHandler.getInvite(token, function (err, invite, subscription) {
if (err) { if (err) {
return callback(err) return callback(err)
} }
@@ -88,15 +88,17 @@ module.exports = TeamInvitesHandler = {
return callback(new Errors.NotFoundError('invite not found')) return callback(new Errors.NotFoundError('invite not found'))
} }
SubscriptionUpdater.addUserToGroup(subscription._id, userId, function( SubscriptionUpdater.addUserToGroup(
err subscription._id,
) { userId,
if (err) { function (err) {
return callback(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 // email is in Subscription.invited_emails when they join. We'll remove this
// after a short while. // after a short while.
createTeamInvitesForLegacyInvitedEmail(email, callback) { createTeamInvitesForLegacyInvitedEmail(email, callback) {
SubscriptionLocator.getGroupsWithEmailInvite(email, function(err, teams) { SubscriptionLocator.getGroupsWithEmailInvite(email, function (err, teams) {
if (err) { if (err) {
return callback(err) return callback(err)
} }
@@ -127,81 +129,83 @@ module.exports = TeamInvitesHandler = {
} }
} }
var createInvite = function(subscription, email, inviter, callback) { var createInvite = function (subscription, email, inviter, callback) {
checkIfInviteIsPossible(subscription, email, function( checkIfInviteIsPossible(
error, subscription,
possible, email,
reason 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) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
if (!possible) {
const opts = { return callback(reason)
to: email,
inviter,
acceptInviteUrl: `${settings.siteUrl}/subscription/invites/${invite.token}/`,
appName: settings.appName
} }
EmailHandler.sendEmail('verifyEmailToJoinTeam', opts, error => {
Object.assign(invite, { invite: true }) // don't send invites when inviting self; add user directly to the group
callback(error, invite) 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 searchConditions = { _id: new ObjectId(subscriptionId.toString()) }
const removeInvite = { $pull: { teamInvites: { email } } } const removeInvite = { $pull: { teamInvites: { email } } }
@@ -227,7 +231,7 @@ var removeLegacyInvite = (subscriptionId, email, callback) =>
callback callback
) )
var checkIfInviteIsPossible = function(subscription, email, callback) { var checkIfInviteIsPossible = function (subscription, email, callback) {
if (!subscription.groupPlan) { if (!subscription.groupPlan) {
logger.log( logger.log(
{ subscriptionId: subscription.id }, { subscriptionId: subscription.id },
@@ -244,7 +248,7 @@ var checkIfInviteIsPossible = function(subscription, email, callback) {
return callback(null, false, { limitReached: true }) return callback(null, false, { limitReached: true })
} }
UserGetter.getUserByAnyEmail(email, function(error, existingUser) { UserGetter.getUserByAnyEmail(email, function (error, existingUser) {
if (error) { if (error) {
return callback(error) return callback(error)
} }
@@ -268,7 +272,7 @@ var checkIfInviteIsPossible = function(subscription, email, callback) {
}) })
} }
var getInviterName = function(inviter) { var getInviterName = function (inviter) {
let inviterName let inviterName
if (inviter.first_name && inviter.last_name) { if (inviter.first_name && inviter.last_name) {
inviterName = `${inviter.first_name} ${inviter.last_name} (${inviter.email})` inviterName = `${inviter.first_name} ${inviter.last_name} (${inviter.email})`

View File

@@ -26,7 +26,7 @@ module.exports = V1SubscriptionManager = {
// - 'v1_free' // - 'v1_free'
getPlanCodeFromV1(userId, callback) { getPlanCodeFromV1(userId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, planCode, v1Id) {} callback = function (err, planCode, v1Id) {}
} }
return V1SubscriptionManager._v1Request( return V1SubscriptionManager._v1Request(
userId, userId,
@@ -36,7 +36,7 @@ module.exports = V1SubscriptionManager = {
return `/api/v1/sharelatex/users/${v1Id}/plan_code` return `/api/v1/sharelatex/users/${v1Id}/plan_code`
} }
}, },
function(error, body, v1Id) { function (error, body, v1Id) {
if (error != null) { if (error != null) {
return callback(error) return callback(error)
} }
@@ -54,7 +54,7 @@ module.exports = V1SubscriptionManager = {
getSubscriptionsFromV1(userId, callback) { getSubscriptionsFromV1(userId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, subscriptions, v1Id) {} callback = function (err, subscriptions, v1Id) {}
} }
return V1SubscriptionManager._v1Request( return V1SubscriptionManager._v1Request(
userId, userId,
@@ -70,7 +70,7 @@ module.exports = V1SubscriptionManager = {
getSubscriptionStatusFromV1(userId, callback) { getSubscriptionStatusFromV1(userId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, status) {} callback = function (err, status) {}
} }
return V1SubscriptionManager._v1Request( return V1SubscriptionManager._v1Request(
userId, userId,
@@ -86,7 +86,7 @@ module.exports = V1SubscriptionManager = {
cancelV1Subscription(userId, callback) { cancelV1Subscription(userId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err) {} callback = function (err) {}
} }
return V1SubscriptionManager._v1Request( return V1SubscriptionManager._v1Request(
userId, userId,
@@ -102,22 +102,23 @@ module.exports = V1SubscriptionManager = {
v1IdForUser(userId, callback) { v1IdForUser(userId, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, v1Id) {} callback = function (err, v1Id) {}
} }
return UserGetter.getUser(userId, { 'overleaf.id': 1 }, function( return UserGetter.getUser(
err, userId,
user { 'overleaf.id': 1 },
) { function (err, user) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
const v1Id = __guard__( const v1Id = __guard__(
user != null ? user.overleaf : undefined, user != null ? user.overleaf : undefined,
x => x.id x => x.id
) )
return callback(null, v1Id) return callback(null, v1Id)
}) }
)
}, },
// v1 accounts created before migration to v2 had github and mendeley for free // v1 accounts created before migration to v2 had github and mendeley for free
@@ -140,13 +141,13 @@ module.exports = V1SubscriptionManager = {
_v1Request(userId, options, callback) { _v1Request(userId, options, callback) {
if (callback == null) { if (callback == null) {
callback = function(err, body, v1Id) {} callback = function (err, body, v1Id) {}
} }
if (!settings.apis.v1.url) { if (!settings.apis.v1.url) {
return callback(null, null) return callback(null, null)
} }
return V1SubscriptionManager.v1IdForUser(userId, function(err, v1Id) { return V1SubscriptionManager.v1IdForUser(userId, function (err, v1Id) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -167,7 +168,7 @@ module.exports = V1SubscriptionManager = {
json: true, json: true,
timeout: 15 * 1000 timeout: 15 * 1000
}, },
function(error, response, body) { function (error, response, body) {
if (error != null) { if (error != null) {
return callback( return callback(
new V1ConnectionError({ new V1ConnectionError({

View File

@@ -15,28 +15,28 @@ const { SystemMessage } = require('../../models/SystemMessage')
module.exports = SystemMessageManager = { module.exports = SystemMessageManager = {
getMessages(callback) { getMessages(callback) {
if (callback == null) { if (callback == null) {
callback = function(error, messages) {} callback = function (error, messages) {}
} }
callback(null, this._cachedMessages) callback(null, this._cachedMessages)
}, },
getMessagesFromDB(callback) { getMessagesFromDB(callback) {
if (callback == null) { if (callback == null) {
callback = function(error, messages) {} callback = function (error, messages) {}
} }
return SystemMessage.find({}, callback) return SystemMessage.find({}, callback)
}, },
clearMessages(callback) { clearMessages(callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return SystemMessage.deleteMany({}, callback) return SystemMessage.deleteMany({}, callback)
}, },
createMessage(content, callback) { createMessage(content, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
const message = new SystemMessage({ content }) const message = new SystemMessage({ content })
return message.save(callback) return message.save(callback)

View File

@@ -7,7 +7,7 @@ const TagsController = {
if (!userId) { if (!userId) {
return next(new Errors.NotFoundError()) return next(new Errors.NotFoundError())
} }
TagsHandler.getAllTags(userId, function(error, allTags) { TagsHandler.getAllTags(userId, function (error, allTags) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
@@ -28,7 +28,7 @@ const TagsController = {
createTag(req, res, next) { createTag(req, res, next) {
const userId = AuthenticationController.getLoggedInUserId(req) const userId = AuthenticationController.getLoggedInUserId(req)
const { name } = req.body const { name } = req.body
TagsHandler.createTag(userId, name, function(error, tag) { TagsHandler.createTag(userId, name, function (error, tag) {
if (error != null) { if (error != null) {
return next(error) return next(error)
} }
@@ -39,7 +39,7 @@ const TagsController = {
addProjectToTag(req, res, next) { addProjectToTag(req, res, next) {
const userId = AuthenticationController.getLoggedInUserId(req) const userId = AuthenticationController.getLoggedInUserId(req)
const { tagId, projectId } = req.params const { tagId, projectId } = req.params
TagsHandler.addProjectToTag(userId, tagId, projectId, function(error) { TagsHandler.addProjectToTag(userId, tagId, projectId, function (error) {
if (error) { if (error) {
return next(error) return next(error)
} }
@@ -50,18 +50,23 @@ const TagsController = {
removeProjectFromTag(req, res, next) { removeProjectFromTag(req, res, next) {
const userId = AuthenticationController.getLoggedInUserId(req) const userId = AuthenticationController.getLoggedInUserId(req)
const { tagId, projectId } = req.params const { tagId, projectId } = req.params
TagsHandler.removeProjectFromTag(userId, tagId, projectId, function(error) { TagsHandler.removeProjectFromTag(
if (error) { userId,
return next(error) tagId,
projectId,
function (error) {
if (error) {
return next(error)
}
res.status(204).end()
} }
res.status(204).end() )
})
}, },
deleteTag(req, res, next) { deleteTag(req, res, next) {
const userId = AuthenticationController.getLoggedInUserId(req) const userId = AuthenticationController.getLoggedInUserId(req)
const { tagId } = req.params const { tagId } = req.params
TagsHandler.deleteTag(userId, tagId, function(error) { TagsHandler.deleteTag(userId, tagId, function (error) {
if (error) { if (error) {
return next(error) return next(error)
} }
@@ -76,7 +81,7 @@ const TagsController = {
if (!name) { if (!name) {
return res.status(400).end() return res.status(400).end()
} }
TagsHandler.renameTag(userId, tagId, name, function(error) { TagsHandler.renameTag(userId, tagId, name, function (error) {
if (error) { if (error) {
return next(error) return next(error)
} }

View File

@@ -7,9 +7,9 @@ function getAllTags(userId, callback) {
function createTag(userId, name, callback) { function createTag(userId, name, callback) {
if (!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 // on duplicate key error return existing tag
if (err && err.code === 11000) { if (err && err.code === 11000) {
return Tag.findOne({ user_id: userId, name }, callback) return Tag.findOne({ user_id: userId, name }, callback)
@@ -20,7 +20,7 @@ function createTag(userId, name, callback) {
function renameTag(userId, tagId, name, callback) { function renameTag(userId, tagId, name, callback) {
if (!callback) { if (!callback) {
callback = function() {} callback = function () {}
} }
Tag.updateOne( Tag.updateOne(
{ {
@@ -38,7 +38,7 @@ function renameTag(userId, tagId, name, callback) {
function deleteTag(userId, tagId, callback) { function deleteTag(userId, tagId, callback) {
if (!callback) { if (!callback) {
callback = function() {} callback = function () {}
} }
Tag.deleteOne( Tag.deleteOne(
{ {
@@ -52,7 +52,7 @@ function deleteTag(userId, tagId, callback) {
// TODO: unused? // TODO: unused?
function updateTagUserIds(oldUserId, newUserId, callback) { function updateTagUserIds(oldUserId, newUserId, callback) {
if (!callback) { if (!callback) {
callback = function() {} callback = function () {}
} }
const searchOps = { user_id: oldUserId } const searchOps = { user_id: oldUserId }
const updateOperation = { $set: { user_id: newUserId } } const updateOperation = { $set: { user_id: newUserId } }
@@ -61,7 +61,7 @@ function updateTagUserIds(oldUserId, newUserId, callback) {
function removeProjectFromTag(userId, tagId, projectId, callback) { function removeProjectFromTag(userId, tagId, projectId, callback) {
if (!callback) { if (!callback) {
callback = function() {} callback = function () {}
} }
const searchOps = { const searchOps = {
_id: tagId, _id: tagId,
@@ -73,7 +73,7 @@ function removeProjectFromTag(userId, tagId, projectId, callback) {
function addProjectToTag(userId, tagId, projectId, callback) { function addProjectToTag(userId, tagId, projectId, callback) {
if (!callback) { if (!callback) {
callback = function() {} callback = function () {}
} }
const searchOps = { const searchOps = {
_id: tagId, _id: tagId,
@@ -85,7 +85,7 @@ function addProjectToTag(userId, tagId, projectId, callback) {
function addProjectToTagName(userId, name, projectId, callback) { function addProjectToTagName(userId, name, projectId, callback) {
if (!callback) { if (!callback) {
callback = function() {} callback = function () {}
} }
const searchOps = { const searchOps = {
name, name,

View File

@@ -57,7 +57,7 @@ module.exports = TemplatesController = {
req.body.templateVersionId, req.body.templateVersionId,
user_id, user_id,
req.body.imageName, req.body.imageName,
function(err, project) { function (err, project) {
if (err != null) { if (err != null) {
return next(err) return next(err)
} }

View File

@@ -49,11 +49,11 @@ const TemplatesManager = {
}, },
timeout: 60 * 1000 timeout: 60 * 1000
}) })
zipReq.on('error', function(err) { zipReq.on('error', function (err) {
logger.warn({ err }, 'error getting zip from template API') logger.warn({ err }, 'error getting zip from template API')
return callback(err) return callback(err)
}) })
return FileWriter.ensureDumpFolderExists(function(err) { return FileWriter.ensureDumpFolderExists(function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -65,7 +65,7 @@ const TemplatesManager = {
fromV1TemplateId: templateId, fromV1TemplateId: templateId,
fromV1TemplateVersionId: templateVersionId fromV1TemplateVersionId: templateVersionId
} }
writeStream.on('close', function() { writeStream.on('close', function () {
if (zipReq.response.statusCode !== 200) { if (zipReq.response.statusCode !== 200) {
logger.warn( logger.warn(
{ uri: zipUrl, statusCode: zipReq.response.statusCode }, { uri: zipUrl, statusCode: zipReq.response.statusCode },
@@ -78,7 +78,7 @@ const TemplatesManager = {
projectName, projectName,
dumpPath, dumpPath,
attributes, attributes,
function(err, project) { function (err, project) {
if (err != null) { if (err != null) {
OError.tag(err, 'problem building project from zip', { OError.tag(err, 'problem building project from zip', {
zipReq zipReq
@@ -97,11 +97,11 @@ const TemplatesManager = {
cb cb
) )
], ],
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
fs.unlink(dumpPath, function(err) { fs.unlink(dumpPath, function (err) {
if (err != null) { if (err != null) {
return logger.err({ err }, 'error unlinking template zip') return logger.err({ err }, 'error unlinking template zip')
} }
@@ -114,7 +114,7 @@ const TemplatesManager = {
{ _id: project._id }, { _id: project._id },
update, update,
{}, {},
function(err) { function (err) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }

View File

@@ -119,7 +119,7 @@ module.exports = {
} }
}, },
parseParams: (parseParams = function(req) { parseParams: (parseParams = function (req) {
let filePath, projectName let filePath, projectName
let path = req.params[0] let path = req.params[0]
const userId = req.params.user_id const userId = req.params.user_id

View File

@@ -25,166 +25,173 @@ const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
module.exports = UpdateMerger = { module.exports = UpdateMerger = {
mergeUpdate(user_id, project_id, path, updateRequest, source, callback) { mergeUpdate(user_id, project_id, path, updateRequest, source, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return FileWriter.writeStreamToDisk(project_id, updateRequest, function( return FileWriter.writeStreamToDisk(
err, project_id,
fsPath updateRequest,
) { function (err, fsPath) {
if (err != null) { if (err != null) {
return callback(err) 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) { _findExistingFileType(project_id, path, callback) {
ProjectEntityHandler.getAllEntities(project_id, function(err, docs, files) { ProjectEntityHandler.getAllEntities(
if (err != null) { project_id,
return callback(err) 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) { _determineFileType(project_id, path, fsPath, callback) {
if (callback == null) { 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 // check if there is an existing file with the same path (we either need
// to overwrite it or delete it) // to overwrite it or delete it)
UpdateMerger._findExistingFileType(project_id, path, function( UpdateMerger._findExistingFileType(
err, project_id,
existingFileType path,
) { function (err, existingFileType) {
if (err) { 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) 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 // 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 // sync, so we'll treat non-utf8 files as binary
const isBinary = binary || encoding !== 'utf-8' const isBinary = binary || encoding !== 'utf-8'
// Existing | Update | Action // Existing | Update | Action
// ---------|-----------|------- // ---------|-----------|-------
// file | isBinary | existing-file // file | isBinary | existing-file
// file | !isBinary | existing-file // file | !isBinary | existing-file
// doc | isBinary | new-file, delete-existing-doc // doc | isBinary | new-file, delete-existing-doc
// doc | !isBinary | existing-doc // doc | !isBinary | existing-doc
// null | isBinary | new-file // null | isBinary | new-file
// null | !isBinary | new-doc // null | !isBinary | new-doc
// if a binary file already exists, always keep it as a binary file // if a binary file already exists, always keep it as a binary file
// even if the update looks like a text file // even if the update looks like a text file
if (existingFileType === 'file') { if (existingFileType === 'file') {
return callback(null, 'existing-file') return callback(null, 'existing-file')
} }
// if there is an existing doc, keep it as a doc except when the // 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 // incoming update is binary. In that case delete the doc and replace
// it with a new file. // it with a new file.
if (existingFileType === 'doc') { if (existingFileType === 'doc') {
if (isBinary) { if (isBinary) {
return callback(null, 'new-file', 'delete-existing-doc') return callback(null, 'new-file', 'delete-existing-doc')
} else { } else {
return callback(null, 'existing-doc') 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) { _mergeUpdate(user_id, project_id, path, fsPath, source, callback) {
if (callback == null) { if (callback == null) {
callback = function(error) {} callback = function (error) {}
} }
return UpdateMerger._determineFileType(project_id, path, fsPath, function( return UpdateMerger._determineFileType(
err, project_id,
fileType, path,
deleteOriginalEntity fsPath,
) { function (err, fileType, deleteOriginalEntity) {
if (err != null) { if (err != null) {
return callback(err) 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) { deleteUpdate(user_id, project_id, path, source, callback) {
if (callback == null) { if (callback == null) {
callback = function() {} callback = function () {}
} }
return EditorController.deleteEntityWithPath( return EditorController.deleteEntityWithPath(
project_id, project_id,
path, path,
source, source,
user_id, user_id,
function() { function () {
return callback() return callback()
} }
) )
@@ -192,32 +199,32 @@ module.exports = UpdateMerger = {
p: { p: {
processDoc(project_id, user_id, fsPath, path, source, callback) { processDoc(project_id, user_id, fsPath, path, source, callback) {
return UpdateMerger.p.readFileIntoTextArray(fsPath, function( return UpdateMerger.p.readFileIntoTextArray(
err, fsPath,
docLines function (err, docLines) {
) { if (err != null) {
if (err != null) { OError.tag(
OError.tag( err,
err, 'error reading file into text array for process doc update',
'error reading file into text array for process doc update', {
{ project_id
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) 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) { processFile(project_id, fsPath, path, source, user_id, callback) {
@@ -228,14 +235,14 @@ module.exports = UpdateMerger = {
null, null,
source, source,
user_id, user_id,
function(err) { function (err) {
return callback(err) return callback(err)
} }
) )
}, },
readFileIntoTextArray(path, callback) { readFileIntoTextArray(path, callback) {
return fs.readFile(path, 'utf8', function(error, content) { return fs.readFile(path, 'utf8', function (error, content) {
if (content == null) { if (content == null) {
content = '' content = ''
} }

View File

@@ -121,7 +121,7 @@ const TokenAccessHandler = {
{ {
'tokens.readAndWritePrefix': numerics 'tokens.readAndWritePrefix': numerics
}, },
function(err, project) { function (err, project) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -263,7 +263,7 @@ const TokenAccessHandler = {
} }
V1Api.request( V1Api.request(
{ url: `/api/v1/sharelatex/docs/${token}/is_published` }, { url: `/api/v1/sharelatex/docs/${token}/is_published` },
function(err, response, body) { function (err, response, body) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -279,7 +279,7 @@ const TokenAccessHandler = {
exported: false exported: false
}) })
} }
UserGetter.getUser(v2UserId, { overleaf: 1 }, function(err, user) { UserGetter.getUser(v2UserId, { overleaf: 1 }, function (err, user) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@@ -289,7 +289,7 @@ const TokenAccessHandler = {
} }
V1Api.request( V1Api.request(
{ url: `/api/v1/sharelatex/users/${v1UserId}/docs/${token}/info` }, { url: `/api/v1/sharelatex/users/${v1UserId}/docs/${token}/info` },
function(err, response, body) { function (err, response, body) {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }

Some files were not shown because too many files have changed in this diff Show More