diff --git a/src/routes/profile.js b/src/routes/profile.js index 13a8d5725..35f10f9d5 100644 --- a/src/routes/profile.js +++ b/src/routes/profile.js @@ -1,15 +1,16 @@ 'use strict'; exports = module.exports = { - get: get, - update: update, - getAvatar: getAvatar, - setAvatar: setAvatar, - clearAvatar: clearAvatar, - changePassword: changePassword, - setTwoFactorAuthenticationSecret: setTwoFactorAuthenticationSecret, - enableTwoFactorAuthentication: enableTwoFactorAuthentication, - disableTwoFactorAuthentication: disableTwoFactorAuthentication + authorize, + get, + update, + getAvatar, + setAvatar, + clearAvatar, + changePassword, + setTwoFactorAuthenticationSecret, + enableTwoFactorAuthentication, + disableTwoFactorAuthentication, }; var assert = require('assert'), @@ -25,6 +26,20 @@ var assert = require('assert'), settings = require('../settings.js'), _ = require('underscore'); +function authorize(req, res, next) { + assert.strictEqual(typeof req.user, 'object'); + + if (users.compareRoles(req.user.role, users.ROLE_USER_MANAGER) >= 0) return next(); + + settings.getDirectoryConfig(function (error, directoryConfig) { + if (error) return next(BoxError.toHttpError(error)); + + if (directoryConfig.lockUserProfiles) return next(new HttpError(403, 'admin has disallowed users from editing profiles')); + + next(); + }); +} + function get(req, res, next) { assert.strictEqual(typeof req.user, 'object'); diff --git a/src/server.js b/src/server.js index 6d78c363b..666ee77d1 100644 --- a/src/server.js +++ b/src/server.js @@ -144,9 +144,9 @@ function initializeExpressSync() { // working off the user behind the provided token router.get ('/api/v1/profile', token, routes.profile.get); - router.post('/api/v1/profile', token, routes.profile.update); + router.post('/api/v1/profile', token, routes.profile.authorize, routes.profile.update); router.get ('/api/v1/profile/avatar/:identifier', routes.profile.getAvatar); // this is not scoped so it can used directly in img tag - router.post('/api/v1/profile/avatar', token, multipart, routes.profile.setAvatar); + router.post('/api/v1/profile/avatar', token, routes.profile.authorize, multipart, routes.profile.setAvatar); router.del ('/api/v1/profile/avatar', token, routes.profile.clearAvatar); router.post('/api/v1/profile/password', token, routes.users.verifyPassword, routes.profile.changePassword); router.post('/api/v1/profile/twofactorauthentication', token, routes.profile.setTwoFactorAuthenticationSecret); diff --git a/src/settings.js b/src/settings.js index 6a9090320..3500c5b95 100644 --- a/src/settings.js +++ b/src/settings.js @@ -50,6 +50,9 @@ exports = module.exports = { getFooter: getFooter, setFooter: setFooter, + getDirectoryConfig: getDirectoryConfig, + setDirectoryConfig: setDirectoryConfig, + getAppstoreListingConfig: getAppstoreListingConfig, setAppstoreListingConfig: setAppstoreListingConfig, @@ -86,6 +89,7 @@ exports = module.exports = { SYSINFO_CONFIG_KEY: 'sysinfo_config', APPSTORE_LISTING_CONFIG_KEY: 'appstore_listing_config', SUPPORT_CONFIG_KEY: 'support_config', + DIRECTORY_CONFIG_KEY: 'directory_config', // strings APP_AUTOUPDATE_PATTERN_KEY: 'app_autoupdate_pattern', @@ -157,6 +161,10 @@ let gDefaults = (function () { result[exports.SYSINFO_CONFIG_KEY] = { provider: 'generic' }; + result[exports.DIRECTORY_CONFIG_KEY] = { + lockUserProfiles: false + }; + result[exports.ADMIN_DOMAIN_KEY] = ''; result[exports.ADMIN_FQDN_KEY] = ''; result[exports.API_SERVER_ORIGIN_KEY] = 'https://api.cloudron.io'; @@ -573,6 +581,30 @@ function setSysinfoConfig(sysinfoConfig, callback) { }); } +function getDirectoryConfig(callback) { + assert.strictEqual(typeof callback, 'function'); + + settingsdb.get(exports.DIRECTORY_CONFIG_KEY, function (error, value) { + if (error && error.reason === BoxError.NOT_FOUND) return callback(null, gDefaults[exports.DIRECTORY_CONFIG_KEY]); + if (error) return callback(error); + + callback(null, JSON.parse(value)); + }); +} + +function setDirectoryConfig(directoryConfig, callback) { + assert.strictEqual(typeof directoryConfig, 'object'); + assert.strictEqual(typeof callback, 'function'); + + settingsdb.set(exports.DIRECTORY_CONFIG_KEY, JSON.stringify(directoryConfig), function (error) { + if (error) return callback(error); + + notifyChange(exports.DIRECTORY_CONFIG_KEY, directoryConfig); + + callback(null); + }); +} + function getAppstoreListingConfig(callback) { assert.strictEqual(typeof callback, 'function'); @@ -696,7 +728,7 @@ function getAll(callback) { result[exports.DEMO_KEY] = !!result[exports.DEMO_KEY]; // convert JSON objects - [exports.BACKUP_CONFIG_KEY, exports.PLATFORM_CONFIG_KEY, exports.EXTERNAL_LDAP_KEY, exports.REGISTRY_CONFIG_KEY, exports.SYSINFO_CONFIG_KEY ].forEach(function (key) { + [exports.BACKUP_CONFIG_KEY, exports.DIRECTORY_CONFIG_KEY, exports.PLATFORM_CONFIG_KEY, exports.EXTERNAL_LDAP_KEY, exports.REGISTRY_CONFIG_KEY, exports.SYSINFO_CONFIG_KEY ].forEach(function (key) { result[key] = typeof result[key] === 'object' ? result[key] : safe.JSON.parse(result[key]); });