Kaynağa Gözat

feat: config wizard save

NGPixel 7 yıl önce
ebeveyn
işleme
18dee58a06

+ 1 - 1
client/js/components/config-manager.component.js

@@ -47,7 +47,7 @@ export default {
         pathRepo: './repo',
         pathRepo: './repo',
         port: siteConfig.port || 80,
         port: siteConfig.port || 80,
         public: (siteConfig.public === true),
         public: (siteConfig.public === true),
-        selfregister: (siteConfig.selfregister === true),
+        selfRegister: (siteConfig.selfRegister === true),
         telemetry: true,
         telemetry: true,
         title: siteConfig.title || 'Wiki',
         title: siteConfig.title || 'Wiki',
         upgrade: false,
         upgrade: false,

+ 9 - 2
config.sample.yml

@@ -1,7 +1,7 @@
 #######################################################################
 #######################################################################
 # Wiki.js - CONFIGURATION                                             #
 # Wiki.js - CONFIGURATION                                             #
 #######################################################################
 #######################################################################
-# Full explanation + examples in the documentation:
+# Full documentation + examples:
 # https://docs.requarks.io/wiki/install
 # https://docs.requarks.io/wiki/install
 
 
 # ---------------------------------------------------------------------
 # ---------------------------------------------------------------------
@@ -39,11 +39,18 @@ redis:
   db: 0
   db: 0
   password: null
   password: null
 
 
+# ---------------------------------------------------------------------
+# Log Level
+# ---------------------------------------------------------------------
+# Possible values: error, warn, info (default), verbose, debug, silly
+
+logLevel: info
+
 # ---------------------------------------------------------------------
 # ---------------------------------------------------------------------
 # Configuration Mode
 # Configuration Mode
 # ---------------------------------------------------------------------
 # ---------------------------------------------------------------------
 # Possible values:
 # Possible values:
-#  - interactive (default)
+#  - interactive (recommended)
 #  - file
 #  - file
 
 
 configMode: interactive
 configMode: interactive

+ 39 - 39
package.json

@@ -33,17 +33,17 @@
   },
   },
   "homepage": "https://github.com/Requarks/wiki#readme",
   "homepage": "https://github.com/Requarks/wiki#readme",
   "engines": {
   "engines": {
-    "node": ">=8.8.1"
+    "node": ">=8.9.3"
   },
   },
   "dependencies": {
   "dependencies": {
-    "apollo-server-express": "1.2.0",
+    "apollo-server-express": "1.3.0",
     "auto-load": "3.0.0",
     "auto-load": "3.0.0",
     "axios": "0.17.1",
     "axios": "0.17.1",
     "bcryptjs-then": "1.0.1",
     "bcryptjs-then": "1.0.1",
     "bluebird": "3.5.1",
     "bluebird": "3.5.1",
     "body-parser": "1.18.2",
     "body-parser": "1.18.2",
     "bugsnag": "2.0.1",
     "bugsnag": "2.0.1",
-    "bull": "3.3.6",
+    "bull": "3.3.7",
     "bunyan": "1.8.12",
     "bunyan": "1.8.12",
     "cheerio": "1.0.0-rc.2",
     "cheerio": "1.0.0-rc.2",
     "child-process-promise": "2.2.1",
     "child-process-promise": "2.2.1",
@@ -59,24 +59,24 @@
     "express-brute": "1.0.1",
     "express-brute": "1.0.1",
     "express-brute-redis": "0.0.1",
     "express-brute-redis": "0.0.1",
     "express-session": "1.15.6",
     "express-session": "1.15.6",
-    "file-type": "7.2.0",
+    "file-type": "7.4.0",
     "filesize.js": "1.0.2",
     "filesize.js": "1.0.2",
-    "follow-redirects": "1.2.5",
-    "fs-extra": "4.0.2",
+    "follow-redirects": "1.2.6",
+    "fs-extra": "5.0.0",
     "git-wrapper2-promise": "0.2.9",
     "git-wrapper2-promise": "0.2.9",
-    "graphql": "0.11.7",
-    "graphql-tools": "2.7.2",
+    "graphql": "0.12.1",
+    "graphql-tools": "2.13.0",
     "highlight.js": "9.12.0",
     "highlight.js": "9.12.0",
-    "i18next": "10.0.7",
-    "i18next-express-middleware": "1.0.7",
+    "i18next": "10.2.1",
+    "i18next-express-middleware": "1.0.9",
     "i18next-localstorage-cache": "1.1.1",
     "i18next-localstorage-cache": "1.1.1",
     "i18next-node-fs-backend": "1.0.0",
     "i18next-node-fs-backend": "1.0.0",
-    "image-size": "0.6.1",
-    "ioredis": "3.2.1",
+    "image-size": "0.6.2",
+    "ioredis": "3.2.2",
     "jimp": "0.2.28",
     "jimp": "0.2.28",
     "js-yaml": "3.10.0",
     "js-yaml": "3.10.0",
     "jsonwebtoken": "8.1.0",
     "jsonwebtoken": "8.1.0",
-    "klaw": "2.1.0",
+    "klaw": "2.1.1",
     "lodash": "4.17.4",
     "lodash": "4.17.4",
     "markdown-it": "8.4.0",
     "markdown-it": "8.4.0",
     "markdown-it-abbr": "1.0.4",
     "markdown-it-abbr": "1.0.4",
@@ -90,9 +90,9 @@
     "markdown-it-task-lists": "2.1.0",
     "markdown-it-task-lists": "2.1.0",
     "mathjax-node": "1.2.1",
     "mathjax-node": "1.2.1",
     "mime-types": "2.1.17",
     "mime-types": "2.1.17",
-    "moment": "2.19.2",
+    "moment": "2.20.0",
     "moment-timezone": "0.5.14",
     "moment-timezone": "0.5.14",
-    "mongodb": "2.2.33",
+    "mongodb": "3.0.0-rc0",
     "multer": "1.3.0",
     "multer": "1.3.0",
     "node-2fa": "1.1.2",
     "node-2fa": "1.1.2",
     "node-graceful": "0.2.3",
     "node-graceful": "0.2.3",
@@ -106,10 +106,10 @@
     "passport-local": "1.0.0",
     "passport-local": "1.0.0",
     "passport-slack": "0.0.7",
     "passport-slack": "0.0.7",
     "passport-windowslive": "1.0.2",
     "passport-windowslive": "1.0.2",
-    "pg": "7.4.0",
+    "pg": "6.4.2",
     "pg-hstore": "2.3.2",
     "pg-hstore": "2.3.2",
-    "pg-promise": "7.3.1",
-    "pm2": "2.7.2",
+    "pg-promise": "7.3.2",
+    "pm2": "2.9.1",
     "pug": "2.0.0-rc.4",
     "pug": "2.0.0-rc.4",
     "qr-image": "3.2.0",
     "qr-image": "3.2.0",
     "read-chunk": "2.1.0",
     "read-chunk": "2.1.0",
@@ -117,65 +117,65 @@
     "request": "2.83.0",
     "request": "2.83.0",
     "request-promise": "4.2.2",
     "request-promise": "4.2.2",
     "semver": "5.4.1",
     "semver": "5.4.1",
-    "sequelize": "4.22.6",
+    "sequelize": "4.28.5",
     "serve-favicon": "2.4.5",
     "serve-favicon": "2.4.5",
     "simplemde": "1.11.2",
     "simplemde": "1.11.2",
     "stream-to-promise": "2.2.0",
     "stream-to-promise": "2.2.0",
-    "tar": "4.0.2",
+    "tar": "4.1.1",
     "through2": "2.0.3",
     "through2": "2.0.3",
     "uuid": "3.1.0",
     "uuid": "3.1.0",
-    "validator": "9.1.1",
+    "validator": "9.2.0",
     "validator-as-promised": "1.0.2",
     "validator-as-promised": "1.0.2",
     "winston": "2.4.0",
     "winston": "2.4.0",
     "yargs": "10.0.3"
     "yargs": "10.0.3"
   },
   },
   "devDependencies": {
   "devDependencies": {
     "@glimpse/glimpse": "0.22.15",
     "@glimpse/glimpse": "0.22.15",
-    "@panter/vue-i18next": "0.8.1",
-    "apollo-client-preset": "1.0.2",
-    "autoprefixer": "7.1.6",
+    "@panter/vue-i18next": "0.9.1",
+    "apollo-client-preset": "1.0.5",
+    "autoprefixer": "7.2.3",
     "babel-cli": "6.26.0",
     "babel-cli": "6.26.0",
     "babel-core": "6.26.0",
     "babel-core": "6.26.0",
     "babel-jest": "21.2.0",
     "babel-jest": "21.2.0",
     "babel-preset-env": "1.6.1",
     "babel-preset-env": "1.6.1",
     "babel-preset-es2015": "6.24.1",
     "babel-preset-es2015": "6.24.1",
     "babel-preset-stage-2": "6.24.1",
     "babel-preset-stage-2": "6.24.1",
-    "brace": "0.10.0",
+    "brace": "0.11.0",
     "colors": "1.1.2",
     "colors": "1.1.2",
     "consolidate": "0.15.0",
     "consolidate": "0.15.0",
-    "eslint": "4.11.0",
+    "eslint": "4.13.1",
     "eslint-config-requarks": "1.0.7",
     "eslint-config-requarks": "1.0.7",
-    "eslint-config-standard": "10.2.1",
+    "eslint-config-standard": "11.0.0-beta.0",
     "eslint-plugin-import": "2.8.0",
     "eslint-plugin-import": "2.8.0",
     "eslint-plugin-node": "5.2.1",
     "eslint-plugin-node": "5.2.1",
     "eslint-plugin-promise": "3.6.0",
     "eslint-plugin-promise": "3.6.0",
     "eslint-plugin-standard": "3.0.1",
     "eslint-plugin-standard": "3.0.1",
     "eslint-plugin-vue": "3.13.1",
     "eslint-plugin-vue": "3.13.1",
     "fuse-box": "2.5.0-beta.1",
     "fuse-box": "2.5.0-beta.1",
-    "graphql-tag": "^2.5.0",
+    "graphql-tag": "^2.6.0",
     "i18next-xhr-backend": "1.5.0",
     "i18next-xhr-backend": "1.5.0",
     "jest": "21.2.1",
     "jest": "21.2.1",
-    "jest-junit": "3.1.0",
+    "jest-junit": "3.4.0",
     "js-cookie": "2.2.0",
     "js-cookie": "2.2.0",
-    "node-sass": "4.6.1",
-    "nodemon": "1.12.1",
+    "node-sass": "4.7.2",
+    "nodemon": "1.13.3",
     "postcss-selector-parser": "3.1.1",
     "postcss-selector-parser": "3.1.1",
     "pug-lint": "2.5.0",
     "pug-lint": "2.5.0",
     "twemoji-awesome": "1.0.6",
     "twemoji-awesome": "1.0.6",
-    "typescript": "2.6.1",
-    "uglify-es": "3.1.9",
-    "vee-validate": "2.0.0-rc.21",
-    "vue": "2.5.3",
-    "vue-clipboards": "1.1.0",
-    "vue-hot-reload-api": "2.2.3",
+    "typescript": "2.6.2",
+    "uglify-es": "3.2.2",
+    "vee-validate": "2.0.0-rc.27",
+    "vue": "2.5.11",
+    "vue-clipboards": "1.2.0",
+    "vue-hot-reload-api": "2.2.4",
     "vue-lodash": "1.0.4",
     "vue-lodash": "1.0.4",
     "vue-material": "^0.8.1",
     "vue-material": "^0.8.1",
     "vue-resource": "1.3.4",
     "vue-resource": "1.3.4",
     "vue-simple-breakpoints": "1.0.3",
     "vue-simple-breakpoints": "1.0.3",
-    "vue-template-compiler": "2.5.3",
+    "vue-template-compiler": "2.5.11",
     "vue-template-es2015-compiler": "1.6.0",
     "vue-template-es2015-compiler": "1.6.0",
     "vuex": "3.0.1",
     "vuex": "3.0.1",
-    "vuex-persistedstate": "2.3.2"
+    "vuex-persistedstate": "2.4.2"
   },
   },
   "jest": {
   "jest": {
     "testResultsProcessor": "./node_modules/jest-junit",
     "testResultsProcessor": "./node_modules/jest-junit",

+ 49 - 6
server/configure.js

@@ -237,6 +237,7 @@ module.exports = () => {
       }
       }
 
 
       // Update config file
       // Update config file
+      wiki.logger.info('Writing config file to disk...')
       let confRaw = await fs.readFileAsync(path.join(wiki.ROOTPATH, 'config.yml'), 'utf8')
       let confRaw = await fs.readFileAsync(path.join(wiki.ROOTPATH, 'config.yml'), 'utf8')
       let conf = yaml.safeLoad(confRaw)
       let conf = yaml.safeLoad(confRaw)
 
 
@@ -256,18 +257,60 @@ module.exports = () => {
       wiki.config.uploads = wiki.config.uploads || {}
       wiki.config.uploads = wiki.config.uploads || {}
 
 
       // Site namespace
       // Site namespace
-      wiki.config.site.title = req.body.title
-      wiki.config.site.path = req.body.path
-      wiki.config.site.lang = req.body.lang
-      wiki.config.site.rtl = _.includes(wiki.data.rtlLangs, req.body.lang)
-      wiki.config.site.sessionSecret = (await crypto.randomBytesAsync(32)).toString('hex')
+      _.set(wiki.config.site, 'title', req.body.title)
+      _.set(wiki.config.site, 'path', req.body.path)
+      _.set(wiki.config.site, 'lang', req.body.lang)
+      _.set(wiki.config.site, 'rtl', _.includes(wiki.data.rtlLangs, req.body.lang))
+      _.set(wiki.config.site, 'sessionSecret', (await crypto.randomBytesAsync(32)).toString('hex'))
 
 
       // Auth namespace
       // Auth namespace
-      wiki.config.auth.public = (req.body.public === 'true')
+      _.set(wiki.config.auth, 'public', req.body.public === 'true')
+      _.set(wiki.config.auth, 'strategies.local.allowSelfRegister', req.body.selfRegister === 'true')
+
+      // Git namespace
+      _.set(wiki.config.git, 'enabled', req.body.gitUseRemote === 'true')
+      if (wiki.config.git.enabled) {
+        _.set(wiki.config.git, 'url', req.body.gitUrl)
+        _.set(wiki.config.git, 'branch', req.body.gitBranch)
+        _.set(wiki.config.git, 'author.defaultEmail', req.body.gitServerEmail)
+        _.set(wiki.config.git, 'author.useUserEmail', req.body.gitShowUserEmail)
+        _.set(wiki.config.git, 'sslVerify', req.body.gitAuthSSL === 'true')
+        _.set(wiki.config.git, 'auth.type', req.body.gitAuthType)
+        switch (wiki.config.git.auth.type) {
+          case 'basic':
+            _.set(wiki.config.git, 'auth.user', req.body.gitAuthUser)
+            _.set(wiki.config.git, 'auth.pass', req.body.gitAuthPass)
+            break
+          case 'ssh':
+            _.set(wiki.config.git, 'auth.keyPath', req.body.gitAuthSSHKey)
+            break
+          case 'sshenv':
+            _.set(wiki.config.git, 'auth.keyEnv', req.body.gitAuthSSHKeyEnv)
+            break
+          case 'sshdb':
+            _.set(wiki.config.git, 'auth.keyContents', req.body.gitAuthSSHKeyDB)
+            break
+        }
+      }
 
 
       // Logging namespace
       // Logging namespace
       wiki.config.logging.telemetry = (req.body.telemetry === 'true')
       wiki.config.logging.telemetry = (req.body.telemetry === 'true')
 
 
+      // Save config to DB
+      wiki.logger.info('Persisting config to DB...')
+      await wiki.configSvc.saveToDb()
+
+      // Create root administrator
+      wiki.logger.info('Creating root administrator...')
+      await wiki.db.User.upsert({
+        email: req.body.adminEmail,
+        provider: 'local',
+        password: await wiki.db.User.hashPassword(req.body.adminPassword),
+        name: 'Administrator',
+        role: 'admin',
+        tfaIsActive: false
+      })
+
       res.json({ ok: true })
       res.json({ ok: true })
     } catch (err) {
     } catch (err) {
       res.json({ ok: false, error: err.message })
       res.json({ ok: false, error: err.message })

+ 121 - 121
server/controllers/uploads.js

@@ -37,126 +37,126 @@ router.get('/t/*', (req, res, next) => {
   })
   })
 })
 })
 
 
