middlewares.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. var debug = require('debug')('crowi:lib:middlewares');
  2. exports.loginChecker = function(crowi, app) {
  3. return function(req, res, next) {
  4. var User = crowi.model('User');
  5. var csrfKey = (req.session && req.session.id) || 'anon';
  6. if (req.csrfToken === null) {
  7. debug('csrfKey', csrfKey);
  8. req.csrfToken = crowi.getTokens().create(csrfKey);
  9. }
  10. // session に user object が入ってる
  11. if (req.session.user && '_id' in req.session.user) {
  12. User.findById(req.session.user._id, function(err, userData) {
  13. if (err) {
  14. next();
  15. } else {
  16. req.user = req.session.user = userData;
  17. res.locals.user = req.user;
  18. next();
  19. }
  20. });
  21. } else {
  22. req.user = req.session.user = false;
  23. res.locals.user = req.user;
  24. next();
  25. }
  26. };
  27. };
  28. exports.csrfVerify = function(crowi, app) {
  29. return function(req, res, next) {
  30. var token = req.body._csrf || req.query._csrf || null;
  31. var csrfKey = (req.session && req.session.id) || 'anon';
  32. if (req.skipCsrfVerify) {
  33. return next();
  34. }
  35. if (crowi.getTokens().verify(csrfKey, token)) {
  36. return next();
  37. }
  38. return res.sendStatus(403);
  39. };
  40. };
  41. exports.swigFunctions = function(crowi, app) {
  42. return function(req, res, next) {
  43. require('../util/swigFunctions')(crowi, app, req, res.locals);
  44. next();
  45. };
  46. };
  47. exports.swigFilters = function(app, swig) {
  48. return function(req, res, next) {
  49. swig.setFilter('path2name', function(string) {
  50. var 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('datetz', function(input, format) {
  63. // timezone
  64. var swigFilters = require('swig/lib/filters');
  65. return swigFilters.date(input, format, app.get('tzoffset'));
  66. });
  67. swig.setFilter('nl2br', function(string) {
  68. return string
  69. .replace(/\n/g, '<br>');
  70. });
  71. swig.setFilter('insertSpaceToEachSlashes', function(string) {
  72. if (string == '/') {
  73. return string;
  74. }
  75. return string.replace(/\//g, ' / ');
  76. });
  77. swig.setFilter('removeLastSlash', function(string) {
  78. if (string == '/') {
  79. return string;
  80. }
  81. return string.substr(0, string.length - 1);
  82. });
  83. swig.setFilter('presentation', function(string) {
  84. // 手抜き
  85. return string
  86. .replace(/[\n]+#/g, '\n\n\n#')
  87. .replace(/\s(https?.+(jpe?g|png|gif))\s/, '\n\n\n![]($1)\n\n\n');
  88. });
  89. swig.setFilter('picture', function(user) {
  90. if (!user) {
  91. return '';
  92. }
  93. user.fbId = user.userId; // migration
  94. if (user.image && user.image != '/images/userpicture.png') {
  95. return user.image;
  96. } else if (user.fbId) {
  97. return '//graph.facebook.com/' + user.fbId + '/picture?size=square';
  98. } else {
  99. return '/images/userpicture.png';
  100. }
  101. });
  102. next();
  103. };
  104. };
  105. exports.adminRequired = function() {
  106. return function(req, res, next) {
  107. if (req.user && '_id' in req.user) {
  108. if (req.user.admin) {
  109. next();
  110. return;
  111. }
  112. return res.redirect('/');
  113. }
  114. return res.redirect('/login');
  115. };
  116. };
  117. exports.loginRequired = function(crowi, app) {
  118. return function(req, res, next) {
  119. var User = crowi.model('User')
  120. if (req.user && '_id' in req.user) {
  121. if (req.user.status === User.STATUS_ACTIVE) {
  122. // Active の人だけ先に進める
  123. return next();
  124. } else if (req.user.status === User.STATUS_REGISTERED) {
  125. return res.redirect('/login/error/registered');
  126. } else if (req.user.status === User.STATUS_SUSPENDED) {
  127. return res.redirect('/login/error/suspended');
  128. } else if (req.user.status === User.STATUS_INVITED) {
  129. return res.redirect('/login/invited');
  130. }
  131. }
  132. req.session.jumpTo = req.originalUrl;
  133. return res.redirect('/login');
  134. };
  135. };
  136. exports.accessTokenParser = function(crowi, app) {
  137. return function(req, res, next) {
  138. var accessToken = req.query.access_token || req.body.access_token || null;
  139. if (!accessToken) {
  140. return next();
  141. }
  142. var User = crowi.model('User')
  143. User.findUserByApiToken(accessToken)
  144. .then(function(userData) {
  145. req.user = userData;
  146. req.skipCsrfVerify = true;
  147. next();
  148. }).catch(function(err) {
  149. next();
  150. });
  151. };
  152. };
  153. // this is for Installer
  154. exports.applicationNotInstalled = function() {
  155. return function(req, res, next) {
  156. var config = req.config;
  157. if (Object.keys(config.crowi).length !== 1) {
  158. req.flash('errorMessage', 'Application already installed.');
  159. return res.redirect('admin'); // admin以外はadminRequiredで'/'にリダイレクトされる
  160. }
  161. return next();
  162. };
  163. };
  164. exports.applicationInstalled = function() {
  165. return function(req, res, next) {
  166. var config = req.config;
  167. if (Object.keys(config.crowi).length === 1) { // app:url is set by process
  168. return res.redirect('/installer');
  169. }
  170. return next();
  171. };
  172. };
  173. exports.awsEnabled = function() {
  174. return function (req, res, next) {
  175. var config = req.config;
  176. if (config.crowi['aws:region'] !== '' && config.crowi['aws:bucket'] !== '' && config.crowi['aws:accessKeyId'] !== '' && config.crowi['aws:secretAccessKey'] !== '') {
  177. req.flash('globalError', 'AWS settings required to use this function. Please ask the administrator.');
  178. return res.redirect('/');
  179. }
  180. return next();
  181. };
  182. };