From c41ab58109736b1b95b3700788e436386620fb51 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 14 Sep 2017 21:11:40 +0700 Subject: [PATCH] Allow Moderator to have read access on assets and settings --- routes/api/assets/index.js | 9 +- routes/api/index.js | 5 +- routes/api/settings/index.js | 5 +- test/server/routes/api/assets/index.js | 108 ++++++++++++++--------- test/server/routes/api/settings/index.js | 30 ++++--- 5 files changed, 95 insertions(+), 62 deletions(-) diff --git a/routes/api/assets/index.js b/routes/api/assets/index.js index 87014b86e..1b2b0c7a9 100644 --- a/routes/api/assets/index.js +++ b/routes/api/assets/index.js @@ -1,5 +1,6 @@ const express = require('express'); const router = express.Router(); +const authorization = require('../../../middleware/authorization'); const errors = require('../../../errors'); const AssetsService = require('../../../services/assets'); @@ -33,7 +34,7 @@ const FilterOpenAssets = (query, filter) => { }; // List assets. -router.get('/', async (req, res, next) => { +router.get('/', authorization.needed('ADMIN', 'MODERATOR'), async (req, res, next) => { const { limit = 20, @@ -72,7 +73,7 @@ router.get('/', async (req, res, next) => { }); // Get an asset by id. -router.get('/:asset_id', async (req, res, next) => { +router.get('/:asset_id', authorization.needed('ADMIN', 'MODERATOR'), async (req, res, next) => { try { // Send back the asset. @@ -87,7 +88,7 @@ router.get('/:asset_id', async (req, res, next) => { } }); -router.put('/:asset_id/settings', async (req, res, next) => { +router.put('/:asset_id/settings', authorization.needed('ADMIN'), async (req, res, next) => { try { await AssetsService.overrideSettings(req.params.asset_id, req.body); res.status(204).end(); @@ -96,7 +97,7 @@ router.put('/:asset_id/settings', async (req, res, next) => { } }); -router.put('/:asset_id/status', async (req, res, next) => { +router.put('/:asset_id/status', authorization.needed('ADMIN'), async (req, res, next) => { const { closedAt, closedMessage diff --git a/routes/api/index.js b/routes/api/index.js index eccd8d435..e44f1e7e5 100644 --- a/routes/api/index.js +++ b/routes/api/index.js @@ -1,5 +1,4 @@ const express = require('express'); -const authorization = require('../../middleware/authorization'); const pkg = require('../../package.json'); const router = express.Router(); @@ -8,8 +7,8 @@ router.get('/', (req, res) => { res.json({version: pkg.version}); }); -router.use('/assets', authorization.needed('ADMIN'), require('./assets')); -router.use('/settings', authorization.needed('ADMIN'), require('./settings')); +router.use('/assets', require('./assets')); +router.use('/settings', require('./settings')); router.use('/auth', require('./auth')); router.use('/users', require('./users')); router.use('/account', require('./account')); diff --git a/routes/api/settings/index.js b/routes/api/settings/index.js index fb54494d1..5202f9a56 100644 --- a/routes/api/settings/index.js +++ b/routes/api/settings/index.js @@ -1,9 +1,10 @@ const express = require('express'); const SettingsService = require('../../../services/settings'); +const authorization = require('../../../middleware/authorization'); const router = express.Router(); -router.get('/', async (req, res, next) => { +router.get('/', authorization.needed('ADMIN', 'MODERATOR'), async (req, res, next) => { try { let settings = await SettingsService.retrieve(); res.json(settings); @@ -12,7 +13,7 @@ router.get('/', async (req, res, next) => { } }); -router.put('/', async (req, res, next) => { +router.put('/', authorization.needed('ADMIN'), async (req, res, next) => { try { await SettingsService.update(req.body); res.status(204).end(); diff --git a/test/server/routes/api/assets/index.js b/test/server/routes/api/assets/index.js index 855b30271..a07b154d4 100644 --- a/test/server/routes/api/assets/index.js +++ b/test/server/routes/api/assets/index.js @@ -37,78 +37,88 @@ describe('/api/v1/assets', () => { describe('#get', () => { it('should return all assets without a search query', async () => { - const res = await chai.request(app) - .get('/api/v1/assets') - .set(passport.inject({roles: ['ADMIN']})); + for (const role of ['ADMIN', 'MODERATOR']) { + const res = await chai.request(app) + .get('/api/v1/assets') + .set(passport.inject({roles: [role]})); - const body = res.body; + const body = res.body; - expect(body).to.have.property('count', 2); - expect(body).to.have.property('result'); + expect(body).to.have.property('count', 2); + expect(body).to.have.property('result'); - const assets = body.result; + const assets = body.result; - expect(assets).to.have.length(2); + expect(assets).to.have.length(2); + } }); it('should return assets that we search for', async () => { - const res = await chai.request(app) - .get('/api/v1/assets?search=term2') - .set(passport.inject({roles: ['ADMIN']})); + for (const role of ['ADMIN', 'MODERATOR']) { + const res = await chai.request(app) + .get('/api/v1/assets?search=term2') + .set(passport.inject({roles: [role]})); - const body = res.body; + const body = res.body; - expect(body).to.have.property('count', 1); - expect(body).to.have.property('result'); + expect(body).to.have.property('count', 1); + expect(body).to.have.property('result'); - const assets = body.result; + const assets = body.result; - expect(assets).to.have.length(1); + expect(assets).to.have.length(1); - const asset = assets[0]; + const asset = assets[0]; - expect(asset).to.have.property('url', 'https://coralproject.net/news/asset2'); - expect(asset).to.have.property('title', 'Asset 2'); + expect(asset).to.have.property('url', 'https://coralproject.net/news/asset2'); + expect(asset).to.have.property('title', 'Asset 2'); + } }); it('should not return assets that we do not search for', async () => { - const res = await chai.request(app) - .get('/api/v1/assets?search=term3') - .set(passport.inject({roles: ['ADMIN']})); - const body = res.body; + for (const role of ['ADMIN', 'MODERATOR']) { + const res = await chai.request(app) + .get('/api/v1/assets?search=term3') + .set(passport.inject({roles: [role]})); + const body = res.body; - expect(body).to.have.property('count', 0); - expect(body).to.have.property('result'); + expect(body).to.have.property('count', 0); + expect(body).to.have.property('result'); - expect(body.result).to.be.empty; + expect(body.result).to.be.empty; + } }); it('should return only closed assets', async () => { - const res = await chai.request(app) - .get('/api/v1/assets?filter=closed') - .set(passport.inject({roles: ['ADMIN']})); - const body = res.body; + for (const role of ['ADMIN', 'MODERATOR']) { + const res = await chai.request(app) + .get('/api/v1/assets?filter=closed') + .set(passport.inject({roles: [role]})); + const body = res.body; - expect(body).to.have.property('count', 1); - expect(body).to.have.property('result'); + expect(body).to.have.property('count', 1); + expect(body).to.have.property('result'); - const assets = body.result; + const assets = body.result; - expect(assets[0]).to.have.property('title', 'Asset 1'); + expect(assets[0]).to.have.property('title', 'Asset 1'); + } }); it('should return only opened assets', async () => { - const res = await chai.request(app) - .get('/api/v1/assets?filter=open') - .set(passport.inject({roles: ['ADMIN']})); - const body = res.body; + for (const role of ['ADMIN', 'MODERATOR']) { + const res = await chai.request(app) + .get('/api/v1/assets?filter=open') + .set(passport.inject({roles: [role]})); + const body = res.body; - expect(body).to.have.property('count', 1); - expect(body).to.have.property('result'); + expect(body).to.have.property('count', 1); + expect(body).to.have.property('result'); - const assets = body.result; + const assets = body.result; - expect(assets[0]).to.have.property('title', 'Asset 2'); + expect(assets[0]).to.have.property('title', 'Asset 2'); + } }); }); @@ -133,6 +143,20 @@ describe('/api/v1/assets', () => { expect(closedAsset).to.have.property('isClosed', true); expect(closedAsset).to.have.property('closedAt').and.to.not.equal(null); }); + + it('should require ADMIN role', async () => { + const today = Date.now(); + + const asset = await AssetsService.findOrCreateByUrl('http://test.com'); + expect(asset).to.have.property('isClosed', false); + expect(asset).to.have.property('closedAt', null); + + const promise = chai.request(app) + .put(`/api/v1/assets/${asset.id}/status`) + .set(passport.inject({roles: ['MODERATOR']})) + .send({closedAt: today}); + await expect(promise).to.eventually.be.rejected; + }); }); }); diff --git a/test/server/routes/api/settings/index.js b/test/server/routes/api/settings/index.js index c7704fc7e..d3728ff2c 100644 --- a/test/server/routes/api/settings/index.js +++ b/test/server/routes/api/settings/index.js @@ -16,17 +16,17 @@ describe('/api/v1/settings', () => { describe('#get', () => { - it('should return a settings object', () => { - return chai.request(app) - .get('/api/v1/settings') - .set(passport.inject({ - roles: ['ADMIN'] - })) - .then((res) => { - expect(res).to.have.status(200); - expect(res).to.be.json; - expect(res.body).to.have.property('moderation', 'PRE'); - }); + it('should return a settings object', async () => { + for (let role of ['ADMIN', 'MODERATOR']) { + const res = await chai.request(app) + .get('/api/v1/settings') + .set(passport.inject({ + roles: [role] + })); + expect(res).to.have.status(200); + expect(res).to.be.json; + expect(res.body).to.have.property('moderation', 'PRE'); + } }); }); @@ -46,6 +46,14 @@ describe('/api/v1/settings', () => { expect(settings).to.have.property('moderation', 'POST'); }); }); + + it('should require ADMIN role', () => { + const promise = chai.request(app) + .put('/api/v1/settings') + .set(passport.inject({roles: ['MODERATOR']})) + .send({moderation: 'POST'}); + return expect(promise).to.eventually.be.rejected; + }); }); });