feat: config wizard save

This commit is contained in:
NGPixel
2017-12-16 23:41:16 -05:00
parent 1f350172b9
commit 18dee58a06
12 changed files with 669 additions and 440 deletions

View File

@@ -237,6 +237,7 @@ module.exports = () => {
}
// Update config file
wiki.logger.info('Writing config file to disk...')
let confRaw = await fs.readFileAsync(path.join(wiki.ROOTPATH, 'config.yml'), 'utf8')
let conf = yaml.safeLoad(confRaw)
@@ -256,18 +257,60 @@ module.exports = () => {
wiki.config.uploads = wiki.config.uploads || {}
// 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
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
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 })
} catch (err) {
res.json({ ok: false, error: err.message })

View File

@@ -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()
// 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
}
// 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 = ''
// 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 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
// 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
// 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
})
})
})
// 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()
// 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
}
// 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 = ''
// 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)
// return wiki.disk.validateUploadsFilename(f.originalname, destFolder, false).then((fname) => {
// destFilename = fname
// destFilePath = path.resolve(destFolderPath, destFilename)
// -> Move file to final destination
// // -> 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
})
})
})
// 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()
}
// router.get('/*', (req, res, next) => {
// let fileName = req.params[0]
// if (!validPathRe.test(fileName)) {
// return res.sendStatus(404).end()
// }
// todo: Authentication-based access
// // todo: Authentication-based access
res.sendFile(fileName, {
root: wiki.git.getRepoPath() + '/uploads/',
dotfiles: 'deny'
}, (err) => {
if (err) {
res.status(err.status).end()
}
})
})
// res.sendFile(fileName, {
// root: wiki.git.getRepoPath() + '/uploads/',
// dotfiles: 'deny'
// }, (err) => {
// if (err) {
// res.status(err.status).end()
// }
// })
// })
module.exports = router

View File

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

View File

@@ -54,28 +54,52 @@ module.exports = {
* @param {Array} subsets Array of subsets to load
* @returns Promise
*/
loadFromDb(subsets) {
async loadFromDb(subsets) {
if (!_.isArray(subsets) || subsets.length === 0) {
subsets = wiki.data.configNamespaces
}
return wiki.db.Setting.findAll({
let results = await wiki.db.Setting.findAll({
attributes: ['key', 'config'],
where: {
key: {
$in: subsets
}
}
}).then(results => {
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
}
})
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, {})
})
}
} catch (err) {
wiki.logger.error(`Failed to save configuration to DB: ${err.message}`)
return false
}
return true
}
}

View File

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

View File

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

View File

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

View File

@@ -112,7 +112,7 @@ block body
label.label(for='ipt-public') Public Access
span.desc Should the site be accessible (read only) without login.
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
span.desc Can users create their own account to gain access?
section
@@ -208,7 +208,7 @@ block body
p.control.is-fullwidth
label.label Private Key location
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"')
p.control.is-fullwidth
label.label Private Key Environment Variable