Skip to content

Commit

Permalink
fix(superadmin): add endpoint for superadmin (#400)
Browse files Browse the repository at this point in the history
* fix(superadmin): add endpoint for superadmin

* fix(superadmin): remove local and add tests

* fix(tests): fix tests

Co-authored-by: WikiRik <WikiRik@users.noreply.github.com>
  • Loading branch information
WikiRik and WikiRik committed Dec 9, 2021
1 parent bdb14d0 commit 493552d
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ GeneralRouter.post('/campaigns', middlewares.ensureAuthorized, campaigns.createC
MemberRouter.use(middlewares.maybeAuthorize, middlewares.ensureAuthorized, fetch.fetchUser);
MemberRouter.get('/my_permissions', myPermissions.getMyPermissions);
MemberRouter.put('/active', members.setUserActive);
MemberRouter.put('/superadmin', members.setUserSuperadmin);
MemberRouter.post('/confirm', members.confirmUser);
MemberRouter.put('/primary-body', members.setPrimaryBody);
MemberRouter.put('/email', members.triggerEmailChange);
Expand Down
12 changes: 12 additions & 0 deletions middlewares/members.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,18 @@ exports.setUserActive = async (req, res) => {
});
};

exports.setUserSuperadmin = async (req, res) => {
if (!req.permissions.hasPermission('global:update_superadmin:member')) {
return errors.makeForbiddenError(res, 'Permission global:update_superadmin:member is required, but not present.');
}

await req.currentUser.update({ superadmin: req.body.superadmin });
return res.json({
success: true,
data: req.currentUser
});
};

exports.confirmUser = async (req, res) => {
if (!req.permissions.hasPermission('global:confirm:member')) {
return errors.makeForbiddenError(res, 'Permission global:confirm:member is required, but not present.');
Expand Down
5 changes: 4 additions & 1 deletion models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ const User = sequelize.define('user', {
superadmin: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false
defaultValue: false,
validate: {
isBoolean: { msg: 'Superadmin should be valid.' }
}
},
privacy_consent: {
type: Sequelize.DATE,
Expand Down
6 changes: 6 additions & 0 deletions scripts/seed.js
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,12 @@ async function createPermissions() {
object: 'member',
scope: 'global',
description: 'Allows to confirm unconfirmed users manually'
},
{
action: 'update_superadmin',
object: 'member',
scope: 'global',
description: 'Allows to add or remove superadmin powers to any user in the system'
}
], { individualHooks: true, validate: true });

Expand Down
137 changes: 137 additions & 0 deletions test/api/users-superadmin.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
const { startServer, stopServer } = require('../../lib/server');
const { request } = require('../scripts/helpers');
const generator = require('../scripts/generator');

describe('User superadmin', () => {
beforeAll(async () => {
await startServer();
});

afterAll(async () => {
await stopServer();
});

afterEach(async () => {
await generator.clearAll();
});

test('should return 404 if the user is not found', async () => {
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);

await generator.createPermission({ scope: 'global', action: 'update_superadmin', object: 'member' });

const res = await request({
uri: '/members/1337/superadmin',
method: 'PUT',
headers: { 'X-Auth-Token': token.value },
body: { superadmin: false }
});

expect(res.statusCode).toEqual(404);
expect(res.body.success).toEqual(false);
expect(res.body).not.toHaveProperty('data');
expect(res.body).toHaveProperty('message');
});

test('should fail if there are validation errors', async () => {
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);

await generator.createPermission({ scope: 'global', action: 'update_superadmin', object: 'member' });

const res = await request({
uri: '/members/' + user.id + '/superadmin',
method: 'PUT',
headers: { 'X-Auth-Token': token.value },
body: { superadmin: 'aaa' }
});

expect(res.statusCode).toEqual(422);
expect(res.body.success).toEqual(false);
expect(res.body).not.toHaveProperty('data');
expect(res.body).toHaveProperty('errors');
expect(res.body.errors).toHaveProperty('superadmin');
});

test('should succeed if everything is okay', async () => {
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);

await generator.createPermission({ scope: 'global', action: 'update_superadmin', object: 'member' });

const res = await request({
uri: '/members/' + user.id + '/superadmin',
method: 'PUT',
headers: { 'X-Auth-Token': token.value },
body: { superadmin: false }
});

expect(res.statusCode).toEqual(200);
expect(res.body.success).toEqual(true);
expect(res.body).not.toHaveProperty('errors');
expect(res.body).toHaveProperty('data');
expect(res.body.data.superadmin).toEqual(false);
});

test('should fail for yourself without permission', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);

const res = await request({
uri: '/members/' + user.id + '/superadmin',
method: 'PUT',
headers: { 'X-Auth-Token': token.value },
body: { superadmin: true }
});

expect(res.statusCode).toEqual(403);
expect(res.body.success).toEqual(false);
expect(res.body).not.toHaveProperty('data');
expect(res.body).toHaveProperty('message');
});

test('should not work with local permission', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);

const otherUser = await generator.createUser();
const permission = await generator.createPermission({ scope: 'local', action: 'update_superadmin', object: 'member' });
const body = await generator.createBody();
const circle = await generator.createCircle({ body_id: body.id });
await generator.createCircleMembership(circle, user);
await generator.createCirclePermission(circle, permission);
await generator.createBodyMembership(body, otherUser);

const res = await request({
uri: '/members/' + otherUser.id + '/superadmin',
method: 'PUT',
headers: { 'X-Auth-Token': token.value },
body: { superadmin: true }
});

expect(res.statusCode).toEqual(403);
expect(res.body.success).toEqual(false);
expect(res.body).not.toHaveProperty('data');
expect(res.body).toHaveProperty('message');
});

test('should fail for other person without permission', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);

const otherUser = await generator.createUser();

const res = await request({
uri: '/members/' + otherUser.id + '/superadmin',
method: 'PUT',
headers: { 'X-Auth-Token': token.value },
body: { superadmin: true }
});

expect(res.statusCode).toEqual(403);
expect(res.body.success).toEqual(false);
expect(res.body).not.toHaveProperty('data');
expect(res.body).toHaveProperty('message');
});
});

0 comments on commit 493552d

Please sign in to comment.