Browse Source

feat: modular logging + setup wizard

NGPixel 7 years ago
parent
commit
2d5a3203db
43 changed files with 710 additions and 460 deletions
  1. 1 4
      .gitignore
  2. 3 0
      assets/svg/login-bg-motif.svg
  3. 4 4
      client/js/app.js
  4. 0 0
      client/js/components/setup.component.js
  5. 1 1
      client/scss/app.scss
  6. 1 1
      client/scss/components/setup.scss
  7. 4 1
      client/scss/pages/_login.scss
  8. 4 4
      config.sample.yml
  9. 0 10
      dev/fuse/index.js
  10. 16 9
      dev/fuse/tasks.js
  11. 36 15
      package.json
  12. 19 3
      server/app/data.yml
  13. 0 0
      server/extensions/authentication/azure.js
  14. 0 0
      server/extensions/authentication/facebook.js
  15. 0 0
      server/extensions/authentication/github.js
  16. 0 0
      server/extensions/authentication/google.js
  17. 0 0
      server/extensions/authentication/ldap.js
  18. 0 2
      server/extensions/authentication/local.js
  19. 0 0
      server/extensions/authentication/microsoft.js
  20. 0 0
      server/extensions/authentication/slack.js
  21. 32 0
      server/extensions/logging/bugsnag.js
  22. 22 0
      server/extensions/logging/console.js
  23. 21 0
      server/extensions/logging/loggly.js
  24. 20 0
      server/extensions/logging/papertrail.js
  25. 32 0
      server/extensions/logging/rollbar.js
  26. 32 0
      server/extensions/logging/sentry.js
  27. 10 10
      server/master.js
  28. 7 14
      server/middlewares/auth.js
  29. 3 5
      server/modules/auth.js
  30. 1 1
      server/modules/db.js
  31. 1 1
      server/modules/disk.js
  32. 3 3
      server/modules/git.js
  33. 10 8
      server/modules/kernel.js
  34. 19 59
      server/modules/logger.js
  35. 1 1
      server/modules/queue.js
  36. 1 1
      server/modules/redis.js
  37. 0 20
      server/modules/winston-transports/bugsnag.js
  38. 0 20
      server/modules/winston-transports/rollbar.js
  39. 0 20
      server/modules/winston-transports/sentry.js
  40. 3 1
      server/setup.js
  41. 7 7
      server/views/master.pug
  42. 4 4
      server/views/setup.pug
  43. 392 231
      yarn.lock

+ 1 - 4
.gitignore

@@ -15,9 +15,6 @@ npm/node_modules
 .node_repl_history
 npm-debug.log*
 
-# NewRelic APM
-newrelic.js
-
 # Generated assets
 /assets/js
 /assets/css
@@ -41,4 +38,4 @@ newrelic.js
 test-results/
 
 # Localization Resources
-/server/locales/*.yml
+/server/locales/**/*.yml

+ 3 - 0
assets/svg/login-bg-motif.svg

@@ -0,0 +1,3 @@
+<svg width='84' height='48' viewBox='0 0 84 48' xmlns='http://www.w3.org/2000/svg'>
+  <path d='M0 0h12v6H0V0zm28 8h12v6H28V8zm14-8h12v6H42V0zm14 0h12v6H56V0zm0 8h12v6H56V8zM42 8h12v6H42V8zm0 16h12v6H42v-6zm14-8h12v6H56v-6zm14 0h12v6H70v-6zm0-16h12v6H70V0zM28 32h12v6H28v-6zM14 16h12v6H14v-6zM0 24h12v6H0v-6zm0 8h12v6H0v-6zm14 0h12v6H14v-6zm14 8h12v6H28v-6zm-14 0h12v6H14v-6zm28 0h12v6H42v-6zm14-8h12v6H56v-6zm0-8h12v6H56v-6zm14 8h12v6H70v-6zm0 8h12v6H70v-6zM14 24h12v6H14v-6zm14-8h12v6H28v-6zM14 8h12v6H14V8zM0 8h12v6H0V8z' fill='#039be5' fill-opacity='0.4' fill-rule='evenodd'/>
+</svg>

+ 4 - 4
client/js/app.js

@@ -1,7 +1,6 @@
 'use strict'
 
 /* global siteConfig */
-/* eslint-disable no-new */
 
 import CONSTANTS from './constants'
 
@@ -14,6 +13,7 @@ import { HttpLink } from 'apollo-link-http'
 import { InMemoryCache } from 'apollo-cache-inmemory'
 import store from './store'
 import icons from '../svg/nc-icons.svg'
+
 // ====================================
 // Load Modules
 // ====================================
@@ -56,7 +56,7 @@ import adminEditUserComponent from './pages/admin-edit-user.component.js'
 import adminProfileComponent from './pages/admin-profile.component.js'
 import adminSettingsComponent from './pages/admin-settings.component.js'
 import adminThemeComponent from './pages/admin-theme.component.js'
-import configManagerComponent from './components/config-manager.component.js'
+import setupComponent from './components/setup.component.js'
 import contentViewComponent from './pages/content-view.component.js'
 import editorComponent from './components/editor.component.js'
 import sourceViewComponent from './pages/source-view.component.js'
