mirror of
https://github.com/overleaf/overleaf.git
synced 2024-09-23 02:55:13 -04:00
290 lines
9.2 KiB
JavaScript
290 lines
9.2 KiB
JavaScript
|
/* eslint-disable
|
||
|
camelcase,
|
||
|
handle-callback-err,
|
||
|
max-len,
|
||
|
*/
|
||
|
// TODO: This file was created by bulk-decaffeinate.
|
||
|
// Fix any style issues and re-enable lint.
|
||
|
/*
|
||
|
* decaffeinate suggestions:
|
||
|
* DS102: Remove unnecessary code created because of implicit returns
|
||
|
* DS207: Consider shorter variations of null checks
|
||
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||
|
*/
|
||
|
let AuthorizationManager
|
||
|
const CollaboratorsHandler = require('../Collaborators/CollaboratorsHandler')
|
||
|
const ProjectGetter = require('../Project/ProjectGetter')
|
||
|
const { User } = require('../../models/User')
|
||
|
const PrivilegeLevels = require('./PrivilegeLevels')
|
||
|
const PublicAccessLevels = require('./PublicAccessLevels')
|
||
|
const Errors = require('../Errors/Errors')
|
||
|
const { ObjectId } = require('mongojs')
|
||
|
const TokenAccessHandler = require('../TokenAccess/TokenAccessHandler')
|
||
|
|
||
|
module.exports = AuthorizationManager = {
|
||
|
getPublicAccessLevel(project_id, callback) {
|
||
|
if (callback == null) {
|
||
|
callback = function(err, level) {}
|
||
|
}
|
||
|
if (!ObjectId.isValid(project_id)) {
|
||
|
return callback(new Error('invalid project id'))
|
||
|
}
|
||
|
// Note, the Project property in the DB is `publicAccesLevel`, without the second `s`
|
||
|
return ProjectGetter.getProject(
|
||
|
project_id,
|
||
|
{ publicAccesLevel: 1 },
|
||
|
function(error, project) {
|
||
|
if (error != null) {
|
||
|
return callback(error)
|
||
|
}
|
||
|
if (project == null) {
|
||
|
return callback(
|
||
|
new Errors.NotFoundError(`no project found with id ${project_id}`)
|
||
|
)
|
||
|
}
|
||
|
return callback(null, project.publicAccesLevel)
|
||
|
}
|
||
|
)
|
||
|
},
|
||
|
|
||
|
// Get the privilege level that the user has for the project
|
||
|
// Returns:
|
||
|
// * privilegeLevel: "owner", "readAndWrite", of "readOnly" if the user has
|
||
|
// access. false if the user does not have access
|
||
|
// * becausePublic: true if the access level is only because the project is public.
|
||
|
// * becauseSiteAdmin: true if access level is only because user is admin
|
||
|
getPrivilegeLevelForProject(user_id, project_id, token, callback) {
|
||
|
if (callback == null) {
|
||
|
callback = function(
|
||
|
error,
|
||
|
privilegeLevel,
|
||
|
becausePublic,
|
||
|
becauseSiteAdmin
|
||
|
) {}
|
||
|
}
|
||
|
if (user_id == null) {
|
||
|
// User is Anonymous, Try Token-based access
|
||
|
return AuthorizationManager.getPublicAccessLevel(project_id, function(
|
||
|
err,
|
||
|
publicAccessLevel
|
||
|
) {
|
||
|
if (err != null) {
|
||
|
return callback(err)
|
||
|
}
|
||
|
if (publicAccessLevel === PublicAccessLevels.TOKEN_BASED) {
|
||
|
// Anonymous users can have read-only access to token-based projects,
|
||
|
// while read-write access must be logged in,
|
||
|
// unless the `enableAnonymousReadAndWriteSharing` setting is enabled
|
||
|
return TokenAccessHandler.isValidToken(project_id, token, function(
|
||
|
err,
|
||
|
isValidReadAndWrite,
|
||
|
isValidReadOnly
|
||
|
) {
|
||
|
if (err != null) {
|
||
|
return callback(err)
|
||
|
}
|
||
|
if (isValidReadOnly) {
|
||
|
// Grant anonymous user read-only access
|
||
|
return callback(null, PrivilegeLevels.READ_ONLY, false, false)
|
||
|
} else if (
|
||
|
isValidReadAndWrite &&
|
||
|
TokenAccessHandler.ANONYMOUS_READ_AND_WRITE_ENABLED
|
||
|
) {
|
||
|
// Grant anonymous user read-and-write access
|
||
|
return callback(
|
||
|
null,
|
||
|
PrivilegeLevels.READ_AND_WRITE,
|
||
|
false,
|
||
|
false
|
||
|
)
|
||
|
} else {
|
||
|
// Deny anonymous access
|
||
|
return callback(null, PrivilegeLevels.NONE, false, false)
|
||
|
}
|
||
|
})
|
||
|
} else if (publicAccessLevel === PublicAccessLevels.READ_ONLY) {
|
||
|
// Legacy public read-only access for anonymous user
|
||
|
return callback(null, PrivilegeLevels.READ_ONLY, true, false)
|
||
|
} else if (publicAccessLevel === PublicAccessLevels.READ_AND_WRITE) {
|
||
|
// Legacy public read-write access for anonymous user
|
||
|
return callback(null, PrivilegeLevels.READ_AND_WRITE, true, false)
|
||
|
} else {
|
||
|
// Deny anonymous user access
|
||
|
return callback(null, PrivilegeLevels.NONE, false, false)
|
||
|
}
|
||
|
})
|
||
|
} else {
|
||
|
// User is present, get their privilege level from database
|
||
|
return CollaboratorsHandler.getMemberIdPrivilegeLevel(
|
||
|
user_id,
|
||
|
project_id,
|
||
|
function(error, privilegeLevel) {
|
||
|
if (error != null) {
|
||
|
return callback(error)
|
||
|
}
|
||
|
if (
|
||
|
privilegeLevel != null &&
|
||
|
privilegeLevel !== PrivilegeLevels.NONE
|
||
|
) {
|
||
|
// The user has direct access
|
||
|
return callback(null, privilegeLevel, false, false)
|
||
|
} else {
|
||
|
return AuthorizationManager.isUserSiteAdmin(user_id, function(
|
||
|
error,
|
||
|
isAdmin
|
||
|
) {
|
||
|
if (error != null) {
|
||
|
return callback(error)
|
||
|
}
|
||
|
if (isAdmin) {
|
||
|
return callback(null, PrivilegeLevels.OWNER, false, true)
|
||
|
} else {
|
||
|
// Legacy public-access system
|
||
|
// User is present (not anonymous), but does not have direct access
|
||
|
return AuthorizationManager.getPublicAccessLevel(
|
||
|
project_id,
|
||
|
function(err, publicAccessLevel) {
|
||
|
if (err != null) {
|
||
|
return callback(err)
|
||
|
}
|
||
|
if (publicAccessLevel === PublicAccessLevels.READ_ONLY) {
|
||
|
return callback(
|
||
|
null,
|
||
|
PrivilegeLevels.READ_ONLY,
|
||
|
true,
|
||
|
false
|
||
|
)
|
||
|
} else if (
|
||
|
publicAccessLevel === PublicAccessLevels.READ_AND_WRITE
|
||
|
) {
|
||
|
return callback(
|
||
|
null,
|
||
|
PrivilegeLevels.READ_AND_WRITE,
|
||
|
true,
|
||
|
false
|
||
|
)
|
||
|
} else {
|
||
|
return callback(null, PrivilegeLevels.NONE, false, false)
|
||
|
}
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
},
|
||
|
|
||
|
canUserReadProject(user_id, project_id, token, callback) {
|
||
|
if (callback == null) {
|
||
|
callback = function(error, canRead) {}
|
||
|
}
|
||
|
return AuthorizationManager.getPrivilegeLevelForProject(
|
||
|
user_id,
|
||
|
project_id,
|
||
|
token,
|
||
|
function(error, privilegeLevel) {
|
||
|
if (error != null) {
|
||
|
return callback(error)
|
||
|
}
|
||
|
return callback(
|
||
|
null,
|
||
|
[
|
||
|
PrivilegeLevels.OWNER,
|
||
|
PrivilegeLevels.READ_AND_WRITE,
|
||
|
PrivilegeLevels.READ_ONLY
|
||
|
].includes(privilegeLevel)
|
||
|
)
|
||
|
}
|
||
|
)
|
||
|
},
|
||
|
|
||
|
canUserWriteProjectContent(user_id, project_id, token, callback) {
|
||
|
if (callback == null) {
|
||
|
callback = function(error, canWriteContent) {}
|
||
|
}
|
||
|
return AuthorizationManager.getPrivilegeLevelForProject(
|
||
|
user_id,
|
||
|
project_id,
|
||
|
token,
|
||
|
function(error, privilegeLevel) {
|
||
|
if (error != null) {
|
||
|
return callback(error)
|
||
|
}
|
||
|
return callback(
|
||
|
null,
|
||
|
[PrivilegeLevels.OWNER, PrivilegeLevels.READ_AND_WRITE].includes(
|
||
|
privilegeLevel
|
||
|
)
|
||
|
)
|
||
|
}
|
||
|
)
|
||
|
},
|
||
|
|
||
|
canUserWriteProjectSettings(user_id, project_id, token, callback) {
|
||
|
if (callback == null) {
|
||
|
callback = function(error, canWriteSettings) {}
|
||
|
}
|
||
|
return AuthorizationManager.getPrivilegeLevelForProject(
|
||
|
user_id,
|
||
|
project_id,
|
||
|
token,
|
||
|
function(error, privilegeLevel, becausePublic) {
|
||
|
if (error != null) {
|
||
|
return callback(error)
|
||
|
}
|
||
|
if (privilegeLevel === PrivilegeLevels.OWNER) {
|
||
|
return callback(null, true)
|
||
|
} else if (
|
||
|
privilegeLevel === PrivilegeLevels.READ_AND_WRITE &&
|
||
|
!becausePublic
|
||
|
) {
|
||
|
return callback(null, true)
|
||
|
} else {
|
||
|
return callback(null, false)
|
||
|
}
|
||
|
}
|
||
|
)
|
||
|
},
|
||
|
|
||
|
canUserAdminProject(user_id, project_id, token, callback) {
|
||
|
if (callback == null) {
|
||
|
callback = function(error, canAdmin, becauseSiteAdmin) {}
|
||
|
}
|
||
|
return AuthorizationManager.getPrivilegeLevelForProject(
|
||
|
user_id,
|
||
|
project_id,
|
||
|
token,
|
||
|
function(error, privilegeLevel, becausePublic, becauseSiteAdmin) {
|
||
|
if (error != null) {
|
||
|
return callback(error)
|
||
|
}
|
||
|
return callback(
|
||
|
null,
|
||
|
privilegeLevel === PrivilegeLevels.OWNER,
|
||
|
becauseSiteAdmin
|
||
|
)
|
||
|
}
|
||
|
)
|
||
|
},
|
||
|
|
||
|
isUserSiteAdmin(user_id, callback) {
|
||
|
if (callback == null) {
|
||
|
callback = function(error, isAdmin) {}
|
||
|
}
|
||
|
if (user_id == null) {
|
||
|
return callback(null, false)
|
||
|
}
|
||
|
return User.findOne({ _id: user_id }, { isAdmin: 1 }, function(
|
||
|
error,
|
||
|
user
|
||
|
) {
|
||
|
if (error != null) {
|
||
|
return callback(error)
|
||
|
}
|
||
|
return callback(null, (user != null ? user.isAdmin : undefined) === true)
|
||
|
})
|
||
|
}
|
||
|
}
|