feat: config wizard UI improv. + upgrade from Mongo

This commit is contained in:
NGPixel
2017-11-19 17:08:23 -05:00
parent ba1d83ebcb
commit 82ea0b50fb
10 changed files with 131 additions and 268 deletions

View File

@@ -1,136 +1,53 @@
'use strict'
/* global winston, ROOTPATH, appconfig */
/* global wiki */
const Promise = require('bluebird')
const crypto = require('crypto')
const fs = Promise.promisifyAll(require('fs-extra'))
const https = require('follow-redirects').https
const klaw = require('klaw')
const path = require('path')
const pm2 = Promise.promisifyAll(require('pm2'))
const tar = require('tar')
const through2 = require('through2')
const zlib = require('zlib')
const _ = require('lodash')
// const pm2 = Promise.promisifyAll(require('pm2'))
// const _ = require('lodash')
const cfgHelper = require('../helpers/config')
module.exports = {
_remoteFile: 'https://github.com/Requarks/wiki/releases/download/{0}/wiki-js.tar.gz',
_installDir: '',
/**
* Install a version of Wiki.js
* Upgrade from Wiki.js 1.x - MongoDB database
*
* @param {any} targetTag The version to install
* @returns {Promise} Promise of the operation
* @param {Object} opts Options object
*/
install (targetTag) {
let self = this
async upgradeFromMongo (opts) {
wiki.telemetry.sendEvent('setup', 'upgradeFromMongo')
self._installDir = path.resolve(ROOTPATH, appconfig.paths.data, 'install')
let mongo = require('mongodb').MongoClient
let parsedMongoConStr = cfgHelper.parseConfigValue(opts.mongoCnStr)
return fs.ensureDirAsync(self._installDir).then(() => {
return fs.emptyDirAsync(self._installDir)
}).then(() => {
let remoteURL = _.replace(self._remoteFile, '{0}', targetTag)
return new Promise((resolve, reject) => {
/**
* Fetch tarball and extract to temporary folder
*/
https.get(remoteURL, resp => {
if (resp.statusCode !== 200) {
return reject(new Error('Remote file not found'))
}
winston.info('[SERVER.System] Install tarball found. Downloading...')
resp.pipe(zlib.createGunzip())
.pipe(tar.Extract({ path: self._installDir }))
.on('error', err => reject(err))
.on('end', () => {
winston.info('[SERVER.System] Tarball extracted. Comparing files...')
/**
* Replace old files
*/
klaw(self._installDir)
.on('error', err => reject(err))
.on('end', () => {
winston.info('[SERVER.System] All files were updated successfully.')
resolve(true)
})
.pipe(self.replaceFile())
})
})
})
}).then(() => {
winston.info('[SERVER.System] Cleaning install leftovers...')
return fs.removeAsync(self._installDir).then(() => {
winston.info('[SERVER.System] Restarting Wiki.js...')
return pm2.restartAsync('wiki').catch(err => { // eslint-disable-line handle-callback-err
winston.error('Unable to restart Wiki.js via pm2... Do a manual restart!')
process.exit()
})
})
}).catch(err => {
winston.warn(err)
})
},
/**
* Replace file if different
*/
replaceFile () {
let self = this
return through2.obj((item, enc, next) => {
if (!item.stats.isDirectory()) {
self.digestFile(item.path).then(sourceHash => {
let destFilePath = _.replace(item.path, self._installDir, ROOTPATH)
return self.digestFile(destFilePath).then(targetHash => {
if (sourceHash === targetHash) {
winston.log('verbose', '[SERVER.System] Skipping ' + destFilePath)
return fs.removeAsync(item.path).then(() => {
return next() || true
})
} else {
winston.log('verbose', '[SERVER.System] Updating ' + destFilePath + '...')
return fs.moveAsync(item.path, destFilePath, { overwrite: true }).then(() => {
return next() || true
})
}
})
}).catch(err => {
throw err
})
} else {
next()
}
})
},
/**
* Generate the hash of a file
*
* @param {String} filePath The absolute path of the file
* @return {Promise<String>} Promise of the hash result
*/
digestFile: (filePath) => {
return new Promise((resolve, reject) => {
let hash = crypto.createHash('sha1')
hash.setEncoding('hex')
fs.createReadStream(filePath)
.on('error', err => { reject(err) })
.on('end', () => {
hash.end()
resolve(hash.read())
})
.pipe(hash)
}).catch(err => {
if (err.code === 'ENOENT') {
return '0'
} else {
throw err
}
// Connect to MongoDB
return mongo.connect(parsedMongoConStr, {
autoReconnect: false,
reconnectTries: 2,
reconnectInterval: 1000,
connectTimeoutMS: 5000,
socketTimeoutMS: 5000
}, async (err, db) => {
try {
if (err !== null) { throw err }
let users = db.collection('users')
// Check if users table is populated
let userCount = await users.count()
if (userCount < 1) {
throw new Error('Users table is empty or invalid!')
}
// Fetch all users
let userData = await users.find({}).toArray()
console.info(userData)
resolve(true)
} catch (err) {
reject(err)
db.close()
}
})
})
}
}