split routes and model code into user-directory.js
This commit is contained in:
+2
-2
@@ -32,7 +32,7 @@ const apps = require('./apps.js'),
|
|||||||
settings = require('./settings.js'),
|
settings = require('./settings.js'),
|
||||||
system = require('./system.js'),
|
system = require('./system.js'),
|
||||||
tasks = require('./tasks.js'),
|
tasks = require('./tasks.js'),
|
||||||
users = require('./users.js');
|
userDirectory = require('./user-directory.js');
|
||||||
|
|
||||||
async function getLocation() {
|
async function getLocation() {
|
||||||
const domain = await settings.get(settings.DASHBOARD_DOMAIN_KEY);
|
const domain = await settings.get(settings.DASHBOARD_DOMAIN_KEY);
|
||||||
@@ -56,7 +56,7 @@ async function clearLocation() {
|
|||||||
|
|
||||||
async function getConfig() {
|
async function getConfig() {
|
||||||
const ubuntuVersion = await system.getUbuntuVersion();
|
const ubuntuVersion = await system.getUbuntuVersion();
|
||||||
const profileConfig = await users.getProfileConfig();
|
const profileConfig = await userDirectory.getProfileConfig();
|
||||||
const externalLdapConfig = await externalLdap.getConfig();
|
const externalLdapConfig = await externalLdap.getConfig();
|
||||||
|
|
||||||
const { fqdn:adminFqdn, domain:adminDomain } = await getLocation();
|
const { fqdn:adminFqdn, domain:adminDomain } = await getLocation();
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ exports = module.exports = {
|
|||||||
tasks: require('./tasks.js'),
|
tasks: require('./tasks.js'),
|
||||||
tokens: require('./tokens.js'),
|
tokens: require('./tokens.js'),
|
||||||
updater: require('./updater.js'),
|
updater: require('./updater.js'),
|
||||||
|
userDirectory: require('./user-directory.js'),
|
||||||
users: require('./users.js'),
|
users: require('./users.js'),
|
||||||
volumes: require('./volumes.js'),
|
volumes: require('./volumes.js'),
|
||||||
wellknown: require('./wellknown.js')
|
wellknown: require('./wellknown.js')
|
||||||
|
|||||||
@@ -27,12 +27,13 @@ const assert = require('assert'),
|
|||||||
path = require('path'),
|
path = require('path'),
|
||||||
paths = require('../paths.js'),
|
paths = require('../paths.js'),
|
||||||
safe = require('safetydance'),
|
safe = require('safetydance'),
|
||||||
|
userDirectory = require('../user-directory.js'),
|
||||||
users = require('../users.js');
|
users = require('../users.js');
|
||||||
|
|
||||||
async function canEditProfile(req, res, next) {
|
async function canEditProfile(req, res, next) {
|
||||||
assert.strictEqual(typeof req.user, 'object');
|
assert.strictEqual(typeof req.user, 'object');
|
||||||
|
|
||||||
const [error, profileConfig] = await safe(users.getProfileConfig());
|
const [error, profileConfig] = await safe(userDirectory.getProfileConfig());
|
||||||
if (error) return next(BoxError.toHttpError(error));
|
if (error) return next(BoxError.toHttpError(error));
|
||||||
|
|
||||||
if (profileConfig.lockUserProfiles) return next(new HttpError(403, 'admin has disallowed users from editing profiles'));
|
if (profileConfig.lockUserProfiles) return next(new HttpError(403, 'admin has disallowed users from editing profiles'));
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
exports = module.exports = {
|
||||||
|
getProfileConfig,
|
||||||
|
setProfileConfig
|
||||||
|
};
|
||||||
|
|
||||||
|
const assert = require('assert'),
|
||||||
|
BoxError = require('../boxerror.js'),
|
||||||
|
HttpError = require('connect-lastmile').HttpError,
|
||||||
|
HttpSuccess = require('connect-lastmile').HttpSuccess,
|
||||||
|
safe = require('safetydance'),
|
||||||
|
userDirectory = require('../user-directory.js');
|
||||||
|
|
||||||
|
async function getProfileConfig(req, res, next) {
|
||||||
|
const [error, directoryConfig] = await safe(userDirectory.getProfileConfig());
|
||||||
|
if (error) return next(BoxError.toHttpError(error));
|
||||||
|
|
||||||
|
next(new HttpSuccess(200, directoryConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setProfileConfig(req, res, next) {
|
||||||
|
assert.strictEqual(typeof req.body, 'object');
|
||||||
|
|
||||||
|
if (typeof req.body.lockUserProfiles !== 'boolean') return next(new HttpError(400, 'lockUserProfiles is required'));
|
||||||
|
if (typeof req.body.mandatory2FA !== 'boolean') return next(new HttpError(400, 'mandatory2FA is required'));
|
||||||
|
|
||||||
|
const [error] = await safe(userDirectory.setProfileConfig(req.body));
|
||||||
|
if (error) return next(BoxError.toHttpError(error));
|
||||||
|
|
||||||
|
next(new HttpSuccess(200, {}));
|
||||||
|
}
|
||||||
@@ -18,9 +18,6 @@ exports = module.exports = {
|
|||||||
getPasswordResetLink,
|
getPasswordResetLink,
|
||||||
sendPasswordResetEmail,
|
sendPasswordResetEmail,
|
||||||
|
|
||||||
setProfileConfig,
|
|
||||||
getProfileConfig,
|
|
||||||
|
|
||||||
getInviteLink,
|
getInviteLink,
|
||||||
sendInviteEmail,
|
sendInviteEmail,
|
||||||
|
|
||||||
@@ -275,22 +272,3 @@ async function sendInviteEmail(req, res, next) {
|
|||||||
|
|
||||||
next(new HttpSuccess(202, {}));
|
next(new HttpSuccess(202, {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getProfileConfig(req, res, next) {
|
|
||||||
const [error, directoryConfig] = await safe(users.getProfileConfig());
|
|
||||||
if (error) return next(BoxError.toHttpError(error));
|
|
||||||
|
|
||||||
next(new HttpSuccess(200, directoryConfig));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setProfileConfig(req, res, next) {
|
|
||||||
assert.strictEqual(typeof req.body, 'object');
|
|
||||||
|
|
||||||
if (typeof req.body.lockUserProfiles !== 'boolean') return next(new HttpError(400, 'lockUserProfiles is required'));
|
|
||||||
if (typeof req.body.mandatory2FA !== 'boolean') return next(new HttpError(400, 'mandatory2FA is required'));
|
|
||||||
|
|
||||||
const [error] = await safe(users.setProfileConfig(req.body));
|
|
||||||
if (error) return next(BoxError.toHttpError(error));
|
|
||||||
|
|
||||||
next(new HttpSuccess(200, {}));
|
|
||||||
}
|
|
||||||
|
|||||||
+2
-2
@@ -215,8 +215,8 @@ async function initializeExpressSync() {
|
|||||||
router.del ('/api/v1/groups/:groupId', token, authorizeUserManager, routes.groups.load, routes.groups.remove);
|
router.del ('/api/v1/groups/:groupId', token, authorizeUserManager, routes.groups.load, routes.groups.remove);
|
||||||
|
|
||||||
// User directory
|
// User directory
|
||||||
router.get ('/api/v1/user_directory/profile_config', token, authorizeAdmin, routes.users.getProfileConfig);
|
router.get ('/api/v1/user_directory/profile_config', token, authorizeAdmin, routes.userDirectory.getProfileConfig);
|
||||||
router.post('/api/v1/user_directory/profile_config', json, token, authorizeAdmin, routes.users.setProfileConfig);
|
router.post('/api/v1/user_directory/profile_config', json, token, authorizeAdmin, routes.userDirectory.setProfileConfig);
|
||||||
|
|
||||||
// External LDAP
|
// External LDAP
|
||||||
router.get ('/api/v1/external_ldap/config', token, authorizeAdmin, routes.externalLdap.getConfig);
|
router.get ('/api/v1/external_ldap/config', token, authorizeAdmin, routes.externalLdap.getConfig);
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/* global it:false */
|
||||||
|
/* global describe:false */
|
||||||
|
/* global before:false */
|
||||||
|
/* global after:false */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('./common.js'),
|
||||||
|
expect = require('expect.js'),
|
||||||
|
tokens = require('../tokens.js'),
|
||||||
|
userDirectory = require('../user-directory.js');
|
||||||
|
|
||||||
|
describe('User Directory', function () {
|
||||||
|
const { setup, cleanup, admin } = common;
|
||||||
|
|
||||||
|
before(setup);
|
||||||
|
after(cleanup);
|
||||||
|
|
||||||
|
describe('profile config', function () {
|
||||||
|
it('can get default profile config', async function () {
|
||||||
|
const profileConfig = await userDirectory.getProfileConfig();
|
||||||
|
expect(profileConfig.lockUserProfiles).to.be(false);
|
||||||
|
expect(profileConfig.mandatory2FA).to.be(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can set default profile config', async function () {
|
||||||
|
await tokens.add({ name: 'token1', identifier: admin.id, clientId: tokens.ID_WEBADMIN, expires: Number.MAX_SAFE_INTEGER, lastUsedTime: null });
|
||||||
|
let result = await tokens.listByUserId(admin.id);
|
||||||
|
expect(result.length).to.be(1); // just confirm the token was really added!
|
||||||
|
|
||||||
|
await userDirectory.setProfileConfig({ mandatory2FA: true, lockUserProfiles: true });
|
||||||
|
result = await tokens.listByUserId(admin.id);
|
||||||
|
expect(result.length).to.be(0); // should have been removed by mandatory 2fa setting change
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
+1
-20
@@ -10,7 +10,6 @@ const BoxError = require('../boxerror.js'),
|
|||||||
expect = require('expect.js'),
|
expect = require('expect.js'),
|
||||||
safe = require('safetydance'),
|
safe = require('safetydance'),
|
||||||
speakeasy = require('speakeasy'),
|
speakeasy = require('speakeasy'),
|
||||||
tokens = require('../tokens.js'),
|
|
||||||
users = require('../users.js'),
|
users = require('../users.js'),
|
||||||
_ = require('underscore');
|
_ = require('underscore');
|
||||||
|
|
||||||
@@ -199,7 +198,7 @@ describe('User', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('can listPaged (search)', async function () {
|
it('can listPaged (search)', async function () {
|
||||||
let results = await users.listPaged(admin.email.slice(0, 8), null, 1, 1);
|
const results = await users.listPaged(admin.email.slice(0, 8), null, 1, 1);
|
||||||
expect(results.length).to.be(1);
|
expect(results.length).to.be(1);
|
||||||
checkUser(results[0], admin);
|
checkUser(results[0], admin);
|
||||||
});
|
});
|
||||||
@@ -632,24 +631,6 @@ describe('User', function () {
|
|||||||
it('can re-create user after user was removed', createOwner);
|
it('can re-create user after user was removed', createOwner);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('profile config', function () {
|
|
||||||
it('can get default profile config', async function () {
|
|
||||||
const profileConfig = await users.getProfileConfig();
|
|
||||||
expect(profileConfig.lockUserProfiles).to.be(false);
|
|
||||||
expect(profileConfig.mandatory2FA).to.be(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can set default profile config', async function () {
|
|
||||||
await tokens.add({ name: 'token1', identifier: admin.id, clientId: tokens.ID_WEBADMIN, expires: Number.MAX_SAFE_INTEGER, lastUsedTime: null });
|
|
||||||
let result = await tokens.listByUserId(admin.id);
|
|
||||||
expect(result.length).to.be(1); // just confirm the token was really added!
|
|
||||||
|
|
||||||
await users.setProfileConfig({ mandatory2FA: true, lockUserProfiles: true });
|
|
||||||
result = await tokens.listByUserId(admin.id);
|
|
||||||
expect(result.length).to.be(0); // should have been removed by mandatory 2fa setting change
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('parseDisplayName', function () {
|
describe('parseDisplayName', function () {
|
||||||
it('parses names', function () {
|
it('parses names', function () {
|
||||||
const names = [
|
const names = [
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
exports = module.exports = {
|
||||||
|
getProfileConfig,
|
||||||
|
setProfileConfig
|
||||||
|
};
|
||||||
|
|
||||||
|
const assert = require('assert'),
|
||||||
|
BoxError = require('./boxerror.js'),
|
||||||
|
constants = require('./constants.js'),
|
||||||
|
debug = require('debug')('box:user-directory'),
|
||||||
|
oidc = require('./oidc.js'),
|
||||||
|
settings = require('./settings.js'),
|
||||||
|
tokens = require('./tokens.js'),
|
||||||
|
users = require('./users.js');
|
||||||
|
|
||||||
|
async function getProfileConfig() {
|
||||||
|
const value = await settings.getJson(settings.PROFILE_CONFIG_KEY);
|
||||||
|
return value || { lockUserProfiles: false, mandatory2FA: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setProfileConfig(profileConfig) {
|
||||||
|
assert.strictEqual(typeof profileConfig, 'object');
|
||||||
|
|
||||||
|
if (constants.DEMO) throw new BoxError(BoxError.BAD_STATE, 'Not allowed in demo mode');
|
||||||
|
|
||||||
|
const oldConfig = await getProfileConfig();
|
||||||
|
await settings.setJson(settings.PROFILE_CONFIG_KEY, profileConfig);
|
||||||
|
|
||||||
|
if (profileConfig.mandatory2FA && !oldConfig.mandatory2FA) {
|
||||||
|
debug('setProfileConfig: logging out non-2FA users to enforce 2FA');
|
||||||
|
|
||||||
|
const allUsers = await users.list();
|
||||||
|
for (const user of allUsers) {
|
||||||
|
if (user.twoFactorAuthenticationEnabled) continue;
|
||||||
|
|
||||||
|
await tokens.delByUserIdAndType(user.id, tokens.ID_WEBADMIN);
|
||||||
|
await oidc.revokeByUserId(user.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-33
@@ -51,9 +51,6 @@ exports = module.exports = {
|
|||||||
getBackgroundImage,
|
getBackgroundImage,
|
||||||
setBackgroundImage,
|
setBackgroundImage,
|
||||||
|
|
||||||
getProfileConfig,
|
|
||||||
setProfileConfig,
|
|
||||||
|
|
||||||
resetSource,
|
resetSource,
|
||||||
|
|
||||||
parseDisplayName,
|
parseDisplayName,
|
||||||
@@ -91,15 +88,15 @@ const appPasswords = require('./apppasswords.js'),
|
|||||||
mail = require('./mail.js'),
|
mail = require('./mail.js'),
|
||||||
mailer = require('./mailer.js'),
|
mailer = require('./mailer.js'),
|
||||||
mysql = require('mysql'),
|
mysql = require('mysql'),
|
||||||
oidc = require('../oidc.js'),
|
|
||||||
qrcode = require('qrcode'),
|
qrcode = require('qrcode'),
|
||||||
safe = require('safetydance'),
|
safe = require('safetydance'),
|
||||||
settings = require('./settings.js'),
|
settings = require('./settings.js'),
|
||||||
speakeasy = require('speakeasy'),
|
speakeasy = require('speakeasy'),
|
||||||
tokens = require('./tokens.js'),
|
tokens = require('./tokens.js'),
|
||||||
translation = require('./translation.js'),
|
translation = require('./translation.js'),
|
||||||
uuid = require('uuid'),
|
|
||||||
uaParser = require('ua-parser-js'),
|
uaParser = require('ua-parser-js'),
|
||||||
|
userDirectory = require('./user-directory.js'),
|
||||||
|
uuid = require('uuid'),
|
||||||
superagent = require('superagent'),
|
superagent = require('superagent'),
|
||||||
util = require('util'),
|
util = require('util'),
|
||||||
validator = require('validator'),
|
validator = require('validator'),
|
||||||
@@ -826,7 +823,7 @@ async function getInviteLink(user, auditSource) {
|
|||||||
if (user.source) throw new BoxError(BoxError.CONFLICT, 'User is from an external directory');
|
if (user.source) throw new BoxError(BoxError.CONFLICT, 'User is from an external directory');
|
||||||
if (!user.inviteToken) throw new BoxError(BoxError.BAD_STATE, 'User already used invite link');
|
if (!user.inviteToken) throw new BoxError(BoxError.BAD_STATE, 'User already used invite link');
|
||||||
|
|
||||||
const directoryConfig = await getProfileConfig();
|
const directoryConfig = await userDirectory.getProfileConfig();
|
||||||
const { fqdn:dashboardFqdn } = await dashboard.getLocation();
|
const { fqdn:dashboardFqdn } = await dashboard.getLocation();
|
||||||
let inviteLink = `https://${dashboardFqdn}/setupaccount.html?inviteToken=${user.inviteToken}&email=${encodeURIComponent(user.email)}`;
|
let inviteLink = `https://${dashboardFqdn}/setupaccount.html?inviteToken=${user.inviteToken}&email=${encodeURIComponent(user.email)}`;
|
||||||
|
|
||||||
@@ -854,7 +851,7 @@ async function setupAccount(user, data, auditSource) {
|
|||||||
assert.strictEqual(typeof data, 'object');
|
assert.strictEqual(typeof data, 'object');
|
||||||
assert(auditSource && typeof auditSource === 'object');
|
assert(auditSource && typeof auditSource === 'object');
|
||||||
|
|
||||||
const profileConfig = await getProfileConfig();
|
const profileConfig = await userDirectory.getProfileConfig();
|
||||||
|
|
||||||
const tmp = { inviteToken: '' };
|
const tmp = { inviteToken: '' };
|
||||||
|
|
||||||
@@ -972,32 +969,6 @@ async function setBackgroundImage(id, backgroundImage) {
|
|||||||
if (result.length === 0) throw new BoxError(BoxError.NOT_FOUND, 'User not found');
|
if (result.length === 0) throw new BoxError(BoxError.NOT_FOUND, 'User not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getProfileConfig() {
|
|
||||||
const value = await settings.getJson(settings.PROFILE_CONFIG_KEY);
|
|
||||||
return value || { lockUserProfiles: false, mandatory2FA: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setProfileConfig(profileConfig) {
|
|
||||||
assert.strictEqual(typeof profileConfig, 'object');
|
|
||||||
|
|
||||||
if (constants.DEMO) throw new BoxError(BoxError.BAD_STATE, 'Not allowed in demo mode');
|
|
||||||
|
|
||||||
const oldConfig = await getProfileConfig();
|
|
||||||
await settings.setJson(settings.PROFILE_CONFIG_KEY, profileConfig);
|
|
||||||
|
|
||||||
if (profileConfig.mandatory2FA && !oldConfig.mandatory2FA) {
|
|
||||||
debug('setProfileConfig: logging out non-2FA users to enforce 2FA');
|
|
||||||
|
|
||||||
const allUsers = await list();
|
|
||||||
for (const user of allUsers) {
|
|
||||||
if (!user.twoFactorAuthenticationEnabled) {
|
|
||||||
await tokens.delByUserIdAndType(user.id, tokens.ID_WEBADMIN);
|
|
||||||
await oidc.revokeByUserId(user.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function resetSource() {
|
async function resetSource() {
|
||||||
await database.query('UPDATE users SET source = ?', [ '' ]);
|
await database.query('UPDATE users SET source = ?', [ '' ]);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user