mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge pull request #6614 from overleaf/jpa-msm-separate-admin-app
[misc] move admin capability from www. to admin. subdomain GitOrigin-RevId: e0daeacf3c06b856ffb9fd35dce76e71f14e8459
This commit is contained in:
parent
c96fbc526e
commit
e82a053c85
25 changed files with 223 additions and 20 deletions
|
@ -67,6 +67,7 @@ RUN chmod +x /usr/local/bin/grunt
|
|||
ENV SHARELATEX_CONFIG /etc/sharelatex/settings.js
|
||||
|
||||
ENV WEB_API_USER "sharelatex"
|
||||
ENV ADMIN_PRIVILEGE_AVAILABLE "true"
|
||||
|
||||
ENV SHARELATEX_APP_NAME "Overleaf Community Edition"
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ const {
|
|||
acceptsJson,
|
||||
} = require('../../infrastructure/RequestContentTypeDetection')
|
||||
const { ParallelLoginError } = require('./AuthenticationErrors')
|
||||
const { hasAdminAccess } = require('../Helpers/AdminAuthorizationHelper')
|
||||
|
||||
function send401WithChallenge(res) {
|
||||
res.setHeader('WWW-Authenticate', 'OverleafLogin')
|
||||
|
@ -107,6 +108,12 @@ const AuthenticationController = {
|
|||
return res.redirect('/login')
|
||||
} // OAuth2 'state' mismatch
|
||||
|
||||
if (Settings.adminOnlyLogin && !hasAdminAccess(user)) {
|
||||
return res.status(403).json({
|
||||
message: { type: 'error', text: 'Admin only panel' },
|
||||
})
|
||||
}
|
||||
|
||||
const auditInfo = AuthenticationController.getAuditInfo(req)
|
||||
|
||||
const anonymousAnalyticsId = req.session.analyticsId
|
||||
|
@ -380,7 +387,7 @@ const AuthenticationController = {
|
|||
return next()
|
||||
}
|
||||
const user = SessionManager.getSessionUser(req.session)
|
||||
if (!(user && user.isAdmin)) {
|
||||
if (!hasAdminAccess(user)) {
|
||||
return next()
|
||||
}
|
||||
const email = user.email
|
||||
|
|
|
@ -8,6 +8,8 @@ const PrivilegeLevels = require('./PrivilegeLevels')
|
|||
const TokenAccessHandler = require('../TokenAccess/TokenAccessHandler')
|
||||
const PublicAccessLevels = require('./PublicAccessLevels')
|
||||
const Errors = require('../Errors/Errors')
|
||||
const { hasAdminAccess } = require('../Helpers/AdminAuthorizationHelper')
|
||||
const Settings = require('@overleaf/settings')
|
||||
|
||||
function isRestrictedUser(userId, privilegeLevel, isTokenMember) {
|
||||
if (privilegeLevel === PrivilegeLevels.NONE) {
|
||||
|
@ -91,8 +93,7 @@ async function getPrivilegeLevelForProjectWithUser(
|
|||
}
|
||||
|
||||
if (!opts.ignoreSiteAdmin) {
|
||||
const isAdmin = await isUserSiteAdmin(userId)
|
||||
if (isAdmin) {
|
||||
if (await isUserSiteAdmin(userId)) {
|
||||
return PrivilegeLevels.OWNER
|
||||
}
|
||||
}
|
||||
|
@ -216,8 +217,9 @@ async function isUserSiteAdmin(userId) {
|
|||
if (!userId) {
|
||||
return false
|
||||
}
|
||||
if (!Settings.adminPrivilegeAvailable) return false
|
||||
const user = await User.findOne({ _id: userId }, { isAdmin: 1 }).exec()
|
||||
return user != null && user.isAdmin === true
|
||||
return hasAdminAccess(user)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -133,8 +133,7 @@ async function ensureUserCanAdminProject(req, res, next) {
|
|||
|
||||
async function ensureUserIsSiteAdmin(req, res, next) {
|
||||
const userId = _getUserId(req)
|
||||
const isAdmin = await AuthorizationManager.promises.isUserSiteAdmin(userId)
|
||||
if (isAdmin) {
|
||||
if (await AuthorizationManager.promises.isUserSiteAdmin(userId)) {
|
||||
logger.log({ userId }, 'allowing user admin access to site')
|
||||
return next()
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ const TagsHandler = require('../Tags/TagsHandler')
|
|||
const Errors = require('../Errors/Errors')
|
||||
const logger = require('@overleaf/logger')
|
||||
const { expressify } = require('../../util/promises')
|
||||
const { hasAdminAccess } = require('../Helpers/AdminAuthorizationHelper')
|
||||
|
||||
module.exports = {
|
||||
removeUserFromProject: expressify(removeUserFromProject),
|
||||
|
@ -82,7 +83,7 @@ async function transferOwnership(req, res, next) {
|
|||
projectId,
|
||||
toUserId,
|
||||
{
|
||||
allowTransferToNonCollaborators: sessionUser.isAdmin,
|
||||
allowTransferToNonCollaborators: hasAdminAccess(sessionUser),
|
||||
sessionUserId: ObjectId(sessionUser._id),
|
||||
}
|
||||
)
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
const Settings = require('@overleaf/settings')
|
||||
|
||||
module.exports = {
|
||||
hasAdminAccess,
|
||||
}
|
||||
|
||||
function hasAdminAccess(user) {
|
||||
if (!Settings.adminPrivilegeAvailable) return false
|
||||
if (!user) return false
|
||||
return Boolean(user.isAdmin)
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
const { UserSchema } = require('../../models/User')
|
||||
const { hasAdminAccess } = require('./AdminAuthorizationHelper')
|
||||
|
||||
module.exports = {
|
||||
hasAnyStaffAccess,
|
||||
}
|
||||
|
||||
function hasAnyStaffAccess(user) {
|
||||
if (user.isAdmin) {
|
||||
if (hasAdminAccess(user)) {
|
||||
return true
|
||||
}
|
||||
if (!user.staffAccess) {
|
||||
|
|
|
@ -39,6 +39,7 @@ const SplitTestHandler = require('../SplitTests/SplitTestHandler')
|
|||
const FeaturesUpdater = require('../Subscription/FeaturesUpdater')
|
||||
const SpellingHandler = require('../Spelling/SpellingHandler')
|
||||
const UserPrimaryEmailCheckHandler = require('../User/UserPrimaryEmailCheckHandler')
|
||||
const { hasAdminAccess } = require('../Helpers/AdminAuthorizationHelper')
|
||||
|
||||
const _ssoAvailable = (affiliation, session, linkedInstitutionIds) => {
|
||||
if (!affiliation.institution) return false
|
||||
|
@ -965,7 +966,7 @@ const ProjectController = {
|
|||
refProviders: _.mapValues(user.refProviders, Boolean),
|
||||
alphaProgram: user.alphaProgram,
|
||||
betaProgram: user.betaProgram,
|
||||
isAdmin: user.isAdmin,
|
||||
isAdmin: hasAdminAccess(user),
|
||||
},
|
||||
userSettings: {
|
||||
mode: user.ace.mode,
|
||||
|
|
|
@ -2,6 +2,7 @@ const { ObjectId } = require('mongodb')
|
|||
const _ = require('lodash')
|
||||
const { promisify } = require('util')
|
||||
const Settings = require('@overleaf/settings')
|
||||
const { hasAdminAccess } = require('../Helpers/AdminAuthorizationHelper')
|
||||
|
||||
const ENGINE_TO_COMPILER_MAP = {
|
||||
latex_dvipdf: 'latex',
|
||||
|
@ -165,7 +166,7 @@ function _addNumericSuffixToProjectName(name, allProjectNames, maxLength) {
|
|||
|
||||
function getAllowedImagesForUser(sessionUser) {
|
||||
const images = Settings.allowedImageNames || []
|
||||
if (sessionUser && sessionUser.isAdmin) {
|
||||
if (hasAdminAccess(sessionUser)) {
|
||||
return images
|
||||
} else {
|
||||
return images.filter(image => !image.adminOnly)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
const { hasAdminAccess } = require('../Helpers/AdminAuthorizationHelper')
|
||||
const UserMembershipAuthorization = {
|
||||
hasStaffAccess(requiredStaffAccess) {
|
||||
return req => {
|
||||
if (!req.user) {
|
||||
return false
|
||||
}
|
||||
if (req.user.isAdmin) {
|
||||
if (hasAdminAccess(req.user)) {
|
||||
return true
|
||||
}
|
||||
return (
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
const csurf = require('csurf')
|
||||
const csrf = csurf()
|
||||
const { promisify } = require('util')
|
||||
const Settings = require('@overleaf/settings')
|
||||
const logger = require('@overleaf/logger')
|
||||
|
||||
// Wrapper for `csurf` middleware that provides a list of routes that can be excluded from csrf checks.
|
||||
//
|
||||
|
@ -35,6 +37,18 @@ class Csrf {
|
|||
this.excluded_routes = {}
|
||||
}
|
||||
|
||||
static blockCrossOriginRequests() {
|
||||
return function (req, res, next) {
|
||||
const { origin } = req.headers
|
||||
// NOTE: Only cross-origin requests must have an origin header set.
|
||||
if (origin && !Settings.allowedOrigins.includes(origin)) {
|
||||
logger.warn({ req }, 'blocking cross-origin request')
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
disableDefaultCsrfProtection(route, method) {
|
||||
if (!this.excluded_routes[route]) {
|
||||
this.excluded_routes[route] = {}
|
||||
|
|
|
@ -12,6 +12,9 @@ const SessionManager = require('../Features/Authentication/SessionManager')
|
|||
const PackageVersions = require('./PackageVersions')
|
||||
const Modules = require('./Modules')
|
||||
const SafeHTMLSubstitute = require('../Features/Helpers/SafeHTMLSubstitution')
|
||||
const {
|
||||
hasAdminAccess,
|
||||
} = require('../Features/Helpers/AdminAuthorizationHelper')
|
||||
|
||||
let webpackManifest
|
||||
switch (process.env.NODE_ENV) {
|
||||
|
@ -299,6 +302,8 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
|
|||
res.locals.getLoggedInUserId = () =>
|
||||
SessionManager.getLoggedInUserId(req.session)
|
||||
res.locals.getSessionUser = () => SessionManager.getSessionUser(req.session)
|
||||
res.locals.hasAdminAccess = () =>
|
||||
hasAdminAccess(SessionManager.getSessionUser(req.session))
|
||||
next()
|
||||
})
|
||||
|
||||
|
|
|
@ -40,6 +40,9 @@ const HttpErrorHandler = require('../Features/Errors/HttpErrorHandler')
|
|||
const UserSessionsManager = require('../Features/User/UserSessionsManager')
|
||||
const AuthenticationController = require('../Features/Authentication/AuthenticationController')
|
||||
const SessionManager = require('../Features/Authentication/SessionManager')
|
||||
const {
|
||||
hasAdminAccess,
|
||||
} = require('../Features/Helpers/AdminAuthorizationHelper')
|
||||
|
||||
const STATIC_CACHE_AGE = Settings.cacheStaticAssets
|
||||
? oneDayInMilliseconds * 365
|
||||
|
@ -141,6 +144,11 @@ app.use(methodOverride())
|
|||
app.use(bearerToken())
|
||||
|
||||
app.use(metrics.http.monitor(logger))
|
||||
|
||||
if (Settings.blockCrossOriginRequests) {
|
||||
app.use(Csrf.blockCrossOriginRequests())
|
||||
}
|
||||
|
||||
RedirectManager.apply(webRouter)
|
||||
ProxyManager.apply(publicApiRouter)
|
||||
|
||||
|
@ -228,10 +236,7 @@ webRouter.use(SessionAutostartMiddleware.invokeCallbackMiddleware)
|
|||
webRouter.use(function (req, res, next) {
|
||||
if (Settings.siteIsOpen) {
|
||||
next()
|
||||
} else if (
|
||||
SessionManager.getSessionUser(req.session) &&
|
||||
SessionManager.getSessionUser(req.session).isAdmin
|
||||
) {
|
||||
} else if (hasAdminAccess(SessionManager.getSessionUser(req.session))) {
|
||||
next()
|
||||
} else {
|
||||
HttpErrorHandler.maintenance(req, res)
|
||||
|
|
|
@ -15,7 +15,7 @@ nav.navbar.navbar-default.navbar-main
|
|||
else
|
||||
a(href='/', aria-label=settings.appName).navbar-brand
|
||||
|
||||
- var canDisplayAdminMenu = getSessionUser() && getSessionUser().isAdmin
|
||||
- var canDisplayAdminMenu = hasAdminAccess()
|
||||
- var canDisplaySplitTestMenu = hasFeature('saas') && (canDisplayAdminMenu || (getSessionUser() && getSessionUser().staffAccess && (getSessionUser().staffAccess.splitTestMetrics || getSessionUser().staffAccess.splitTestManagement)))
|
||||
.navbar-collapse.collapse(data-ol-navbar-main-collapse)
|
||||
ul.nav.navbar-nav.navbar-right
|
||||
|
|
|
@ -10,7 +10,7 @@ nav.navbar.navbar-default.navbar-main
|
|||
else
|
||||
a(href='/', aria-label=settings.appName).navbar-brand
|
||||
|
||||
- var canDisplayAdminMenu = getSessionUser() && getSessionUser().isAdmin
|
||||
- var canDisplayAdminMenu = hasAdminAccess()
|
||||
- var canDisplaySplitTestMenu = hasFeature('saas') && (canDisplayAdminMenu || (getSessionUser() && getSessionUser().staffAccess && (getSessionUser().staffAccess.splitTestMetrics || getSessionUser().staffAccess.splitTestManagement)))
|
||||
.navbar-collapse.collapse(collapse="navCollapsed")
|
||||
ul.nav.navbar-nav.navbar-right
|
||||
|
|
|
@ -283,6 +283,12 @@ module.exports = {
|
|||
bcryptRounds: parseInt(process.env.BCRYPT_ROUNDS, 10) || 12,
|
||||
}, // number of rounds used to hash user passwords (raised to power 2)
|
||||
|
||||
adminUrl: process.env.ADMIN_URL,
|
||||
adminOnlyLogin: process.env.ADMIN_ONLY_LOGIN === 'true',
|
||||
adminPrivilegeAvailable: process.env.ADMIN_PRIVILEGE_AVAILABLE === 'true',
|
||||
blockCrossOriginRequests: process.env.BLOCK_CROSS_ORIGIN_REQUESTS === 'true',
|
||||
allowedOrigins: (process.env.ALLOWED_ORIGINS || siteUrl).split(','),
|
||||
|
||||
httpAuthUsers,
|
||||
|
||||
// Default features
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
ADMIN_PRIVILEGE_AVAILABLE=true
|
||||
BCRYPT_ROUNDS=1
|
||||
REDIS_HOST=redis
|
||||
QUEUES_REDIS_HOST=redis
|
||||
|
|
|
@ -25,6 +25,9 @@ const UserGetter = require('../../../../app/src/Features/User/UserGetter')
|
|||
const { User } = require('../../../../app/src/models/User')
|
||||
const AuthenticationController = require('../../../../app/src/Features/Authentication/AuthenticationController')
|
||||
const SessionManager = require('../../../../app/src/Features/Authentication/SessionManager')
|
||||
const {
|
||||
hasAdminAccess,
|
||||
} = require('../../../../app/src/Features/Helpers/AdminAuthorizationHelper')
|
||||
|
||||
module.exports = LaunchpadController = {
|
||||
_getAuthMethod() {
|
||||
|
@ -67,7 +70,7 @@ module.exports = LaunchpadController = {
|
|||
if (err != null) {
|
||||
return next(err)
|
||||
}
|
||||
if (user && user.isAdmin) {
|
||||
if (hasAdminAccess(user)) {
|
||||
return res.render(Path.resolve(__dirname, '../views/launchpad'), {
|
||||
wsUrl: Settings.wsUrl,
|
||||
adminUserExists,
|
||||
|
|
|
@ -31,7 +31,9 @@ describe('LaunchpadController', function () {
|
|||
this.User = {}
|
||||
this.LaunchpadController = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'@overleaf/settings': (this.Settings = {}),
|
||||
'@overleaf/settings': (this.Settings = {
|
||||
adminPrivilegeAvailable: true,
|
||||
}),
|
||||
'@overleaf/metrics': (this.Metrics = {}),
|
||||
'../../../../app/src/Features/User/UserRegistrationHandler':
|
||||
(this.UserRegistrationHandler = {}),
|
||||
|
|
64
services/web/test/acceptance/src/AdminOnlyLoginTests.js
Normal file
64
services/web/test/acceptance/src/AdminOnlyLoginTests.js
Normal file
|
@ -0,0 +1,64 @@
|
|||
const Settings = require('@overleaf/settings')
|
||||
const { expect } = require('chai')
|
||||
const User = require('./helpers/User').promises
|
||||
|
||||
describe('AdminOnlyLogin', function () {
|
||||
let adminUser, regularUser
|
||||
const flagBefore = Settings.adminOnlyLogin
|
||||
after(function () {
|
||||
Settings.adminOnlyLogin = flagBefore
|
||||
})
|
||||
|
||||
beforeEach('create admin user', async function () {
|
||||
adminUser = new User()
|
||||
await adminUser.ensureUserExists()
|
||||
await adminUser.ensureAdmin()
|
||||
})
|
||||
|
||||
beforeEach('create regular user', async function () {
|
||||
regularUser = new User()
|
||||
await regularUser.ensureUserExists()
|
||||
})
|
||||
|
||||
async function expectCanLogin(user) {
|
||||
const response = await user.login()
|
||||
expect(response.statusCode).to.equal(200)
|
||||
expect(response.body).to.deep.equal({ redir: '/project' })
|
||||
}
|
||||
|
||||
async function expectRejectedLogin(user) {
|
||||
const response = await user.login()
|
||||
expect(response.statusCode).to.equal(403)
|
||||
expect(response.body).to.deep.equal({
|
||||
message: { type: 'error', text: 'Admin only panel' },
|
||||
})
|
||||
}
|
||||
|
||||
describe('adminOnlyLogin=true', function () {
|
||||
beforeEach(function () {
|
||||
Settings.adminOnlyLogin = true
|
||||
})
|
||||
|
||||
it('should allow the admin user to login', async function () {
|
||||
await expectCanLogin(adminUser)
|
||||
})
|
||||
|
||||
it('should block a regular user from login', async function () {
|
||||
await expectRejectedLogin(regularUser)
|
||||
})
|
||||
})
|
||||
|
||||
describe('adminOnlyLogin=false', function () {
|
||||
beforeEach(function () {
|
||||
Settings.adminOnlyLogin = false
|
||||
})
|
||||
|
||||
it('should allow the admin user to login', async function () {
|
||||
await expectCanLogin(adminUser)
|
||||
})
|
||||
|
||||
it('should allow a regular user to login', async function () {
|
||||
await expectCanLogin(regularUser)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -0,0 +1,62 @@
|
|||
const Settings = require('@overleaf/settings')
|
||||
const { expect } = require('chai')
|
||||
const User = require('./helpers/User').promises
|
||||
|
||||
describe('AdminPrivilegeAvailable', function () {
|
||||
let adminUser
|
||||
const flagBefore = Settings.adminPrivilegeAvailable
|
||||
after(function () {
|
||||
Settings.adminPrivilegeAvailable = flagBefore
|
||||
})
|
||||
|
||||
beforeEach('create admin user', async function () {
|
||||
adminUser = new User()
|
||||
await adminUser.ensureUserExists()
|
||||
await adminUser.ensureAdmin()
|
||||
await adminUser.login()
|
||||
})
|
||||
|
||||
let projectIdOwned, otherUsersProjectId
|
||||
beforeEach('create owned project', async function () {
|
||||
projectIdOwned = await adminUser.createProject('owned project')
|
||||
})
|
||||
|
||||
beforeEach('create other user and project', async function () {
|
||||
const otherUser = new User()
|
||||
await otherUser.login()
|
||||
|
||||
otherUsersProjectId = await otherUser.createProject('other users project')
|
||||
})
|
||||
|
||||
async function hasAccess(projectId) {
|
||||
const { response } = await adminUser.doRequest(
|
||||
'GET',
|
||||
`/project/${projectId}`
|
||||
)
|
||||
return response.statusCode === 200
|
||||
}
|
||||
|
||||
describe('adminPrivilegeAvailable=true', function () {
|
||||
beforeEach(function () {
|
||||
Settings.adminPrivilegeAvailable = true
|
||||
})
|
||||
it('should grant the admin access to owned project', async function () {
|
||||
expect(await hasAccess(projectIdOwned)).to.equal(true)
|
||||
})
|
||||
it('should grant the admin access to non-owned project', async function () {
|
||||
expect(await hasAccess(otherUsersProjectId)).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('adminPrivilegeAvailable=false', function () {
|
||||
beforeEach(function () {
|
||||
Settings.adminPrivilegeAvailable = false
|
||||
})
|
||||
it('should grant the admin access to owned project', async function () {
|
||||
expect(await hasAccess(projectIdOwned)).to.equal(true)
|
||||
})
|
||||
it('should block the admin from non-owned project', async function () {
|
||||
expect(await hasAccess(otherUsersProjectId)).to.equal(false)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -33,6 +33,10 @@ describe('AuthenticationController', function () {
|
|||
|
||||
this.AuthenticationController = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'../Helpers/AdminAuthorizationHelper': (this.AdminAuthorizationHelper =
|
||||
{
|
||||
hasAdminAccess: sinon.stub().returns(false),
|
||||
}),
|
||||
'./AuthenticationErrors': AuthenticationErrors,
|
||||
'../User/UserAuditLogHandler': (this.UserAuditLogHandler = {
|
||||
addEntry: sinon.stub().yields(null),
|
||||
|
@ -158,6 +162,7 @@ describe('AuthenticationController', function () {
|
|||
this.SessionManager.getSessionUser = sinon
|
||||
.stub()
|
||||
.returns({ isAdmin: true })
|
||||
this.AdminAuthorizationHelper.hasAdminAccess.returns(true)
|
||||
this.AuthenticationController.validateAdmin(this.req, this.res, err => {
|
||||
this.SessionManager.getSessionUser.called.should.equal(true)
|
||||
expect(err).to.exist
|
||||
|
@ -167,6 +172,7 @@ describe('AuthenticationController', function () {
|
|||
|
||||
it('should block an admin with a bad domain', function (done) {
|
||||
this.SessionManager.getSessionUser = sinon.stub().returns(this.badAdmin)
|
||||
this.AdminAuthorizationHelper.hasAdminAccess.returns(true)
|
||||
this.AuthenticationController.validateAdmin(this.req, this.res, err => {
|
||||
this.SessionManager.getSessionUser.called.should.equal(true)
|
||||
expect(err).to.exist
|
||||
|
|
|
@ -54,7 +54,10 @@ describe('AuthorizationManager', function () {
|
|||
'../Project/ProjectGetter': this.ProjectGetter,
|
||||
'../../models/User': { User: this.User },
|
||||
'../TokenAccess/TokenAccessHandler': this.TokenAccessHandler,
|
||||
'@overleaf/settings': { passwordStrengthOptions: {} },
|
||||
'@overleaf/settings': {
|
||||
passwordStrengthOptions: {},
|
||||
adminPrivilegeAvailable: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const SandboxedModule = require('sandboxed-module')
|
||||
const sinon = require('sinon')
|
||||
const { expect } = require('chai')
|
||||
const modulePath = '../../../../app/src/Features/Helpers/AuthorizationHelper'
|
||||
|
||||
|
@ -6,6 +7,9 @@ describe('AuthorizationHelper', function () {
|
|||
beforeEach(function () {
|
||||
this.AuthorizationHelper = SandboxedModule.require(modulePath, {
|
||||
requires: {
|
||||
'./AdminAuthorizationHelper': (this.AdminAuthorizationHelper = {
|
||||
hasAdminAccess: sinon.stub().returns(false),
|
||||
}),
|
||||
'../../models/User': {
|
||||
UserSchema: {
|
||||
obj: {
|
||||
|
@ -38,11 +42,13 @@ describe('AuthorizationHelper', function () {
|
|||
|
||||
it('with admin user', function () {
|
||||
const user = { isAdmin: true }
|
||||
this.AdminAuthorizationHelper.hasAdminAccess.returns(true)
|
||||
expect(this.AuthorizationHelper.hasAnyStaffAccess(user)).to.be.true
|
||||
})
|
||||
|
||||
it('with staff user', function () {
|
||||
const user = { staffAccess: { adminMetrics: true, somethingElse: false } }
|
||||
this.AdminAuthorizationHelper.hasAdminAccess.returns(true)
|
||||
expect(this.AuthorizationHelper.hasAnyStaffAccess(user)).to.be.true
|
||||
})
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ describe('ProjectHelper', function () {
|
|||
}
|
||||
|
||||
this.Settings = {
|
||||
adminPrivilegeAvailable: true,
|
||||
allowedImageNames: [
|
||||
{ imageName: 'texlive-full:2018.1', imageDesc: 'TeX Live 2018' },
|
||||
{ imageName: 'texlive-full:2019.1', imageDesc: 'TeX Live 2019' },
|
||||
|
|
Loading…
Reference in a new issue