master.js 5.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
const autoload = require('auto-load')
const bodyParser = require('body-parser')
const compression = require('compression')
const cookieParser = require('cookie-parser')
const cors = require('cors')
const express = require('express')
const favicon = require('serve-favicon')
const http = require('http')
const path = require('path')
const session = require('express-session')
const SessionRedisStore = require('connect-redis')(session)
12
const { ApolloServer } = require('apollo-server-express')
NGPixel's avatar
NGPixel committed
13
// const oauth2orize = require('oauth2orize')
14

15
/* global WIKI */
NGPixel's avatar
NGPixel committed
16

NGPixel's avatar
NGPixel committed
17
module.exports = async () => {
18
  // ----------------------------------------
19
  // Load core modules
20 21
  // ----------------------------------------

22 23
  WIKI.auth = require('./core/auth').init()
  WIKI.lang = require('./core/localization').init()
24 25

  // ----------------------------------------
26
  // Load middlewares
27 28
  // ----------------------------------------

29 30
  var mw = autoload(path.join(WIKI.SERVERPATH, '/middlewares'))
  var ctrl = autoload(path.join(WIKI.SERVERPATH, '/controllers'))
31 32 33 34 35 36

  // ----------------------------------------
  // Define Express App
  // ----------------------------------------

  const app = express()
37
  WIKI.app = app
38 39 40 41 42 43 44
  app.use(compression())

  // ----------------------------------------
  // Security
  // ----------------------------------------

  app.use(mw.security)
45 46
  app.use(cors(WIKI.config.cors))
  app.options('*', cors(WIKI.config.cors))
47
  app.enable('trust proxy')
48 49 50 51 52

  // ----------------------------------------
  // Public Assets
  // ----------------------------------------

53 54
  app.use(favicon(path.join(WIKI.ROOTPATH, 'assets', 'favicon.ico')))
  app.use(express.static(path.join(WIKI.ROOTPATH, 'assets'), {
55 56 57 58
    index: false,
    maxAge: '7d'
  }))

59 60 61 62
  // ----------------------------------------
  // OAuth2 Server
  // ----------------------------------------

NGPixel's avatar
NGPixel committed
63
  // const OAuth2Server = oauth2orize.createServer()
64

65 66 67 68 69
  // ----------------------------------------
  // Passport Authentication
  // ----------------------------------------

  let sessionStore = new SessionRedisStore({
70
    client: WIKI.redis
71
  })
NGPixel's avatar
NGPixel committed
72

73 74 75 76
  app.use(cookieParser())
  app.use(session({
    name: 'wikijs.sid',
    store: sessionStore,
77
    secret: WIKI.config.sessionSecret,
78 79 80
    resave: false,
    saveUninitialized: false
  }))
81 82
  app.use(WIKI.auth.passport.initialize())
  app.use(WIKI.auth.passport.session())
83 84 85 86 87 88 89 90 91 92

  // ----------------------------------------
  // SEO
  // ----------------------------------------

  app.use(mw.seo)

  // ----------------------------------------
  // View Engine Setup
  // ----------------------------------------
NGPixel's avatar
NGPixel committed
93

94
  app.set('views', path.join(WIKI.SERVERPATH, 'views'))
95
  app.set('view engine', 'pug')
NGPixel's avatar
NGPixel committed
96

97 98
  app.use(bodyParser.json({ limit: '1mb' }))
  app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' }))
NGPixel's avatar
NGPixel committed
99

100 101 102 103
  // ----------------------------------------
  // Localization
  // ----------------------------------------

104
  WIKI.lang.attachMiddleware(app)
105

106 107 108
  // ----------------------------------------
  // View accessible data
  // ----------------------------------------
NGPixel's avatar
NGPixel committed
109

110
  app.locals.basedir = WIKI.ROOTPATH
111 112
  app.locals._ = require('lodash')
  app.locals.moment = require('moment')
113
  app.locals.moment.locale(WIKI.config.lang.code)
114
  app.locals.config = WIKI.config
NGPixel's avatar
NGPixel committed
115

NGPixel's avatar
NGPixel committed
116 117 118 119 120
  // ----------------------------------------
  // HMR (Dev Mode Only)
  // ----------------------------------------

  if (global.DEV) {
121 122
    app.use(global.WP_DEV.devMiddleware)
    app.use(global.WP_DEV.hotMiddleware)
NGPixel's avatar
NGPixel committed
123 124
  }

125
  // ----------------------------------------
126 127 128 129 130 131 132 133 134 135 136 137
  // Apollo Server (GraphQL)
  // ----------------------------------------

  const graphqlSchema = require('./graph')
  const apolloServer = new ApolloServer({
    ...graphqlSchema,
    context: ({ req, res }) => ({ req, res })
  })
  apolloServer.applyMiddleware({ app })

  // ----------------------------------------
  // Routing
138
  // ----------------------------------------
NGPixel's avatar
NGPixel committed
139

140
  app.use('/', ctrl.auth)
NGPixel's avatar
NGPixel committed
141

142
  app.use('/', mw.auth, ctrl.common)
NGPixel's avatar
NGPixel committed
143

144 145 146
  // ----------------------------------------
  // Error handling
  // ----------------------------------------
NGPixel's avatar
NGPixel committed
147

148
  app.use((req, res, next) => {
149 150 151 152
    var err = new Error('Not Found')
    err.status = 404
    next(err)
  })
NGPixel's avatar
NGPixel committed
153

154
  app.use((err, req, res, next) => {
155 156 157
    res.status(err.status || 500)
    res.render('error', {
      message: err.message,
158
      error: WIKI.IS_DEBUG ? err : {}
159
    })
NGPixel's avatar
NGPixel committed
160 161
  })

162
  // ----------------------------------------
163
  // HTTP server
164 165
  // ----------------------------------------

NGPixel's avatar
NGPixel committed
166 167
  let srvConnections = {}

168
  WIKI.logger.info(`HTTP Server on port: [ ${WIKI.config.port} ]`)
169

170 171
  app.set('port', WIKI.config.port)
  WIKI.server = http.createServer(app)
172

173
  WIKI.server.listen(WIKI.config.port, WIKI.config.bindIP)
174
  WIKI.server.on('error', (error) => {
175
    if (error.syscall !== 'listen') {
NGPixel's avatar
NGPixel committed
176
      throw error
177 178 179 180 181
    }

    // handle specific listen errors with friendly messages
    switch (error.code) {
      case 'EACCES':
182
        WIKI.logger.error('Listening on port ' + WIKI.config.port + ' requires elevated privileges!')
183 184
        return process.exit(1)
      case 'EADDRINUSE':
185
        WIKI.logger.error('Port ' + WIKI.config.port + ' is already in use!')
186 187 188 189 190
        return process.exit(1)
      default:
        throw error
    }
  })
NGPixel's avatar
NGPixel committed
191

192
  WIKI.server.on('connection', conn => {
NGPixel's avatar
NGPixel committed
193 194 195 196 197 198 199
    let key = `${conn.remoteAddress}:${conn.remotePort}`
    srvConnections[key] = conn
    conn.on('close', function() {
      delete srvConnections[key]
    })
  })

200 201
  WIKI.server.on('listening', () => {
    WIKI.logger.info('HTTP Server: [ RUNNING ]')
202
  })
NGPixel's avatar
NGPixel committed
203

204 205
  WIKI.server.destroy = (cb) => {
    WIKI.server.close(cb)
NGPixel's avatar
NGPixel committed
206 207 208 209 210
    for (let key in srvConnections) {
      srvConnections[key].destroy()
    }
  }

211
  return true
NGPixel's avatar
NGPixel committed
212
}