bookmark.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // disable no-return-await for model functions
  2. /* eslint-disable no-return-await */
  3. module.exports = function(crowi) {
  4. const debug = require('debug')('growi:models:bookmark');
  5. const mongoose = require('mongoose');
  6. const ObjectId = mongoose.Schema.Types.ObjectId;
  7. const bookmarkEvent = crowi.event('bookmark');
  8. let bookmarkSchema = null;
  9. bookmarkSchema = new mongoose.Schema({
  10. page: { type: ObjectId, ref: 'Page', index: true },
  11. user: { type: ObjectId, ref: 'User', index: true },
  12. createdAt: { type: Date, default: Date.now },
  13. });
  14. bookmarkSchema.index({ page: 1, user: 1 }, { unique: true });
  15. bookmarkSchema.statics.countByPageId = async function(pageId) {
  16. return await this.count({ page: pageId });
  17. };
  18. /**
  19. * @return {object} key: page._id, value: bookmark count
  20. */
  21. bookmarkSchema.statics.getPageIdToCountMap = async function(pageIds) {
  22. const results = await this.aggregate()
  23. .match({ page: { $in: pageIds } })
  24. .group({ _id: '$page', count: { $sum: 1 } });
  25. // convert to map
  26. const idToCountMap = {};
  27. results.forEach((result) => {
  28. idToCountMap[result._id] = result.count;
  29. });
  30. return idToCountMap;
  31. };
  32. bookmarkSchema.statics.populatePage = async function(bookmarks) {
  33. const Bookmark = this;
  34. const User = crowi.model('User');
  35. return Bookmark.populate(bookmarks, [
  36. { path: 'page' },
  37. { path: 'lastUpdateUser', model: 'User', select: User.USER_PUBLIC_FIELDS },
  38. ]);
  39. };
  40. // bookmark チェック用
  41. bookmarkSchema.statics.findByPageIdAndUserId = function(pageId, userId) {
  42. const Bookmark = this;
  43. return new Promise(((resolve, reject) => {
  44. return Bookmark.findOne({ page: pageId, user: userId }, (err, doc) => {
  45. if (err) {
  46. return reject(err);
  47. }
  48. return resolve(doc);
  49. });
  50. }));
  51. };
  52. /**
  53. * option = {
  54. * limit: Int
  55. * offset: Int
  56. * requestUser: User
  57. * }
  58. */
  59. bookmarkSchema.statics.findByUser = function(user, option) {
  60. const Bookmark = this;
  61. const requestUser = option.requestUser || null;
  62. debug('Finding bookmark with requesting user:', requestUser);
  63. const limit = option.limit || 50;
  64. const offset = option.offset || 0;
  65. const populatePage = option.populatePage || false;
  66. return new Promise(((resolve, reject) => {
  67. Bookmark
  68. .find({ user: user._id })
  69. .sort({ createdAt: -1 })
  70. .skip(offset)
  71. .limit(limit)
  72. .exec((err, bookmarks) => {
  73. if (err) {
  74. return reject(err);
  75. }
  76. if (!populatePage) {
  77. return resolve(bookmarks);
  78. }
  79. return Bookmark.populatePage(bookmarks, requestUser).then(resolve);
  80. });
  81. }));
  82. };
  83. bookmarkSchema.statics.add = async function(page, user) {
  84. const Bookmark = this;
  85. const newBookmark = new Bookmark({ page, user, createdAt: Date.now() });
  86. try {
  87. const bookmark = await newBookmark.save();
  88. bookmarkEvent.emit('create', page._id);
  89. return bookmark;
  90. }
  91. catch (err) {
  92. if (err.code === 11000) {
  93. // duplicate key (dummy response of new object)
  94. return newBookmark;
  95. }
  96. debug('Bookmark.save failed', err);
  97. throw err;
  98. }
  99. };
  100. /**
  101. * Remove bookmark
  102. * used only when removing the page
  103. * @param {string} pageId
  104. */
  105. bookmarkSchema.statics.removeBookmarksByPageId = async function(pageId) {
  106. const Bookmark = this;
  107. try {
  108. const data = await Bookmark.remove({ page: pageId });
  109. bookmarkEvent.emit('delete', pageId);
  110. return data;
  111. }
  112. catch (err) {
  113. debug('Bookmark.remove failed (removeBookmarkByPage)', err);
  114. throw err;
  115. }
  116. };
  117. bookmarkSchema.statics.removeBookmark = async function(pageId, user) {
  118. const Bookmark = this;
  119. try {
  120. const data = await Bookmark.findOneAndRemove({ page: pageId, user });
  121. bookmarkEvent.emit('delete', pageId);
  122. return data;
  123. }
  124. catch (err) {
  125. debug('Bookmark.findOneAndRemove failed', err);
  126. throw err;
  127. }
  128. };
  129. return mongoose.model('Bookmark', bookmarkSchema);
  130. };