setup.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. const path = require('path')
  2. const os = require('os')
  3. /* global WIKI */
  4. module.exports = () => {
  5. WIKI.config.site = {
  6. path: '',
  7. title: 'Wiki.js'
  8. }
  9. WIKI.system = require('./core/system')
  10. // ----------------------------------------
  11. // Load modules
  12. // ----------------------------------------
  13. const bodyParser = require('body-parser')
  14. const compression = require('compression')
  15. const express = require('express')
  16. const favicon = require('serve-favicon')
  17. const http = require('http')
  18. const Promise = require('bluebird')
  19. const fs = require('fs-extra')
  20. const _ = require('lodash')
  21. const cfgHelper = require('./helpers/config')
  22. const crypto = Promise.promisifyAll(require('crypto'))
  23. // ----------------------------------------
  24. // Define Express App
  25. // ----------------------------------------
  26. let app = express()
  27. app.use(compression())
  28. // ----------------------------------------
  29. // Public Assets
  30. // ----------------------------------------
  31. app.use(favicon(path.join(WIKI.ROOTPATH, 'assets', 'favicon.ico')))
  32. app.use(express.static(path.join(WIKI.ROOTPATH, 'assets')))
  33. // ----------------------------------------
  34. // View Engine Setup
  35. // ----------------------------------------
  36. app.set('views', path.join(WIKI.SERVERPATH, 'views'))
  37. app.set('view engine', 'pug')
  38. app.use(bodyParser.json())
  39. app.use(bodyParser.urlencoded({ extended: false }))
  40. app.locals.config = WIKI.config
  41. app.locals.data = WIKI.data
  42. app.locals._ = require('lodash')
  43. // ----------------------------------------
  44. // HMR (Dev Mode Only)
  45. // ----------------------------------------
  46. if (global.DEV) {
  47. app.use(global.WP_DEV.devMiddleware)
  48. app.use(global.WP_DEV.hotMiddleware)
  49. }
  50. // ----------------------------------------
  51. // Controllers
  52. // ----------------------------------------
  53. app.get('*', async (req, res) => {
  54. let packageObj = await fs.readJson(path.join(WIKI.ROOTPATH, 'package.json'))
  55. res.render('setup', {
  56. packageObj,
  57. telemetryClientID: WIKI.telemetry.cid
  58. })
  59. })
  60. /**
  61. * Finalize
  62. */
  63. app.post('/finalize', async (req, res) => {
  64. WIKI.telemetry.sendEvent('setup', 'finalize')
  65. try {
  66. // Upgrade from WIKI.js 1.x?
  67. if (req.body.upgrade) {
  68. await WIKI.system.upgradeFromMongo({
  69. mongoCnStr: cfgHelper.parseConfigValue(req.body.upgMongo)
  70. })
  71. }
  72. // Create directory structure
  73. const dataPath = path.join(process.cwd(), 'data')
  74. await fs.ensureDir(dataPath)
  75. await fs.ensureDir(path.join(dataPath, 'cache'))
  76. await fs.ensureDir(path.join(dataPath, 'uploads'))
  77. // Set config
  78. _.set(WIKI.config, 'defaultEditor', 'markdown')
  79. _.set(WIKI.config, 'graphEndpoint', 'https://graph.requarks.io')
  80. _.set(WIKI.config, 'lang.code', 'en')
  81. _.set(WIKI.config, 'lang.autoUpdate', true)
  82. _.set(WIKI.config, 'lang.namespacing', false)
  83. _.set(WIKI.config, 'lang.namespaces', [])
  84. _.set(WIKI.config, 'public', false)
  85. _.set(WIKI.config, 'sessionSecret', (await crypto.randomBytesAsync(32)).toString('hex'))
  86. _.set(WIKI.config, 'telemetry.isEnabled', req.body.telemetry === 'true')
  87. _.set(WIKI.config, 'telemetry.clientId', WIKI.telemetry.cid)
  88. _.set(WIKI.config, 'theming.theme', 'default')
  89. _.set(WIKI.config, 'theming.darkMode', false)
  90. _.set(WIKI.config, 'title', 'Wiki.js')
  91. // Save config to DB
  92. WIKI.logger.info('Persisting config to DB...')
  93. await WIKI.configSvc.saveToDb([
  94. 'defaultEditor',
  95. 'graphEndpoint',
  96. 'lang',
  97. 'public',
  98. 'sessionSecret',
  99. 'telemetry',
  100. 'theming',
  101. 'title'
  102. ])
  103. // Create default locale
  104. WIKI.logger.info('Installing default locale...')
  105. await WIKI.models.locales.query().insert({
  106. code: 'en',
  107. strings: require('./locales/default.json'),
  108. isRTL: false,
  109. name: 'English',
  110. nativeName: 'English'
  111. })
  112. // Load authentication strategies + enable local
  113. await WIKI.models.authentication.refreshStrategiesFromDisk()
  114. await WIKI.models.authentication.query().patch({ isEnabled: true }).where('key', 'local')
  115. // Load editors + enable default
  116. await WIKI.models.editors.refreshEditorsFromDisk()
  117. await WIKI.models.editors.query().patch({ isEnabled: true }).where('key', 'markdown')
  118. // Load loggers
  119. await WIKI.models.loggers.refreshLoggersFromDisk()
  120. // Load renderers
  121. await WIKI.models.renderers.refreshRenderersFromDisk()
  122. // Load search engines + enable default
  123. await WIKI.models.searchEngines.refreshSearchEnginesFromDisk()
  124. await WIKI.models.searchEngines.query().patch({ isEnabled: true }).where('key', 'db')
  125. // Load storage targets
  126. await WIKI.models.storage.refreshTargetsFromDisk()
  127. // Create root administrator
  128. WIKI.logger.info('Creating root administrator...')
  129. await WIKI.models.users.query().delete().where({
  130. providerKey: 'local',
  131. email: req.body.adminEmail
  132. })
  133. await WIKI.models.users.query().insert({
  134. email: req.body.adminEmail,
  135. provider: 'local',
  136. password: req.body.adminPassword,
  137. name: 'Administrator',
  138. role: 'admin',
  139. locale: 'en',
  140. defaultEditor: 'markdown',
  141. tfaIsActive: false
  142. })
  143. // Create Guest account
  144. WIKI.logger.info('Creating guest account...')
  145. const guestUsr = await WIKI.models.users.query().findOne({
  146. providerKey: 'local',
  147. email: 'guest@example.com'
  148. })
  149. if (!guestUsr) {
  150. await WIKI.models.users.query().insert({
  151. provider: 'local',
  152. email: 'guest@example.com',
  153. name: 'Guest',
  154. password: '',
  155. role: 'guest',
  156. locale: 'en',
  157. defaultEditor: 'markdown',
  158. tfaIsActive: false
  159. })
  160. }
  161. WIKI.logger.info('Setup is complete!')
  162. res.json({
  163. ok: true,
  164. redirectPath: '/',
  165. redirectPort: WIKI.config.port
  166. }).end()
  167. WIKI.config.setup = false
  168. WIKI.logger.info('Stopping Setup...')
  169. WIKI.server.destroy(() => {
  170. WIKI.logger.info('Setup stopped. Starting Wiki.js...')
  171. _.delay(() => {
  172. WIKI.kernel.bootMaster()
  173. }, 1000)
  174. })
  175. } catch (err) {
  176. res.json({ ok: false, error: err.message })
  177. }
  178. })
  179. // ----------------------------------------
  180. // Error handling
  181. // ----------------------------------------
  182. app.use(function (req, res, next) {
  183. var err = new Error('Not Found')
  184. err.status = 404
  185. next(err)
  186. })
  187. app.use(function (err, req, res, next) {
  188. res.status(err.status || 500)
  189. res.send({
  190. message: err.message,
  191. error: WIKI.IS_DEBUG ? err : {}
  192. })
  193. WIKI.logger.error(err.message)
  194. WIKI.telemetry.sendError(err)
  195. })
  196. // ----------------------------------------
  197. // Start HTTP server
  198. // ----------------------------------------
  199. WIKI.logger.info(`HTTP Server on port: [ ${WIKI.config.port} ]`)
  200. app.set('port', WIKI.config.port)
  201. WIKI.server = http.createServer(app)
  202. WIKI.server.listen(WIKI.config.port, WIKI.config.bindIP)
  203. var openConnections = []
  204. WIKI.server.on('connection', (conn) => {
  205. let key = conn.remoteAddress + ':' + conn.remotePort
  206. openConnections[key] = conn
  207. conn.on('close', () => {
  208. delete openConnections[key]
  209. })
  210. })
  211. WIKI.server.destroy = (cb) => {
  212. WIKI.server.close(cb)
  213. for (let key in openConnections) {
  214. openConnections[key].destroy()
  215. }
  216. }
  217. WIKI.server.on('error', (error) => {
  218. if (error.syscall !== 'listen') {
  219. throw error
  220. }
  221. switch (error.code) {
  222. case 'EACCES':
  223. WIKI.logger.error('Listening on port ' + WIKI.config.port + ' requires elevated privileges!')
  224. return process.exit(1)
  225. case 'EADDRINUSE':
  226. WIKI.logger.error('Port ' + WIKI.config.port + ' is already in use!')
  227. return process.exit(1)
  228. default:
  229. throw error
  230. }
  231. })
  232. WIKI.server.on('listening', () => {
  233. WIKI.logger.info('HTTP Server: [ RUNNING ]')
  234. WIKI.logger.info('========================================')
  235. WIKI.logger.info(`Browse to http://localhost:${WIKI.config.port}/`)
  236. WIKI.logger.info('========================================')
  237. })
  238. }