You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
3.8 KiB
142 lines
3.8 KiB
// user-notification.js
|
|
// Copyright (C) 2022 DTP Technologies, LLC
|
|
// License: Apache-2.0
|
|
|
|
'use strict';
|
|
|
|
const path = require('path');
|
|
|
|
const mongoose = require('mongoose');
|
|
const UserNotification = mongoose.model('UserNotification');
|
|
|
|
const pug = require('pug');
|
|
|
|
const { SiteService } = require('../../lib/site-lib');
|
|
|
|
class UserNotificationService extends SiteService {
|
|
|
|
constructor (dtp) {
|
|
super(dtp, module.exports);
|
|
this.populateUserNotification = [
|
|
{
|
|
path: 'user',
|
|
select: '_id username username_lc displayName picture',
|
|
},
|
|
{
|
|
path: 'event',
|
|
populate: [
|
|
{
|
|
path: 'attachment',
|
|
},
|
|
],
|
|
},
|
|
];
|
|
}
|
|
|
|
async start ( ) {
|
|
await super.start();
|
|
this.templates = { };
|
|
this.templates.notification = pug.compileFile(path.join(this.dtp.config.root, 'app', 'views', 'notification', 'components', 'notification-standalone.pug'));
|
|
}
|
|
|
|
middleware (options) {
|
|
options = Object.assign({
|
|
withNotifications: false,
|
|
}, options || { });
|
|
return async (req, res, next) => {
|
|
res.locals.middleware = res.locals.middleware || { };
|
|
const data = res.locals.middleware.notifications = { };
|
|
if (!req.user) {
|
|
// requests with no user don't matter to this middleware
|
|
return next();
|
|
}
|
|
try {
|
|
data.newCount = await this.getNewCountForUser(req.user);
|
|
if (options.withNotifications) {
|
|
data.new = await this.getForUser(req.user, { skip: 0, cpp: 10 });
|
|
}
|
|
return next();
|
|
} catch (error) {
|
|
this.log.error('failed to populate route with notifications data', { error });
|
|
return next(error);
|
|
}
|
|
};
|
|
}
|
|
|
|
async create (user, event) {
|
|
const notification = new UserNotification();
|
|
notification.created = event.created;
|
|
notification.user = user._id;
|
|
notification.status = 'new';
|
|
notification.event = event._id;
|
|
await notification.save();
|
|
|
|
await this.dtp.redis.hincrby(`user:${user._id}:notification`, 'newCount', 1);
|
|
|
|
return notification.toObject();
|
|
}
|
|
|
|
async getNewCountForUser (user) {
|
|
const userKey = `user:${user._id}:notification`;
|
|
let count;
|
|
|
|
const value = await this.dtp.redis.hget(userKey, 'newCount');
|
|
if (!value) {
|
|
count = await UserNotification.countDocuments({ user: user._id, status: 'new' });
|
|
await this.dtp.redis.hset(userKey, 'newCount', count);
|
|
return count;
|
|
}
|
|
|
|
count = parseInt(value, 10);
|
|
if (count < 0) {
|
|
count = await UserNotification.countDocuments({ user: user._id, status: 'new' });
|
|
await this.dtp.redis.hset(userKey, 'newCount', count);
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
async getForUser (user, pagination) {
|
|
const notifications = await UserNotification
|
|
.find({ user: user._id })
|
|
.sort({ created: -1 })
|
|
.skip(pagination.skip)
|
|
.limit(pagination.cpp)
|
|
.populate(this.populateUserNotification)
|
|
.lean();
|
|
|
|
const newNotifications = notifications.filter((notif) => notif.status === 'new');
|
|
if (newNotifications.length > 0) {
|
|
await UserNotification.updateMany(
|
|
{ _id: { $in: newNotifications.map((notif) => notif._id) } },
|
|
{ $set: { status: 'seen' } },
|
|
);
|
|
await this.dtp.redis.hincrby(
|
|
`user:${user._id}:notification`,
|
|
'newCount',
|
|
-(newNotifications.length),
|
|
);
|
|
}
|
|
|
|
return notifications;
|
|
}
|
|
|
|
async getById (notificationId) {
|
|
const notification = await UserNotification
|
|
.findById(notificationId)
|
|
.populate(this.populateUserNotification)
|
|
.lean();
|
|
return notification;
|
|
}
|
|
|
|
async removeForUser (user) {
|
|
await UserNotification.deleteMany({ user: user._id });
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
logId: 'svc:user-notification',
|
|
index: 'userNotification',
|
|
className: 'UserNotificationService',
|
|
create: (dtp) => { return new UserNotificationService(dtp); },
|
|
};
|