mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
Merge pull request #3495 from overleaf/ae-prettier-2
Upgrade Prettier to v2 GitOrigin-RevId: 85aa3fa1acb6332c4f58c46165a43d1a51471f33
This commit is contained in:
@@ -5,3 +5,4 @@ frontend/js/vendor
|
|||||||
modules/**/frontend/js/vendor
|
modules/**/frontend/js/vendor
|
||||||
public/js
|
public/js
|
||||||
public/minjs
|
public/minjs
|
||||||
|
frontend/stylesheets/components/nvd3.less
|
||||||
|
|||||||
@@ -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
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
}
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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')
|
)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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'))
|
||||||
|
|||||||
@@ -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)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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)
|
)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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'))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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'))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(
|
||||||
`\
|
`\
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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 })
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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)
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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})`
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 = ''
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user