@@ -74,7 +74,7 @@ window.CONSTANTS = CONSTANTS
 
 window.graphQL = new ApolloClient({
   link: new HttpLink({
-    uri: window.location.protocol + '//' + window.location.host + siteConfig.path + '/graphql'
+    uri: window.location.protocol + '//' + window.location.host + siteConfig.path + 'graphql'
   }),
   cache: new InMemoryCache(),
   connectToDevTools: (process.env.node_env === 'development')
@@ -111,7 +111,6 @@ Vue.component('adminSettings', adminSettingsComponent)
 Vue.component('adminTheme', adminThemeComponent)
 Vue.component('anchor', anchorComponent)
 Vue.component('colorPicker', colorPickerComponent)
-Vue.component('configManager', configManagerComponent)
 Vue.component('contentView', contentViewComponent)
 Vue.component('editor', editorComponent)
 Vue.component('editorCodeblock', editorCodeblockComponent)
@@ -130,6 +129,7 @@ Vue.component('modalProfile2fa', modalProfile2faComponent)
 Vue.component('modalUpgradeSystem', modalUpgradeSystemComponent)
 Vue.component('pageLoader', pageLoaderComponent)
 Vue.component('search', searchComponent)
+Vue.component('setup', setupComponent)
 Vue.component('sourceView', sourceViewComponent)
 Vue.component('toggle', toggleComponent)
 Vue.component('tree', treeComponent)

+ 0 - 0
client/js/components/config-manager.component.js → client/js/components/setup.component.js


+ 1 - 1
client/scss/app.scss

@@ -16,7 +16,6 @@ $primary: 'indigo';
 @import 'components/button';
 @import 'components/collapsable-nav';
 @import 'components/color-picker';
-@import 'components/config-manager';
 @import 'components/footer';
 @import 'components/form';
 @import 'components/grid';
@@ -27,6 +26,7 @@ $primary: 'indigo';
 @import 'components/nav';
 @import 'components/panel';
 @import 'components/search';
+@import 'components/setup';
 @import 'components/sidebar';
 @import 'components/table';
 @import 'components/toggle';

+ 1 - 1
client/scss/components/config-manager.scss → client/scss/components/setup.scss

@@ -1,4 +1,4 @@
-.config-manager {
+.setup {
   background-color: #1565c0;
   background-image: url('../svg/config-bg.svg');
   width: 100%;

+ 4 - 1
client/scss/pages/_login.scss

@@ -1,5 +1,8 @@
 .login {
-  background-image: linear-gradient(to right, mc('blue', '400'), mc('blue', '600'));
+  background-color: #0288d1;
+  background-image: url('../svg/login-bg-motif.svg');
+  background-repeat: repeat;
+  background-size: 30%;
   width: 100%;
   height: 100%;
   display: flex;

+ 4 - 4
config.sample.yml

@@ -21,6 +21,7 @@ paths:
 # ---------------------------------------------------------------------
 # Database
 # ---------------------------------------------------------------------
+# PostgreSQL 9.5 or later required
 
 db:
   host: localhost
@@ -32,6 +33,7 @@ db:
 # ---------------------------------------------------------------------
 # Redis
 # ---------------------------------------------------------------------
+# Redis 3.2 or later required
 
 redis:
   host: localhost
@@ -49,11 +51,9 @@ logLevel: info
 # ---------------------------------------------------------------------
 # Configuration Mode
 # ---------------------------------------------------------------------
-# Possible values:
-#  - interactive (recommended)
-#  - file
+# Possible values: auto (default), file, setup
 
-configMode: interactive
+configMode: auto
 
 # ---------------------------------------------------------------------
 # Background Workers

+ 0 - 10
dev/fuse/index.js

@@ -171,16 +171,6 @@ Promise.mapSeries(tasksToRun, fn => fn()).then(() => {
 
   fuse.run().then(() => {
     console.info(colors.green.bold('\nAssets compilation + bundling completed.'))
-
-    if (opts.dev) {
-      nodemon({
-        exec: 'node server',
-        ignore: ['assets/', 'client/', 'data/', 'dev/', 'node_modules/', 'repo/', 'test/', 'test-results/'],
-        ext: 'js json graphql',
-        watch: ['server'],
-        env: { 'NODE_ENV': 'development' }
-      })
-    }
     return true
   }).catch(err => {
     console.error(colors.red(' X Bundle compilation failed! ' + err.message))

+ 16 - 9
dev/fuse/tasks.js

@@ -10,6 +10,9 @@ const yaml = require('js-yaml')
 const _ = require('lodash')
 
 module.exports = {
+  /**
+   * Fetch Localization Resources from Lokalise
+   */
   async fetchLocalizationResources () {
     console.info(colors.white('  └── ') + colors.green('Fetching latest localization resources...'))
     let langs = await request({
@@ -26,18 +29,22 @@ module.exports = {
         let lang = {}
         let langTotal = 0
         langData.forEach(item => {
-          if (item.is_archived === '1') { return }
-          item.key = _.replace(item.key, '::', '.')
-          _.set(lang, item.key, item.translation)
+          if (item.is_archived === '1' || _.includes(item.key, '::')) { return }
+          let keyParts = item.key.split(':')
+          let keyNamespace = (keyParts.length > 1) ? _.head(keyParts) : 'common'
+          let keyString = _.last(keyParts)
+          _.set(lang, `${keyNamespace}.${keyString}`, item.translation)
           langTotal++
         })
-        let langYaml = yaml.safeDump(lang, {
-          indent: 2,
-          sortKeys: true,
-          lineWidth: 2048
+        _.forOwn(lang, (langObject, langNamespace) => {
+          let langYaml = yaml.safeDump(langObject, {
+            indent: 2,
+            sortKeys: true,
+            lineWidth: 2048
+          })
+          fs.outputFileSync(path.join(process.cwd(), `server/locales/${langKey}/${langNamespace}.yml`), langYaml, 'utf8')
         })
-        fs.writeFileSync(path.join(process.cwd(), `server/locales/${langKey}.yml`), langYaml, 'utf8')
-        console.info(colors.white(`      ${langKey}.yml - ${langTotal} keys written`))
+        console.info(colors.white(`      ${langKey} - ${langTotal} keys written`))
       })
     } else {
       throw new Error('Failed to fetch language list from Lokalise API.')

+ 36 - 15
package.json

@@ -8,7 +8,9 @@
     "stop": "node wiki stop",
     "restart": "node wiki restart",
     "build": "node dev/fuse --build",
-    "dev": "node dev/fuse --dev",
+    "dev:client": "node dev/fuse --dev",
+    "dev:server": "nodemon",
+    "dev:server:alt": "node-dev server --no-deps --respawn --no-notify",
     "test": "eslint --ext .js,.vue . && jest"
   },
   "bin": {
@@ -36,7 +38,7 @@
     "node": ">=8.9.3"
   },
   "dependencies": {
-    "apollo-server-express": "1.3.0",
+    "apollo-server-express": "1.3.2",
     "auto-load": "3.0.0",
     "axios": "0.17.1",
     "bcryptjs-then": "1.0.1",
@@ -64,8 +66,8 @@
     "follow-redirects": "1.2.6",
     "fs-extra": "5.0.0",
     "git-wrapper2-promise": "0.2.9",
-    "graphql": "0.12.1",
-    "graphql-tools": "2.13.0",
+    "graphql": "0.12.3",
+    "graphql-tools": "2.14.1",
     "highlight.js": "9.12.0",
     "i18next": "10.2.1",
     "i18next-express-middleware": "1.0.9",
@@ -90,7 +92,7 @@
     "markdown-it-task-lists": "2.1.0",
     "mathjax-node": "1.2.1",
     "mime-types": "2.1.17",
-    "moment": "2.20.0",
+    "moment": "2.20.1",
     "moment-timezone": "0.5.14",
     "mongodb": "3.0.0-rc0",
     "multer": "1.3.0",
@@ -117,11 +119,11 @@
     "request": "2.83.0",
     "request-promise": "4.2.2",
     "semver": "5.4.1",
-    "sequelize": "4.28.5",
+    "sequelize": "4.28.6",
     "serve-favicon": "2.4.5",
     "simplemde": "1.11.2",
     "stream-to-promise": "2.2.0",
-    "tar": "4.1.1",
+    "tar": "4.2.0",
     "through2": "2.0.3",
     "uuid": "3.1.0",
     "validator": "9.2.0",
@@ -136,7 +138,7 @@
     "autoprefixer": "7.2.3",
     "babel-cli": "6.26.0",
     "babel-core": "6.26.0",
-    "babel-jest": "21.2.0",
+    "babel-jest": "22.0.4",
     "babel-preset-env": "1.6.1",
     "babel-preset-es2015": "6.24.1",
     "babel-preset-stage-2": "6.24.1",
@@ -152,27 +154,28 @@
     "eslint-plugin-standard": "3.0.1",
     "eslint-plugin-vue": "3.13.1",
     "fuse-box": "2.5.0-beta.1",
-    "graphql-tag": "^2.6.0",
+    "graphql-tag": "^2.6.1",
     "i18next-xhr-backend": "1.5.0",
-    "jest": "21.2.1",
-    "jest-junit": "3.4.0",
+    "jest": "22.0.4",
+    "jest-junit": "3.4.1",
     "js-cookie": "2.2.0",
+    "node-dev": "3.1.3",
     "node-sass": "4.7.2",
-    "nodemon": "1.13.3",
+    "nodemon": "1.14.3",
     "postcss-selector-parser": "3.1.1",
     "pug-lint": "2.5.0",
     "twemoji-awesome": "1.0.6",
     "typescript": "2.6.2",
     "uglify-es": "3.2.2",
     "vee-validate": "2.0.0-rc.27",
-    "vue": "2.5.11",
+    "vue": "2.5.13",
     "vue-clipboards": "1.2.0",
     "vue-hot-reload-api": "2.2.4",
     "vue-lodash": "1.0.4",
     "vue-material": "^0.8.1",
-    "vue-resource": "1.3.4",
+    "vue-resource": "1.3.5",
     "vue-simple-breakpoints": "1.0.3",
-    "vue-template-compiler": "2.5.11",
+    "vue-template-compiler": "2.5.13",
     "vue-template-es2015-compiler": "1.6.0",
     "vuex": "3.0.1",
     "vuex-persistedstate": "2.4.2"
@@ -192,6 +195,24 @@
     "classNameTemplate": "{classname}-{title}",
     "titleTemplate": "{classname}-{title}"
   },
+  "nodemonConfig": {
+    "exec": "node server --dev",
+    "ignore": [
+      "assets/",
+      "client/",
+      "data/",
+      "dev/",
+      "test/",
+      "test-results/"
+    ],
+    "ext": "js json graphql",
+    "watch": [
+      "server"
+    ],
+    "env": {
+      "NODE_ENV": "development"
+    }
+  },
   "collective": {
     "type": "opencollective",
     "url": "https://opencollective.com/wikijs",

+ 19 - 3
server/app/data.yml

@@ -5,6 +5,7 @@
 name: Wiki.js
 defaults:
   config:
+    # File defaults
     port: 80
     paths:
       repo: ./repo
@@ -20,15 +21,30 @@ defaults:
       port: 6379
       db: 0
       password: null
-    configMode: interactive
+    configMode: auto
     workers: 0
     ha:
       node: primary
       readonly: false
+    # DB defaults
+    auth:
+      public: false
+      strategies:
+        local:
+          enabled: true
+          allowSelfRegister: false
+    git:
+      enabled: false
+    logging:
+      telemetry: false
+      loggers:
+        console:
+          enabled: true
     site:
-      path: ''
       lang: en
-    title: Wiki.js
+      path: ''
+      rtl: false
+      title: Wiki.js
 configNamespaces:
   - auth
   - features

+ 0 - 0
server/authentication/azure.js → server/extensions/authentication/azure.js


+ 0 - 0
server/authentication/facebook.js → server/extensions/authentication/facebook.js


+ 0 - 0
server/authentication/github.js → server/extensions/authentication/github.js


+ 0 - 0
server/authentication/google.js → server/extensions/authentication/google.js


+ 0 - 0
server/authentication/ldap.js → server/extensions/authentication/ldap.js


+ 0 - 2
server/authentication/local.js → server/extensions/authentication/local.js

@@ -1,5 +1,3 @@
-'use strict'
-
 /* global wiki */
 
 // ------------------------------------

+ 0 - 0
server/authentication/microsoft.js → server/extensions/authentication/microsoft.js


+ 0 - 0
server/authentication/slack.js → server/extensions/authentication/slack.js


+ 32 - 0
server/extensions/logging/bugsnag.js

@@ -0,0 +1,32 @@
+const util = require('util')
+const winston = require('winston')
+const _ = require('lodash')
+
+// ------------------------------------
+// Bugsnag
+// ------------------------------------
+
+module.exports = {
+  key: 'bugsnag',
+  title: 'Bugsnag',
+  props: ['key'],
+  init (logger, conf) {
+    let BugsnagLogger = winston.transports.BugsnagLogger = function (options) {
+      this.name = 'bugsnagLogger'
+      this.level = options.level || 'warn'
+      this.bugsnag = require('bugsnag')
+      this.bugsnag.register(options.key)
+    }
+    util.inherits(BugsnagLogger, winston.Transport)
+
+    BugsnagLogger.prototype.log = function (level, msg, meta, callback) {
+      this.bugsnag.notify(new Error(msg), _.assignIn(meta, { severity: level }))
+      callback(null, true)
+    }
+
+    logger.add(BugsnagLogger, {
+      level: 'warn',
+      key: conf.key
+    })
+  }
+}

+ 22 - 0
server/extensions/logging/console.js

@@ -0,0 +1,22 @@
+const winston = require('winston')
+
+/* global wiki */
+
+// ------------------------------------
+// Console
+// ------------------------------------
+
+module.exports = {
+  key: 'console',
+  title: 'Console',
+  props: [],
+  init (logger, conf) {
+    logger.add(winston.transports.Console, {
+      level: wiki.config.logLevel,
+      prettyPrint: true,
+      colorize: true,
+      silent: false,
+      timestamp: true
+    })
+  }
+}

+ 21 - 0
server/extensions/logging/loggly.js

@@ -0,0 +1,21 @@
+const winston = require('winston')
+
+// ------------------------------------
+// Loggly
+// ------------------------------------
+
+module.exports = {
+  key: 'loggly',
+  title: 'Loggly',
+  props: ['token', 'subdomain'],
+  init (logger, conf) {
+    require('winston-loggly-bulk')
+    logger.add(winston.transports.Loggly, {
+      token: conf.token,
+      subdomain: conf.subdomain,
+      tags: ['wiki-js'],
+      level: 'warn',
+      json: true
+    })
+  }
+}

+ 20 - 0
server/extensions/logging/papertrail.js

@@ -0,0 +1,20 @@
+const winston = require('winston')
+
+// ------------------------------------
+// Papertrail
+// ------------------------------------
+
+module.exports = {
+  key: 'papertrail',
+  title: 'Papertrail',
+  props: ['host', 'port'],
+  init (logger, conf) {
+    require('winston-papertrail').Papertrail // eslint-disable-line no-unused-expressions
+    logger.add(winston.transports.Papertrail, {
+      host: conf.host,
+      port: conf.port,
+      level: 'warn',
+      program: 'wiki.js'
+    })
+  }
+}

+ 32 - 0
server/extensions/logging/rollbar.js

@@ -0,0 +1,32 @@
+const util = require('util')
+const winston = require('winston')
+const _ = require('lodash')
+
+// ------------------------------------
+// Rollbar
+// ------------------------------------
+
+module.exports = {
+  key: 'rollbar',
+  title: 'Rollbar',
+  props: ['key'],
+  init (logger, conf) {
+    let RollbarLogger = winston.transports.RollbarLogger = function (options) {
+      this.name = 'rollbarLogger'
+      this.level = options.level || 'warn'
+      this.rollbar = require('rollbar')
+      this.rollbar.init(options.key)
+    }
+    util.inherits(RollbarLogger, winston.Transport)
+
+    RollbarLogger.prototype.log = function (level, msg, meta, callback) {
+      this.rollbar.handleErrorWithPayloadData(new Error(msg), _.assignIn(meta, { level }))
+      callback(null, true)
+    }
+
+    logger.add(RollbarLogger, {
+      level: 'warn',
+      key: conf.key
+    })
+  }
+}

+ 32 - 0
server/extensions/logging/sentry.js

@@ -0,0 +1,32 @@
+const util = require('util')
+const winston = require('winston')
+
+// ------------------------------------
+// Sentry
+// ------------------------------------
+
+module.exports = {
+  key: 'sentry',
+  title: 'Sentry',
+  props: ['key'],
+  init (logger, conf) {
+    let SentryLogger = winston.transports.RollbarLogger = function (options) {
+      this.name = 'sentryLogger'
+      this.level = options.level || 'warn'
+      this.raven = require('raven')
+      this.raven.config(options.key).install()
+    }
+    util.inherits(SentryLogger, winston.Transport)
+
+    SentryLogger.prototype.log = function (level, msg, meta, callback) {
+      level = (level === 'warn') ? 'warning' : level
+      this.raven.captureMessage(msg, { level, extra: meta })
+      callback(null, true)
+    }
+
+    logger.add(SentryLogger, {
+      level: 'warn',
+      key: conf.key
+    })
+  }
+}

+ 10 - 10
server/master.js

@@ -29,7 +29,7 @@ module.exports = async () => {
   const path = require('path')
   const session = require('express-session')
   const SessionRedisStore = require('connect-redis')(session)
-  const graceful = require('node-graceful')
+  // const graceful = require('node-graceful')
   const graphqlApollo = require('apollo-server-express')
   const graphqlSchema = require('./modules/graphql')
 
@@ -142,7 +142,7 @@ module.exports = async () => {
   // Start HTTP server
   // ----------------------------------------
 
-  wiki.logger.info(`HTTP Server on port: ${wiki.config.port}`)
+  wiki.logger.info(`HTTP Server on port: [ ${wiki.config.port} ]`)
 
   app.set('port', wiki.config.port)
   let server = http.createServer(app)
@@ -167,20 +167,20 @@ module.exports = async () => {
   })
 
   server.on('listening', () => {
-    wiki.logger.info('HTTP Server: RUNNING')
+    wiki.logger.info('HTTP Server: [ RUNNING ]')
   })
 
   // ----------------------------------------
   // Graceful shutdown
   // ----------------------------------------
 
-  graceful.on('exit', () => {
-    wiki.logger.info('- SHUTTING DOWN - Performing git sync...')
-    return global.git.resync().then(() => {
-      wiki.logger.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.')
-      process.exit()
-    })
-  })
+  // graceful.on('exit', () => {
+  //   wiki.logger.info('- SHUTTING DOWN - Performing git sync...')
+  //   return global.git.resync().then(() => {
+  //     wiki.logger.info('- SHUTTING DOWN - Git sync successful. Now safe to exit.')
+  //     process.exit()
+  //   })
+  // })
 
   return true
 }

+ 7 - 14
server/middlewares/auth.js

@@ -1,23 +1,16 @@
-'use strict'
-
-/* global rights */
+/* global wiki */
 
 /**
  * Authentication middleware
- *
- * @param      {Express Request}   req     Express Request object
- * @param      {Express Response}  res     Express Response object
- * @param      {Function}          next    Next callback function
- * @return     {any}               void
  */
 module.exports = (req, res, next) => {
   // Is user authenticated ?
 
   if (!req.isAuthenticated()) {
-    if (req.app.locals.appconfig.public !== true) {
+    if (wiki.config.auth.public !== true) {
       return res.redirect('/login')
     } else {
-      req.user = rights.guest
+      // req.user = rights.guest
       res.locals.isGuest = true
     }
   } else {
@@ -26,11 +19,11 @@ module.exports = (req, res, next) => {
 
   // Check permissions
 
-  res.locals.rights = rights.check(req)
+  // res.locals.rights = rights.check(req)
 
-  if (!res.locals.rights.read) {
-    return res.render('error-forbidden')
-  }
+  // if (!res.locals.rights.read) {
+  //   return res.render('error-forbidden')
+  // }
 
   // Expose user data
 

+ 3 - 5
server/modules/auth.js

@@ -31,11 +31,9 @@ module.exports = {
 
     // Load authentication strategies
 
-    wiki.config.auth.strategies.local = {}
-
-    _.forOwn(wiki.config.auth.strategies, (strategyConfig, strategyKey) => {
+    _.forOwn(_.omitBy(wiki.config.auth.strategies, s => s.enabled === false), (strategyConfig, strategyKey) => {
       strategyConfig.callbackURL = `${wiki.config.site.host}${wiki.config.site.path}/login/${strategyKey}/callback`
-      let strategy = require(`../authentication/${strategyKey}`)
+      let strategy = require(`../extensions/authentication/${strategyKey}`)
       strategy.init(passport, strategyConfig)
       fs.readFile(path.join(wiki.ROOTPATH, `assets/svg/auth-icon-${strategyKey}.svg`), 'utf8').then(iconData => {
         strategy.icon = iconData
@@ -47,7 +45,7 @@ module.exports = {
         }
       })
       this.strategies[strategy.key] = strategy
-      wiki.logger.info(`Authentication Provider ${strategyKey}: OK`)
+      wiki.logger.info(`Authentication Provider ${strategyKey}: [ OK ]`)
     })
 
     // Create Guest account for first-time

+ 1 - 1
server/modules/db.js

@@ -80,7 +80,7 @@ module.exports = {
     // Attempt to connect and authenticate to DB
 
     self.inst.authenticate().then(() => {
-      wiki.logger.info('Database (PostgreSQL) connection: OK')
+      wiki.logger.info('Database (PostgreSQL) connection: [ OK ]')
     }).catch(err => {
       wiki.logger.error('Failed to connect to PostgreSQL instance.')
       wiki.logger.error(err)

+ 1 - 1
server/modules/disk.js

@@ -115,7 +115,7 @@ module.exports = {
       wiki.logger.error(err)
     }
 
-    wiki.logger.info('Disk Data Paths: OK')
+    wiki.logger.info('Disk Data Paths: [ OK ]')
   },
 
   /**

+ 3 - 3
server/modules/git.js

@@ -88,8 +88,8 @@ module.exports = {
         self._repo.exists = false
       })
     }).then(() => {
-      if (wiki.config.git === false) {
-        wiki.logger.warn('Remote Git syncing is disabled. Not recommended!')
+      if (wiki.config.git.enabled === false) {
+        wiki.logger.warn('Git Remote Sync: [ DISABLED ]')
         return Promise.resolve(true)
       }
 
@@ -129,7 +129,7 @@ module.exports = {
       wiki.logger.error('Git remote error!')
       throw err
     }).then(() => {
-      wiki.logger.info('Git Repository: OK')
+      wiki.logger.info('Git Repository: [ OK ]')
       return true
     })
   },

+ 10 - 8
server/modules/kernel.js

@@ -37,11 +37,11 @@ module.exports = {
    */
   bootMaster() {
     this.preBootMaster().then(sequenceResults => {
-      if (_.every(sequenceResults, rs => rs === true)) {
+      if (_.every(sequenceResults, rs => rs === true) && wiki.config.configMode !== 'setup') {
         this.postBootMaster()
       } else {
         wiki.logger.info('Starting configuration manager...')
-        require('../configure')()
+        require('../setup')()
       }
       return true
     }).catch(err => {
@@ -52,13 +52,15 @@ module.exports = {
   /**
    * Post-Master Boot Sequence
    */
-  postBootMaster() {
-    require('../master')().then(() => {
-      _.times(this.numWorker, this.spawnWorker)
+  async postBootMaster() {
+    await require('../master')()
 
-      wiki.queue.uplClearTemp.add({}, {
-        repeat: { cron: '*/15 * * * *' }
-      })
+    _.times(this.numWorkers, () => {
+      this.spawnWorker()
+    })
+
+    wiki.queue.uplClearTemp.add({}, {
+      repeat: { cron: '*/15 * * * *' }
     })
 
     cluster.on('exit', (worker, code, signal) => {

+ 19 - 59
server/modules/logger.js

@@ -1,26 +1,18 @@
-'use strict'
-
 /* global wiki */
 
 const cluster = require('cluster')
+const _ = require('lodash')
+const fs = require('fs-extra')
+const path = require('path')
 
 module.exports = {
+  loggers: {},
   init() {
     let winston = require('winston')
 
-    // Console
-
     let logger = new (winston.Logger)({
       level: wiki.config.logLevel,
-      transports: [
-        new (winston.transports.Console)({
-          level: wiki.config.logLevel,
-          prettyPrint: true,
-          colorize: true,
-          silent: false,
-          timestamp: true
-        })
-      ]
+      transports: []
     })
 
     logger.filters.push((level, msg) => {
@@ -28,52 +20,20 @@ module.exports = {
       return '[' + processName + '] ' + msg
     })
 
-    // External services
-
-    // if (wiki.config.externalLogging.bugsnag) {
-    //   const bugsnagTransport = require('./winston-transports/bugsnag')
-    //   logger.add(bugsnagTransport, {
-    //     level: 'warn',
-    //     key: wiki.config.externalLogging.bugsnag
-    //   })
-    // }
-
-    // if (wiki.config.externalLogging.loggly) {
-    //   require('winston-loggly-bulk')
-    //   logger.add(winston.transports.Loggly, {
-    //     token: wiki.config.externalLogging.loggly.token,
-    //     subdomain: wiki.config.externalLogging.loggly.subdomain,
-    //     tags: ['wiki-js'],
-    //     level: 'warn',
-    //     json: true
-    //   })
-    // }
-
-    // if (wiki.config.externalLogging.papertrail) {
-    //   require('winston-papertrail').Papertrail // eslint-disable-line no-unused-expressions
-    //   logger.add(winston.transports.Papertrail, {
-    //     host: wiki.config.externalLogging.papertrail.host,
-    //     port: wiki.config.externalLogging.papertrail.port,
-    //     level: 'warn',
-    //     program: 'wiki.js'
-    //   })
-    // }
-
-    // if (wiki.config.externalLogging.rollbar) {
-    //   const rollbarTransport = require('./winston-transports/rollbar')
-    //   logger.add(rollbarTransport, {
-    //     level: 'warn',
-    //     key: wiki.config.externalLogging.rollbar
-    //   })
-    // }
-
-    // if (wiki.config.externalLogging.sentry) {
-    //   const sentryTransport = require('./winston-transports/sentry')
-    //   logger.add(sentryTransport, {
-    //     level: 'warn',
-    //     key: wiki.config.externalLogging.sentry
-    //   })
-    // }
+    _.forOwn(_.omitBy(wiki.config.logging.loggers, s => s.enabled === false), (loggerConfig, loggerKey) => {
+      let loggerModule = require(`../extensions/logging/${loggerKey}`)
+      loggerModule.init(logger, loggerConfig)
+      fs.readFile(path.join(wiki.ROOTPATH, `assets/svg/auth-icon-${loggerKey}.svg`), 'utf8').then(iconData => {
+        logger.icon = iconData
+      }).catch(err => {
+        if (err.code === 'ENOENT') {
+          logger.icon = '[missing icon]'
+        } else {
+          logger.error(err)
+        }
+      })
+      this.loggers[logger.key] = loggerModule
+    })
 
     return logger
   }

+ 1 - 1
server/modules/queue.js

@@ -29,7 +29,7 @@ module.exports = {
         keyStream.on('end', resolve)
       })
     }).then(() => {
-      wiki.logger.info('Purging old queue jobs: OK')
+      wiki.logger.info('Purging old queue jobs: [ OK ]')
     }).return(true).catch(err => {
       wiki.logger.error(err)
     })

+ 1 - 1
server/modules/redis.js

@@ -21,7 +21,7 @@ module.exports = {
     if (isPlainObject(wiki.config.redis)) {
       let red = new Redis(wiki.config.redis)
       red.on('ready', () => {
-        wiki.logger.info('Redis connection: OK')
+        wiki.logger.info('Redis connection: [ OK ]')
       })
       red.on('error', () => {
         wiki.logger.error('Failed to connect to Redis instance!')

+ 0 - 20
server/modules/winston-transports/bugsnag.js

@@ -1,20 +0,0 @@
-'use strict'
-
-const util = require('util')
-const winston = require('winston')
-const _ = require('lodash')
-
-let BugsnagLogger = winston.transports.BugsnagLogger = function (options) {
-  this.name = 'bugsnagLogger'
-  this.level = options.level || 'warn'
-  this.bugsnag = require('bugsnag')
-  this.bugsnag.register(options.key)
-}
-util.inherits(BugsnagLogger, winston.Transport)
-
-BugsnagLogger.prototype.log = function (level, msg, meta, callback) {
-  this.bugsnag.notify(new Error(msg), _.assignIn(meta, { severity: level }))
-  callback(null, true)
-}
-
-module.exports = BugsnagLogger

+ 0 - 20
server/modules/winston-transports/rollbar.js

@@ -1,20 +0,0 @@
-'use strict'
-
-const util = require('util')
-const winston = require('winston')
-const _ = require('lodash')
-
-let RollbarLogger = winston.transports.RollbarLogger = function (options) {
-  this.name = 'rollbarLogger'
-  this.level = options.level || 'warn'
-  this.rollbar = require('rollbar')
-  this.rollbar.init(options.key)
-}
-util.inherits(RollbarLogger, winston.Transport)
-
-RollbarLogger.prototype.log = function (level, msg, meta, callback) {
-  this.rollbar.handleErrorWithPayloadData(new Error(msg), _.assignIn(meta, { level }))
-  callback(null, true)
-}
-
-module.exports = RollbarLogger

+ 0 - 20
server/modules/winston-transports/sentry.js

@@ -1,20 +0,0 @@
-'use strict'
-
-const util = require('util')
-const winston = require('winston')
-
-let SentryLogger = winston.transports.RollbarLogger = function (options) {
-  this.name = 'sentryLogger'
-  this.level = options.level || 'warn'
-  this.raven = require('raven')
-  this.raven.config(options.key).install()
-}
-util.inherits(SentryLogger, winston.Transport)
-
-SentryLogger.prototype.log = function (level, msg, meta, callback) {
-  level = (level === 'warn') ? 'warning' : level
-  this.raven.captureMessage(msg, { level, extra: meta })
-  callback(null, true)
-}
-
-module.exports = SentryLogger

+ 3 - 1
server/configure.js → server/setup.js

@@ -63,7 +63,7 @@ module.exports = () => {
 
   app.get('*', async (req, res) => {
     let packageObj = await fs.readJson(path.join(wiki.ROOTPATH, 'package.json'))
-    res.render('configure/index', {
+    res.render('setup', {
       packageObj,
       telemetryClientID: wiki.telemetry.cid
     })
@@ -265,6 +265,7 @@ module.exports = () => {
 
       // Auth namespace
       _.set(wiki.config.auth, 'public', req.body.public === 'true')
+      _.set(wiki.config.auth, 'strategies.local.enabled', true)
       _.set(wiki.config.auth, 'strategies.local.allowSelfRegister', req.body.selfRegister === 'true')
 
       // Git namespace
@@ -311,6 +312,7 @@ module.exports = () => {
         tfaIsActive: false
       })
 
+      wiki.logger.info('Setup is complete!')
       res.json({ ok: true })
     } catch (err) {
       res.json({ ok: false, error: err.message })

+ 7 - 7
server/views/master.pug

@@ -6,24 +6,24 @@ html
     meta(name='viewport', content='width=device-width, initial-scale=1')
     meta(name='theme-color', content='#009688')
     meta(name='msapplication-TileColor', content='#009688')
-    meta(name='msapplication-TileImage', content=config.site.path + '/favicons/ms-icon-144x144.png')
+    meta(name='msapplication-TileImage', content=config.site.path + 'favicons/ms-icon-144x144.png')
     title= config.site.title
 
     //- Favicon
     each favsize in [57, 60, 72, 76, 114, 120, 144, 152, 180]
-      link(rel='apple-touch-icon', sizes=favsize + 'x' + favsize, href=config.site.path + '/favicons/apple-icon-' + favsize + 'x' + favsize + '.png')
-    link(rel='icon', type='image/png', sizes='192x192', href=config.site.path + '/favicons/android-icon-192x192.png')
+      link(rel='apple-touch-icon', sizes=favsize + 'x' + favsize, href=config.site.path + 'favicons/apple-icon-' + favsize + 'x' + favsize + '.png')
+    link(rel='icon', type='image/png', sizes='192x192', href=config.site.path + 'favicons/android-icon-192x192.png')
     each favsize in [32, 96, 16]
-      link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href=config.site.path + '/favicons/favicon-' + favsize + 'x' + favsize + '.png')
-    link(rel='manifest', href=config.site.path + '/manifest.json')
+      link(rel='icon', type='image/png', sizes=favsize + 'x' + favsize, href=config.site.path + 'favicons/favicon-' + favsize + 'x' + favsize + '.png')
+    link(rel='manifest', href=config.site.path + 'manifest.json')
 
     //- Site Lang
     script.
       var siteConfig = !{JSON.stringify(config.site)}
 
     //- JS / CSS
-    script(type='text/javascript', src=config.site.path + '/js/libs.js')
-    script(type='text/javascript', src=config.site.path + '/js/app.js')
+    script(type='text/javascript', src=config.site.path + 'js/libs.js')
+    script(type='text/javascript', src=config.site.path + 'js/app.js')
 
     block head
 

+ 4 - 4
server/views/configure/index.pug → server/views/setup.pug

@@ -1,9 +1,9 @@
-extends ../master.pug
+extends master.pug
 
 block body
   body
-    #app.config-manager
-      config-manager(inline-template)
+    #app.setup
+      setup(inline-template)
         div
           .container
             .content(v-cloak)
@@ -342,7 +342,7 @@ block body
                       h4 All done!
                     p(v-if='!loading && final.ok'): strong Wiki.js was configured successfully and is now ready for use.
                     p(v-if='!loading && final.ok')
-                      | Click the <strong>Start</strong> button below to start the Wiki.js server.
+                      | Click the <strong>Start</strong> button below to launch your newly configured wiki.
                     p(v-if='!loading && !final.ok') #[svg.icons.is-18.is-text: use(xlink:href='#nc-square-remove-12')] Error: {{ final.error }}
                   .panel-footer
                     .progress-bar: div(v-bind:style='{width: currentProgress}')

File diff suppressed because it is too large
+ 392 - 231
yarn.lock


Some files were not shown because too many files changed in this diff