users: cannot update profile fields of external user
This commit is contained in:
@@ -213,7 +213,7 @@ describe('Users API', function () {
|
||||
|
||||
describe('admin status', function () {
|
||||
it('set second user as admin succeeds', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}`)
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${user.id}/role`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ role: users.ROLE_ADMIN });
|
||||
|
||||
@@ -229,7 +229,7 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
it('make self as admin fails', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${owner.id}`)
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${owner.id}/role`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ role: users.ROLE_ADMIN })
|
||||
.ok(() => true);
|
||||
@@ -238,7 +238,7 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
it('make self as normal user fails', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${owner.id}`)
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${owner.id}/role`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ role: users.ROLE_USER })
|
||||
.ok(() => true);
|
||||
@@ -247,7 +247,7 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
it('remove second user as admin succeeds', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}`)
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${user.id}/role`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ role: users.ROLE_USER });
|
||||
|
||||
@@ -255,7 +255,7 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
it('normal user cannot change role of admin', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${owner.id}`)
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${owner.id}/role`)
|
||||
.query({ access_token: user.token })
|
||||
.send({ role: users.ROLE_USER })
|
||||
.ok(() => true);
|
||||
@@ -307,9 +307,9 @@ describe('Users API', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', function () {
|
||||
describe('profile update', function () {
|
||||
it('change email fails due to missing token', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}/profile`)
|
||||
.send({ email: 'newemail@cloudron.local' })
|
||||
.ok(() => true);
|
||||
|
||||
@@ -317,7 +317,7 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
it('change email fails due to invalid email', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}/profile`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ email: 'newemail@cloudron' })
|
||||
.ok(() => true);
|
||||
@@ -326,7 +326,7 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
it('change fallbackEmail fails due to invalid email', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}/profile`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ fallbackEmail: 'newemail@cloudron' })
|
||||
.ok(() => true);
|
||||
@@ -335,7 +335,7 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
it('change user succeeds without email nor displayName', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}/profile`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({});
|
||||
|
||||
@@ -344,7 +344,7 @@ describe('Users API', function () {
|
||||
|
||||
it('change email succeeds', async function () {
|
||||
user2.email = 'NewEmail@cloudron.local';
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}/profile`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ email: user2.email });
|
||||
|
||||
@@ -360,7 +360,7 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
it('cannot change email to existing one', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}/profile`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ email: owner.email })
|
||||
.ok(() => true);
|
||||
@@ -371,7 +371,7 @@ describe('Users API', function () {
|
||||
it('can change display name', async function () {
|
||||
const displayName = 'New name';
|
||||
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}/profile`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ displayName: displayName });
|
||||
|
||||
@@ -416,9 +416,39 @@ describe('Users API', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('active', function () {
|
||||
it('can make user inactive', async function () {
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${user.id}/active`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ active: false });
|
||||
|
||||
expect(response.statusCode).to.equal(204);
|
||||
|
||||
const response2 = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`)
|
||||
.query({ access_token: owner.token });
|
||||
|
||||
expect(response2.statusCode).to.equal(200);
|
||||
expect(response2.body.active).to.equal(false);
|
||||
});
|
||||
|
||||
it('can make user active', async function () {
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${user.id}/active`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ active: true });
|
||||
|
||||
expect(response.statusCode).to.equal(204);
|
||||
|
||||
const response2 = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`)
|
||||
.query({ access_token: owner.token });
|
||||
|
||||
expect(response2.statusCode).to.equal(200);
|
||||
expect(response2.body.active).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('role - user manager', function () {
|
||||
it('can make normal user a usermanager', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}`)
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${user.id}/role`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ role: users.ROLE_USER_MANAGER });
|
||||
|
||||
@@ -452,7 +482,7 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
it('cannot change admin bit of another', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${owner.id}`)
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${owner.id}/role`)
|
||||
.query({ access_token: user.token })
|
||||
.send({ role: users.ROLE_ADMIN })
|
||||
.ok(() => true);
|
||||
@@ -461,7 +491,7 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
it('cannot change admin bit of self', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}`)
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${user.id}/role`)
|
||||
.query({ access_token: user.token })
|
||||
.send({ role: users.ROLE_ADMIN })
|
||||
.ok(() => true);
|
||||
@@ -506,7 +536,7 @@ describe('Users API', function () {
|
||||
|
||||
describe('role - mail manager', function () {
|
||||
it('can make normal user a usermanager', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}`)
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${user.id}/role`)
|
||||
.query({ access_token: owner.token })
|
||||
.send({ role: users.ROLE_MAIL_MANAGER });
|
||||
|
||||
@@ -523,7 +553,7 @@ describe('Users API', function () {
|
||||
});
|
||||
|
||||
it('cannot change admin bit of self', async function () {
|
||||
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}`)
|
||||
const response = await superagent.put(`${serverUrl}/api/v1/users/${user.id}/role`)
|
||||
.query({ access_token: user.token })
|
||||
.send({ role: users.ROLE_ADMIN })
|
||||
.ok(() => true);
|
||||
|
||||
+43
-17
@@ -2,10 +2,14 @@
|
||||
|
||||
exports = module.exports = {
|
||||
get,
|
||||
update,
|
||||
list,
|
||||
add,
|
||||
del,
|
||||
|
||||
setRole,
|
||||
setActive,
|
||||
updateProfile,
|
||||
|
||||
setPassword,
|
||||
verifyPassword,
|
||||
setGroups,
|
||||
@@ -32,7 +36,8 @@ const assert = require('assert'),
|
||||
HttpError = require('connect-lastmile').HttpError,
|
||||
HttpSuccess = require('connect-lastmile').HttpSuccess,
|
||||
safe = require('safetydance'),
|
||||
users = require('../users.js');
|
||||
users = require('../users.js'),
|
||||
_ = require('underscore');
|
||||
|
||||
async function load(req, res, next) {
|
||||
assert.strictEqual(typeof req.params.userId, 'string');
|
||||
@@ -70,7 +75,40 @@ async function add(req, res, next) {
|
||||
next(new HttpSuccess(201, { id }));
|
||||
}
|
||||
|
||||
async function update(req, res, next) {
|
||||
async function setRole(req, res, next) {
|
||||
assert.strictEqual(typeof req.resource, 'object');
|
||||
assert.strictEqual(typeof req.user, 'object');
|
||||
assert.strictEqual(typeof req.body, 'object');
|
||||
|
||||
if (typeof req.body.role !== 'string') return next(new HttpError(400, 'role must be a string'));
|
||||
if (req.user.id === req.resource.id) return next(new HttpError(409, 'Cannot set role flag on self'));
|
||||
|
||||
if (users.compareRoles(req.user.role, req.body.role) < 0) return next(new HttpError(403, `role '${req.body.role}' is required but you are only '${req.user.role}'`));
|
||||
if (users.compareRoles(req.user.role, req.resource.role) < 0) return next(new HttpError(403, `role '${req.resource.role}' is required but you are only '${req.user.role}'`));
|
||||
|
||||
const [error] = await safe(users.update(req.resource, { role: req.body.role }, AuditSource.fromRequest(req)));
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(204));
|
||||
}
|
||||
|
||||
async function setActive(req, res, next) {
|
||||
assert.strictEqual(typeof req.resource, 'object');
|
||||
assert.strictEqual(typeof req.user, 'object');
|
||||
assert.strictEqual(typeof req.body, 'object');
|
||||
|
||||
if (typeof req.body.active !== 'boolean') return next(new HttpError(400, 'active must be a boolean'));
|
||||
if (req.user.id === req.resource.id) return next(new HttpError(409, 'Cannot set active flag on self'));
|
||||
|
||||
if (users.compareRoles(req.user.role, req.resource.role) < 0) return next(new HttpError(403, `role '${req.resource.role}' is required but you are only '${req.user.role}'`));
|
||||
|
||||
const [error] = await safe(users.update(req.resource, { active: req.body.active }, AuditSource.fromRequest(req)));
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(204));
|
||||
}
|
||||
|
||||
async function updateProfile(req, res, next) {
|
||||
assert.strictEqual(typeof req.resource, 'object');
|
||||
assert.strictEqual(typeof req.user, 'object');
|
||||
assert.strictEqual(typeof req.body, 'object');
|
||||
@@ -79,23 +117,11 @@ async function update(req, res, next) {
|
||||
if ('email' in req.body && typeof req.body.email !== 'string') return next(new HttpError(400, 'email must be string'));
|
||||
if ('fallbackEmail' in req.body && typeof req.body.fallbackEmail !== 'string') return next(new HttpError(400, 'fallbackEmail must be string'));
|
||||
if ('displayName' in req.body && typeof req.body.displayName !== 'string') return next(new HttpError(400, 'displayName must be string'));
|
||||
if ('username' in req.body && typeof req.body.username !== 'string') return next(new HttpError(400, 'username must be a string'));
|
||||
|
||||
if ('role' in req.body) {
|
||||
if (typeof req.body.role !== 'string') return next(new HttpError(400, 'role must be a string'));
|
||||
if (req.user.id === req.resource.id) return next(new HttpError(409, 'Cannot set role flag on self'));
|
||||
|
||||
if (users.compareRoles(req.user.role, req.body.role) < 0) return next(new HttpError(403, `role '${req.body.role}' is required but you are only '${req.user.role}'`));
|
||||
}
|
||||
|
||||
if ('active' in req.body) {
|
||||
if (typeof req.body.active !== 'boolean') return next(new HttpError(400, 'active must be a boolean'));
|
||||
if (req.user.id === req.resource.id) return next(new HttpError(409, 'Cannot set active flag on self'));
|
||||
}
|
||||
|
||||
if (users.compareRoles(req.user.role, req.resource.role) < 0) return next(new HttpError(403, `role '${req.resource.role}' is required but you are only '${req.user.role}'`));
|
||||
|
||||
const [error] = await safe(users.update(req.resource, req.body, AuditSource.fromRequest(req)));
|
||||
const data = _.pick(req.body, 'username', 'email', 'fallbackEmail', 'displayName');
|
||||
const [error] = await safe(users.updateProfile(req.resource, data, AuditSource.fromRequest(req)));
|
||||
if (error) return next(BoxError.toHttpError(error));
|
||||
|
||||
next(new HttpSuccess(204));
|
||||
|
||||
Reference in New Issue
Block a user