Skip to content

Commit 1a9b26d

Browse files
authored
Merge pull request #20 from zjuasmn/dev
add seen notification server support
2 parents 4dda9ec + 40cfc23 commit 1a9b26d

File tree

7 files changed

+91
-0
lines changed

7 files changed

+91
-0
lines changed

docs/swagger_api.yaml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ paths:
7070
read:
7171
type: boolean
7272
description: read flag
73+
seen:
74+
type: boolean
75+
description: seen flag
7376
contents:
7477
type: object
7578
description: the event message in JSON format
@@ -152,6 +155,42 @@ paths:
152155
description: "Internal server error."
153156
schema:
154157
$ref: "#/definitions/Error"
158+
/notifications/{id}/seen:
159+
put:
160+
description:
161+
mark notification(s) as seen, id can be single id or '-' separated ids
162+
security:
163+
- jwt: []
164+
parameters:
165+
- in: path
166+
name: id
167+
description: notification id
168+
required: true
169+
type: integer
170+
format: int64
171+
responses:
172+
200:
173+
description: OK, the notification(s) are marked as seen
174+
400:
175+
description: "Invalid input"
176+
schema:
177+
$ref: "#/definitions/Error"
178+
401:
179+
description: "authentication failed"
180+
schema:
181+
$ref: "#/definitions/Error"
182+
403:
183+
description: "Action not allowed."
184+
schema:
185+
$ref: "#/definitions/Error"
186+
404:
187+
description: "Notification is not found"
188+
schema:
189+
$ref: "#/definitions/Error"
190+
500:
191+
description: "Internal server error."
192+
schema:
193+
$ref: "#/definitions/Error"
155194
/notificationsettings:
156195
get:
157196
description:

migrations/v1.2.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE public."Notifications"
2+
ADD COLUMN seen boolean;

src/app.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ function startKafkaConsumer(handlers) {
5656
version: notification.version || null,
5757
contents: _.extend({}, messageJSON, notification.contents),
5858
read: false,
59+
seen: false,
5960
}))))
6061
// commit offset
6162
.then(() => consumer.commitOffset({ topic, partition, offset: m.offset }))

src/controllers/NotificationController.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ function* markAllRead(req, res) {
3434
res.end();
3535
}
3636

37+
/**
38+
* Mark a notification as seen.
39+
* @param req the request
40+
* @param res the response
41+
*/
42+
function* markAsSeen(req, res) {
43+
yield NotificationService.markAsSeen(req.params.id, req.user.userId);
44+
res.end();
45+
}
46+
3747
/**
3848
* Get notification settings.
3949
* @param req the request
@@ -58,6 +68,7 @@ module.exports = {
5868
listNotifications,
5969
markAsRead,
6070
markAllRead,
71+
markAsSeen,
6172
getSettings,
6273
updateSettings,
6374
};

src/models/Notification.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module.exports = (sequelize, DataTypes) => sequelize.define('Notification', {
1616
type: { type: DataTypes.STRING, allowNull: false },
1717
contents: { type: DataTypes.JSONB, allowNull: false },
1818
read: { type: DataTypes.BOOLEAN, allowNull: false },
19+
seen: { type: DataTypes.BOOLEAN, allowNull: true },
1920
version: { type: DataTypes.SMALLINT, allowNull: true },
2021
}, {});
2122

src/routes.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ module.exports = {
1919
method: 'markAllRead',
2020
},
2121
},
22+
'/notifications/:id/seen': {
23+
put: {
24+
controller: 'NotificationController',
25+
method: 'markAsSeen',
26+
},
27+
},
2228
'/notificationsettings': {
2329
get: {
2430
controller: 'NotificationController',

src/services/NotificationService.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,36 @@ markAllRead.schema = {
174174
userId: Joi.number().required(),
175175
};
176176

177+
/**
178+
* Mark notification(s) as seen.
179+
* @param {Number} id the notification id or '-' separated ids
180+
* @param {Number} userId the user id
181+
*/
182+
function* markAsSeen(id, userId) {
183+
const ids = _.map(id.split('-'), (str) => {
184+
const idInt = Number(str);
185+
if (!_.isInteger(idInt)) {
186+
throw new errors.BadRequestError(`Notification id should be integer: ${str}`);
187+
}
188+
return idInt;
189+
});
190+
const entities = yield models.Notification.findAll({ where: { id: { $in: ids }, seen: { $not: true } } });
191+
if (!entities || entities.length === 0) {
192+
throw new errors.NotFoundError(`Cannot find un-seen Notification where id = ${id}`);
193+
}
194+
_.each(entities, (entity) => {
195+
if (Number(entity.userId) !== userId) {
196+
throw new errors.ForbiddenError(`Cannot access Notification where id = ${entity.id}`);
197+
}
198+
});
199+
yield models.Notification.update({ seen: true }, { where: { id: { $in: ids }, seen: { $not: true } } });
200+
}
201+
202+
markAsSeen.schema = {
203+
id: Joi.string().required(),
204+
userId: Joi.number().required(),
205+
};
206+
177207
updateSettings.schema = {
178208
data: Joi.array().min(1).items(Joi.object().keys({
179209
topic: Joi.string().required(),
@@ -188,6 +218,7 @@ module.exports = {
188218
listNotifications,
189219
markAsRead,
190220
markAllRead,
221+
markAsSeen,
191222
getSettings,
192223
updateSettings,
193224
};

0 commit comments

Comments
 (0)