middlewares.js 5.4 KB

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