-router.post('/img', wiki.disk.uploadImgHandler, (req, res, next) => {
-  let destFolder = _.chain(req.body.folder).trim().toLower().value()
-
-  wiki.upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
-    if (!destFolderPath) {
-      res.json({ ok: false, msg: wiki.lang.t('errors:invalidfolder') })
-      return true
-    }
-
-    Promise.map(req.files, (f) => {
-      let destFilename = ''
-      let destFilePath = ''
-
-      return wiki.disk.validateUploadsFilename(f.originalname, destFolder, true).then((fname) => {
-        destFilename = fname
-        destFilePath = path.resolve(destFolderPath, destFilename)
-
-        return readChunk(f.path, 0, 262)
-      }).then((buf) => {
-        // -> Check MIME type by magic number
-
-        let mimeInfo = fileType(buf)
-        if (!_.includes(['image/png', 'image/jpeg', 'image/gif', 'image/webp'], mimeInfo.mime)) {
-          return Promise.reject(new Error(wiki.lang.t('errors:invalidfiletype')))
-        }
-        return true
-      }).then(() => {
-        // -> Move file to final destination
-
-        return fs.moveAsync(f.path, destFilePath, { clobber: false })
-      }).then(() => {
-        return {
-          ok: true,
-          filename: destFilename,
-          filesize: f.size
-        }
-      }).reflect()
-    }, {concurrency: 3}).then((results) => {
-      let uplResults = _.map(results, (r) => {
-        if (r.isFulfilled()) {
-          return r.value()
-        } else {
-          return {
-            ok: false,
-            msg: r.reason().message
-          }
-        }
-      })
-      res.json({ ok: true, results: uplResults })
-      return true
-    }).catch((err) => {
-      res.json({ ok: false, msg: err.message })
-      return true
-    })
-  })
-})
-
-router.post('/file', wiki.disk.uploadFileHandler, (req, res, next) => {
-  let destFolder = _.chain(req.body.folder).trim().toLower().value()
-
-  wiki.upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
-    if (!destFolderPath) {
-      res.json({ ok: false, msg: wiki.lang.t('errors:invalidfolder') })
-      return true
-    }
-
-    Promise.map(req.files, (f) => {
-      let destFilename = ''
-      let destFilePath = ''
-
-      return wiki.disk.validateUploadsFilename(f.originalname, destFolder, false).then((fname) => {
-        destFilename = fname
-        destFilePath = path.resolve(destFolderPath, destFilename)
-
-        // -> Move file to final destination
-
-        return fs.moveAsync(f.path, destFilePath, { clobber: false })
-      }).then(() => {
-        return {
-          ok: true,
-          filename: destFilename,
-          filesize: f.size
-        }
-      }).reflect()
-    }, {concurrency: 3}).then((results) => {
-      let uplResults = _.map(results, (r) => {
-        if (r.isFulfilled()) {
-          return r.value()
-        } else {
-          return {
-            ok: false,
-            msg: r.reason().message
-          }
-        }
-      })
-      res.json({ ok: true, results: uplResults })
-      return true
-    }).catch((err) => {
-      res.json({ ok: false, msg: err.message })
-      return true
-    })
-  })
-})
-
-router.get('/*', (req, res, next) => {
-  let fileName = req.params[0]
-  if (!validPathRe.test(fileName)) {
-    return res.sendStatus(404).end()
-  }
-
-  // todo: Authentication-based access
-
-  res.sendFile(fileName, {
-    root: wiki.git.getRepoPath() + '/uploads/',
-    dotfiles: 'deny'
-  }, (err) => {
-    if (err) {
-      res.status(err.status).end()
-    }
-  })
-})
+// router.post('/img', wiki.disk.uploadImgHandler, (req, res, next) => {
+//   let destFolder = _.chain(req.body.folder).trim().toLower().value()
+
+//   wiki.upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
+//     if (!destFolderPath) {
+//       res.json({ ok: false, msg: wiki.lang.t('errors:invalidfolder') })
+//       return true
+//     }
+
+//     Promise.map(req.files, (f) => {
+//       let destFilename = ''
+//       let destFilePath = ''
+
+//       return wiki.disk.validateUploadsFilename(f.originalname, destFolder, true).then((fname) => {
+//         destFilename = fname
+//         destFilePath = path.resolve(destFolderPath, destFilename)
+
+//         return readChunk(f.path, 0, 262)
+//       }).then((buf) => {
+//         // -> Check MIME type by magic number
+
+//         let mimeInfo = fileType(buf)
+//         if (!_.includes(['image/png', 'image/jpeg', 'image/gif', 'image/webp'], mimeInfo.mime)) {
+//           return Promise.reject(new Error(wiki.lang.t('errors:invalidfiletype')))
+//         }
+//         return true
+//       }).then(() => {
+//         // -> Move file to final destination
+
+//         return fs.moveAsync(f.path, destFilePath, { clobber: false })
+//       }).then(() => {
+//         return {
+//           ok: true,
+//           filename: destFilename,
+//           filesize: f.size
+//         }
+//       }).reflect()
+//     }, {concurrency: 3}).then((results) => {
+//       let uplResults = _.map(results, (r) => {
+//         if (r.isFulfilled()) {
+//           return r.value()
+//         } else {
+//           return {
+//             ok: false,
+//             msg: r.reason().message
+//           }
+//         }
+//       })
+//       res.json({ ok: true, results: uplResults })
+//       return true
+//     }).catch((err) => {
+//       res.json({ ok: false, msg: err.message })
+//       return true
+//     })
+//   })
+// })
+
+// router.post('/file', wiki.disk.uploadFileHandler, (req, res, next) => {
+//   let destFolder = _.chain(req.body.folder).trim().toLower().value()
+
+//   wiki.upl.validateUploadsFolder(destFolder).then((destFolderPath) => {
+//     if (!destFolderPath) {
+//       res.json({ ok: false, msg: wiki.lang.t('errors:invalidfolder') })
+//       return true
+//     }
+
+//     Promise.map(req.files, (f) => {
+//       let destFilename = ''
+//       let destFilePath = ''
+
+//       return wiki.disk.validateUploadsFilename(f.originalname, destFolder, false).then((fname) => {
+//         destFilename = fname
+//         destFilePath = path.resolve(destFolderPath, destFilename)
+
+//         // -> Move file to final destination
+
+//         return fs.moveAsync(f.path, destFilePath, { clobber: false })
+//       }).then(() => {
+//         return {
+//           ok: true,
+//           filename: destFilename,
+//           filesize: f.size
+//         }
+//       }).reflect()
+//     }, {concurrency: 3}).then((results) => {
+//       let uplResults = _.map(results, (r) => {
+//         if (r.isFulfilled()) {
+//           return r.value()
+//         } else {
+//           return {
+//             ok: false,
+//             msg: r.reason().message
+//           }
+//         }
+//       })
+//       res.json({ ok: true, results: uplResults })
+//       return true
+//     }).catch((err) => {
+//       res.json({ ok: false, msg: err.message })
+//       return true
+//     })
+//   })
+// })
+
+// router.get('/*', (req, res, next) => {
+//   let fileName = req.params[0]
+//   if (!validPathRe.test(fileName)) {
+//     return res.sendStatus(404).end()
+//   }
+
+//   // todo: Authentication-based access
+
+//   res.sendFile(fileName, {
+//     root: wiki.git.getRepoPath() + '/uploads/',
+//     dotfiles: 'deny'
+//   }, (err) => {
+//     if (err) {
+//       res.status(err.status).end()
+//     }
+//   })
+// })
 
 
 module.exports = router
 module.exports = router

