setup.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. const path = require('path')
  2. /* global WIKI */
  3. module.exports = () => {
  4. WIKI.config.site = {
  5. path: '',
  6. title: 'Wiki.js'
  7. }
  8. WIKI.system = require('./core/system')
  9. // ----------------------------------------
  10. // Load modules
  11. // ----------------------------------------
  12. const bodyParser = require('body-parser')
  13. const compression = require('compression')
  14. const express = require('express')
  15. const favicon = require('serve-favicon')
  16. const http = require('http')
  17. const Promise = require('bluebird')
  18. const fs = Promise.promisifyAll(require('fs-extra'))
  19. const yaml = require('js-yaml')
  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. // Update config file
  73. WIKI.logger.info('Writing config file to disk...')
  74. let confRaw = await fs.readFileAsync(path.join(WIKI.ROOTPATH, 'config.yml'), 'utf8')
  75. let conf = yaml.safeLoad(confRaw)
  76. // Create directory structure
  77. await fs.ensureDir(conf.paths.data)
  78. await fs.ensureDir(path.join(conf.paths.data, 'cache'))
  79. await fs.ensureDir(path.join(conf.paths.data, 'temp-upload'))
  80. await fs.ensureDir(conf.paths.content)
  81. // Set config
  82. _.set(WIKI.config, 'defaultEditor', 'markdown')
  83. _.set(WIKI.config, 'graphEndpoint', 'https://graph.requarks.io')
  84. _.set(WIKI.config, 'lang.code', 'en')
  85. _.set(WIKI.config, 'lang.autoUpdate', true)
  86. _.set(WIKI.config, 'lang.namespacing', false)
  87. _.set(WIKI.config, 'lang.namespaces', [])
  88. _.set(WIKI.config, 'public', false)
  89. _.set(WIKI.config, 'sessionSecret', (await crypto.randomBytesAsync(32)).toString('hex'))
  90. _.set(WIKI.config, 'telemetry.isEnabled', req.body.telemetry === 'true')
  91. _.set(WIKI.config, 'telemetry.clientId', WIKI.telemetry.cid)
  92. _.set(WIKI.config, 'theming.theme', 'default')
  93. _.set(WIKI.config, 'theming.darkMode', false)
  94. _.set(WIKI.config, 'title', 'Wiki.js')
  95. // Save config to DB
  96. WIKI.logger.info('Persisting config to DB...')
  97. await WIKI.configSvc.saveToDb([
  98. 'defaultEditor',
  99. 'graphEndpoint',
  100. 'lang',
  101. 'public',
  102. 'sessionSecret',
  103. 'telemetry',
  104. 'theming',
  105. 'title'
  106. ])
  107. // Create default locale
  108. WIKI.logger.info('Installing default locale...')
  109. await WIKI.models.locales.query().insert({
  110. code: 'en',
  111. strings: require('./locales/default.json'),
  112. isRTL: false,
  113. name: 'English',
  114. nativeName: 'English'
  115. })
  116. // Load authentication strategies + enable local
  117. await WIKI.models.authentication.refreshStrategiesFromDisk()
  118. await WIKI.models.authentication.query().patch({ isEnabled: true }).where('key', 'local')
  119. // Load editors + enable default
  120. await WIKI.models.editors.refreshEditorsFromDisk()
  121. await WIKI.models.editors.query().patch({ isEnabled: true }).where('key', 'markdown')
  122. // Load renderers
  123. await WIKI.models.renderers.refreshRenderersFromDisk()
  124. // Load storage targets
  125. await WIKI.models.storage.refreshTargetsFromDisk()
  126. // Create root administrator
  127. WIKI.logger.info('Creating root administrator...')
  128. await WIKI.models.users.query().delete().where({
  129. providerKey: 'local',
  130. email: req.body.adminEmail
  131. })
  132. await WIKI.models.users.query().insert({
  133. email: req.body.adminEmail,
  134. provider: 'local',
  135. password: req.body.adminPassword,
  136. name: 'Administrator',
  137. role: 'admin',
  138. locale: 'en',
  139. defaultEditor: 'markdown',
  140. tfaIsActive: false
  141. })
  142. // Create Guest account
  143. WIKI.logger.info('Creating guest account...')
  144. const guestUsr = await WIKI.models.users.query().findOne({
  145. providerKey: 'local',
  146. email: 'guest@example.com'
  147. })
  148. if (!guestUsr) {
  149. await WIKI.models.users.query().insert({
  150. provider: 'local',
  151. email: 'guest@example.com',
  152. name: 'Guest',
  153. password: '',
  154. role: 'guest',
  155. locale: 'en',
  156. defaultEditor: 'markdown',
  157. tfaIsActive: false
  158. })
  159. }
  160. WIKI.logger.info('Setup is complete!')
  161. res.json({
  162. ok: true,
  163. redirectPath: '/',
  164. redirectPort: WIKI.config.port
  165. }).end()
  166. WIKI.config.setup = false
  167. WIKI.logger.info('Stopping Setup...')
  168. WIKI.server.destroy(() => {
  169. WIKI.logger.info('Setup stopped. Starting Wiki.js...')
  170. _.delay(() => {
  171. WIKI.kernel.bootMaster()
  172. }, 1000)
  173. })
  174. } catch (err) {
  175. res.json({ ok: false, error: err.message })
  176. }
  177. })
  178. // ----------------------------------------
  179. // Error handling
  180. // ----------------------------------------
  181. app.use(function (req, res, next) {
  182. var err = new Error('Not Found')
  183. err.status = 404
  184. next(err)
  185. })
  186. app.use(function (err, req, res, next) {
  187. res.status(err.status || 500)
  188. res.send({
  189. message: err.message,
  190. error: WIKI.IS_DEBUG ? err : {}
  191. })
  192. WIKI.logger.error(err.message)
  193. WIKI.telemetry.sendError(err)
  194. })
  195. // ----------------------------------------
  196. // Start HTTP server
  197. // ----------------------------------------
  198. WIKI.logger.info(`HTTP Server on port: [ ${WIKI.config.port} ]`)
  199. app.set('port', WIKI.config.port)
  200. WIKI.server = http.createServer(app)
  201. WIKI.server.listen(WIKI.config.port)
  202. var openConnections = []
  203. WIKI.server.on('connection', (conn) => {
  204. let key = conn.remoteAddress + ':' + conn.remotePort
  205. openConnections[key] = conn
  206. conn.on('close', () => {
  207. delete openConnections[key]
  208. })
  209. })
  210. WIKI.server.destroy = (cb) => {
  211. WIKI.server.close(cb)
  212. for (let key in openConnections) {
  213. openConnections[key].destroy()
  214. }
  215. }
  216. WIKI.server.on('error', (error) => {
  217. if (error.syscall !== 'listen') {
  218. throw error
  219. }
  220. switch (error.code) {
  221. case 'EACCES':
  222. WIKI.logger.error('Listening on port ' + WIKI.config.port + ' requires elevated privileges!')
  223. return process.exit(1)
  224. case 'EADDRINUSE':
  225. WIKI.logger.error('Port ' + WIKI.config.port + ' is already in use!')
  226. return process.exit(1)
  227. default:
  228. throw error
  229. }
  230. })
  231. WIKI.server.on('listening', () => {
  232. WIKI.logger.info('HTTP Server: [ RUNNING ]')
  233. })
  234. }