express-init.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. 'use strict';
  2. module.exports = function(crowi, app) {
  3. const debug = require('debug')('growi:crowi:express-init')
  4. , path = require('path')
  5. , express = require('express')
  6. , helmet = require('helmet')
  7. , bodyParser = require('body-parser')
  8. , cookieParser = require('cookie-parser')
  9. , methodOverride = require('method-override')
  10. , passport = require('passport')
  11. , session = require('express-session')
  12. , sanitizer = require('express-sanitizer')
  13. , basicAuth = require('basic-auth-connect')
  14. , flash = require('connect-flash')
  15. , swig = require('swig-templates')
  16. , webpackAssets = require('express-webpack-assets')
  17. , i18next = require('i18next')
  18. , i18nFsBackend = require('i18next-node-fs-backend')
  19. , i18nSprintf = require('i18next-sprintf-postprocessor')
  20. , i18nMiddleware = require('i18next-express-middleware')
  21. , i18nUserSettingDetector = require('../util/i18nUserSettingDetector')
  22. , env = crowi.node_env
  23. , config = crowi.getConfig()
  24. , middleware = require('../util/middlewares')
  25. , Config = crowi.model('Config')
  26. , User = crowi.model('User')
  27. ;
  28. const lngDetector = new i18nMiddleware.LanguageDetector();
  29. lngDetector.addDetector(i18nUserSettingDetector);
  30. i18next
  31. .use(lngDetector)
  32. .use(i18nFsBackend)
  33. .use(i18nSprintf)
  34. .init({
  35. // debug: true,
  36. fallbackLng: [User.LANG_EN_US],
  37. whitelist: Object.keys(User.getLanguageLabels()).map((k) => User[k]),
  38. backend: {
  39. loadPath: crowi.localeDir + '{{lng}}/translation.json'
  40. },
  41. detection: {
  42. order: ['userSettingDetector', 'header', 'navigator'],
  43. },
  44. overloadTranslationOptionHandler: i18nSprintf.overloadTranslationOptionHandler
  45. });
  46. app.use(helmet());
  47. app.use(function(req, res, next) {
  48. const now = new Date()
  49. , tzoffset = -(config.crowi['app:timezone'] || 9) * 60 // for datez
  50. , Page = crowi.model('Page')
  51. , User = crowi.model('User')
  52. , Config = crowi.model('Config')
  53. ;
  54. app.set('tzoffset', tzoffset);
  55. req.config = config;
  56. req.csrfToken = null;
  57. config.crowi['app:siteUrl:fixed'] = (config.crowi['app:siteUrl'] != null)
  58. ? config.crowi['app:siteUrl'] // prioritized with v3.2.4 and above
  59. : (req.headers['x-forwarded-proto'] == 'https' ? 'https' : req.protocol) + '://' + req.get('host'); // auto generate (default with v3.2.3 and below)
  60. res.locals.req = req;
  61. res.locals.baseUrl = config.crowi['app:siteUrl:fixed'];
  62. res.locals.config = config;
  63. res.locals.env = env;
  64. res.locals.now = now;
  65. res.locals.tzoffset = tzoffset;
  66. res.locals.consts = {
  67. pageGrants: Page.getGrantLabels(),
  68. userStatus: User.getUserStatusLabels(),
  69. language: User.getLanguageLabels(),
  70. restrictGuestMode: Config.getRestrictGuestModeLabels(),
  71. registrationMode: Config.getRegistrationModeLabels(),
  72. };
  73. res.locals.local_config = Config.getLocalconfig(config); // config for browser context
  74. next();
  75. });
  76. app.set('port', crowi.port);
  77. const staticOption = (crowi.node_env === 'production') ? {maxAge: '30d'} : {};
  78. app.use(express.static(crowi.publicDir, staticOption));
  79. app.engine('html', swig.renderFile);
  80. app.use(webpackAssets(
  81. path.join(crowi.publicDir, 'manifest.json'),
  82. { devMode: (crowi.node_env === 'development') })
  83. );
  84. // app.set('view cache', false); // Default: true in production, otherwise undefined. -- 2017.07.04 Yuki Takei
  85. app.set('view engine', 'html');
  86. app.set('views', crowi.viewsDir);
  87. app.use(methodOverride());
  88. app.use(bodyParser.urlencoded({ extended: true, limit: '50mb' }));
  89. app.use(bodyParser.json({limit: '50mb'}));
  90. app.use(sanitizer());
  91. app.use(cookieParser());
  92. app.use(session(crowi.sessionConfig));
  93. // Set basic auth middleware
  94. app.use(function(req, res, next) {
  95. if (req.query.access_token || req.body.access_token) {
  96. return next();
  97. }
  98. // FIXME:
  99. // healthcheck endpoint exclude from basic authentication.
  100. // however, hard coding is not desirable.
  101. // need refactoring (ex. setting basic authentication for each routes)
  102. if (req.path === '/_api/v3/healthcheck') {
  103. return next();
  104. }
  105. if (config.crowi['security:basicName'] && config.crowi['security:basicSecret']) {
  106. return basicAuth(
  107. config.crowi['security:basicName'],
  108. config.crowi['security:basicSecret'])(req, res, next);
  109. }
  110. else {
  111. next();
  112. }
  113. });
  114. // passport
  115. if (Config.isEnabledPassport(config)) {
  116. debug('initialize Passport');
  117. app.use(passport.initialize());
  118. app.use(passport.session());
  119. }
  120. app.use(flash());
  121. app.use(middleware.swigFilters(crowi, app, swig));
  122. app.use(middleware.swigFunctions(crowi, app));
  123. app.use(middleware.csrfKeyGenerator(crowi, app));
  124. // switch loginChecker
  125. if (Config.isEnabledPassport(config)) {
  126. app.use(middleware.loginCheckerForPassport(crowi, app));
  127. }
  128. else {
  129. app.use(middleware.loginChecker(crowi, app));
  130. }
  131. app.use(i18nMiddleware.handle(i18next));
  132. };