+ 1 - 1
server/master.js

@@ -1,6 +1,6 @@
 /* global wiki */
 /* global wiki */
 
 
-module.exports = () => {
+module.exports = async () => {
   // ----------------------------------------
   // ----------------------------------------
   // Load global modules
   // Load global modules
   // ----------------------------------------
   // ----------------------------------------

+ 35 - 11
server/modules/config.js

@@ -54,28 +54,52 @@ module.exports = {
    * @param {Array} subsets Array of subsets to load
    * @param {Array} subsets Array of subsets to load
    * @returns Promise
    * @returns Promise
    */
    */
-  loadFromDb(subsets) {
+  async loadFromDb(subsets) {
     if (!_.isArray(subsets) || subsets.length === 0) {
     if (!_.isArray(subsets) || subsets.length === 0) {
       subsets = wiki.data.configNamespaces
       subsets = wiki.data.configNamespaces
     }
     }
 
 
-    return wiki.db.Setting.findAll({
+    let results = await wiki.db.Setting.findAll({
       attributes: ['key', 'config'],
       attributes: ['key', 'config'],
       where: {
       where: {
         key: {
         key: {
           $in: subsets
           $in: subsets
         }
         }
       }
       }
-    }).then(results => {
-      if (_.isArray(results) && results.length === subsets.length) {
-        results.forEach(result => {
-          wiki.config[result.key] = result.config
+    })
+    if (_.isArray(results) && results.length === subsets.length) {
+      results.forEach(result => {
+        wiki.config[result.key] = result.config
+      })
+      return true
+    } else {
+      wiki.logger.warn('DB Configuration is empty or incomplete.')
+      return false
+    }
+  },
+  /**
+   * Save config to DB
+   *
+   * @param {Array} subsets Array of subsets to save
+   * @returns Promise
+   */
+  async saveToDb(subsets) {
+    if (!_.isArray(subsets) || subsets.length === 0) {
+      subsets = wiki.data.configNamespaces
+    }
+
+    try {
+      for (let set of subsets) {
+        await wiki.db.Setting.upsert({
+          key: set,
+          config: _.get(wiki.config, set, {})
         })
         })
-        return true
-      } else {
-        wiki.logger.warn('DB Configuration is empty or incomplete.')
-        return false
       }
       }
-    })
+    } catch (err) {
+      wiki.logger.error(`Failed to save configuration to DB: ${err.message}`)
+      return false
+    }
+
+    return true
   }
   }
 }
 }

+ 2 - 2
server/modules/db.js

@@ -73,7 +73,7 @@ module.exports = {
         min: 0,
         min: 0,
         idle: 10000
         idle: 10000
       },
       },
