diff --git a/packages/component-publons/.gitignore b/packages/component-publons/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..59ff5cd1f687b2ad8339cb159a605672cbc76340 --- /dev/null +++ b/packages/component-publons/.gitignore @@ -0,0 +1,9 @@ +_build/ +api/ +logs/ +node_modules/ +uploads/ +.env.* +.env +config/local*.* +public/apidoc \ No newline at end of file diff --git a/packages/component-publons/README.md b/packages/component-publons/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a54c7ef61b096eae3e96f52c5228ab9c0e1adaa0 --- /dev/null +++ b/packages/component-publons/README.md @@ -0,0 +1,26 @@ +# Publons Component + +### Retrieve a list of suggested reviewers [GET] + +This endpoint allow to call the Publons API and get a list of suggested reviewers. + +#### Publons Reviewers Request + +`GET /api/fragments/:fragmentId/publons` + +| URI Parameter | Requiered | Requirements | Description | +| ------------- | --------- | ------------ | ------------------ | +| fragmentId | No | String | The ID of the fragment | + +#### Publons Reviewers Response + +```javascript +HTTP/1.1 200 OK +{ + "name": "Bradley Bundy", + "profileUrl": "https://publons.com/author/1249425/bradley-bundy", + "reviews": 16, + "institution": "Brigham Young University", + "email": "bundy@byu.edu" + } +``` \ No newline at end of file diff --git a/packages/component-publons/apidoc.json b/packages/component-publons/apidoc.json new file mode 100644 index 0000000000000000000000000000000000000000..6483df8bf42a56e7987a8d41c9fb643695a1a4fb --- /dev/null +++ b/packages/component-publons/apidoc.json @@ -0,0 +1,8 @@ +{ + "name": "Component Publons API documentation", + "version": "0.0.1", + "description": "A list of APIs for the Publons Component", + "template": { + "forceLanguage": "en" + } +} diff --git a/packages/component-publons/config/authsome-mode.js b/packages/component-publons/config/authsome-mode.js new file mode 100644 index 0000000000000000000000000000000000000000..9c663beae1962d9fc13141f8439dc0a84214ae08 --- /dev/null +++ b/packages/component-publons/config/authsome-mode.js @@ -0,0 +1,3 @@ +const authsomeMode = require('xpub-faraday/config/authsome-mode') + +module.exports = authsomeMode diff --git a/packages/component-publons/config/default.js b/packages/component-publons/config/default.js new file mode 100644 index 0000000000000000000000000000000000000000..9950c9b354fa8710a4f043a07ac2b86a3cf6bd2f --- /dev/null +++ b/packages/component-publons/config/default.js @@ -0,0 +1,3 @@ +const defaultConfig = require('xpub-faraday/config/default') + +module.exports = defaultConfig diff --git a/packages/component-publons/config/test.js b/packages/component-publons/config/test.js new file mode 100644 index 0000000000000000000000000000000000000000..9950c9b354fa8710a4f043a07ac2b86a3cf6bd2f --- /dev/null +++ b/packages/component-publons/config/test.js @@ -0,0 +1,3 @@ +const defaultConfig = require('xpub-faraday/config/default') + +module.exports = defaultConfig diff --git a/packages/component-publons/index.js b/packages/component-publons/index.js new file mode 100644 index 0000000000000000000000000000000000000000..42baa8ee9e58e3707967c281f66eaa34668476d8 --- /dev/null +++ b/packages/component-publons/index.js @@ -0,0 +1,5 @@ +module.exports = { + backend: () => app => { + require('./src/Publons')(app) + }, +} diff --git a/packages/component-publons/package.json b/packages/component-publons/package.json new file mode 100644 index 0000000000000000000000000000000000000000..9ab5b8a3f62649267d70354ecb4e655239568e85 --- /dev/null +++ b/packages/component-publons/package.json @@ -0,0 +1,40 @@ +{ + "name": "pubsweet-component-publons", + "version": "0.0.1", + "description": "publons component for pubsweet", + "license": "MIT", + "author": "Collaborative Knowledge Foundation", + "files": [ + "src" + ], + "main": "index.js", + "scripts": { + "test": "jest", + "docs": "./node_modules/.bin/apidoc -e \"(node_modules|public)\" -o public/apidoc", + "open-docs": "open public/apidoc/index.html" + }, + "repository": { + "type": "git", + "url": "https://gitlab.coko.foundation/xpub/xpub-faraday", + "path": "component-publons" + }, + "dependencies": { + "body-parser": "^1.17.2" + }, + "peerDependencies": { + "@pubsweet/logger": "^0.0.1", + "pubsweet-server": "^1.0.1" + }, + "devDependencies": { + "apidoc": "^0.17.6", + "jest": "^22.1.1", + "supertest": "^3.0.0" + }, + "jest": { + "verbose": true, + "testRegex": "/src/.*.test.js$" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/component-publons/src/Publons.js b/packages/component-publons/src/Publons.js new file mode 100644 index 0000000000000000000000000000000000000000..28b7a0628be6b385ffcb26298647da6a8c2d7020 --- /dev/null +++ b/packages/component-publons/src/Publons.js @@ -0,0 +1,35 @@ +const bodyParser = require('body-parser') + +const Publons = app => { + app.use(bodyParser.json()) + const basePath = '/api/fragments/:fragmentId/publons' + const routePath = './routes/publons' + const authBearer = app.locals.passport.authenticate('bearer', { + session: false, + }) + /** + * @api {get} /api/fragments/:fragmentId/publons List publons reviewers + * @apiGroup Publons + * @apiParam {id} fragmentId Fragment id + * @apiSuccessExample {json} Success + * HTTP/1.1 200 OK + * { + * "name": "Bradley Bundy", + * "profileUrl": "https://publons.com/author/1249425/bradley-bundy", + * "reviews": 16, + * "institution": "Brigham Young University", + * "email": "bundy@byu.edu" + * } + * @apiErrorExample {json} List errors + * HTTP/1.1 403 Forbidden + * HTTP/1.1 400 Bad Request + * HTTP/1.1 404 Not Found + */ + app.get( + `${basePath}`, + authBearer, + require(`${routePath}/get`)(app.locals.models), + ) +} + +module.exports = Publons diff --git a/packages/component-publons/src/routes/publons/get.js b/packages/component-publons/src/routes/publons/get.js new file mode 100644 index 0000000000000000000000000000000000000000..379ccd4d42815ac61804f35878501e02ba8ea147 --- /dev/null +++ b/packages/component-publons/src/routes/publons/get.js @@ -0,0 +1,35 @@ +// const config = require('config') +const { + authsome: authsomeHelper, + services, +} = require('pubsweet-component-helper-service') + +// const configRoles = config.get('roles') + +module.exports = models => async (req, res) => { + const { fragmentId } = req.params + + try { + const fragment = await models.Fragment.find(fragmentId) + + const authsome = authsomeHelper.getAuthsome(models) + const target = { + fragment, + path: req.route.path, + } + + const canGet = await authsome.can(req.user, 'GET', target) + + if (!canGet) + return res.status(403).json({ + error: 'Unauthorized.', + }) + + res.status(200).json() + } catch (e) { + const notFoundError = await services.handleNotFoundError(e, 'Fragment') + return res.status(notFoundError.status).json({ + error: notFoundError.message, + }) + } +} diff --git a/packages/component-publons/src/tests/publons/get.test.js b/packages/component-publons/src/tests/publons/get.test.js new file mode 100644 index 0000000000000000000000000000000000000000..8a5d8a66ca80f98785ea5745cc02d19d76fbcd4d --- /dev/null +++ b/packages/component-publons/src/tests/publons/get.test.js @@ -0,0 +1,74 @@ +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/publons/get' +const route = { + path: '/api/fragments/:fragmentId/publons', +} +describe('Get fragment invitations route handler', () => { + let testFixtures = {} + let models + beforeEach(() => { + testFixtures = cloneDeep(fixtures) + models = Model.build(testFixtures) + }) + it('should return success when the request data is correct', async () => { + const { handlingEditor } = testFixtures.users + const { fragment } = testFixtures.fragments + + const res = await requests.sendRequest({ + userId: handlingEditor.id, + route, + models, + path, + params: { + fragmentId: fragment.id, + }, + }) + + expect(res.statusCode).toBe(200) + // const data = JSON.parse(res._getData()) + }) + it('should return an error when the fragment does not exist', async () => { + const { handlingEditor } = testFixtures.users + + const res = await requests.sendRequest({ + userId: handlingEditor.id, + route, + models, + path, + params: { + fragmentId: 'invalid-id', + }, + }) + expect(res.statusCode).toBe(404) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual(`Fragment not found`) + }) + it('should return an error when a user does not have invitation rights', async () => { + const { user } = testFixtures.users + const { fragment } = testFixtures.fragments + + const res = await requests.sendRequest({ + userId: user.id, + route, + models, + path, + params: { + fragmentId: fragment.id, + }, + }) + expect(res.statusCode).toBe(403) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('Unauthorized.') + }) +}) diff --git a/packages/component-publons/src/tests/requests.js b/packages/component-publons/src/tests/requests.js new file mode 100644 index 0000000000000000000000000000000000000000..6696fc7c91db5dff36caf192aae5ac5068fab506 --- /dev/null +++ b/packages/component-publons/src/tests/requests.js @@ -0,0 +1,24 @@ +const httpMocks = require('node-mocks-http') + +const sendRequest = async ({ + body = {}, + userId, + route, + models, + path, + params = {}, + query = {}, +}) => { + const req = httpMocks.createRequest({ + body, + }) + req.user = userId + req.route = route + req.params = params + req.query = query + const res = httpMocks.createResponse() + await require(path)(models)(req, res) + return res +} + +module.exports = { sendRequest }