Files
cloudron-box/src/routes/test/users-test.js
Girish Ramakrishnan 2ca94f3159 user: remove make local feature
we discussed a bit on what this does and it's confusing as it stands:

* Use case of this is lost in the realms of time
* Possible guess by is that it was to move users of different Cloudron to a central cloudron
* Currently, the design is a bit flawed because the make user local button doesn’t pin the user. The state is lost in next synchronization.
* Maybe, one should use export/import user for this use case
* Let’s disable this button for now, feature is not complete.
2024-01-13 11:02:25 +01:00

612 lines
24 KiB
JavaScript

/* global it:false */
/* global describe:false */
/* global before:false */
/* global after:false */
'use strict';
const common = require('./common.js'),
expect = require('expect.js'),
superagent = require('superagent'),
users = require('../../users.js');
describe('Users API', function () {
const { setup, cleanup, serverUrl, owner, user, dashboardDomain } = common;
const user2 = {
id: null,
username: 'User2',
password: 'Foobar?1339',
email: 'uSer2@cloudron.LoCal',
token: null
};
const user3 = {
id: null,
username: 'transientuser',
password: 'Foobar?1334',
email: 'transient@cloudron.LoCal',
};
const unnamedUser = {
id: null,
email: 'unnameduser@cloudron.local',
};
const userWithPassword = {
id: null,
username: 'userwithpassword',
password: 'Secret123#',
email: 'userwithpassword@cloudron.local',
token: null
};
before(setup);
after(cleanup);
describe('user info', async function () {
it('cannot get userInfo of random user', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/users/baduserid`)
.query({ access_token: owner.token })
.ok(() => true);
expect(response.statusCode).to.equal(404);
});
it('can get userInfo with token', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`)
.query({ access_token: owner.token });
expect(response.statusCode).to.equal(200);
expect(response.body.username).to.equal(user.username.toLowerCase());
expect(response.body.email).to.equal(user.email.toLowerCase());
expect(response.body.groupIds).to.eql([]);
expect(response.body.role).to.be(users.ROLE_USER);
});
it('cannot get userInfo with normal user token', async function () {
const reponse = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`)
.query({ access_token: user.token })
.ok(() => true);
expect(reponse.statusCode).to.equal(403);
});
});
describe('create user', function () {
it('cannot create user without email', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
.send({ username: user2.username })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('cannot create user with non email fallbackEmail', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
.send({ username: user2.username, email: user2.email, fallbackEmail: 'notanemail' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('create second user succeeds', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
.send({ username: user2.username, email: user2.email });
expect(response.statusCode).to.equal(201);
user2.id = response.body.id;
});
it('get userInfo succeeds for second user', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token });
expect(response.statusCode).to.equal(200);
expect(response.body.username).to.equal(user2.username.toLowerCase());
expect(response.body.email).to.equal(user2.email.toLowerCase());
expect(response.body.groupIds).to.eql([]);
});
it('create user missing username succeeds', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
.send({ email: unnamedUser.email });
expect(response.statusCode).to.equal(201);
unnamedUser.id = response.body.id;
});
it('create user missing email fails', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
.send({ username: 'someusername' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('create user reserved name fails', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
.send({ username: 'no-reply', email: 'reserved@cloudron.local' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('create user with short name succeeds', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
.send({ username: 'n', email: 'singleletter@cloudron.local' });
expect(response.statusCode).to.equal(201);
});
it('create user with same username should fail', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
.send({ username: user2.username, email: user2.email })
.ok(() => true);
expect(response.statusCode).to.equal(409);
});
it('cannot create user with bad password', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
.send({ username: 'badpassworduser', email: 'badpass@cloudron.local', password:'tooweak' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('can create user with a password', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
.send({ username: userWithPassword.username, email: userWithPassword.email, password: userWithPassword.password });
expect(response.statusCode).to.equal(201);
userWithPassword.id = response.body.id;
});
it('did set password of created user', async function () {
await users.verify(userWithPassword.id, userWithPassword.password, users.AP_WEBADMIN, {});
});
});
describe('invite', function () {
it('creationg fails for unknown user', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/users/randomuserid/invite_link`)
.query({ access_token: owner.token })
.send({})
.ok(() => true);
expect(response.statusCode).to.equal(404);
});
it('creation succeeds', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/users/${user.id}/invite_link`)
.query({ access_token: owner.token })
.send({})
.ok(() => true);
expect(response.statusCode).to.equal(200);
expect(response.body.inviteLink).to.be.a('string');
});
it('sending succeeds', async function () {
common.clearMailQueue();
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}/send_invite_email`)
.query({ access_token: owner.token })
.send({ email: user.email });
expect(response.statusCode).to.equal(202);
await common.checkMails(1);
});
});
describe('admin status', function () {
it('set second user as admin succeeds', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}`)
.query({ access_token: owner.token })
.send({ role: users.ROLE_ADMIN });
expect(response.statusCode).to.equal(204);
});
it('did set second user as admin', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/users/${user.id}`)
.query({ access_token: owner.token });
expect(response.statusCode).to.equal(200);
expect(response.body.role).to.be(users.ROLE_ADMIN);
});
it('make self as admin fails', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${owner.id}`)
.query({ access_token: owner.token })
.send({ role: users.ROLE_ADMIN })
.ok(() => true);
expect(response.statusCode).to.equal(409);
});
it('make self as normal user fails', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${owner.id}`)
.query({ access_token: owner.token })
.send({ role: users.ROLE_USER })
.ok(() => true);
expect(response.statusCode).to.equal(409);
});
it('remove second user as admin succeeds', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}`)
.query({ access_token: owner.token })
.send({ role: users.ROLE_USER });
expect(response.statusCode).to.equal(204);
});
it('normal user cannot change role of admin', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${owner.id}`)
.query({ access_token: user.token })
.send({ role: users.ROLE_USER })
.ok(() => true);
expect(response.statusCode).to.equal(403);
});
});
describe('groups', function () {
it('lists groupIds when listing users', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token });
expect(response.statusCode).to.equal(200);
expect(response.body.users).to.be.an('array');
response.body.users.forEach(function (user) {
expect('groupIds' in user).to.be(true);
});
});
});
describe('list users', function () {
it('list users fails for normal user', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/users`)
.query({ access_token: user.token })
.ok(() => true);
expect(response.statusCode).to.equal(403);
});
it('list users succeeds for admin', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token });
expect(response.statusCode).to.equal(200);
expect(response.body.users).to.be.an('array');
expect(response.body.users.length).to.be.greaterThan(3);
response.body.users.forEach(function (user) {
expect(user).to.be.an('object');
expect(user.id).to.be.ok();
expect(user.email).to.be.ok();
expect(user.role).to.be.ok();
if (!user.email.startsWith('unnamed')) expect(user.username).to.be.ok();
expect(user.password).to.not.be.ok();
expect(user.salt).to.not.be.ok();
});
});
});
describe('update', function () {
it('change email fails due to missing token', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
.send({ email: 'newemail@cloudron.local' })
.ok(() => true);
expect(response.statusCode).to.equal(401);
});
it('change email fails due to invalid email', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token })
.send({ email: 'newemail@cloudron' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('change fallbackEmail fails due to invalid email', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token })
.send({ fallbackEmail: 'newemail@cloudron' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('change user succeeds without email nor displayName', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token })
.send({});
expect(response.statusCode).to.equal(204);
});
it('change email succeeds', async function () {
user2.email = 'NewEmail@cloudron.local';
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token })
.send({ email: user2.email });
expect(response.statusCode).to.equal(204);
const response2 = await superagent.get(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token });
expect(response2.statusCode).to.equal(200);
expect(response2.body.username).to.equal(user2.username.toLowerCase());
expect(response2.body.email).to.equal(user2.email.toLowerCase());
expect(response2.body.displayName).to.equal('');
});
it('cannot change email to existing one', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token })
.send({ email: owner.email })
.ok(() => true);
expect(response.statusCode).to.equal(409);
});
it('can change display name', async function () {
const displayName = 'New name';
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token })
.send({ displayName: displayName });
expect(response.statusCode).to.equal(204);
const response2 = await superagent.get(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token });
expect(response2.statusCode).to.equal(200);
expect(response2.body.displayName).to.equal(displayName);
});
});
describe('password', function () {
it('change password fails due to missing token', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}/password`)
.send({ password: 'youdontsay' })
.ok(() => true);
expect(response.statusCode).to.equal(401);
});
it('change password fails due to small password', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}/password`)
.query({ access_token: owner.token })
.send({ password: 'small' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('change password succeeds', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}/password`)
.query({ access_token: owner.token })
.send({ password: 'bigenough' });
expect(response.statusCode).to.equal(204);
});
it('did change the user password', async function () {
await users.verify(user.id, 'bigenough', users.AP_WEBADMIN, {});
});
});
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}`)
.query({ access_token: owner.token })
.send({ role: users.ROLE_USER_MANAGER });
expect(response.statusCode).to.equal(204);
});
it('can list users as usermanager', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/users`)
.query({ access_token: user.token });
expect(response.statusCode).to.equal(200);
expect(response.body.users).to.be.an(Array);
expect(response.body.users.length).to.be.greaterThan(3);
});
it('cannot set password of admin', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${owner.id}/password`)
.query({ access_token: user.token })
.send({ password: 'bigenough' })
.ok(() => true);
expect(response.statusCode).to.equal(403);
});
it('can set password of another', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}/password`)
.query({ access_token: user.token })
.send({ password: 'bigenough' });
expect(response.statusCode).to.equal(204);
});
it('cannot change admin bit of another', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${owner.id}`)
.query({ access_token: user.token })
.send({ role: users.ROLE_ADMIN })
.ok(() => true);
expect(response.statusCode).to.equal(403);
});
it('cannot change admin bit of self', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}`)
.query({ access_token: user.token })
.send({ role: users.ROLE_ADMIN })
.ok(() => true);
expect(response.statusCode).to.equal(409);
});
it('cannot remove admin', async function () {
const response = await superagent.del(`${serverUrl}/api/v1/users/${owner.id}`)
.query({ access_token: user.token })
.ok(() => true);
expect(response.statusCode).to.equal(403);
});
it('can create user as user manager', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: user.token })
.send({ username: user3.username, email: user3.email });
expect(response.statusCode).to.equal(201);
user3.id = response.body.id;
});
it('can remove normal user as user manager', async function () {
const response = await superagent.del(`${serverUrl}/api/v1/users/${user3.id}`)
.query({ access_token: user.token });
expect(response.statusCode).to.equal(204);
});
it('add mailbox fails', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/mail/${dashboardDomain}/mailboxes`)
.send({ name: 'support', ownerId: owner.id, ownerType: 'user', active: true })
.query({ access_token: user.token })
.ok(() => true);
expect(response.statusCode).to.equal(403);
});
});
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}`)
.query({ access_token: owner.token })
.send({ role: users.ROLE_MAIL_MANAGER });
expect(response.statusCode).to.equal(204);
});
it('can list users as mail manager', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/users`)
.query({ access_token: user.token });
expect(response.statusCode).to.equal(200);
expect(response.body.users).to.be.an(Array);
expect(response.body.users.length).to.be.greaterThan(3);
});
it('cannot change admin bit of self', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user.id}`)
.query({ access_token: user.token })
.send({ role: users.ROLE_ADMIN })
.ok(() => true);
expect(response.statusCode).to.equal(409);
});
it('cannot remove admin', async function () {
const response = await superagent.del(`${serverUrl}/api/v1/users/${owner.id}`)
.query({ access_token: user.token })
.ok(() => true);
expect(response.statusCode).to.equal(403);
});
it('can create user as mail manager', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: user.token })
.send({ username: user3.username, email: user3.email });
expect(response.statusCode).to.equal(201);
user3.id = response.body.id;
});
it('can remove normal user as mail manager', async function () {
const response = await superagent.del(`${serverUrl}/api/v1/users/${user3.id}`)
.query({ access_token: user.token });
expect(response.statusCode).to.equal(204);
});
it('add mailbox succeeds as mail manager', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/mail/${dashboardDomain}/mailboxes`)
.send({ name: 'support', ownerId: owner.id, ownerType: 'user', active: true, storageQuota: 0, messagesQuota: 0 })
.query({ access_token: user.token });
expect(response.statusCode).to.equal(201);
});
it('list mailbox succeeds as mail manager', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/mail/${dashboardDomain}/mailboxes`)
.query({ access_token: user.token });
expect(response.statusCode).to.equal(200);
expect(response.body.mailboxes.length).to.be(1);
expect(response.body.mailboxes[0].name).to.be('support');
});
});
describe('remove', function () {
it('remove random user fails', async function () {
const response = await superagent.del(`${serverUrl}/api/v1/users/randomid`)
.query({ access_token: owner.token })
.ok(() => true);
expect(response.statusCode).to.equal(404);
});
it('user cannot removes himself', async function () {
const response = await superagent.del(`${serverUrl}/api/v1/users/${owner.id}`)
.query({ access_token: owner.token })
.ok(() => true);
expect(response.statusCode).to.equal(409);
});
it('admin removes normal user', async function () {
const response = await superagent.del(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token })
.ok(() => true);
expect(response.statusCode).to.equal(204);
});
it('admin removes himself should not be allowed', async function () {
const response = await superagent.del(`${serverUrl}/api/v1/users/${owner.id}`)
.query({ access_token: owner.token })
.ok(() => true);
expect(response.statusCode).to.equal(409);
});
});
});