Skip to content

Commit

Permalink
Merge for v2.0.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul McCafferty committed May 17, 2021
1 parent 178c2c3 commit ffc30ed
Show file tree
Hide file tree
Showing 39 changed files with 2,387 additions and 838 deletions.
13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
{
"name": "hdruk-rdt-api",
"version": "0.1.0",
"config": {
"mongodbMemoryServer": {
"version": "latest"
}
},
"version": "0.1.1",
"private": true,
"dependencies": {
"@google-cloud/monitoring": "^2.1.0",
"@google-cloud/storage": "^5.3.0",
"@sendgrid/mail": "^7.1.0",
"@sentry/node": "^5.29.0",
"@sentry/node": "^6.3.5",
"@sentry/tracing": "^6.3.5",
"ajv": "^8.1.0",
"ajv-formats": "^2.0.2",
"async": "^3.2.0",
Expand Down Expand Up @@ -36,6 +42,7 @@
"jsonwebtoken": "^8.5.1",
"keygrip": "^1.1.0",
"lodash": "^4.17.19",
"mailchimp-api-v3": "^1.15.0",
"moment": "^2.27.0",
"mongoose": "^5.9.12",
"morgan": "^1.10.0",
Expand Down Expand Up @@ -63,7 +70,7 @@
"babel-jest": "^26.6.3",
"eslint": "^7.20.0",
"jest": "^26.6.3",
"mongodb-memory-server": "^6.9.2",
"mongodb-memory-server": "6.9.2",
"nodemon": "^2.0.3",
"supertest": "^4.0.2"
},
Expand Down
4 changes: 4 additions & 0 deletions src/config/account.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getUserByUserId } from '../resources/user/user.repository';
import ga4ghUtils from '../resources/utilities/ga4gh.utils';
import { to } from 'await-to-js';
import { isNil } from 'lodash';

Expand Down Expand Up @@ -40,6 +41,9 @@ class Account {
if (claimsToSend.includes('rquestroles')) {
claim.rquestroles = user.advancedSearchRoles;
}
if (claimsToSend.includes('ga4gh_passport_v1')) {
claim.ga4gh_passport_v1 = await ga4ghUtils.buildGa4ghVisas(user);
}
}

return claim;
Expand Down
11 changes: 11 additions & 0 deletions src/config/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ export const clients = [
id_token_signed_response_alg: 'HS256',
post_logout_redirect_uris: ['https://web.uatbeta.healthdatagateway.org/search?search=&logout=true'],
},
{
//GA4GH passports
client_id: process.env.GA4GHClientID,
client_secret: process.env.GA4GHClientSecret,
grant_types: ['authorization_code', 'implicit'],
response_types: ['code id_token'],
redirect_uris: process.env.GA4GHRedirectURI.split(',') || [''],
id_token_signed_response_alg: 'HS256',
post_logout_redirect_uris: ['https://web.uatbeta.healthdatagateway.org/search?search=&logout=true'],
},
];

export const interactions = {
Expand All @@ -58,6 +68,7 @@ export const claims = {
email: ['email'],
profile: ['firstname', 'lastname'],
rquestroles: ['rquestroles'],
ga4gh_passport_v1: ['ga4gh_passport_v1'],
};

export const features = {
Expand Down
33 changes: 26 additions & 7 deletions src/config/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,39 @@ import cookieParser from 'cookie-parser';
import { connectToDatabase } from './db';
import { initialiseAuthentication } from '../resources/auth';
import * as Sentry from '@sentry/node';
import * as Tracing from '@sentry/tracing';
import helper from '../resources/utilities/helper.util';

require('dotenv').config();

if (helper.getEnvironment() !== 'local') {
Sentry.init({
dsn: 'https://[email protected]/5653683',
environment: helper.getEnvironment(),
});
}
var app = express();

Sentry.init({
dsn: 'https://[email protected]/5653683',
environment: helper.getEnvironment(),
integrations: [
// enable HTTP calls tracing
new Sentry.Integrations.Http({ tracing: true }),
// enable Express.js middleware tracing
new Tracing.Integrations.Express({
// trace all requests to the default router
app,
}),
],
tracesSampleRate: 1.0,
});
// RequestHandler creates a separate execution context using domains, so that every
// transaction/span/breadcrumb is attached to its own Hub instance
app.use(Sentry.Handlers.requestHandler());
// TracingHandler creates a trace for every incoming request
app.use(Sentry.Handlers.tracingHandler());
app.use(Sentry.Handlers.errorHandler());

const Account = require('./account');
const configuration = require('./configuration');

const API_PORT = process.env.PORT || 3001;
const session = require('express-session');
var app = express();
app.disable('x-powered-by');

configuration.findAccount = Account.findAccount;
Expand Down Expand Up @@ -213,6 +229,7 @@ app.use('/api/v2/papers', require('../resources/paper/v2/paper.route'));

app.use('/api/v1/counter', require('../resources/tool/counter.route'));
app.use('/api/v1/coursecounter', require('../resources/course/coursecounter.route'));
app.use('/api/v1/collectioncounter', require('../resources/collections/collectioncounter.route'));

app.use('/api/v1/discourse', require('../resources/discourse/discourse.route'));

Expand All @@ -231,6 +248,8 @@ app.use('/api/v1/help', require('../resources/help/help.router'));

app.use('/api/v2/filters', require('../resources/filters/filters.route'));

app.use('/api/v1/mailchimp', require('../services/mailchimp/mailchimp.route'));

initialiseAuthentication(app);

// launch our backend into a port
Expand Down
2 changes: 1 addition & 1 deletion src/resources/account/account.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,6 @@ async function sendEmailNotifications(tool, activeflag) {
if (err) {
return new Error({ success: false, error: err });
}
emailGenerator.sendEmail(emailRecipients, `${hdrukEmail}`, subject, html);
emailGenerator.sendEmail(emailRecipients, `${hdrukEmail}`, subject, html, false);
});
}
1 change: 1 addition & 0 deletions src/resources/auth/auth.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ router.get('/status', function (req, res, next) {
id: req.user.id,
name: req.user.firstname + ' ' + req.user.lastname,
loggedIn: true,
email: req.user.email,
teams: [...adminArray, ...teamArray],
provider: req.user.provider,
advancedSearchRoles: req.user.advancedSearchRoles,
Expand Down
7 changes: 6 additions & 1 deletion src/resources/auth/strategies/oidc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import { ROLES } from '../../user/user.roles';
import queryString from 'query-string';
import Url from 'url';
import { discourseLogin } from '../sso/sso.discourse.service';

import { isNil } from 'lodash';
const OidcStrategy = passportOidc.Strategy;
const baseAuthUrl = process.env.AUTH_PROVIDER_URI;
const eventLogController = require('../../eventlog/eventlog.controller');
import { UserModel } from '../../user/user.model';

const strategy = app => {
const strategyOptions = {
Expand All @@ -34,13 +35,17 @@ const strategy = app => {

let [err, user] = await to(getUserByProviderId(profile._json.eduPersonTargetedID));
if (err || user) {
if (user && !user.affiliation) {
UserModel.findOneAndUpdate({ id: user.id }, { $set: { affiliation: profile._json.eduPersonScopedAffilation } });
}
return done(err, user);
}

const [createdError, createdUser] = await to(
createUser({
provider: 'oidc',
providerId: profile._json.eduPersonTargetedID,
affiliation: !isNil(profile._json.eduPersonScopedAffilation) ? profile._json.eduPersonScopedAffilation : 'no.organization',
firstname: '',
lastname: '',
email: '',
Expand Down
21 changes: 21 additions & 0 deletions src/resources/collections/collectioncounter.route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import express from 'express';
import { Collections } from './collections.model';
const rateLimit = require('express-rate-limit');

const router = express.Router();

const datasetLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute window
max: 50, // start blocking after 50 requests
message: 'Too many calls have been made to this api from this IP, please try again after an hour',
});

router.post('/update', datasetLimiter, async (req, res) => {
const { id, counter } = req.body;
Collections.findOneAndUpdate({ id: id }, { counter: counter }, err => {
if (err) return res.json({ success: false, error: err });
return res.json({ success: true });
});
});

module.exports = router;
1 change: 1 addition & 0 deletions src/resources/collections/collections.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const CollectionSchema = new Schema(
id: Number,
name: String,
description: String,
updatedon: Date,
imageLink: String,
authors: [Number],
// emailNotifications: Boolean,
Expand Down
25 changes: 15 additions & 10 deletions src/resources/collections/collections.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,20 +115,23 @@ router.get('/entityid/:entityID', async (req, res) => {
});

router.put('/edit', passport.authenticate('jwt'), utils.checkIsInRole(ROLES.Admin, ROLES.Creator), async (req, res) => {
const collectionCreator = req.body.collectionCreator;
let { id, name, description, imageLink, authors, relatedObjects, publicflag, keywords, previousPublicFlag } = req.body;
let { id, name, description, imageLink, authors, relatedObjects, publicflag, keywords, previousPublicFlag, collectionCreator } = req.body;
imageLink = urlValidator.validateURL(imageLink);
let updatedon = Date.now();

let collectionId = parseInt(id);

await Collections.findOneAndUpdate(
{ id: id },
{
{ id: collectionId },
{ //lgtm [js/sql-injection]
name: inputSanitizer.removeNonBreakingSpaces(name),
description: inputSanitizer.removeNonBreakingSpaces(description),
imageLink: imageLink,
authors: authors,
relatedObjects: relatedObjects,
publicflag: publicflag,
keywords: keywords,
updatedon: updatedon
},
err => {
if (err) {
Expand All @@ -139,7 +142,7 @@ router.put('/edit', passport.authenticate('jwt'), utils.checkIsInRole(ROLES.Admi
return res.json({ success: true });
});

await Collections.find({ id: id }, { publicflag: 1, id: 1, activeflag: 1, authors: 1, name: 1 }).then(async res => {
await Collections.find({ id: collectionId }, { publicflag: 1, id: 1, activeflag: 1, authors: 1, name: 1 }).then(async res => {
if (previousPublicFlag === false && publicflag === true) {
await sendEmailNotifications(res[0], res[0].activeflag, collectionCreator, true);

Expand Down Expand Up @@ -170,6 +173,7 @@ router.post('/add', passport.authenticate('jwt'), utils.checkIsInRole(ROLES.Admi
collections.activeflag = 'active';
collections.publicflag = publicflag;
collections.keywords = keywords;
collections.updatedon = Date.now();

if (collections.authors) {
collections.authors.forEach(async authorId => {
Expand All @@ -191,10 +195,11 @@ router.post('/add', passport.authenticate('jwt'), utils.checkIsInRole(ROLES.Admi
});

router.put('/status', passport.authenticate('jwt'), utils.checkIsInRole(ROLES.Admin, ROLES.Creator), async (req, res) => {
var { id, activeflag } = req.body;
var isAuthorAdmin = false;
let { id, activeflag } = req.body;
let isAuthorAdmin = false;
let collectionId = parseInt(id);

var q = Collections.aggregate([{ $match: { $and: [{ id: parseInt(req.body.id) }, { authors: req.user.id }] } }]);
let q = Collections.aggregate([{ $match: { $and: [{ id: parseInt(req.body.id) }, { authors: req.user.id }] } }]);
q.exec((err, data) => {
if (data.length === 1) {
isAuthorAdmin = true;
Expand All @@ -206,8 +211,8 @@ router.put('/status', passport.authenticate('jwt'), utils.checkIsInRole(ROLES.Ad

if (isAuthorAdmin) {
Collections.findOneAndUpdate(
{ id: id },
{
{ id: collectionId },
{ //lgtm [js/sql-injection]
activeflag: activeflag,
},
err => {
Expand Down
6 changes: 3 additions & 3 deletions src/resources/course/course.repository.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ const editCourse = async (req, res) => {

Course.findOneAndUpdate(
{ id: id },
{
{ //lgtm [js/sql-injection]
title: inputSanitizer.removeNonBreakingSpaces(req.body.title),
link: urlValidator.validateURL(inputSanitizer.removeNonBreakingSpaces(req.body.link)),
provider: inputSanitizer.removeNonBreakingSpaces(req.body.provider),
Expand Down Expand Up @@ -398,7 +398,7 @@ async function sendEmailNotifications(tool, activeflag, rejectionReason) {
if (err) {
return new Error({ success: false, error: err });
}
emailGenerator.sendEmail(emailRecipients, `${hdrukEmail}`, subject, html);
emailGenerator.sendEmail(emailRecipients, `${hdrukEmail}`, subject, html, false);
});
} else {
// 3. Find the creator of the course if they have opted in to email updates
Expand All @@ -418,7 +418,7 @@ async function sendEmailNotifications(tool, activeflag, rejectionReason) {
if (err) {
return new Error({ success: false, error: err });
}
emailGenerator.sendEmail(emailRecipients, `${hdrukEmail}`, subject, html);
emailGenerator.sendEmail(emailRecipients, `${hdrukEmail}`, subject, html, false);
});

// 5. Find all admins regardless of email opt-in preference
Expand Down
2 changes: 1 addition & 1 deletion src/resources/datarequest/datarequest.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2011,7 +2011,6 @@ module.exports = {
);

options = {
userType: '',
userEmail: appEmail,
publisher,
datasetTitles,
Expand Down Expand Up @@ -2109,6 +2108,7 @@ module.exports = {
) {
// Retrieve all custodian user Ids to generate notifications
custodianManagers = teamController.getTeamMembersByRole(accessRecord.datasets[0].publisher.team, constants.roleTypes.MANAGER);
// check if publisher.team has email notifications
custodianUserIds = custodianManagers.map(user => user.id);
await notificationBuilder.triggerNotificationMessage(
custodianUserIds,
Expand Down
1 change: 1 addition & 0 deletions src/resources/datarequest/datarequest.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const DataRequestSchema = new Schema(
questionAnswers: { type: Object, default: {} },
},
],
originId: { type: Schema.Types.ObjectId, ref: 'data_request' }
},
{
timestamps: true,
Expand Down
16 changes: 14 additions & 2 deletions src/resources/datarequest/datarequest.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import passport from 'passport';
import _ from 'lodash';
import multer from 'multer';
import { param } from 'express-validator';
import { logger } from '../utilities/logger';
const amendmentController = require('./amendment/amendment.controller');
const datarequestController = require('./datarequest.controller');
const fs = require('fs');
Expand All @@ -16,18 +17,29 @@ const storage = multer.diskStorage({
},
});
const multerMid = multer({ storage: storage });
const logCategory = 'Data Access Request';

const router = express.Router();

// @route GET api/v1/data-access-request
// @desc GET Access requests for user
// @access Private - Applicant (Gateway User) and Custodian Manager/Reviewer
router.get('/', passport.authenticate('jwt'), datarequestController.getAccessRequestsByUser);
router.get(
'/',
passport.authenticate('jwt'),
logger.logRequestMiddleware({ logCategory, action: 'Viewed personal Data Access Request dashboard' }),
datarequestController.getAccessRequestsByUser
);

// @route GET api/v1/data-access-request/:requestId
// @desc GET a single data access request by Id
// @access Private - Applicant (Gateway User) and Custodian Manager/Reviewer
router.get('/:requestId', passport.authenticate('jwt'), datarequestController.getAccessRequestById);
router.get(
'/:requestId',
passport.authenticate('jwt'),
logger.logRequestMiddleware({ logCategory, action: 'Opened a Data Access Request application' }),
datarequestController.getAccessRequestById
);

// @route GET api/v1/data-access-request/dataset/:datasetId
// @desc GET Access request for user
Expand Down
Loading

0 comments on commit ffc30ed

Please sign in to comment.