From 24a3a44442255d368c6fd7219151c23710914b8c Mon Sep 17 00:00:00 2001 From: WikiRik Date: Wed, 1 Dec 2021 17:06:32 +0000 Subject: [PATCH 1/3] fix(superadmin): add endpoint for superadmin --- lib/server.js | 1 + middlewares/members.js | 12 ++++++++++++ scripts/seed.js | 12 ++++++++++++ 3 files changed, 25 insertions(+) diff --git a/lib/server.js b/lib/server.js index 85fef85c..3238d7a8 100644 --- a/lib/server.js +++ b/lib/server.js @@ -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); diff --git a/middlewares/members.js b/middlewares/members.js index aac6c26b..76aa5293 100644 --- a/middlewares/members.js +++ b/middlewares/members.js @@ -173,6 +173,18 @@ exports.setUserActive = async (req, res) => { }); }; +exports.setUserSuperadmin = async (req, res) => { + if (!req.permissions.hasPermission('update_superadmin:member')) { + return errors.makeForbiddenError(res, 'Permission 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.'); diff --git a/scripts/seed.js b/scripts/seed.js index 221f9885..8ed2a522 100644 --- a/scripts/seed.js +++ b/scripts/seed.js @@ -801,6 +801,18 @@ 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' + }, + { + action: 'update_superadmin', + object: 'member', + scope: 'local', + description: 'Allows to add or remove superadmin powers to users that are member in the body that you got this permission from' } ], { individualHooks: true, validate: true }); From 2b75cc458cde853e4691a7fb11dbe355414765bc Mon Sep 17 00:00:00 2001 From: WikiRik Date: Wed, 1 Dec 2021 17:19:50 +0000 Subject: [PATCH 2/3] fix(superadmin): remove local and add tests --- middlewares/members.js | 4 +- scripts/seed.js | 6 -- test/api/users-superadmin.test.js | 137 ++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 test/api/users-superadmin.test.js diff --git a/middlewares/members.js b/middlewares/members.js index 76aa5293..59378500 100644 --- a/middlewares/members.js +++ b/middlewares/members.js @@ -174,8 +174,8 @@ exports.setUserActive = async (req, res) => { }; exports.setUserSuperadmin = async (req, res) => { - if (!req.permissions.hasPermission('update_superadmin:member')) { - return errors.makeForbiddenError(res, 'Permission update_superadmin:member is required, but not present.'); + 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 }); diff --git a/scripts/seed.js b/scripts/seed.js index 8ed2a522..5a5a60f1 100644 --- a/scripts/seed.js +++ b/scripts/seed.js @@ -807,12 +807,6 @@ async function createPermissions() { object: 'member', scope: 'global', description: 'Allows to add or remove superadmin powers to any user in the system' - }, - { - action: 'update_superadmin', - object: 'member', - scope: 'local', - description: 'Allows to add or remove superadmin powers to users that are member in the body that you got this permission from' } ], { individualHooks: true, validate: true }); diff --git a/test/api/users-superadmin.test.js b/test/api/users-superadmin.test.js new file mode 100644 index 00000000..0d2a06bc --- /dev/null +++ b/test/api/users-superadmin.test.js @@ -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: 'local', 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.supeardmin).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'); + }); +}); From 6865361ae3aff3c5360b50ae1d5292b5e3a411af Mon Sep 17 00:00:00 2001 From: WikiRik Date: Wed, 1 Dec 2021 17:28:30 +0000 Subject: [PATCH 3/3] fix(tests): fix tests --- models/User.js | 5 ++++- test/api/users-superadmin.test.js | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/models/User.js b/models/User.js index d0d4df1e..7fef0a32 100644 --- a/models/User.js +++ b/models/User.js @@ -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, diff --git a/test/api/users-superadmin.test.js b/test/api/users-superadmin.test.js index 0d2a06bc..cb60dcd6 100644 --- a/test/api/users-superadmin.test.js +++ b/test/api/users-superadmin.test.js @@ -58,7 +58,7 @@ describe('User superadmin', () => { const user = await generator.createUser({ superadmin: true }); const token = await generator.createAccessToken({}, user); - await generator.createPermission({ scope: 'local', action: 'update_superadmin', object: 'member' }); + await generator.createPermission({ scope: 'global', action: 'update_superadmin', object: 'member' }); const res = await request({ uri: '/members/' + user.id + '/superadmin', @@ -71,7 +71,7 @@ describe('User superadmin', () => { expect(res.body.success).toEqual(true); expect(res.body).not.toHaveProperty('errors'); expect(res.body).toHaveProperty('data'); - expect(res.body.data.supeardmin).toEqual(false); + expect(res.body.data.superadmin).toEqual(false); }); test('should fail for yourself without permission', async () => {