overleaf/services/web/app/src/Features/Authorization/AuthorizationManager.js
Alasdair Smith 0ca81de78c Merge pull request #1717 from overleaf/as-decaffeinate-backend
Decaffeinate backend

GitOrigin-RevId: 4ca9f94fc809cab6f47cec8254cacaf1bb3806fa
2019-05-29 09:32:21 +00:00

289 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)
})
}
}