| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- import logger from '@overleaf/logger'
- import { db, ObjectId } from './mongodb.js'
- export default {
- getUserNotifications(userId, callback) {
- if (callback == null) {
- callback = function () {}
- }
- const query = {
- user_id: new ObjectId(userId),
- templateKey: { $exists: true },
- }
- db.notifications.find(query).toArray(callback)
- },
- _countExistingNotifications(userId, notification, callback) {
- if (callback == null) {
- callback = function () {}
- }
- const query = {
- user_id: new ObjectId(userId),
- key: notification.key,
- }
- return db.notifications.count(query, function (err, count) {
- if (err != null) {
- return callback(err)
- }
- return callback(null, count)
- })
- },
- addNotification(userId, notification, callback) {
- return this._countExistingNotifications(
- userId,
- notification,
- function (err, count) {
- if (err != null) {
- return callback(err)
- }
- if (count !== 0 && !notification.forceCreate) {
- return callback()
- }
- const doc = {
- user_id: new ObjectId(userId),
- key: notification.key,
- messageOpts: notification.messageOpts,
- templateKey: notification.templateKey,
- }
- // TTL index on the optional `expires` field, which should arrive as an iso date-string, corresponding to
- // a datetime in the future when the document should be automatically removed.
- // in Mongo, TTL indexes only work on date fields, and ignore the document when that field is missing
- // see `README.md` for instruction on creating TTL index
- if (notification.expires != null) {
- try {
- doc.expires = new Date(notification.expires)
- const _testValue = doc.expires.toISOString()
- } catch (error) {
- err = error
- logger.error(
- { userId, expires: notification.expires },
- 'error converting `expires` field to Date'
- )
- return callback(err)
- }
- }
- db.notifications.updateOne(
- { user_id: doc.user_id, key: notification.key },
- { $set: doc },
- { upsert: true },
- callback
- )
- }
- )
- },
- removeNotificationId(userId, notificationId, callback) {
- const searchOps = {
- user_id: new ObjectId(userId),
- _id: new ObjectId(notificationId),
- }
- const updateOperation = { $unset: { templateKey: true, messageOpts: true } }
- db.notifications.updateOne(searchOps, updateOperation, callback)
- },
- removeNotificationKey(userId, notificationKey, callback) {
- const searchOps = {
- user_id: new ObjectId(userId),
- key: notificationKey,
- }
- const updateOperation = { $unset: { templateKey: true } }
- db.notifications.updateOne(searchOps, updateOperation, callback)
- },
- removeNotificationByKeyOnly(notificationKey, callback) {
- const searchOps = { key: notificationKey }
- const updateOperation = { $unset: { templateKey: true } }
- db.notifications.updateOne(searchOps, updateOperation, callback)
- },
- countNotificationsByKeyOnly(notificationKey, callback) {
- const searchOps = { key: notificationKey, templateKey: { $exists: true } }
- db.notifications.count(searchOps, callback)
- },
- deleteUnreadNotificationsByKeyOnlyBulk(notificationKey, callback) {
- if (typeof notificationKey !== 'string') {
- throw new Error('refusing to bulk delete arbitrary notifications')
- }
- const searchOps = { key: notificationKey, templateKey: { $exists: true } }
- db.notifications.deleteMany(searchOps, (err, result) => {
- if (err) return callback(err)
- callback(null, result.deletedCount)
- })
- },
- // hard delete of doc, rather than removing the templateKey
- deleteNotificationByKeyOnly(notificationKey, callback) {
- const searchOps = { key: notificationKey }
- db.notifications.deleteOne(searchOps, callback)
- },
- }
|