You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.3 KiB

  1. /* global wiki */
  2. module.exports = () => {
  3. // ----------------------------------------
  4. // Load global modules
  5. // ----------------------------------------
  6. wiki.auth = require('./modules/auth').init()
  7. wiki.disk = require('./modules/disk').init()
  8. wiki.docs = require('./modules/documents').init()
  9. wiki.git = require('./modules/git').init(false)
  10. wiki.lang = require('./modules/localization').init()
  11. wiki.mark = require('./modules/markdown')
  12. wiki.search = require('./modules/search').init()
  13. wiki.upl = require('./modules/uploads').init()
  14. // ----------------------------------------
  15. // Load modules
  16. // ----------------------------------------
  17. const autoload = require('auto-load')
  18. const bodyParser = require('body-parser')
  19. const compression = require('compression')
  20. const cookieParser = require('cookie-parser')
  21. const express = require('express')
  22. const favicon = require('serve-favicon')
  23. const flash = require('connect-flash')
  24. const http = require('http')
  25. const path = require('path')
  26. const session = require('express-session')
  27. const SessionRedisStore = require('connect-redis')(session)
  28. const graceful = require('node-graceful')
  29. const graphqlApollo = require('apollo-server-express')
  30. const graphqlSchema = require('./modules/graphql')
  31. var mw = autoload(path.join(wiki.SERVERPATH, '/middlewares'))
  32. var ctrl = autoload(path.join(wiki.SERVERPATH, '/controllers'))
  33. // ----------------------------------------
  34. // Define Express App
  35. // ----------------------------------------
  36. const app = express()
  37. wiki.app = app
  38. app.use(compression())
  39. // ----------------------------------------
  40. // Security
  41. // ----------------------------------------
  42. app.use(mw.security)
  43. // ----------------------------------------
  44. // Public Assets
  45. // ----------------------------------------
  46. app.use(favicon(path.join(wiki.ROOTPATH, 'assets', 'favicon.ico')))
  47. app.use(express.static(path.join(wiki.ROOTPATH, 'assets'), {
  48. index: false,
  49. maxAge: '7d'
  50. }))
  51. // ----------------------------------------
  52. // Passport Authentication
  53. // ----------------------------------------
  54. let sessionStore = new SessionRedisStore({
  55. client: wiki.redis
  56. })
  57. app.use(cookieParser())
  58. app.use(session({
  59. name: 'wikijs.sid',
  60. store: sessionStore,
  61. secret: wiki.config.site.sessionSecret,
  62. resave: false,
  63. saveUninitialized: false
  64. }))
  65. app.use(flash())
  66. app.use(wiki.auth.passport.initialize())
  67. app.use(wiki.auth.passport.session())
  68. // ----------------------------------------
  69. // SEO
  70. // ----------------------------------------
  71. app.use(mw.seo)
  72. // ----------------------------------------
  73. // View Engine Setup
  74. // ----------------------------------------
  75. app.set('views', path.join(wiki.SERVERPATH, 'views'))
  76. app.set('view engine', 'pug')
  77. app.use(bodyParser.json({ limit: '1mb' }))
  78. app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' }))
  79. // ----------------------------------------
  80. // View accessible data
  81. // ----------------------------------------
  82. app.locals.basedir = wiki.ROOTPATH
  83. app.locals._ = require('lodash')
  84. app.locals.t = wiki.lang.engine.t.bind(wiki.lang)
  85. app.locals.moment = require('moment')
  86. app.locals.moment.locale(wiki.config.site.lang)
  87. app.locals.config = wiki.config
  88. app.use(mw.flash)
  89. // ----------------------------------------
  90. // Controllers
  91. // ----------------------------------------
  92. app.use('/', ctrl.auth)
  93. app.use('/graphql', graphqlApollo.graphqlExpress({ schema: graphqlSchema }))
  94. app.use('/graphiql', graphqlApollo.graphiqlExpress({ endpointURL: '/graphql' }))
  95. // app.use('/uploads', mw.auth, ctrl.uploads)
  96. app.use('/admin', mw.auth, ctrl.admin)
  97. app.use('/', mw.auth, ctrl.pages)
  98. // ----------------------------------------
  99. // Error handling
  100. // ----------------------------------------
  101. app.use(function (req, res, next) {
  102. var err = new Error('Not Found')
  103. err.status = 404
  104. next(err)
  105. })
  106. app.use(function (err, req, res, next) {
  107. res.status(err.status || 500)
  108. res.render('error', {
  109. message: err.message,
  110. error: wiki.IS_DEBUG ? err : {}
  111. })
  112. })
  113. // ----------------------------------------
  114. // Start HTTP server
  115. // ----------------------------------------
  116. wiki.logger.info(`HTTP Server on port: ${wiki.config.port}`)
  117. app.set('port', wiki.config.port)
  118. let server = http.createServer(app)
  119. server.listen(wiki.config.port)
  120. server.on('error', (error) => {
  121. if (error.syscall !== 'listen') {
  122. throw error
  123. }
  124. // handle specific listen errors with friendly messages
  125. switch (error.code) {
  126. case 'EACCES':
  127. wiki.logger.error('Listening on port ' + wiki.config.port + ' requires elevated privileges!')
  128. return process.exit(1)
  129. case 'EADDRINUSE':
  130. wiki.logger.error('Port ' + wiki.config.port + ' is already in use!')
  131. return process.exit(1)
  132. default:
  133. throw error
  134. }
  135. })
  136. server.on('listening', () => {
  137. wiki.logger.info('HTTP Server: RUNNING')
  138. })
  139. // ----------------------------------------
  140. // Graceful shutdown
  141. // ----------------------------------------
  142. graceful.on('exit', () => {
  143. wiki.logger.info('- SHUTTING DOWN - Performing git sync...')
  144. return global.git.resync().then(() => {
  145. wiki.logger.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.')
  146. process.exit()
  147. })
  148. })
  149. return true
  150. }