revisions.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. const loggerFactory = require('@alias/logger');
  2. const logger = loggerFactory('growi:routes:apiv3:pages');
  3. const express = require('express');
  4. const { query, param } = require('express-validator');
  5. const ErrorV3 = require('../../models/vo/error-apiv3');
  6. const router = express.Router();
  7. const PAGE_ITEMS = 30;
  8. /**
  9. * @swagger
  10. * tags:
  11. * name: Revisions
  12. */
  13. /**
  14. * @swagger
  15. *
  16. * components:
  17. * schemas:
  18. * Revision:
  19. * description: Revision
  20. * type: object
  21. * properties:
  22. * _id:
  23. * type: string
  24. * description: revision ID
  25. * example: 5e0734e472560e001761fa68
  26. * __v:
  27. * type: number
  28. * description: DB record version
  29. * example: 0
  30. * author:
  31. * $ref: '#/components/schemas/User/properties/_id'
  32. * body:
  33. * type: string
  34. * description: content body
  35. * example: |
  36. * # test
  37. *
  38. * test
  39. * format:
  40. * type: string
  41. * description: format
  42. * example: markdown
  43. * path:
  44. * type: string
  45. * description: path
  46. * example: /user/alice/test
  47. * createdAt:
  48. * type: string
  49. * description: date created at
  50. * example: 2010-01-01T00:00:00.000Z
  51. */
  52. module.exports = (crowi) => {
  53. const certifySharedPage = require('../../middlewares/certify-shared-page')(crowi);
  54. const accessTokenParser = require('../../middlewares/access-token-parser')(crowi);
  55. const loginRequired = require('../../middlewares/login-required')(crowi, true);
  56. const apiV3FormValidator = require('../../middlewares/apiv3-form-validator')(crowi);
  57. const {
  58. Revision,
  59. Page,
  60. User,
  61. } = crowi.models;
  62. const validator = {
  63. retrieveRevisions: [
  64. query('pageId').isMongoId().withMessage('pageId is required'),
  65. query('selectedPage').isInt({ min: 0 }).withMessage('selectedPage must be int'),
  66. ],
  67. retrieveRevisionById: [
  68. query('pageId').isMongoId().withMessage('pageId is required'),
  69. param('id').isMongoId().withMessage('id is required'),
  70. ],
  71. };
  72. /**
  73. * @swagger
  74. *
  75. * /revisions/list:
  76. * get:
  77. * tags: [Revisions]
  78. * description: Get revisions by page id
  79. * parameters:
  80. * - in: query
  81. * name: pageId
  82. * schema:
  83. * type: string
  84. * description: page id
  85. * responses:
  86. * 200:
  87. * description: Return revisions belong to page
  88. *
  89. */
  90. router.get('/list', certifySharedPage, accessTokenParser, loginRequired, validator.retrieveRevisions, apiV3FormValidator, async(req, res) => {
  91. const pageId = req.query.pageId;
  92. const { isSharedPage } = req;
  93. const selectedPage = parseInt(req.query.selectedPage) || 1;
  94. // check whether accessible
  95. if (!isSharedPage && !(await Page.isAccessiblePageByViewer(pageId, req.user))) {
  96. return res.apiv3Err(new ErrorV3('Current user is not accessible to this page.', 'forbidden-page'), 403);
  97. }
  98. try {
  99. const page = await Page.findOne({ _id: pageId });
  100. const paginateResult = await Revision.paginate(
  101. { path: page.path },
  102. {
  103. page: selectedPage,
  104. limit: PAGE_ITEMS,
  105. sort: { createdAt: -1 },
  106. populate: {
  107. path: 'author',
  108. select: User.USER_PUBLIC_FIELDS,
  109. },
  110. },
  111. );
  112. return res.apiv3(paginateResult);
  113. }
  114. catch (err) {
  115. const msg = 'Error occurred in getting revisions by poge id';
  116. logger.error('Error', err);
  117. return res.apiv3Err(new ErrorV3(msg, 'faild-to-find-revisions'), 500);
  118. }
  119. });
  120. /**
  121. * @swagger
  122. *
  123. * /revisions/{id}:
  124. * get:
  125. * tags: [Revisions]
  126. * description: Get one revision by id
  127. * parameters:
  128. * - in: query
  129. * name: pageId
  130. * required: true
  131. * description: page id
  132. * schema:
  133. * type: string
  134. * - in: path
  135. * name: id
  136. * required: true
  137. * description: revision id
  138. * schema:
  139. * type: string
  140. * responses:
  141. * 200:
  142. * description: Return revision
  143. *
  144. */
  145. router.get('/:id', certifySharedPage, accessTokenParser, loginRequired, validator.retrieveRevisionById, apiV3FormValidator, async(req, res) => {
  146. const revisionId = req.params.id;
  147. const pageId = req.query.pageId;
  148. const { isSharedPage } = req;
  149. // check whether accessible
  150. if (!isSharedPage && !(await Page.isAccessiblePageByViewer(pageId, req.user))) {
  151. return res.apiv3Err(new ErrorV3('Current user is not accessible to this page.', 'forbidden-page'), 403);
  152. }
  153. try {
  154. const revision = await Revision.findById(revisionId).populate('author', User.USER_PUBLIC_FIELDS);
  155. return res.apiv3({ revision });
  156. }
  157. catch (err) {
  158. const msg = 'Error occurred in getting revision data by id';
  159. logger.error('Error', err);
  160. return res.apiv3Err(new ErrorV3(msg, 'faild-to-find-revision'), 500);
  161. }
  162. });
  163. return router;
  164. };