setup.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. const path = require('path')
  2. const uuid = require('uuid/v4')
  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. // Create default groups
  113. WIKI.logger.info('Creating default groups...')
  114. const adminGroup = await WIKI.models.groups.query().insert({
  115. name: 'Administrators',
  116. permissions: JSON.stringify(['manage:system']),
  117. isSystem: true
  118. })
  119. const guestGroup = await WIKI.models.groups.query().insert({
  120. name: 'Guests',
  121. permissions: JSON.stringify(['read:pages']),
  122. isSystem: true
  123. })
  124. // Load authentication strategies + enable local
  125. await WIKI.models.authentication.refreshStrategiesFromDisk()
  126. await WIKI.models.authentication.query().patch({ isEnabled: true }).where('key', 'local')
  127. // Load editors + enable default
  128. await WIKI.models.editors.refreshEditorsFromDisk()
  129. await WIKI.models.editors.query().patch({ isEnabled: true }).where('key', 'markdown')
  130. // Load loggers
  131. await WIKI.models.loggers.refreshLoggersFromDisk()
  132. // Load renderers
  133. await WIKI.models.renderers.refreshRenderersFromDisk()
  134. // Load search engines + enable default
  135. await WIKI.models.searchEngines.refreshSearchEnginesFromDisk()
  136. await WIKI.models.searchEngines.query().patch({ isEnabled: true }).where('key', 'db')
  137. // Load storage targets
  138. await WIKI.models.storage.refreshTargetsFromDisk()
  139. // Create root administrator
  140. WIKI.logger.info('Creating root administrator...')
  141. await WIKI.models.users.query().delete().where({
  142. providerKey: 'local',
  143. email: req.body.adminEmail
  144. })
  145. const adminUser = await WIKI.models.users.query().insert({
  146. email: req.body.adminEmail,
  147. provider: 'local',
  148. password: req.body.adminPassword,
  149. name: 'Administrator',
  150. locale: 'en',
  151. defaultEditor: 'markdown',
  152. tfaIsActive: false
  153. })
  154. await adminUser.$relatedQuery('groups').relate(adminGroup.id)
  155. // Create Guest account
  156. WIKI.logger.info('Creating guest account...')
  157. await WIKI.models.users.query().delete().where({
  158. providerKey: 'local',
  159. email: 'guest@example.com'
  160. })
  161. const guestUser = await WIKI.models.users.query().insert({
  162. provider: 'local',
  163. email: 'guest@example.com',
  164. name: 'Guest',
  165. password: '',
  166. locale: 'en',
  167. defaultEditor: 'markdown',
  168. tfaIsActive: false
  169. })
  170. await guestUser.$relatedQuery('groups').relate(guestGroup.id)
  171. // Create site nav
  172. WIKI.logger.info('Creating default site navigation')
  173. await WIKI.models.navigation.query().delete().where({ key: 'site' })
  174. await WIKI.models.navigation.query().insert({
  175. key: 'site',
  176. config: [
  177. {
  178. id: uuid(),
  179. icon: 'home',
  180. kind: 'link',
  181. label: 'Home',
  182. target: '/',
  183. targetType: 'home'
  184. }
  185. ]
  186. })
  187. WIKI.logger.info('Setup is complete!')
  188. res.json({
  189. ok: true,
  190. redirectPath: '/',
  191. redirectPort: WIKI.config.port
  192. }).end()
  193. WIKI.config.setup = false
  194. WIKI.logger.info('Stopping Setup...')
  195. WIKI.server.destroy(() => {
  196. WIKI.logger.info('Setup stopped. Starting Wiki.js...')
  197. _.delay(() => {
  198. WIKI.kernel.bootMaster()
  199. }, 1000)
  200. })
  201. } catch (err) {
  202. res.json({ ok: false, error: err.message })
  203. }
  204. })
  205. // ----------------------------------------
  206. // Error handling
  207. // ----------------------------------------
  208. app.use(function (req, res, next) {
  209. var err = new Error('Not Found')
  210. err.status = 404
  211. next(err)
  212. })
  213. app.use(function (err, req, res, next) {
  214. res.status(err.status || 500)
  215. res.send({
  216. message: err.message,
  217. error: WIKI.IS_DEBUG ? err : {}
  218. })
  219. WIKI.logger.error(err.message)
  220. WIKI.telemetry.sendError(err)
  221. })
  222. // ----------------------------------------
  223. // Start HTTP server
  224. // ----------------------------------------
  225. WIKI.logger.info(`HTTP Server on port: [ ${WIKI.config.port} ]`)
  226. app.set('port', WIKI.config.port)
  227. WIKI.server = http.createServer(app)
  228. WIKI.server.listen(WIKI.config.port, WIKI.config.bindIP)
  229. var openConnections = []
  230. WIKI.server.on('connection', (conn) => {
  231. let key = conn.remoteAddress + ':' + conn.remotePort
  232. openConnections[key] = conn
  233. conn.on('close', () => {
  234. delete openConnections[key]
  235. })
  236. })
  237. WIKI.server.destroy = (cb) => {
  238. WIKI.server.close(cb)
  239. for (let key in openConnections) {
  240. openConnections[key].destroy()
  241. }
  242. }
  243. WIKI.server.on('error', (error) => {
  244. if (error.syscall !== 'listen') {
  245. throw error
  246. }
  247. switch (error.code) {
  248. case 'EACCES':
  249. WIKI.logger.error('Listening on port ' + WIKI.config.port + ' requires elevated privileges!')
  250. return process.exit(1)
  251. case 'EADDRINUSE':
  252. WIKI.logger.error('Port ' + WIKI.config.port + ' is already in use!')
  253. return process.exit(1)
  254. default:
  255. throw error
  256. }
  257. })
  258. WIKI.server.on('listening', () => {
  259. WIKI.logger.info('HTTP Server: [ RUNNING ]')
  260. WIKI.logger.info('========================================')
  261. WIKI.logger.info(`Browse to http://localhost:${WIKI.config.port}/`)
  262. WIKI.logger.info('========================================')
  263. })
  264. }