Browse Source

Setup Wizard - Admin create + config write

NGPixel 8 years ago
parent
commit
87f3d26a47
6 changed files with 126 additions and 40 deletions
  1. 0 0
      assets/js/configure.js
  2. 1 0
      client/js/configure.js
  3. 116 28
      configure.js
  4. 1 1
      npm/package.json
  5. 1 1
      package.json
  6. 7 10
      views/configure/index.pug

File diff suppressed because it is too large
+ 0 - 0
assets/js/configure.js


+ 1 - 0
client/js/configure.js

@@ -46,6 +46,7 @@ jQuery(document).ready(function ($) {
         db: 'mongodb://localhost:27017/wiki',
         pathData: './data',
         pathRepo: './repo',
+        gitUseRemote: true,
         gitUrl: '',
         gitBranch: 'master',
         gitAuthType: 'ssh',

+ 116 - 28
configure.js

@@ -51,14 +51,14 @@ module.exports = (port, spinner) => {
 
   app.get('*', (req, res) => {
     let langs = []
+    let conf = {}
     try {
       langs = yaml.safeLoad(fs.readFileSync('./app/data.yml', 'utf8')).langs
+      conf = yaml.safeLoad(fs.readFileSync('./config.yml', 'utf8'))
     } catch (err) {
       console.error(err)
     }
-    res.render('configure/index', {
-      langs
-    })
+    res.render('configure/index', { langs, conf })
   })
 
   /**
@@ -164,11 +164,16 @@ module.exports = (port, spinner) => {
     const dataDir = path.resolve(ROOTPATH, req.body.pathData)
     const gitDir = path.resolve(ROOTPATH, req.body.pathRepo)
 
-    let urlObj = url.parse(req.body.gitUrl)
-    if (req.body.gitAuthType === 'basic') {
-      urlObj.auth = req.body.gitAuthUser + ':' + req.body.gitAuthPass
+    let gitRemoteUrl = ''
+    console.log(req.body)
+
+    if (req.body.gitUseRemote === true) {
+      let urlObj = url.parse(req.body.gitUrl)
+      if (req.body.gitAuthType === 'basic') {
+        urlObj.auth = req.body.gitAuthUser + ':' + req.body.gitAuthPass
+      }
+      gitRemoteUrl = url.format(urlObj)
     }
-    const gitRemoteUrl = url.format(urlObj)
 
     Promise.mapSeries([
       () => {
@@ -183,21 +188,25 @@ module.exports = (port, spinner) => {
         })
       },
       () => {
+        if (req.body.gitUseRemote === false) { return false }
         return exec.stdout('git', ['config', '--local', 'user.name', req.body.gitSignatureName], { cwd: gitDir }).then(result => {
           return 'Git Signature Name has been set successfully.'
         })
       },
       () => {
+        if (req.body.gitUseRemote === false) { return false }
         return exec.stdout('git', ['config', '--local', 'user.email', req.body.gitSignatureEmail], { cwd: gitDir }).then(result => {
           return 'Git Signature Name has been set successfully.'
         })
       },
       () => {
+        if (req.body.gitUseRemote === false) { return false }
         return exec.stdout('git', ['config', '--local', '--bool', 'http.sslVerify', req.body.gitAuthSSL], { cwd: gitDir }).then(result => {
           return 'Git SSL Verify flag has been set successfully.'
         })
       },
       () => {
+        if (req.body.gitUseRemote === false) { return false }
         if (req.body.gitAuthType === 'ssh') {
           return exec.stdout('git', ['config', '--local', 'core.sshCommand', 'ssh -i "' + req.body.gitAuthSSHKey + '" -o StrictHostKeyChecking=no'], { cwd: gitDir }).then(result => {
             return 'Git SSH Private Key path has been set successfully.'
@@ -207,6 +216,7 @@ module.exports = (port, spinner) => {
         }
       },
       () => {
+        if (req.body.gitUseRemote === false) { return false }
         return exec.stdout('git', ['remote', 'remove', 'origin'], { cwd: gitDir }).catch(err => {
           if (_.includes(err.message, 'No such remote')) {
             return true
@@ -220,6 +230,7 @@ module.exports = (port, spinner) => {
         })
       },
       () => {
+        if (req.body.gitUseRemote === false) { return false }
         return exec.stdout('git', ['pull', 'origin', req.body.gitBranch], { cwd: gitDir }).then(result => {
           return 'Git Pull operation successful.'
         })
@@ -233,38 +244,115 @@ module.exports = (port, spinner) => {
   })
 
   /**
-   * Check the DB connection
+   * Finalize
    */
   app.post('/finalize', (req, res) => {
+    const bcrypt = require('bcryptjs-then')
+    const crypto = Promise.promisifyAll(require('crypto'))
     let mongo = require('mongodb').MongoClient
-    mongo.connect(req.body.db, {
-      autoReconnect: false,
-      reconnectTries: 2,
-      reconnectInterval: 1000,
-      connectTimeoutMS: 5000,
-      socketTimeoutMS: 5000
-    }, (err, db) => {
-      if (err === null) {
-        // Try to create a test collection
-        db.createCollection('test', (err, results) => {
+
+    Promise.join(
+      new Promise((resolve, reject) => {
+        mongo.connect(req.body.db, {
+          autoReconnect: false,
+          reconnectTries: 2,
+          reconnectInterval: 1000,
+          connectTimeoutMS: 5000,
+          socketTimeoutMS: 5000
+        }, (err, db) => {
           if (err === null) {
-            // Try to drop test collection
-            db.dropCollection('test', (err, results) => {
+            db.createCollection('users', { strict: false }, (err, results) => {
               if (err === null) {
-                res.json({ ok: true })
+                bcrypt.hash(req.body.adminPassword).then(adminPwdHash => {
+                  db.collection('users').findOneAndUpdate({
+                    provider: 'local',
+                    email: req.body.adminEmail
+                  }, {
+                    provider: 'local',
+                    email: req.body.adminEmail,
+                    name: 'Administrator',
+                    password: adminPwdHash,
+                    rights: [{
+                      role: 'admin',
+                      path: '/',
+                      exact: false,
+                      deny: false
+                    }],
+                    updatedAt: new Date(),
+                    createdAt: new Date()
+                  }, {
+                    upsert: true,
+                    returnOriginal: false
+                  }, (err, results) => {
+                    if (err === null) {
+                      resolve(true)
+                    } else {
+                      reject(err)
+                    }
+                    db.close()
+                  })
+                })
               } else {
-                res.json({ ok: false, error: 'Unable to delete test collection. Verify permissions. ' + err.message })
+                reject(err)
+                db.close()
               }
-              db.close()
             })
           } else {
-            res.json({ ok: false, error: 'Unable to create test collection. Verify permissions. ' + err.message })
-            db.close()
+            reject(err)
           }
         })
-      } else {
-        res.json({ ok: false, error: err.message })
-      }
+      }),
+      fs.readFileAsync('./config.yml', 'utf8').then(confRaw => {
+        let conf = yaml.safeLoad(confRaw)
+        conf.title = req.body.title
+        conf.host = req.body.host
+        conf.port = req.body.port
+        conf.paths = {
+          repo: req.body.pathRepo,
+          data: req.body.pathData
+        }
+        conf.uploads = {
+          maxImageFileSize: (conf.uploads && _.isNumber(conf.uploads.maxImageFileSize)) ? conf.uploads.maxImageFileSize : 3,
+          maxOtherFileSize: (conf.uploads && _.isNumber(conf.uploads.maxOtherFileSize)) ? conf.uploads.maxOtherFileSize : 100
+        }
+        conf.lang = req.body.lang
+        conf.public = (conf.public === true)
+        if (conf.auth && conf.auth.local) {
+          conf.auth.local = { enabled: true }
+        } else {
+          conf.auth = { local: { enabled: true } }
+        }
+        conf.admin = req.body.adminEmail
+        conf.db = req.body.db
+        if (req.body.gitUseRemote === false) {
+          conf.git = false
+        } else {
+          conf.git = {
+            url: req.body.gitUrl,
+            branch: req.body.gitBranch,
+            auth: {
+              type: req.body.gitAuthType,
+              username: req.body.gitAuthUser,
+              password: req.body.gitAuthPass,
+              privateKey: req.body.gitAuthSSHKey,
+              sslVerify: (req.body.gitAuthSSL === true)
+            },
+            signature: {
+              name: req.body.gitSignatureName,
+              email: req.body.gitSignatureEmail
+            }
+          }
+        }
+        return crypto.randomBytesAsync(32).then(buf => {
+          conf.sessionSecret = buf.toString('hex')
+          confRaw = yaml.safeDump(conf)
+          return fs.writeFileAsync('./config.yml', confRaw)
+        })
+      })
+    ).then(() => {
+      res.json({ ok: true })
+    }).catch(err => {
+      res.json({ ok: false, error: err.message })
     })
   })
 

+ 1 - 1
npm/package.json

@@ -1,6 +1,6 @@
 {
   "name": "wiki.js",
-  "version": "1.0.0-beta.8.1",
+  "version": "1.0.0-beta.9",
   "description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown",
   "main": "install.js",
   "scripts": {

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "wiki",
-  "version": "1.0.0-beta.8",
+  "version": "1.0.0-beta.9",
   "description": "A modern, lightweight and powerful wiki app built on NodeJS, Git and Markdown",
   "main": "server.js",
   "scripts": {

+ 7 - 10
views/configure/index.pug

@@ -278,8 +278,8 @@ html
                 .panel-footer
                   .progress-bar: div(v-bind:style='{width: currentProgress}')
                   button.button.is-indigo.is-outlined(v-on:click='proceedToPaths', v-bind:disabled='loading') Back
-                  button.button.is-indigo.is-outlined(v-on:click='proceedToAdmin', v-bind:disabled='loading') Skip this step
-                  button.button.is-indigo(v-on:click='proceedToGitCheck', v-bind:disabled='loading || errors.any("git")') Continue
+                  button.button.is-indigo.is-outlined(v-on:click='conf.gitUseRemote = false; proceedToGitCheck()', v-bind:disabled='loading') Skip this step
+                  button.button.is-indigo(v-on:click='conf.gitUseRemote = true; proceedToGitCheck()', v-bind:disabled='loading || errors.any("git")') Continue
             
             //- ==============================================
             //- GIT CHECK
@@ -291,7 +291,7 @@ html
                   span Git Repository Check
                   i(v-if='loading')
                 .panel-content.is-text
-                  p(v-if='loading') #[i.icon-loader.animated.rotateIn.infinite] Testing the connection to Git repository...
+                  p(v-if='loading') #[i.icon-loader.animated.rotateIn.infinite] Verifying Git repository settings...
                   p(v-if='!loading && gitcheck.ok')
                     ul
                       li(v-for='rs in gitcheck.results') #[i.icon-check] {{rs}}
@@ -321,18 +321,18 @@ html
                     p.control.is-fullwidth
                       label.label Administrator Email
                       input(type='text', placeholder='e.g. admin@example.com', v-model='conf.adminEmail', data-vv-scope='admin', name='ipt-adminemail', v-validate='{ required: true, email: true }')
-                      span.desc The full git repository URL to connect to.
+                      span.desc The email address of the administrator account
                   section.columns
                     .column
                       p.control.is-fullwidth
                         label.label Password
                         input(type='password', v-model='conf.adminPassword', data-vv-scope='admin', name='ipt-adminpwd', v-validate='{ required: true, min: 8 }')
-                        span.desc The full git repository URL to connect to.
+                        span.desc At least 8 characters long.
                     .column
                       p.control.is-fullwidth
                         label.label Confirm Password
                         input(type='password', v-model='conf.adminPasswordConfirm', data-vv-scope='admin', name='ipt-adminpwd2', v-validate='{ required: true, confirmed: "ipt-adminpwd" }')
-                        span.desc The git branch to use when synchronizing changes.
+                        span.desc Verify your password again.
                 .panel-footer
                   .progress-bar: div(v-bind:style='{width: currentProgress}')
                   button.button.is-indigo.is-outlined(v-on:click='proceedToGit', v-bind:disabled='loading') Back
@@ -349,9 +349,6 @@ html
                   i(v-if='loading')
                 .panel-content.is-text
                   p(v-if='loading') #[i.icon-loader.animated.rotateIn.infinite] Finalizing your installation...
-                  p(v-if='!loading && final.ok')
-                    ul
-                      li(v-for='rs in final.results') #[i.icon-check] {{rs}}
                   p(v-if='!loading && final.ok')
                     i.icon-check
                     strong  Wiki.js was configured successfully and is now ready for use.
@@ -360,7 +357,7 @@ html
                   p(v-if='!loading && !final.ok') #[i.icon-square-cross] Error: {{ final.error }}
                 .panel-footer
                   .progress-bar: div(v-bind:style='{width: currentProgress}')
-                  button.button.is-indigo.is-outlined(v-on:click='proceedToWelcome', v-bind:disabled='loading') Back
+                  button.button.is-indigo.is-outlined(v-on:click='proceedToAdmin', v-bind:disabled='loading') Back
                   button.button.is-teal(v-on:click='proceedToFinal', v-if='!loading && !final.ok') Try Again
                   button.button.is-green(v-on:click='finish', v-if='loading || final.ok', v-bind:disabled='loading') Start
 

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