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.

159 lines
4.8 KiB

  1. 'use strict'
  2. module.exports = (port, spinner) => {
  3. const ROOTPATH = __dirname
  4. const IS_DEBUG = process.env.NODE_ENV === 'development'
  5. // ----------------------------------------
  6. // Load modules
  7. // ----------------------------------------
  8. const bodyParser = require('body-parser')
  9. const compression = require('compression')
  10. const express = require('express')
  11. const favicon = require('serve-favicon')
  12. const http = require('http')
  13. const path = require('path')
  14. const Promise = require('bluebird')
  15. const _ = require('lodash')
  16. // ----------------------------------------
  17. // Define Express App
  18. // ----------------------------------------
  19. var app = express()
  20. app.use(compression())
  21. // ----------------------------------------
  22. // Public Assets
  23. // ----------------------------------------
  24. app.use(favicon(path.join(ROOTPATH, 'assets', 'favicon.ico')))
  25. app.use(express.static(path.join(ROOTPATH, 'assets')))
  26. // ----------------------------------------
  27. // View Engine Setup
  28. // ----------------------------------------
  29. app.set('views', path.join(ROOTPATH, 'views'))
  30. app.set('view engine', 'pug')
  31. app.use(bodyParser.json())
  32. app.use(bodyParser.urlencoded({ extended: false }))
  33. app.locals._ = require('lodash')
  34. // ----------------------------------------
  35. // Controllers
  36. // ----------------------------------------
  37. app.get('*', (req, res) => {
  38. res.render('configure/index')
  39. })
  40. app.post('/syscheck', (req, res) => {
  41. Promise.mapSeries([
  42. () => {
  43. const semver = require('semver')
  44. if (!semver.satisfies(semver.clean(process.version), '>=4.6.0')) {
  45. throw new Error('Node.js version is too old. Minimum is v4.6.0.')
  46. }
  47. return 'Node.js ' + process.version + ' detected. Minimum is v4.6.0.'
  48. },
  49. () => {
  50. return Promise.try(() => {
  51. require('crypto')
  52. }).catch(err => { // eslint-disable-line handle-callback-err
  53. throw new Error('Crypto Node.js module is not available.')
  54. }).return('Node.js Crypto module is available.')
  55. },
  56. () => {
  57. const exec = require('child_process').exec
  58. const semver = require('semver')
  59. return new Promise((resolve, reject) => {
  60. exec('git --version', (err, stdout, stderr) => {
  61. if (err || stdout.length < 3) {
  62. reject(new Error('Git is not installed or not reachable from PATH.'))
  63. }
  64. let gitver = _.chain(stdout.replace(/[^\d.]/g, '')).split('.').take(3).join('.').value()
  65. if (!semver.satisfies(semver.clean(gitver), '>=2.11.0')) {
  66. reject(new Error('Git version is too old. Minimum is v2.11.0.'))
  67. }
  68. resolve('Git v' + gitver + ' detected. Minimum is v2.11.0.')
  69. })
  70. })
  71. },
  72. () => {
  73. const os = require('os')
  74. if (os.totalmem() < 1024 * 1024 * 768) {
  75. throw new Error('Not enough memory. Minimum is 768 MB.')
  76. }
  77. return _.round(os.totalmem() / (1024 * 1024)) + ' MB of system memory available. Minimum is 768 MB.'
  78. },
  79. () => {
  80. let fs = require('fs')
  81. return Promise.try(() => {
  82. fs.accessSync(path.join(ROOTPATH, 'config.yml'), (fs.constants || fs).W_OK)
  83. }).catch(err => { // eslint-disable-line handle-callback-err
  84. throw new Error('config.yml file is not writable by Node.js process or was not created properly.')
  85. }).return('config.yml is writable by the setup process.')
  86. }
  87. ], test => { return test() }).then(results => {
  88. res.json({ ok: true, results })
  89. }).catch(err => {
  90. res.json({ ok: false, error: err.message })
  91. })
  92. })
  93. // ----------------------------------------
  94. // Error handling
  95. // ----------------------------------------
  96. app.use(function (req, res, next) {
  97. var err = new Error('Not Found')
  98. err.status = 404
  99. next(err)
  100. })
  101. app.use(function (err, req, res, next) {
  102. res.status(err.status || 500)
  103. res.send({
  104. message: err.message,
  105. error: IS_DEBUG ? err : {}
  106. })
  107. spinner.fail(err.message)
  108. process.exit(1)
  109. })
  110. // ----------------------------------------
  111. // Start HTTP server
  112. // ----------------------------------------
  113. spinner.text = 'Starting HTTP server...'
  114. app.set('port', port)
  115. var server = http.createServer(app)
  116. server.listen(port)
  117. server.on('error', (error) => {
  118. if (error.syscall !== 'listen') {
  119. throw error
  120. }
  121. switch (error.code) {
  122. case 'EACCES':
  123. spinner.fail('Listening on port ' + port + ' requires elevated privileges!')
  124. process.exit(1)
  125. break
  126. case 'EADDRINUSE':
  127. spinner.fail('Port ' + port + ' is already in use!')
  128. process.exit(1)
  129. break
  130. default:
  131. throw error
  132. }
  133. })
  134. server.on('listening', () => {
  135. spinner.text = 'Browse to http://localhost:' + port + ' to configure Wiki.js!'
  136. })
  137. }