From ac4890631c665eac3619e454117a62c865e0754a Mon Sep 17 00:00:00 2001 From: Sebastian Mihalache <sebi.mihalache@gmail.com> Date: Thu, 4 Oct 2018 10:40:53 +0300 Subject: [PATCH] feat(manuscript-manager): Get Fragments Endpoint --- .../src/fixtures/teams.js | 2 +- .../src/Fragments.js | 23 +++++ .../src/routes/fragments/get.js | 20 ++++ .../src/tests/fragments/get.test.js | 92 +++++++++++++++++++ .../xpub-faraday/config/authsome-helpers.js | 20 ++++ packages/xpub-faraday/config/authsome-mode.js | 17 ++++ 6 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 packages/component-manuscript-manager/src/routes/fragments/get.js create mode 100644 packages/component-manuscript-manager/src/tests/fragments/get.test.js diff --git a/packages/component-fixture-manager/src/fixtures/teams.js b/packages/component-fixture-manager/src/fixtures/teams.js index acd600dc7..3e3c2ec33 100644 --- a/packages/component-fixture-manager/src/fixtures/teams.js +++ b/packages/component-fixture-manager/src/fixtures/teams.js @@ -36,7 +36,7 @@ const teams = { type: 'fragment', id: fragment.id, }, - members: [reviewer.id, inactiveReviewer.id], + members: [reviewer.id, inactiveReviewer.id, handlingEditor.id], save: jest.fn(() => teams.revTeam), updateProperties: jest.fn(() => teams.revTeam), id: revTeamID, diff --git a/packages/component-manuscript-manager/src/Fragments.js b/packages/component-manuscript-manager/src/Fragments.js index 01e11a935..40a384bea 100644 --- a/packages/component-manuscript-manager/src/Fragments.js +++ b/packages/component-manuscript-manager/src/Fragments.js @@ -49,6 +49,29 @@ const Fragments = app => { authBearer, require(`${routePath}/post`)(app.locals.models), ) + /** + * @api {get} /api/fragments Get latest fragments + * @apiGroup Fragments + * @apiSuccessExample {json} Success + * HTTP/1.1 200 OK + * [ + * { + * "type": "fragment", + * "files": {}, + * "owners": [ + * "2494cbdf-06a8-4403-999b-ae93e23f32c8", + * "ed39345d-a95f-46d8-b5e1-75a2744beefe" + * ], + * } + * ] + * @apiErrorExample {json} Get fragments errors + * HTTP/1.1 403 Forbidden + */ + app.get( + '/api/fragments', + authBearer, + require(`${routePath}/get`)(app.locals.models), + ) } module.exports = Fragments diff --git a/packages/component-manuscript-manager/src/routes/fragments/get.js b/packages/component-manuscript-manager/src/routes/fragments/get.js new file mode 100644 index 000000000..0c45552b1 --- /dev/null +++ b/packages/component-manuscript-manager/src/routes/fragments/get.js @@ -0,0 +1,20 @@ +const { + authsome: authsomeHelper, +} = require('pubsweet-component-helper-service') + +module.exports = models => async (req, res) => { + const authsome = authsomeHelper.getAuthsome(models) + const target = { + path: req.route.path, + } + + const fragments = await authsome.can(req.user, 'GET', target) + + if (!fragments) { + return res.status(403).json({ + error: 'Unauthorized.', + }) + } + + res.status(200).json(fragments) +} diff --git a/packages/component-manuscript-manager/src/tests/fragments/get.test.js b/packages/component-manuscript-manager/src/tests/fragments/get.test.js new file mode 100644 index 000000000..6fe423081 --- /dev/null +++ b/packages/component-manuscript-manager/src/tests/fragments/get.test.js @@ -0,0 +1,92 @@ +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' +process.env.SUPPRESS_NO_CONFIG_WARNING = true + +const cloneDeep = require('lodash/cloneDeep') +const fixturesService = require('pubsweet-component-fixture-service') +const requests = require('../requests') + +const { Model, fixtures } = fixturesService +jest.mock('@pubsweet/component-send-email', () => ({ + send: jest.fn(), +})) + +const path = '../routes/fragments/get' +const route = { + path: '/api/fragments', +} +describe('Get fragments route handler', () => { + let testFixtures = {} + let models + beforeEach(() => { + testFixtures = cloneDeep(fixtures) + models = Model.build(testFixtures) + }) + + it('should return latest fragments if the request user is HE', async () => { + const { handlingEditor } = testFixtures.users + + const res = await requests.sendRequest({ + userId: handlingEditor.id, + route, + models, + path, + }) + + expect(res.statusCode).toBe(200) + const data = JSON.parse(res._getData()) + + expect(data).toHaveLength(1) + expect(data[0].type).toEqual('fragment') + expect(data[0].recommendations).toHaveLength(3) + }) + + it('should return latest fragments if the request user is reviewer', async () => { + const { recReviewer } = testFixtures.users + + const res = await requests.sendRequest({ + userId: recReviewer.id, + route, + models, + path, + }) + + expect(res.statusCode).toBe(200) + const data = JSON.parse(res._getData()) + + expect(data).toHaveLength(1) + expect(data[0].type).toEqual('fragment') + expect(data[0].recommendations).toHaveLength(1) + expect(data[0].authors[0]).not.toHaveProperty('email') + }) + + it('should return an error if the request user is unauthenticated', async () => { + const res = await requests.sendRequest({ + route, + models, + path, + }) + + expect(res.statusCode).toBe(403) + const data = JSON.parse(res._getData()) + + expect(data.error).toEqual('Unauthorized.') + }) + + it('should return all fragments if the request user is admin/EiC', async () => { + const { editorInChief } = testFixtures.users + + const res = await requests.sendRequest({ + userId: editorInChief.id, + route, + models, + path, + }) + + expect(res.statusCode).toBe(200) + const data = JSON.parse(res._getData()) + + expect(data).toHaveLength(2) + expect(data[0].type).toEqual('fragment') + expect(data[0].recommendations).toHaveLength(3) + }) +}) diff --git a/packages/xpub-faraday/config/authsome-helpers.js b/packages/xpub-faraday/config/authsome-helpers.js index 130516c90..57fb08dff 100644 --- a/packages/xpub-faraday/config/authsome-helpers.js +++ b/packages/xpub-faraday/config/authsome-helpers.js @@ -203,6 +203,25 @@ const getUsersList = async ({ UserModel, user }) => { const parseUser = ({ user }) => omit(user, sensitiveUserProperties) +const getFragments = async ({ user, models }) => { + const userPermisssions = await getUserPermissions({ user, Team: models.Team }) + + return Promise.all( + userPermisssions.map(async up => { + let fragment = {} + if (up.objectType === 'collection') { + const coll = await models.Collection.find(up.objectId) + const latestFragmentId = coll.fragments[coll.fragments.length - 1] + fragment = await models.Fragment.find(latestFragmentId) + } else { + fragment = await models.Fragment.find(up.objectId) + } + + return stripeFragmentByRole({ fragment, role: up.role, user }) + }), + ) +} + module.exports = { filterObjectData, parseAuthorsData, @@ -220,4 +239,5 @@ module.exports = { stripeFragmentByRole, getUsersList, parseUser, + getFragments, } diff --git a/packages/xpub-faraday/config/authsome-mode.js b/packages/xpub-faraday/config/authsome-mode.js index 4d42abca0..59e9436c9 100644 --- a/packages/xpub-faraday/config/authsome-mode.js +++ b/packages/xpub-faraday/config/authsome-mode.js @@ -172,6 +172,13 @@ async function applyAuthenticatedUserPolicy(user, operation, object, context) { if (get(object, 'type') === 'user') { return helpers.parseUser({ user: object }) } + + if (get(object, 'path') === '/api/fragments') { + return helpers.getFragments({ + user, + models: context.models, + }) + } } if (operation === 'POST') { @@ -299,6 +306,16 @@ async function applyEditorInChiefPolicy(user, operation, object, context) { if (get(object, 'type') === 'user') { return helpers.parseUser({ user: object }) } + + if (get(object, 'path') === '/api/fragments') { + const collections = await context.models.Collection.all() + return Promise.all( + collections.map(coll => { + const latestFragmentId = coll.fragments[coll.fragments.length - 1] + return context.models.Fragment.find(latestFragmentId) + }), + ) + } } return true } -- GitLab