pages.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. const loggerFactory = require('@alias/logger');
  2. const logger = loggerFactory('growi:routes:apiv3:pages'); // eslint-disable-line no-unused-vars
  3. const express = require('express');
  4. const pathUtils = require('growi-commons').pathUtils;
  5. const router = express.Router();
  6. /**
  7. * @swagger
  8. * tags:
  9. * name: Pages
  10. */
  11. module.exports = (crowi) => {
  12. const accessTokenParser = require('../../middlewares/access-token-parser')(crowi);
  13. const loginRequired = require('../../middlewares/login-required')(crowi, true);
  14. const loginRequiredStrictly = require('../../middlewares/login-required')(crowi, true);
  15. const adminRequired = require('../../middlewares/admin-required')(crowi);
  16. const csrf = require('../../middlewares/csrf')(crowi);
  17. const Page = crowi.model('Page');
  18. const PageTagRelation = crowi.model('PageTagRelation');
  19. const GlobalNotificationSetting = crowi.model('GlobalNotificationSetting');
  20. const pageService = crowi.pageService;
  21. const globalNotificationService = crowi.getGlobalNotificationService();
  22. // TODO swagger and validation
  23. router.post('/', accessTokenParser, loginRequiredStrictly, csrf, async(req, res) => {
  24. const {
  25. body, grant, grantUserGroupId, overwriteScopesOfDescendants, isSlackEnabled, slackChannels, socketClientId, pageTags,
  26. } = req.body;
  27. let pagePath = req.body.path;
  28. // check whether path starts slash
  29. pagePath = pathUtils.addHeadingSlash(pagePath);
  30. // check page existence
  31. const isExist = await Page.count({ path: pagePath }) > 0;
  32. if (isExist) {
  33. return res.apiv3Err(err, 409);
  34. }
  35. const options = { socketClientId };
  36. if (grant != null) {
  37. options.grant = grant;
  38. options.grantUserGroupId = grantUserGroupId;
  39. }
  40. const createdPage = await Page.create(pagePath, body, req.user, options);
  41. let savedTags;
  42. if (pageTags != null) {
  43. await PageTagRelation.updatePageTags(createdPage.id, pageTags);
  44. savedTags = await PageTagRelation.listTagNamesByPage(createdPage.id);
  45. }
  46. const result = { page: pageService.serializeToObj(createdPage), tags: savedTags };
  47. // update scopes for descendants
  48. if (overwriteScopesOfDescendants) {
  49. Page.applyScopesToDescendantsAsyncronously(createdPage, req.user);
  50. }
  51. // global notification
  52. try {
  53. await globalNotificationService.fire(GlobalNotificationSetting.EVENT.PAGE_CREATE, createdPage, req.user);
  54. }
  55. catch (err) {
  56. logger.error('Create notification failed', err);
  57. }
  58. // user notification
  59. if (isSlackEnabled) {
  60. await notifyToSlackByUser(createdPage, req.user, slackChannels, 'create', false);
  61. }
  62. return res.apiv3(result);
  63. });
  64. /**
  65. * @swagger
  66. *
  67. * /pages/recent:
  68. * get:
  69. * tags: [Pages]
  70. * description: Get recently updated pages
  71. * responses:
  72. * 200:
  73. * description: Return pages recently updated
  74. *
  75. */
  76. router.get('/recent', loginRequired, async(req, res) => {
  77. const limit = 20;
  78. const offset = parseInt(req.query.offset) || 0;
  79. const queryOptions = {
  80. offset,
  81. limit,
  82. includeTrashed: false,
  83. isRegExpEscapedFromPath: true,
  84. sort: 'updatedAt',
  85. desc: -1,
  86. };
  87. try {
  88. const result = await Page.findListWithDescendants('/', req.user, queryOptions);
  89. if (result.pages.length > limit) {
  90. result.pages.pop();
  91. }
  92. return res.apiv3(result);
  93. }
  94. catch (err) {
  95. res.code = 'unknown';
  96. logger.error('Failed to get recent pages', err);
  97. return res.apiv3Err(err, 500);
  98. }
  99. });
  100. /**
  101. * @swagger
  102. *
  103. * /pages/empty-trash:
  104. * delete:
  105. * tags: [Pages]
  106. * description: empty trash
  107. * responses:
  108. * 200:
  109. * description: Succeeded to remove all trash pages
  110. */
  111. router.delete('/empty-trash', loginRequired, adminRequired, csrf, async(req, res) => {
  112. try {
  113. const pages = await Page.completelyDeletePageRecursively('/trash', req.user);
  114. return res.apiv3({ pages });
  115. }
  116. catch (err) {
  117. res.code = 'unknown';
  118. logger.error('Failed to delete trash pages', err);
  119. return res.apiv3Err(err, 500);
  120. }
  121. });
  122. router.get('/subordinated-list', accessTokenParser, loginRequired, async(req, res) => {
  123. const { path } = req.query;
  124. try {
  125. const pageData = await Page.findByPath(path);
  126. const result = await Page.findManageableListWithDescendants(pageData, req.user);
  127. const resultPaths = result.map(element => element.path);
  128. return res.apiv3({ resultPaths });
  129. }
  130. catch (err) {
  131. res.code = 'unknown';
  132. logger.error('Failed to find the path', err);
  133. return res.apiv3Err(err, 500);
  134. }
  135. });
  136. return router;
  137. };