migrate permissions and admin flag to user.role

This commit is contained in:
Girish Ramakrishnan
2020-02-21 12:17:06 -08:00
parent a8f1b0241e
commit 0e156b9376
27 changed files with 245 additions and 254 deletions

View File

@@ -15,7 +15,7 @@ exports = module.exports = {
get: get,
getByResetToken: getByResetToken,
getByUsername: getByUsername,
getAllAdmins: getAllAdmins,
getAdmins: getAdmins,
resetPasswordByIdentifier: resetPasswordByIdentifier,
setPassword: setPassword,
update: updateUser,
@@ -34,14 +34,21 @@ exports = module.exports = {
AP_SFTP: 'sftp',
AP_WEBADMIN: 'webadmin',
ROLE_ADMIN: 'admin',
ROLE_USER: 'user',
ROLE_USER_MANAGER: 'usermanager',
ROLE_OWNER: 'owner',
compareRoles: compareRoles,
getAppPasswords: getAppPasswords,
getAppPassword: getAppPassword,
addAppPassword: addAppPassword,
delAppPassword: delAppPassword
};
let accesscontrol = require('./accesscontrol.js'),
assert = require('assert'),
const ORDERED_ROLES = [ exports.ROLE_USER, exports.ROLE_USER_MANAGER, exports.ROLE_ADMIN, exports.ROLE_OWNER ];
let assert = require('assert'),
BoxError = require('./boxerror.js'),
crypto = require('crypto'),
constants = require('./constants.js'),
@@ -116,7 +123,7 @@ function validatePassword(password) {
// remove all fields that should never be sent out via REST API
function removePrivateFields(user) {
return _.pick(user, 'id', 'username', 'email', 'fallbackEmail', 'displayName', 'groupIds', 'admin', 'active', 'source', 'permissions');
return _.pick(user, 'id', 'username', 'email', 'fallbackEmail', 'displayName', 'groupIds', 'active', 'source', 'role');
}
// remove all fields that Non-privileged users must not see
@@ -132,11 +139,8 @@ function create(username, password, email, displayName, options, auditSource, ca
assert(options && typeof options === 'object');
assert(auditSource && typeof auditSource === 'object');
const isOwner = !!options.owner;
const isAdmin = !!options.admin;
const source = options.source || ''; // empty is local user
const invitor = options.invitor || null;
const permissions = options.permissions || null;
const role = options.role || exports.ROLE_USER;
var error;
@@ -160,7 +164,7 @@ function create(username, password, email, displayName, options, auditSource, ca
error = validateDisplayName(displayName);
if (error) return callback(error);
error = accesscontrol.validatePermissions(permissions);
error = validateRole(role);
if (error) return callback(error);
crypto.randomBytes(CRYPTO_SALT_SIZE, function (error, salt) {
@@ -181,21 +185,18 @@ function create(username, password, email, displayName, options, auditSource, ca
modifiedAt: now,
resetToken: '',
displayName: displayName,
admin: isOwner || isAdmin,
source: source,
permissions: permissions
role: role
};
userdb.add(user.id, user, function (error) {
if (error) return callback(error);
// when this is used to create the owner, then we have to patch the auditSource to contain himself
if (isOwner) {
auditSource.userId = user.id;
auditSource.username = user.username;
}
if (!auditSource.userId) auditSource.userId = user.id;
if (!auditSource.username) auditSource.username= user.username;
eventlog.add(eventlog.ACTION_USER_ADD, auditSource, { userId: user.id, email: user.email, user: removePrivateFields(user), invitor: invitor });
eventlog.add(eventlog.ACTION_USER_ADD, auditSource, { userId: user.id, email: user.email, user: removePrivateFields(user) });
callback(null, user);
});
@@ -413,7 +414,7 @@ function updateUser(user, data, auditSource, callback) {
assert.strictEqual(typeof callback, 'function');
var error;
data = _.pick(data, 'email', 'fallbackEmail', 'displayName', 'username', 'admin', 'active', 'permissions');
data = _.pick(data, 'email', 'fallbackEmail', 'displayName', 'username', 'active', 'role');
if (_.isEmpty(data)) return callback();
@@ -435,8 +436,8 @@ function updateUser(user, data, auditSource, callback) {
if (error) return callback(error);
}
if (data.permissions) {
error = accesscontrol.validatePermissions(data.permissions);
if (data.role) {
error = validateRole(data.role);
if (error) return callback(error);
}
@@ -448,7 +449,7 @@ function updateUser(user, data, auditSource, callback) {
eventlog.add(eventlog.ACTION_USER_UPDATE, auditSource, {
userId: user.id,
user: removePrivateFields(newUser),
adminStatusChanged: ((newUser.admin && !user.admin) || (!newUser.admin && user.admin)),
roleChanged: newUser.role !== user.role,
activeStatusChanged: ((newUser.active && !user.active) || (!newUser.active && user.active))
});
@@ -468,13 +469,18 @@ function setMembership(user, groupIds, callback) {
});
}
function getAllAdmins(callback) {
function getAdmins(callback) {
assert.strictEqual(typeof callback, 'function');
userdb.getAllAdmins(function (error, admins) {
userdb.getByRole(exports.ROLE_OWNER, function (error, owners) {
if (error) return callback(error);
callback(null, admins);
userdb.getByRole(exports.ROLE_ADMIN, function (error, admins) {
if (error && error.reason === BoxError.NOT_FOUND) return callback(null, owners);
if (error) return callback(error);
callback(null, owners.concat(admins));
});
});
}
@@ -542,11 +548,11 @@ function createOwner(username, password, email, displayName, auditSource, callba
// This is only not allowed for the owner
if (username === '') return callback(new BoxError(BoxError.BAD_FIELD, 'Username cannot be empty'));
count(function (error, count) {
isActivated(function (error, activated) {
if (error) return callback(error);
if (count !== 0) return callback(new BoxError(BoxError.ALREADY_EXISTS, 'Owner already exists'));
if (activated) return callback(new BoxError(BoxError.ALREADY_EXISTS, 'Cloudron already activated'));
create(username, password, email, displayName, { owner: true }, auditSource, function (error, user) {
create(username, password, email, displayName, { role: exports.ROLE_OWNER }, auditSource, function (error, user) {
if (error) return callback(error);
callback(null, user);
@@ -555,10 +561,10 @@ function createOwner(username, password, email, displayName, auditSource, callba
}
function getOwner(callback) {
userdb.getOwner(function (error, owner) {
userdb.getByRole(exports.ROLE_OWNER, function (error, results) {
if (error) return callback(error);
return callback(null, owner);
return callback(null, results[0]);
});
}
@@ -655,6 +661,24 @@ function disableTwoFactorAuthentication(userId, callback) {
});
}
function validateRole(role) {
assert.strictEqual(typeof role, 'string');
if (ORDERED_ROLES.indexOf(role) !== -1) return null;
return new BoxError(BoxError.BAD_FIELD, `Invalid role '${role}'`);
}
function compareRoles(role1, role2) {
assert.strictEqual(typeof role1, 'string');
assert.strictEqual(typeof role2, 'string');
let roleInt1 = ORDERED_ROLES.indexOf(role1);
let roleInt2 = ORDERED_ROLES.indexOf(role2);
return roleInt1 - roleInt2;
}
function validateAppPasswordName(name) {
assert.strictEqual(typeof name, 'string');