diff --git a/src/apps.js b/src/apps.js index 47f125265..4fb2eb24e 100644 --- a/src/apps.js +++ b/src/apps.js @@ -785,9 +785,9 @@ function isOperator(app, user) { if (!app.operators) return isAdmin(user); - if (app.operators.users.some(function (e) { return e === user.id; })) return true; + if (app.operators.users.includes(user.id)) return true; if (!app.operators.groups) return isAdmin(user); - if (app.operators.groups.some(function (gid) { return Array.isArray(user.groupIds) && user.groupIds.indexOf(gid) !== -1; })) return true; + if (app.operators.groups.some(function (gid) { return Array.isArray(user.groupIds) && user.groupIds.includes(gid); })) return true; return isAdmin(user); } @@ -798,9 +798,9 @@ function canAccess(app, user) { if (app.accessRestriction === null) return true; - if (app.accessRestriction.users.some(function (e) { return e === user.id; })) return true; + if (app.accessRestriction.users.includes(user.id)) return true; if (!app.accessRestriction.groups) return isOperator(app, user); - if (app.accessRestriction.groups.some(function (gid) { return Array.isArray(user.groupIds) && user.groupIds.indexOf(gid) !== -1; })) return true; + if (app.accessRestriction.groups.some(function (gid) { return Array.isArray(user.groupIds) && user.groupIds.includes(gid); })) return true; return isOperator(app, user); } diff --git a/src/groups.js b/src/groups.js index e32c93bd3..e58693ffa 100644 --- a/src/groups.js +++ b/src/groups.js @@ -20,11 +20,14 @@ exports = module.exports = { setLocalMembership, resetSources, + setAllowedApps, + // exported for testing _getMembership: getMembership }; -const assert = require('assert'), +const apps = require('./apps.js'), + assert = require('assert'), BoxError = require('./boxerror.js'), constants = require('./constants.js'), database = require('./database.js'), @@ -116,6 +119,13 @@ async function getByName(name) { return result[0]; } +async function getAppIds(groupId) { + assert.strictEqual(typeof groupId, 'string'); + + const results = await database.query('SELECT id FROM apps WHERE JSON_CONTAINS(accessRestrictionJson, ?, "$.groups")', [ `"${groupId}"` ]); + return results.map(r => r.id); +} + async function getWithMembers(id) { assert.strictEqual(typeof id, 'string'); @@ -128,12 +138,18 @@ async function getWithMembers(id) { const result = results[0]; result.userIds = result.userIds ? result.userIds.split(',') : [ ]; + result.appIds = getAppIds(result.id); return result; } async function list() { const results = await database.query('SELECT ' + GROUPS_FIELDS + ' FROM userGroups ORDER BY name'); + + for (const r of results) { + r.appIds = getAppIds(r.id); + } + return results; } @@ -264,3 +280,22 @@ async function setName(group, name, auditSource) { async function resetSources() { await database.query('UPDATE userGroups SET source = ?', [ '' ]); } + +async function setAllowedApps(group, appIds, auditSource) { + assert.strictEqual(typeof group, 'object'); + assert(Array.isArray(appIds)); + assert.strictEqual(typeof auditSource, 'object'); + + const result = await apps.list(); + for (const app of result) { + const accessRestriction = app.accessRestriction || { users: [], groups: [] }; + if (appIds.includes(app.id)) { // add + if (accessRestriction.groups.includes(group.id)) continue; + accessRestriction.groups.push(group.id); + } else { // remove + if (!accessRestriction.groups?.includes(group.id)) continue; + accessRestriction.groups = accessRestriction.groups.filter(gid => gid !== group.id); + } + await apps.update(app.id, { accessRestriction }); + } +} diff --git a/src/routes/groups.js b/src/routes/groups.js index 361d55902..39f802b00 100644 --- a/src/routes/groups.js +++ b/src/routes/groups.js @@ -8,7 +8,8 @@ exports = module.exports = { add, setName, del, - setMembers + setMembers, + setAllowedApps }; const assert = require('assert'), @@ -72,6 +73,19 @@ async function setMembers(req, res, next) { next(new HttpSuccess(200, {})); } +async function setAllowedApps(req, res, next) { + assert.strictEqual(typeof req.resource, 'object'); + + if (!req.body.appIds) return next(new HttpError(404, 'missing or invalid userIds fields')); + if (!Array.isArray(req.body.appIds)) return next(new HttpError(404, 'appIds must be an array')); + if (req.body.appIds.some((a) => typeof a !== 'string')) return next(new HttpError(400, 'appIds array must contain strings')); + + const [error] = await safe(groups.setAllowedApps(req.resource, req.body.appIds, AuditSource.fromRequest(req))); + if (error) return next(BoxError.toHttpError(error)); + + next(new HttpSuccess(200, {})); +} + async function list(req, res, next) { const [error, result] = await safe(groups.listWithMembers()); if (error) return next(BoxError.toHttpError(error)); diff --git a/src/server.js b/src/server.js index a1e8f0162..e5ef7022e 100644 --- a/src/server.js +++ b/src/server.js @@ -216,6 +216,7 @@ async function initializeExpressSync() { router.post('/api/v1/groups', json, token, authorizeUserManager, routes.groups.add); router.get ('/api/v1/groups/:groupId', token, authorizeUserManager, routes.groups.load, routes.groups.get); router.put ('/api/v1/groups/:groupId/members', json, token, authorizeUserManager, routes.groups.load, routes.groups.setMembers); + router.put ('/api/v1/groups/:groupId/apps', json, token, authorizeUserManager, routes.groups.load, routes.groups.setAllowedApps); router.put ('/api/v1/groups/:groupId/name', json, token, authorizeUserManager, routes.groups.load, routes.groups.setName); router.del ('/api/v1/groups/:groupId', token, authorizeUserManager, routes.groups.load, routes.groups.del);