bookmarks.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. const loggerFactory = require('@alias/logger');
  2. const logger = loggerFactory('growi:routes:apiv3:bookmarks'); // eslint-disable-line no-unused-vars
  3. const express = require('express');
  4. const { body, query } = require('express-validator');
  5. const router = express.Router();
  6. /**
  7. * @swagger
  8. * tags:
  9. * name: Bookmarks
  10. */
  11. /**
  12. * @swagger
  13. *
  14. * components:
  15. * schemas:
  16. * Bookmark:
  17. * description: Bookmark
  18. * type: object
  19. * properties:
  20. * _id:
  21. * type: string
  22. * description: page ID
  23. * example: 5e07345972560e001761fa63
  24. * __v:
  25. * type: number
  26. * description: DB record version
  27. * example: 0
  28. * createdAt:
  29. * type: string
  30. * description: date created at
  31. * example: 2010-01-01T00:00:00.000Z
  32. * page:
  33. * $ref: '#/components/schemas/Page/properties/_id'
  34. * user:
  35. * $ref: '#/components/schemas/User/properties/_id'
  36. *
  37. * BookmarkParams:
  38. * description: BookmarkParams
  39. * type: object
  40. * properties:
  41. * pageId:
  42. * type: string
  43. * description: page ID
  44. * example: 5e07345972560e001761fa63
  45. * bool:
  46. * type: boolean
  47. * description: boolean for bookmark status
  48. */
  49. module.exports = (crowi) => {
  50. const accessTokenParser = require('../../middlewares/access-token-parser')(crowi);
  51. const loginRequired = require('../../middlewares/login-required')(crowi);
  52. const csrf = require('../../middlewares/csrf')(crowi);
  53. const apiV3FormValidator = require('../../middlewares/apiv3-form-validator')(crowi);
  54. const { Page, Bookmark, User } = crowi.models;
  55. const validator = {
  56. bookmarks: [
  57. body('pageId').isString(),
  58. body('bool').isBoolean(),
  59. ],
  60. bookmarkInfo: [
  61. query('pageId').isMongoId(),
  62. ],
  63. };
  64. /**
  65. * @swagger
  66. *
  67. * /bookmarks:
  68. * get:
  69. * tags: [Bookmarks]
  70. * summary: /bookmarks
  71. * description: Get bookmarked status
  72. * operationId: getBookmarkedStatus
  73. * parameters:
  74. * - name: pageId
  75. * in: query
  76. * description: page id
  77. * schema:
  78. * type: string
  79. * responses:
  80. * 200:
  81. * description: Succeeded to get bookmarked status.
  82. * content:
  83. * application/json:
  84. * schema:
  85. * $ref: '#/components/schemas/Bookmark'
  86. */
  87. router.get('/', accessTokenParser, loginRequired, validator.bookmarkInfo, async(req, res) => {
  88. const { pageId } = req.query;
  89. try {
  90. const bookmarks = await Bookmark.findByPageIdAndUserId(pageId, req.user);
  91. const sumOfBookmarks = await Bookmark.countByPageId(pageId);
  92. return res.apiv3({ bookmarks, sumOfBookmarks });
  93. }
  94. catch (err) {
  95. logger.error('get-bookmark-failed', err);
  96. return res.apiv3Err(err, 500);
  97. }
  98. });
  99. // select page from bookmark where userid = userid
  100. /**
  101. * @swagger
  102. *
  103. * /bookmarks/{userId}:
  104. * get:
  105. * tags: [Bookmarks]
  106. * summary: /bookmarks/{userId}
  107. * description: Get my bookmarked status
  108. * operationId: getMyBookmarkedStatus
  109. * parameters:
  110. * - name: userId
  111. * in: path
  112. * required: true
  113. * description: user id
  114. * schema:
  115. * type: string
  116. * - name: page
  117. * in: query
  118. * description: selected page number
  119. * schema:
  120. * type: number
  121. * - name: limit
  122. * in: query
  123. * description: page item limit
  124. * schema:
  125. * type: number
  126. * - name: offset
  127. * in: query
  128. * description: page item offset
  129. * schema:
  130. * type: number
  131. * responses:
  132. * 200:
  133. * description: Succeeded to get my bookmarked status.
  134. * content:
  135. * application/json:
  136. * schema:
  137. * $ref: '#/components/schemas/Bookmark'
  138. */
  139. validator.myBookmarkList = [
  140. query('page').isInt({ min: 1 }),
  141. query('limit').if(value => value != null).isInt({ max: 300 }).withMessage('You should set less than 300 or not to set limit.'),
  142. ];
  143. router.get('/:userId', accessTokenParser, loginRequired, validator.myBookmarkList, apiV3FormValidator, async(req, res) => {
  144. const { userId } = req.params;
  145. const page = req.query.page;
  146. const limit = parseInt(req.query.limit) || await crowi.configManager.getConfig('crowi', 'customize:showPageLimitationM') || 30;
  147. if (userId == null) {
  148. return res.apiv3Err('User id is not found or forbidden', 400);
  149. }
  150. if (limit == null) {
  151. return res.apiv3Err('Could not catch page limit', 400);
  152. }
  153. try {
  154. const paginationResult = await Bookmark.paginate(
  155. {
  156. user: { $in: userId },
  157. },
  158. {
  159. populate: {
  160. path: 'page',
  161. model: 'Page',
  162. populate: {
  163. path: 'lastUpdateUser',
  164. model: 'User',
  165. select: User.USER_PUBLIC_FIELDS,
  166. },
  167. },
  168. page,
  169. limit,
  170. },
  171. );
  172. return res.apiv3({ paginationResult });
  173. }
  174. catch (err) {
  175. logger.error('get-bookmark-failed', err);
  176. return res.apiv3Err(err, 500);
  177. }
  178. });
  179. /**
  180. * @swagger
  181. *
  182. * /bookmarks:
  183. * put:
  184. * tags: [Bookmarks]
  185. * summary: /bookmarks
  186. * description: Update bookmarked status
  187. * operationId: updateBookmarkedStatus
  188. * requestBody:
  189. * content:
  190. * application/json:
  191. * schema:
  192. * $ref: '#/components/schemas/BookmarkParams'
  193. * responses:
  194. * 200:
  195. * description: Succeeded to update bookmarked status.
  196. * content:
  197. * application/json:
  198. * schema:
  199. * $ref: '#/components/schemas/Bookmark'
  200. */
  201. router.put('/', accessTokenParser, loginRequired, csrf, validator.bookmarks, apiV3FormValidator, async(req, res) => {
  202. const { pageId, bool } = req.body;
  203. let bookmark;
  204. try {
  205. const page = await Page.findByIdAndViewer(pageId, req.user);
  206. if (page == null) {
  207. return res.apiv3Err(`Page '${pageId}' is not found or forbidden`);
  208. }
  209. if (bool) {
  210. bookmark = await Bookmark.add(page, req.user);
  211. }
  212. else {
  213. bookmark = await Bookmark.removeBookmark(page, req.user);
  214. }
  215. }
  216. catch (err) {
  217. logger.error('update-bookmark-failed', err);
  218. return res.apiv3Err(err, 500);
  219. }
  220. bookmark.depopulate('page');
  221. bookmark.depopulate('user');
  222. return res.apiv3({ bookmark });
  223. });
  224. /**
  225. * @swagger
  226. *
  227. * /count-bookmarks:
  228. * get:
  229. * tags: [Bookmarks]
  230. * summary: /bookmarks
  231. * description: Count bookmsrks
  232. * requestBody:
  233. * content:
  234. * application/json:
  235. * schema:
  236. * $ref: '#/components/schemas/BookmarkParams'
  237. * responses:
  238. * 200:
  239. * description: Succeeded to count bookmarks.
  240. * content:
  241. * application/json:
  242. * schema:
  243. * $ref: '#/components/schemas/Bookmark'
  244. */
  245. return router;
  246. };