Skip to content

Commit d660164

Browse files
committed
add notification swagger; use params for notification GET; permission update
1 parent b01a7fe commit d660164

5 files changed

Lines changed: 234 additions & 43 deletions

File tree

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: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -332,17 +332,6 @@ router.route('/')
332332
report.projects.forEach((project) => {
333333
projectIdArray.push(project.project_id);
334334
});
335-
const userGroup = await db.models.userGroup.findOne({where: {name: 'admin'}});
336-
337-
const notify = await db.models.notification.findOrCreate({
338-
where: {
339-
userId: req.user.id,
340-
eventType: NOTIFICATION_EVENT.REPORT_CREATED,
341-
templateId: report.templateId,
342-
projectId: report.projects[0].project_id,
343-
userGroupId: userGroup.id,
344-
},
345-
});
346335

347336
await email.notifyUsers(
348337
`Report Created: ${req.body.patientId} ${req.body.template}`,
@@ -351,9 +340,15 @@ router.route('/')
351340
Created by: ${req.user.firstName} ${req.user.lastName}
352341
Project: ${req.body.project}
353342
Template: ${req.body.template}
354-
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.`,
355347
{
356-
id: notify[0].id,
348+
userId: req.user.id,
349+
eventType: NOTIFICATION_EVENT.REPORT_CREATED,
350+
templateId: report.templateId,
351+
projectId: report.projects[0].project_id,
357352
},
358353
);
359354

app/routes/report/reportUser.js

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -134,27 +134,6 @@ router.route('/')
134134
const reportProject = await db.models.reportProject.findOne({where: {report_id: req.report.id}});
135135
const project = await db.models.project.findOne({where: {id: reportProject.project_id}});
136136
const template = await db.models.template.findOne({where: {id: report.templateId}});
137-
const userGroup = await db.models.userGroup.findOne({where: {name: 'admin'}});
138-
139-
const notifyReq = await db.models.notification.findOrCreate({
140-
where: {
141-
userId: req.user.id,
142-
eventType: NOTIFICATION_EVENT.USER_BOUND,
143-
templateId: report.templateId,
144-
projectId: reportProject.project_id,
145-
userGroupId: userGroup.id,
146-
},
147-
});
148-
149-
const notifyBinding = await db.models.notification.findOrCreate({
150-
where: {
151-
userId: bindUser.id,
152-
eventType: NOTIFICATION_EVENT.USER_BOUND,
153-
templateId: report.templateId,
154-
projectId: reportProject.project_id,
155-
userGroupId: userGroup.id,
156-
},
157-
});
158137

159138
// Try sending email
160139
try {
@@ -163,9 +142,15 @@ router.route('/')
163142
`User ${bindUser.firstName} ${bindUser.lastName} has been bound to report ${req.report.ident} as ${role}.
164143
Report Type: ${template.name}
165144
Patient Id: ${report.patientId}
166-
Project: ${project.name}`,
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.`,
167149
{
168-
id: [notifyReq[0].id, notifyBinding[0].id],
150+
userId: [req.user.id, bindUser.id],
151+
eventType: NOTIFICATION_EVENT.USER_BOUND,
152+
templateId: report.templateId,
153+
projectId: reportProject.project_id,
169154
},
170155
);
171156
logger.info('Email sent successfully');

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 that user or user group want to be notified',
234+
},
235+
template: {
236+
type: 'string',
237+
format: 'uuid',
238+
description: 'ident of template that 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

app/routes/swagger/swagger.json

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7882,6 +7882,164 @@
78827882
}
78837883
}
78847884
}
7885+
},
7886+
"/notification/notifications": {
7887+
"get": {
7888+
"summary": "Get Notifications",
7889+
"description": "Retrieve all notifications",
7890+
"parameters": [
7891+
{
7892+
"name": "user",
7893+
"in": "query",
7894+
"required": false,
7895+
"description": "Filter notifications by user ident",
7896+
"schema": {
7897+
"type": "string",
7898+
"format": "uuid"
7899+
}
7900+
},
7901+
{
7902+
"name": "user_group",
7903+
"in": "query",
7904+
"required": false,
7905+
"description": "Filter templates by user_group ident",
7906+
"schema": {
7907+
"type": "string",
7908+
"format": "uuid"
7909+
}
7910+
},
7911+
{
7912+
"name": "project",
7913+
"in": "query",
7914+
"required": false,
7915+
"description": "Filter templates by project ident",
7916+
"schema": {
7917+
"type": "string",
7918+
"format": "uuid"
7919+
}
7920+
},
7921+
{
7922+
"name": "template",
7923+
"in": "query",
7924+
"required": false,
7925+
"description": "Filter templates by template ident",
7926+
"schema": {
7927+
"type": "string",
7928+
"format": "uuid"
7929+
}
7930+
}
7931+
],
7932+
"tags": [
7933+
"Notifications"
7934+
],
7935+
"security": [
7936+
{
7937+
"basicAuth": []
7938+
}
7939+
],
7940+
"responses": {
7941+
"200": {
7942+
"description": "Returns an array of all notifications",
7943+
"content": {
7944+
"application/json": {
7945+
"schema": {
7946+
"type": "array",
7947+
"items": {
7948+
"$ref": "#/components/schemas/notificationAssociations"
7949+
}
7950+
}
7951+
}
7952+
}
7953+
},
7954+
"401": {
7955+
"$ref": "#/components/responses/UnauthorizedError"
7956+
}
7957+
}
7958+
},
7959+
"post": {
7960+
"summary": "Create Notification",
7961+
"description": "Upload a new notiifcation",
7962+
"parameters": [],
7963+
"requestBody": {
7964+
"description": "Notification data",
7965+
"required": true,
7966+
"content": {
7967+
"multipart/form-data": {
7968+
"schema": {
7969+
"$ref": "#/components/schemas/notificationCreate"
7970+
}
7971+
}
7972+
}
7973+
},
7974+
"tags": [
7975+
"Notifications"
7976+
],
7977+
"security": [
7978+
{
7979+
"basicAuth": []
7980+
}
7981+
],
7982+
"responses": {
7983+
"200": {
7984+
"description": "Returns the details of the created notifcation",
7985+
"content": {
7986+
"application/json": {
7987+
"schema": {
7988+
"$ref": "#/components/schemas/notificationAssociations"
7989+
}
7990+
}
7991+
}
7992+
},
7993+
"401": {
7994+
"$ref": "#/components/responses/UnauthorizedError"
7995+
},
7996+
"409": {
7997+
"description": "Must specify project, template, eventType, and user or user_group"
7998+
}
7999+
}
8000+
},
8001+
"delete": {
8002+
"summary": "Delete Notification",
8003+
"description": "Removes the specified notification",
8004+
"requestBody": {
8005+
"description": "Notification data",
8006+
"required": true,
8007+
"content": {
8008+
"multipart/form-data": {
8009+
"schema": {
8010+
"type": "object",
8011+
"properties": {
8012+
"ident": {
8013+
"type": "string",
8014+
"format": "uuid",
8015+
"description": "The ident of the notification"
8016+
}
8017+
},
8018+
"required": ["ident"]
8019+
}
8020+
}
8021+
}
8022+
},
8023+
"tags": [
8024+
"Notifications"
8025+
],
8026+
"security": [
8027+
{
8028+
"basicAuth": []
8029+
}
8030+
],
8031+
"responses": {
8032+
"204": {
8033+
"description": "No content"
8034+
},
8035+
"401": {
8036+
"$ref": "#/components/responses/UnauthorizedError"
8037+
},
8038+
"404": {
8039+
"description": "Notification not found"
8040+
}
8041+
}
8042+
}
78858043
}
78868044
},
78878045
"externalDocs": {

0 commit comments

Comments
 (0)