markdown-setting.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. const loggerFactory = require('@alias/logger');
  2. const logger = loggerFactory('growi:routes:apiv3:markdown-setting');
  3. const express = require('express');
  4. const router = express.Router();
  5. const { body } = require('express-validator');
  6. const ErrorV3 = require('../../models/vo/error-apiv3');
  7. const validator = {
  8. lineBreak: [
  9. body('isEnabledLinebreaks').isBoolean(),
  10. body('isEnabledLinebreaksInComments').isBoolean(),
  11. ],
  12. indent: [
  13. body('adminPreferredIndentSize').isIn([2, 4]),
  14. body('isIndentSizeForced').isBoolean(),
  15. ],
  16. presentationSetting: [
  17. body('pageBreakSeparator').isInt().not().isEmpty(),
  18. ],
  19. xssSetting: [
  20. body('isEnabledXss').isBoolean(),
  21. body('tagWhiteList').isArray(),
  22. body('attrWhiteList').isArray(),
  23. ],
  24. };
  25. /**
  26. * @swagger
  27. * tags:
  28. * name: MarkDownSetting
  29. */
  30. /**
  31. * @swagger
  32. *
  33. * components:
  34. * schemas:
  35. * LineBreakParams:
  36. * description: LineBreakParams
  37. * type: object
  38. * properties:
  39. * isEnabledLinebreaks:
  40. * type: boolean
  41. * description: enable lineBreak
  42. * isEnabledLinebreaksInComments:
  43. * type: boolean
  44. * description: enable lineBreak in comment
  45. * PresentationParams:
  46. * description: PresentationParams
  47. * type: object
  48. * properties:
  49. * pageBreakSeparator:
  50. * type: number
  51. * description: number of pageBreakSeparator
  52. * pageBreakCustomSeparator:
  53. * type: string
  54. * description: string of pageBreakCustomSeparator
  55. * XssParams:
  56. * description: XssParams
  57. * type: object
  58. * properties:
  59. * isEnabledPrevention:
  60. * type: boolean
  61. * description: enable xss
  62. * xssOption:
  63. * type: number
  64. * description: number of xss option
  65. * tagWhiteList:
  66. * type: array
  67. * description: array of tag whiteList
  68. * items:
  69. * type: string
  70. * description: tag whitelist
  71. * attrWhiteList:
  72. * type: array
  73. * description: array of attr whiteList
  74. * items:
  75. * type: string
  76. * description: attr whitelist
  77. */
  78. module.exports = (crowi) => {
  79. const loginRequiredStrictly = require('../../middlewares/login-required')(crowi);
  80. const adminRequired = require('../../middlewares/admin-required')(crowi);
  81. const csrf = require('../../middlewares/csrf')(crowi);
  82. const apiV3FormValidator = require('../../middlewares/apiv3-form-validator')(crowi);
  83. /**
  84. * @swagger
  85. *
  86. * /markdown-setting:
  87. * get:
  88. * tags: [MarkDownSetting]
  89. * operationId: getMarkdownSetting
  90. * summary: /markdown-setting
  91. * description: Get markdown parameters
  92. * responses:
  93. * 200:
  94. * description: params of markdown
  95. * content:
  96. * application/json:
  97. * schema:
  98. * properties:
  99. * markdownParams:
  100. * type: object
  101. * description: markdown params
  102. */
  103. router.get('/', loginRequiredStrictly, adminRequired, async(req, res) => {
  104. const markdownParams = {
  105. isEnabledLinebreaks: await crowi.configManager.getConfig('markdown', 'markdown:isEnabledLinebreaks'),
  106. isEnabledLinebreaksInComments: await crowi.configManager.getConfig('markdown', 'markdown:isEnabledLinebreaksInComments'),
  107. adminPreferredIndentSize: await crowi.configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize'),
  108. isIndentSizeForced: await crowi.configManager.getConfig('markdown', 'markdown:isIndentSizeForced'),
  109. pageBreakSeparator: await crowi.configManager.getConfig('markdown', 'markdown:presentation:pageBreakSeparator'),
  110. pageBreakCustomSeparator: await crowi.configManager.getConfig('markdown', 'markdown:presentation:pageBreakCustomSeparator'),
  111. isEnabledXss: await crowi.configManager.getConfig('markdown', 'markdown:xss:isEnabledPrevention'),
  112. xssOption: await crowi.configManager.getConfig('markdown', 'markdown:xss:option'),
  113. tagWhiteList: await crowi.configManager.getConfig('markdown', 'markdown:xss:tagWhiteList'),
  114. attrWhiteList: await crowi.configManager.getConfig('markdown', 'markdown:xss:attrWhiteList'),
  115. };
  116. return res.apiv3({ markdownParams });
  117. });
  118. /**
  119. * @swagger
  120. *
  121. * /markdown-setting/lineBreak:
  122. * put:
  123. * tags: [MarkDownSetting]
  124. * operationId: updateLineBreakMarkdownSetting
  125. * summary: /markdown-setting/lineBreak
  126. * description: Update lineBreak setting
  127. * requestBody:
  128. * required: true
  129. * content:
  130. * application/json:
  131. * schema:
  132. * $ref: '#/components/schemas/LineBreakParams'
  133. * responses:
  134. * 200:
  135. * description: Succeeded to update lineBreak setting
  136. * content:
  137. * application/json:
  138. * schema:
  139. * $ref: '#/components/schemas/LineBreakParams'
  140. */
  141. router.put('/lineBreak', loginRequiredStrictly, adminRequired, csrf, validator.lineBreak, apiV3FormValidator, async(req, res) => {
  142. const requestLineBreakParams = {
  143. 'markdown:isEnabledLinebreaks': req.body.isEnabledLinebreaks,
  144. 'markdown:isEnabledLinebreaksInComments': req.body.isEnabledLinebreaksInComments,
  145. };
  146. try {
  147. await crowi.configManager.updateConfigsInTheSameNamespace('markdown', requestLineBreakParams);
  148. const lineBreaksParams = {
  149. isEnabledLinebreaks: await crowi.configManager.getConfig('markdown', 'markdown:isEnabledLinebreaks'),
  150. isEnabledLinebreaksInComments: await crowi.configManager.getConfig('markdown', 'markdown:isEnabledLinebreaksInComments'),
  151. };
  152. return res.apiv3({ lineBreaksParams });
  153. }
  154. catch (err) {
  155. const msg = 'Error occurred in updating lineBreak';
  156. logger.error('Error', err);
  157. return res.apiv3Err(new ErrorV3(msg, 'update-lineBreak-failed'));
  158. }
  159. });
  160. router.put('/indent', loginRequiredStrictly, adminRequired, csrf, validator.indent, apiV3FormValidator, async(req, res) => {
  161. const requestIndentParams = {
  162. 'markdown:adminPreferredIndentSize': req.body.adminPreferredIndentSize,
  163. 'markdown:isIndentSizeForced': req.body.isIndentSizeForced,
  164. };
  165. try {
  166. await crowi.configManager.updateConfigsInTheSameNamespace('markdown', requestIndentParams);
  167. const indentParams = {
  168. adminPreferredIndentSize: await crowi.configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize'),
  169. isIndentSizeForced: await crowi.configManager.getConfig('markdown', 'markdown:isIndentSizeForced'),
  170. };
  171. return res.apiv3({ indentParams });
  172. }
  173. catch (err) {
  174. const msg = 'Error occurred in updating indent';
  175. logger.error('Error', err);
  176. return res.apiv3Err(new ErrorV3(msg, 'update-indent-failed'));
  177. }
  178. });
  179. /**
  180. * @swagger
  181. *
  182. * /markdown-setting/presentation:
  183. * put:
  184. * tags: [MarkDownSetting]
  185. * operationId: updatePresentationMarkdownSetting
  186. * summary: /markdown-setting/presentation
  187. * description: Update presentation
  188. * requestBody:
  189. * required: true
  190. * content:
  191. * application/json:
  192. * schema:
  193. * $ref: '#/components/schemas/PresentationParams'
  194. * responses:
  195. * 200:
  196. * description: Succeeded to update presentation setting
  197. * content:
  198. * application/json:
  199. * schema:
  200. * $ref: '#/components/schemas/PresentationParams'
  201. */
  202. router.put('/presentation', loginRequiredStrictly, adminRequired, csrf, validator.presentationSetting, apiV3FormValidator, async(req, res) => {
  203. if (req.body.pageBreakSeparator === 3 && req.body.pageBreakCustomSeparator === '') {
  204. return res.apiv3Err(new ErrorV3('customRegularExpression is required'));
  205. }
  206. const requestPresentationParams = {
  207. 'markdown:presentation:pageBreakSeparator': req.body.pageBreakSeparator,
  208. 'markdown:presentation:pageBreakCustomSeparator': req.body.pageBreakCustomSeparator,
  209. };
  210. try {
  211. await crowi.configManager.updateConfigsInTheSameNamespace('markdown', requestPresentationParams);
  212. const presentationParams = {
  213. pageBreakSeparator: await crowi.configManager.getConfig('markdown', 'markdown:presentation:pageBreakSeparator'),
  214. pageBreakCustomSeparator: await crowi.configManager.getConfig('markdown', 'markdown:presentation:pageBreakCustomSeparator') || '',
  215. };
  216. return res.apiv3({ presentationParams });
  217. }
  218. catch (err) {
  219. const msg = 'Error occurred in updating presentation';
  220. logger.error('Error', err);
  221. return res.apiv3Err(new ErrorV3(msg, 'update-presentation-failed'));
  222. }
  223. });
  224. /**
  225. * @swagger
  226. *
  227. * /markdown-setting/xss:
  228. * put:
  229. * tags: [MarkDownSetting]
  230. * operationId: updateXssMarkdownSetting
  231. * summary: /markdown-setting/xss
  232. * description: Update xss
  233. * requestBody:
  234. * required: true
  235. * content:
  236. * application/json:
  237. * schema:
  238. * $ref: '#/components/schemas/XssParams'
  239. * responses:
  240. * 200:
  241. * description: Succeeded to update xss setting
  242. * content:
  243. * application/json:
  244. * schema:
  245. * $ref: '#/components/schemas/XssParams'
  246. */
  247. router.put('/xss', loginRequiredStrictly, adminRequired, csrf, validator.xssSetting, apiV3FormValidator, async(req, res) => {
  248. if (req.body.isEnabledXss && req.body.xssOption == null) {
  249. return res.apiv3Err(new ErrorV3('xss option is required'));
  250. }
  251. const reqestXssParams = {
  252. 'markdown:xss:isEnabledPrevention': req.body.isEnabledXss,
  253. 'markdown:xss:option': req.body.xssOption,
  254. 'markdown:xss:tagWhiteList': req.body.tagWhiteList,
  255. 'markdown:xss:attrWhiteList': req.body.attrWhiteList,
  256. };
  257. try {
  258. await crowi.configManager.updateConfigsInTheSameNamespace('markdown', reqestXssParams);
  259. const xssParams = {
  260. isEnabledXss: await crowi.configManager.getConfig('markdown', 'markdown:xss:isEnabledPrevention'),
  261. xssOption: await crowi.configManager.getConfig('markdown', 'markdown:xss:option'),
  262. tagWhiteList: await crowi.configManager.getConfig('markdown', 'markdown:xss:tagWhiteList'),
  263. attrWhiteList: await crowi.configManager.getConfig('markdown', 'markdown:xss:attrWhiteList'),
  264. };
  265. return res.apiv3({ xssParams });
  266. }
  267. catch (err) {
  268. const msg = 'Error occurred in updating xss';
  269. logger.error('Error', err);
  270. return res.apiv3Err(new ErrorV3(msg, 'update-xss-failed'));
  271. }
  272. });
  273. return router;
  274. };