index.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. const nodePath = require('path');
  2. const { pathUtils } = require('@growi/core/dist/utils');
  3. const mongoose = require('mongoose');
  4. /**
  5. * parent schema for GlobalNotificationSetting model
  6. */
  7. const globalNotificationSettingSchema = new mongoose.Schema({
  8. isEnabled: { type: Boolean, required: true, default: true },
  9. triggerPath: { type: String, required: true },
  10. triggerEvents: { type: [String] },
  11. });
  12. /*
  13. * e.g. "/a/b/c" => ["/a/b/c", "/a/b", "/a", "/"]
  14. */
  15. const generatePathsOnTree = (path, pathList) => {
  16. pathList.push(path);
  17. if (path === '/') {
  18. return pathList;
  19. }
  20. const newPath = nodePath.posix.dirname(path);
  21. return generatePathsOnTree(newPath, pathList);
  22. };
  23. /*
  24. * e.g. "/a/b/c" => ["/a/b/c", "/a/b", "/a", "/"]
  25. */
  26. const generatePathsToMatch = (originalPath) => {
  27. const pathList = generatePathsOnTree(originalPath, []);
  28. return pathList.map((path) => {
  29. // except for the original trigger path ("/a/b/c"), append "*" to find all matches
  30. // e.g. ["/a/b/c", "/a/b", "/a", "/"] => ["/a/b/c", "/a/b/*", "/a/*", "/*"]
  31. if (path !== originalPath) {
  32. return `${pathUtils.addTrailingSlash(path)}*`;
  33. }
  34. return path;
  35. });
  36. };
  37. /**
  38. * GlobalNotificationSetting Class
  39. * @class GlobalNotificationSetting
  40. */
  41. class GlobalNotificationSetting {
  42. /** @type {import('~/server/crowi').default} Crowi instance */
  43. crowi;
  44. /** @param {import('~/server/crowi').default} crowi Crowi instance */
  45. constructor(crowi) {
  46. this.crowi = crowi;
  47. }
  48. /**
  49. * enable notification setting
  50. * @param {string} id
  51. */
  52. static async enable(id) {
  53. // biome-ignore lint/complexity/noThisInStatic: 'this' refers to the mongoose model here, not the class defined in this file
  54. const setting = await this.findOne({ _id: id });
  55. setting.isEnabled = true;
  56. setting.save();
  57. return setting;
  58. }
  59. /**
  60. * disable notification setting
  61. * @param {string} id
  62. */
  63. static async disable(id) {
  64. // biome-ignore lint/complexity/noThisInStatic: 'this' refers to the mongoose model here, not the class defined in this file
  65. const setting = await this.findOne({ _id: id });
  66. setting.isEnabled = false;
  67. setting.save();
  68. return setting;
  69. }
  70. /**
  71. * find all notification settings
  72. */
  73. static async findAll() {
  74. // biome-ignore lint/complexity/noThisInStatic: 'this' refers to the mongoose model here, not the class defined in this file
  75. const settings = await this.find().sort({
  76. triggerPath: 1,
  77. });
  78. return settings;
  79. }
  80. /**
  81. * find a list of notification settings by path and a list of events
  82. * @param {string} path
  83. * @param {string} event
  84. */
  85. static async findSettingByPathAndEvent(event, path, type) {
  86. const pathsToMatch = generatePathsToMatch(path);
  87. // biome-ignore lint/complexity/noThisInStatic: 'this' refers to the mongoose model here, not the class defined in this file
  88. const settings = await this.find({
  89. triggerPath: { $in: pathsToMatch },
  90. triggerEvents: event,
  91. __t: type,
  92. isEnabled: true,
  93. }).sort({ triggerPath: 1 });
  94. return settings;
  95. }
  96. }
  97. module.exports = {
  98. class: GlobalNotificationSetting,
  99. schema: globalNotificationSettingSchema,
  100. };