middlewares.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // don't add any more middlewares to this file.
  2. // all new middlewares should be an independent file under /server/routes/middlewares
  3. // eslint-disable-next-line no-unused-vars
  4. const logger = require('@alias/logger')('growi:lib:middlewares');
  5. const { formatDistanceStrict } = require('date-fns');
  6. const pathUtils = require('growi-commons').pathUtils;
  7. const md5 = require('md5');
  8. const entities = require('entities');
  9. module.exports = (crowi) => {
  10. const { configManager, appService } = crowi;
  11. const middlewares = {};
  12. middlewares.csrfKeyGenerator = function() {
  13. return function(req, res, next) {
  14. const csrfKey = (req.session && req.session.id) || 'anon';
  15. if (req.csrfToken === null) {
  16. req.csrfToken = crowi.getTokens().create(csrfKey);
  17. }
  18. next();
  19. };
  20. };
  21. middlewares.loginCheckerForPassport = function(req, res, next) {
  22. res.locals.user = req.user;
  23. next();
  24. };
  25. middlewares.swigFunctions = function() {
  26. return function(req, res, next) {
  27. require('../util/swigFunctions')(crowi, req, res.locals);
  28. next();
  29. };
  30. };
  31. middlewares.swigFilters = function(swig) {
  32. // define a function for Gravatar
  33. const generateGravatarSrc = function(user) {
  34. const email = user.email || '';
  35. const hash = md5(email.trim().toLowerCase());
  36. return `https://gravatar.com/avatar/${hash}`;
  37. };
  38. // define a function for uploaded picture
  39. const getUploadedPictureSrc = function(user) {
  40. if (user.image) {
  41. return user.image;
  42. }
  43. if (user.imageAttachment != null) {
  44. return user.imageAttachment.filePathProxied;
  45. }
  46. return '/images/icons/user.svg';
  47. };
  48. return function(req, res, next) {
  49. swig.setFilter('path2name', (string) => {
  50. const name = string.replace(/(\/)$/, '');
  51. if (name.match(/.+\/([^/]+\/\d{4}\/\d{2}\/\d{2})$/)) { // /.../hoge/YYYY/MM/DD 形式のページ
  52. return name.replace(/.+\/([^/]+\/\d{4}\/\d{2}\/\d{2})$/, '$1');
  53. }
  54. if (name.match(/.+\/([^/]+\/\d{4}\/\d{2})$/)) { // /.../hoge/YYYY/MM 形式のページ
  55. return name.replace(/.+\/([^/]+\/\d{4}\/\d{2})$/, '$1');
  56. }
  57. if (name.match(/.+\/([^/]+\/\d{4})$/)) { // /.../hoge/YYYY 形式のページ
  58. return name.replace(/.+\/([^/]+\/\d{4})$/, '$1');
  59. }
  60. return name.replace(/.+\/(.+)?$/, '$1'); // ページの末尾を拾う
  61. });
  62. swig.setFilter('normalizeDateInPath', (path) => {
  63. const patterns = [
  64. [/20(\d{2})(\d{2})(\d{2})(.+)/g, '20$1/$2/$3/$4'],
  65. [/20(\d{2})(\d{2})(\d{2})/g, '20$1/$2/$3'],
  66. [/20(\d{2})(\d{2})(.+)/g, '20$1/$2/$3'],
  67. [/20(\d{2})(\d{2})/g, '20$1/$2'],
  68. [/20(\d{2})_(\d{1,2})_(\d{1,2})_?(.+)/g, '20$1/$2/$3/$4'],
  69. [/20(\d{2})_(\d{1,2})_(\d{1,2})/g, '20$1/$2/$3'],
  70. [/20(\d{2})_(\d{1,2})_?(.+)/g, '20$1/$2/$3'],
  71. [/20(\d{2})_(\d{1,2})/g, '20$1/$2'],
  72. ];
  73. for (let i = 0; i < patterns.length; i++) {
  74. const mat = patterns[i][0];
  75. const rep = patterns[i][1];
  76. if (path.match(mat)) {
  77. return path.replace(mat, rep);
  78. }
  79. }
  80. return path;
  81. });
  82. swig.setFilter('datetz', (input, format) => {
  83. // timezone
  84. const swigFilters = require('swig-templates/lib/filters');
  85. return swigFilters.date(input, format, crowi.appService.getTzoffset());
  86. });
  87. swig.setFilter('dateDistance', (input) => {
  88. return formatDistanceStrict(input, new Date());
  89. });
  90. swig.setFilter('nl2br', (string) => {
  91. return string
  92. .replace(/\n/g, '<br>');
  93. });
  94. swig.setFilter('removeTrailingSlash', (string) => {
  95. return pathUtils.removeTrailingSlash(string);
  96. });
  97. swig.setFilter('addTrailingSlash', (string) => {
  98. return pathUtils.addTrailingSlash(string);
  99. });
  100. swig.setFilter('presentation', (string) => {
  101. // 手抜き
  102. return string
  103. .replace(/\s(https?.+(jpe?g|png|gif))\s/, '\n\n\n![]($1)\n\n\n');
  104. });
  105. swig.setFilter('gravatar', generateGravatarSrc);
  106. swig.setFilter('uploadedpicture', getUploadedPictureSrc);
  107. swig.setFilter('picture', (user) => {
  108. if (!user) {
  109. return '/images/icons/user.svg';
  110. }
  111. if (user.isGravatarEnabled === true) {
  112. return generateGravatarSrc(user);
  113. }
  114. return getUploadedPictureSrc(user);
  115. });
  116. swig.setFilter('encodeHTML', (string) => {
  117. return entities.encodeHTML(string);
  118. });
  119. swig.setFilter('preventXss', (string) => {
  120. return crowi.xss.process(string);
  121. });
  122. swig.setFilter('slice', (list, start, end) => {
  123. return list.slice(start, end);
  124. });
  125. next();
  126. };
  127. };
  128. // this is for Installer
  129. middlewares.applicationNotInstalled = async function(req, res, next) {
  130. const isInstalled = await appService.isDBInitialized();
  131. if (isInstalled) {
  132. req.flash('errorMessage', req.t('message.application_already_installed'));
  133. return res.redirect('admin'); // admin以外はadminRequiredで'/'にリダイレクトされる
  134. }
  135. return next();
  136. };
  137. middlewares.applicationInstalled = async function(req, res, next) {
  138. const isInstalled = await appService.isDBInitialized();
  139. if (!isInstalled) {
  140. return res.redirect('/installer');
  141. }
  142. return next();
  143. };
  144. middlewares.awsEnabled = function() {
  145. return function(req, res, next) {
  146. if ((configManager.getConfig('crowi', 'aws:region') !== '' || this.configManager.getConfig('crowi', 'aws:customEndpoint') !== '')
  147. && configManager.getConfig('crowi', 'aws:bucket') !== ''
  148. && configManager.getConfig('crowi', 'aws:accessKeyId') !== ''
  149. && configManager.getConfig('crowi', 'aws:secretAccessKey') !== '') {
  150. req.flash('globalError', req.t('message.aws_sttings_required'));
  151. return res.redirect('/');
  152. }
  153. return next();
  154. };
  155. };
  156. return middlewares;
  157. };