-      logging: log => { wiki.logger.log('verbose', log) },
+      logging: log => { wiki.logger.log('debug', log) },
       operatorsAliases
       operatorsAliases
     })
     })
 
 
@@ -110,7 +110,7 @@ module.exports = {
       syncSchemas() {
       syncSchemas() {
         return self.inst.sync({
         return self.inst.sync({
           force: false,
           force: false,
-          logging: log => { wiki.logger.log('verbose', log) }
+          logging: log => { wiki.logger.log('debug', log) }
         })
         })
       },
       },
       // -> Set Connection App Name
       // -> Set Connection App Name

+ 2 - 2
server/modules/logger.js

@@ -11,10 +11,10 @@ module.exports = {
     // Console
     // Console
 
 
     let logger = new (winston.Logger)({
     let logger = new (winston.Logger)({
-      level: (wiki.IS_DEBUG) ? 'debug' : 'info',
+      level: wiki.config.logLevel,
       transports: [
       transports: [
         new (winston.transports.Console)({
         new (winston.transports.Console)({
-          level: (wiki.IS_DEBUG) ? 'debug' : 'info',
+          level: wiki.config.logLevel,
           prettyPrint: true,
           prettyPrint: true,
           colorize: true,
           colorize: true,
           silent: false,
           silent: false,

+ 2 - 0
server/modules/system.js

@@ -14,6 +14,8 @@ module.exports = {
   async upgradeFromMongo (opts) {
   async upgradeFromMongo (opts) {
     wiki.telemetry.sendEvent('setup', 'upgradeFromMongo')
     wiki.telemetry.sendEvent('setup', 'upgradeFromMongo')
 
 
+    wiki.logger.info('Upgrading from MongoDB...')
+
     let mongo = require('mongodb').MongoClient
     let mongo = require('mongodb').MongoClient
     let parsedMongoConStr = cfgHelper.parseConfigValue(opts.mongoCnStr)
     let parsedMongoConStr = cfgHelper.parseConfigValue(opts.mongoCnStr)
 
 

+ 2 - 2
server/views/configure/index.pug

@@ -112,7 +112,7 @@ block body
                           label.label(for='ipt-public') Public Access
                           label.label(for='ipt-public') Public Access
                           span.desc Should the site be accessible (read only) without login.
                           span.desc Should the site be accessible (read only) without login.
                         p.control.is-fullwidth
                         p.control.is-fullwidth
-                          input#ipt-selfregister(type='checkbox', v-model='conf.selfregister', data-vv-scope='general', name='ipt-selfregister')
+                          input#ipt-selfregister(type='checkbox', v-model='conf.selfRegister', data-vv-scope='general', name='ipt-selfregister')
                           label.label(for='ipt-selfregister') Allow Self-Registration
                           label.label(for='ipt-selfregister') Allow Self-Registration
                           span.desc Can users create their own account to gain access?
                           span.desc Can users create their own account to gain access?
                     section
                     section
@@ -208,7 +208,7 @@ block body
                         p.control.is-fullwidth
                         p.control.is-fullwidth
                           label.label Private Key location
                           label.label Private Key location
                           input(type='text', placeholder='e.g. /etc/wiki/keys/git.pem', v-model='conf.gitAuthSSHKey')
                           input(type='text', placeholder='e.g. /etc/wiki/keys/git.pem', v-model='conf.gitAuthSSHKey')
-                          span.desc The full path to the private key on disk.
+                          span.desc The full path to the #[strong unencrypted] private key on disk.
                       .column(v-show='conf.gitAuthType === "sshenv"')
                       .column(v-show='conf.gitAuthType === "sshenv"')
                         p.control.is-fullwidth
                         p.control.is-fullwidth
                           label.label Private Key Environment Variable
                           label.label Private Key Environment Variable

Dosya farkı çok büyük olduğundan ihmal edildi
+ 323 - 193
yarn.lock


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor