Skip to content

Commit 3ad793c

Browse files
authored
Merge pull request #447 from bcgsc/feature/DEVSU-2656-email-notification
feature/DEVSU-2656 email notification
2 parents 5ea6d17 + baba63b commit 3ad793c

11 files changed

Lines changed: 281 additions & 78 deletions

File tree

app/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const nconf = require('nconf');
22
const {merge} = require('lodash');
3+
require('dotenv').config();
34

45
const ENV = process.env.NODE_ENV || 'local';
56

app/libs/email.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@ const getEmailList = async (triggers) => {
3535
const emailList = [];
3636
for (const notif of notifs) {
3737
if (notif.user) {
38-
if (!emailList.includes(notif.user.email)
38+
if (!emailList.some((el) => {return el.toEmail === notif.user.email;})
3939
&& notif.user.email.endsWith(domain)
4040
&& notif.user.allowNotifications) {
4141
emailList.push({toEmail: notif.user.email, notifId: notif.id, eventType: notif.eventType});
4242
}
43-
} else if (notif.userGroup) {
43+
}
44+
if (notif.userGroup) {
4445
for (const groupUser of notif.userGroup.users) {
45-
if (!emailList.includes(groupUser.email)
46+
if (!emailList.some((el) => {return el.toEmail === groupUser.email;})
4647
&& groupUser.email.endsWith(domain)
4748
&& groupUser.allowNotifications) {
4849
emailList.push({toEmail: groupUser.email, notifId: notif.id, eventType: notif.eventType});

app/queue.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -152,20 +152,6 @@ const emailProcessor = async (job) => {
152152
});
153153

154154
try {
155-
try {
156-
const notification = await db.models.notificationTrack.findOne({
157-
where: {
158-
notificationId: job.data.notifId,
159-
jobId: job.id,
160-
},
161-
});
162-
await notification.update({
163-
outcome: 'processing',
164-
});
165-
} catch (error) {
166-
logger.error(`Unable to add process notification track ${error}`);
167-
throw new Error(error);
168-
}
169155
await transporter.sendMail(job.data.mailOptions);
170156
} catch (err) {
171157
logger.error(JSON.stringify(job.data.mailOptions));

app/routes/notification/notification.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const db = require('../../models');
55
const logger = require('../../log');
66

77
const {getUserProjects, isAdmin} = require('../../libs/helperFunctions');
8+
const {NOTIFICATION_EVENT} = require('../../constants');
89

910
const router = express.Router({mergeParams: true});
1011

@@ -18,6 +19,9 @@ const pairs = {
1819
// for each entry in pairs, assumes the key-named value in
1920
// req.body is the ident, and gets the id of the corresponding object.
2021
router.use(async (req, res, next) => {
22+
if (req.method === 'GET') {
23+
req.body = req.query;
24+
}
2125
const operations = [];
2226

2327
for (const [key, value] of Object.entries(pairs)) {
@@ -95,9 +99,10 @@ router.route('/')
9599
}
96100
})
97101
.post(async (req, res) => {
98-
// TODO: Delete admin check once notification is properly implemented/tested
99-
if (!isAdmin(req.user)) {
100-
return res.status(HTTP_STATUS.FORBIDDEN);
102+
if (req.user.id !== req.body.user_id && !isAdmin(req.user)) {
103+
return res.status(HTTP_STATUS.FORBIDDEN).json({
104+
error: {message: 'only user self and admin can create notification'},
105+
});
101106
}
102107

103108
if (req.body.user_id && req.body.user_group_id) {
@@ -124,12 +129,18 @@ router.route('/')
124129
});
125130
}
126131

127-
if (!req.body.event_type) {
132+
if (!req.body.eventType) {
128133
return res.status(HTTP_STATUS.CONFLICT).json({
129134
error: {message: 'Event type must be specified'},
130135
});
131136
}
132137

138+
if (!Object.values(NOTIFICATION_EVENT).includes(req.body.eventType)) {
139+
return res.status(HTTP_STATUS.CONFLICT).json({
140+
error: {message: 'Event type must be reportCreated or userBound'},
141+
});
142+
}
143+
133144
// check the given user, if any, is bound to the given project (or is admin)
134145
if (req.body.user_id) {
135146
let notifUser;
@@ -174,7 +185,7 @@ router.route('/')
174185
projectId: req.body.project_id,
175186
userId: req.body.user_id ? req.body.user_id : null,
176187
userGroupId: req.body.user_group_id ? req.body.user_group_id : null,
177-
eventType: req.body.event_type,
188+
eventType: req.body.eventType,
178189
templateId: req.body.template_id,
179190
},
180191
});
@@ -197,7 +208,7 @@ router.route('/')
197208
try {
198209
notification = await db.models.notification.findOne({
199210
where: {ident: req.body.ident},
200-
attributes: ['id', 'ident'],
211+
attributes: ['id', 'ident', 'userId'],
201212
});
202213
} catch (error) {
203214
logger.error(`Error while trying to find notification ${error}`);
@@ -213,6 +224,12 @@ router.route('/')
213224
});
214225
}
215226

227+
if (req.user.id !== notification.userId && !isAdmin(req.user)) {
228+
return res.status(HTTP_STATUS.FORBIDDEN).json({
229+
error: {message: 'only user self and admin can delete notification'},
230+
});
231+
}
232+
216233
try {
217234
await notification.destroy();
218235
return res.status(HTTP_STATUS.NO_CONTENT).send();

app/routes/report/report.js

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -333,27 +333,22 @@ router.route('/')
333333
projectIdArray.push(project.project_id);
334334
});
335335

336-
await db.models.notification.findOrCreate({
337-
where: {
338-
userId: req.user.id,
339-
eventType: NOTIFICATION_EVENT.REPORT_CREATED,
340-
templateId: report.templateId,
341-
projectId: report.projects[0].project_id,
342-
},
343-
});
344-
345336
await email.notifyUsers(
346337
`Report Created: ${req.body.patientId} ${req.body.template}`,
347338
`New report:
348339
Ident: ${report.ident}
349340
Created by: ${req.user.firstName} ${req.user.lastName}
350341
Project: ${req.body.project}
351342
Template: ${req.body.template}
352-
Patient: ${req.body.patientId}`,
343+
Patient: ${req.body.patientId}
344+
345+
You're receiving this email because you have email notifications enabled in your account settings.
346+
If you no longer wish to receive these notifications, you can unsubscribe at any time by visiting your User Profile and turning off the "Allow email notifications" option.`,
353347
{
348+
userId: req.user.id,
354349
eventType: NOTIFICATION_EVENT.REPORT_CREATED,
355350
templateId: report.templateId,
356-
projectId: projectIdArray,
351+
projectId: report.projects[0].project_id,
357352
},
358353
);
359354

app/routes/report/reportUser.js

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -132,30 +132,29 @@ router.route('/')
132132

133133
const report = await db.models.report.findOne({where: {id: req.report.id}});
134134
const reportProject = await db.models.reportProject.findOne({where: {report_id: req.report.id}});
135-
const notif = await db.models.notification.findOrCreate({
136-
where: {
137-
userId: req.user.id,
138-
eventType: NOTIFICATION_EVENT.USER_BOUND,
139-
templateId: report.templateId,
140-
projectId: reportProject.project_id,
141-
},
142-
});
135+
const project = await db.models.project.findOne({where: {id: reportProject.project_id}});
136+
const template = await db.models.template.findOne({where: {id: report.templateId}});
143137

144138
// Try sending email
145139
try {
146140
await email.notifyUsers(
147141
`${bindUser.firstName} ${bindUser.lastName} has been bound to a report`,
148-
`User ${bindUser.firstName} ${bindUser.lastName} has been bound to report ${req.report.ident} as ${role}`,
142+
`User ${bindUser.firstName} ${bindUser.lastName} has been bound to report ${req.report.ident} as ${role}.
143+
Report Type: ${template.name}
144+
Patient Id: ${report.patientId}
145+
Project: ${project.name}
146+
147+
You're receiving this email because you have email notifications enabled in your account settings.
148+
If you no longer wish to receive these notifications, you can unsubscribe at any time by visiting your User Profile and turning off the "Allow email notifications" option.`,
149149
{
150+
userId: [req.user.id, bindUser.id],
150151
eventType: NOTIFICATION_EVENT.USER_BOUND,
151-
templateId: req.report.templateId,
152+
templateId: report.templateId,
153+
projectId: reportProject.project_id,
152154
},
153155
);
154-
155-
await notif[0].update({status: 'Success'}, {userId: req.user.id});
156156
logger.info('Email sent successfully');
157157
} catch (error) {
158-
await notif[0].update({status: 'Unsuccess'}, {userId: req.user.id});
159158
logger.error(`Email not sent successfully: ${error}`);
160159
}
161160

app/routes/swagger/schemas.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const schemas = {};
1010
const ID_FIELDS = [
1111
'germlineReportId', 'user_id', 'createdBy_id', 'addedBy_id', 'variantId',
1212
'gene1Id', 'gene2Id', 'reviewerId', 'biofxAssignedId', 'logoId', 'headerId', 'templateId',
13-
'product_id', 'addedById',
13+
'product_id', 'addedById', 'userId', 'projectId', 'userGroupId',
1414
];
1515
const PUBLIC_VIEW_EXCLUDE = [...ID_FIELDS, 'id', 'reportId', 'geneId', 'deletedAt', 'updatedBy'];
1616
const GENERAL_EXCLUDE = REPORT_EXCLUDE.concat(ID_FIELDS);
@@ -207,6 +207,42 @@ Object.assign(schemas.germlineReportUserCreate.properties, {
207207
},
208208
});
209209

210+
// notification create
211+
schemas.notificationAssociations = schemaGenerator(db.models.notification, {
212+
isJsonSchema: false, title: 'notificationAssociations', exclude: [...GENERAL_EXCLUDE], associations: true, includeAssociations: ['project', 'template', 'user'],
213+
});
214+
215+
Object.assign(schemas.notificationCreate.properties, {
216+
eventType: {
217+
type: 'string',
218+
description: 'either reportCreated or userBound',
219+
},
220+
user: {
221+
type: 'string',
222+
format: 'uuid',
223+
description: 'ident of user to notify, either user or user_group should be specified',
224+
},
225+
user_group: {
226+
type: 'string',
227+
format: 'uuid',
228+
description: 'ident of user group to notify, either user or user_group should be specified',
229+
},
230+
project: {
231+
type: 'string',
232+
format: 'uuid',
233+
description: 'ident of project for which user or user group want to be notified',
234+
},
235+
template: {
236+
type: 'string',
237+
format: 'uuid',
238+
description: 'ident of template for which user or user group want to be notified',
239+
},
240+
});
241+
242+
Object.assign(schemas.notificationCreate, {
243+
required: ['project', 'template', 'eventType'],
244+
});
245+
210246
// *PUT request body*
211247

212248
// add template name to report update

0 commit comments

Comments
 (0)