Merge remote-tracking branch 'upstream/dev' into dev

pull/2754/head
Bharat Rajagopalan 3 years ago
commit 2b527daa06

@ -14,13 +14,14 @@
[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/)
[![Chat on Slack](https://img.shields.io/badge/slack-requarks-CC2B5E.svg?style=flat&logo=slack)](https://wiki.requarks.io/slack)
[![Twitter Follow](https://img.shields.io/badge/follow-%40requarks-blue.svg?style=flat&logo=twitter)](https://twitter.com/requarks)
[![Reddit](https://img.shields.io/badge/reddit-%2Fr%2Fwikijs-orange?logo=reddit&logoColor=white)](https://www.reddit.com/r/wikijs/)
[![Subscribe to Newsletter](https://img.shields.io/badge/newsletter-subscribe-yellow.svg?style=flat&logo=mailchimp)](https://blog.js.wiki/subscribe)
##### A modern, lightweight and powerful wiki app built on NodeJS
</div>
- **[Official Website](https://wiki.js.org/)**
- **[Official Website](https://js.wiki/)**
- **[Documentation](https://docs.requarks.io/)**
- [Requirements](https://docs.requarks.io/install/requirements)
- [Installation](https://docs.requarks.io/install)
@ -107,6 +108,7 @@ Support this project by becoming a sponsor. Your name will show up in the Contri
- Jay Lee ([@polyglotm](https://github.com/polyglotm))
- Kelly Wardrop ([@dropcoded](https://github.com/dropcoded))
- Loki ([@binaryloki](https://github.com/binaryloki))
- Marcilio Leite Neto ([@marclneto](https://github.com/marclneto))
- Mattias Johnson ([@mattiasJohnson](https://github.com/mattiasJohnson))
- Mitchell Rowton ([@mrowton](https://github.com/mrowton))
- M. Scott Ford ([@mscottford](https://github.com/mscottford))
@ -230,6 +232,7 @@ Thank you to all our patrons! 🙏 [[Become a patron](https://www.patreon.com/re
- Alex Zen
- Arti Zirk
- Brandon Curtis
- Dave 'Sri' Seah
- djagoo
- Douglas Lassance
- Ernie Reid
@ -248,6 +251,7 @@ Thank you to all our patrons! 🙏 [[Become a patron](https://www.patreon.com/re
- Matt Gedigian
- Patryk
- Philipp Schürch
- Tracey Duffy
- Richeir
- SmartNET.works
- Stepan Sokolovskyi

@ -107,6 +107,8 @@ The following table lists the configurable parameters of the Wiki.js chart and t
| `postgresql.postgresqlUser` | Postgres username | `postgres` |
| `postgresql.postgresqlHost` | External postgres host | `nil` |
| `postgresql.postgresqlPassword` | External postgres password | `nil` |
| `postgresql.existingSecret` | Provide an existing `Secret` for postgres | `nil` |
| `postgresql.existingSecretKey` | The postgres password key in the existing `Secret` | `postgresql-password` |
| `postgresql.postgresqlPort` | External postgres port | `5432` |
| `postgresql.ssl` | Enable external postgres SSL connection | `false` |
| `postgresql.ca` | Certificate of Authority path for postgres | `nil` |
@ -137,11 +139,11 @@ By default, PostgreSQL is installed as part of the chart.
### Using an external PostgreSQL server
To use an external PostgreSQL server, set `postgresql.enabled` to `false` and then set `postgresql.postgresqlHost` and `postgresql.postgresqlPassword`. The other options (`postgresql.postgresqlDatabase`, `postgresql.postgresqlUser` and `postgresql.postgresqlPort`) may also want changing from their default values.
To use an external PostgreSQL server, set `postgresql.enabled` to `false` and then set `postgresql.postgresqlHost` and `postgresql.postgresqlPassword`. To use an existing `Secret`, set `postgresql.existingSecret`. The other options (`postgresql.postgresqlDatabase`, `postgresql.postgresqlUser`, `postgresql.postgresqlPort` and `postgresql.existingSecretKey`) may also want changing from their default values.
To use an SSL connection you can set `postgresql.ssl` to `true` and if needed the path to a Certificate of Authority can be set using `postgresql.ca` to `/path/to/ca`. Default `postgresql.ssl` value is `false`.
You also need to add the follow Helm template to your deployment:
If `postgresql.existingSecret` is not specified, you also need to add the following Helm template to your deployment in order to create the postgresql `Secret`:
```yaml
kind: Secret

@ -76,7 +76,7 @@ router.post('/u', (req, res, next) => {
}
// Sanitize filename
fileMeta.originalname = sanitize(fileMeta.originalname.toLowerCase().replace(/[\s,;]+/g, '_'))
fileMeta.originalname = sanitize(fileMeta.originalname.toLowerCase().replace(/[\s,;#]+/g, '_'))
// Check if user can upload at path
const assetPath = (folderId) ? hierarchy.map(h => h.slug).join('/') + `/${fileMeta.originalname}` : fileMeta.originalname

@ -40,11 +40,11 @@ module.exports = {
}
},
async unload () {
if (this.fdCache) {
const fds = Object.values(this.fdCache)
if (fds.length > 0) {
WIKI.logger.info('Closing ASAR file descriptors...')
for (const fdItem in this.fdCache) {
fs.closeSync(this.fdCache[fdItem].fd)
}
const closeAsync = require('util').promisify(fs.close)
await Promise.all(fds.map(x => closeAsync(x.fd)))
this.fdCache = {}
}
},

@ -107,19 +107,21 @@ module.exports = {
* Graceful shutdown
*/
async shutdown () {
if (WIKI.models) {
await WIKI.models.unsubscribeToNotifications()
await WIKI.models.knex.client.pool.destroy()
await WIKI.models.knex.destroy()
if (WIKI.servers) {
await WIKI.servers.stopServers()
}
if (WIKI.scheduler) {
WIKI.scheduler.stop()
await WIKI.scheduler.stop()
}
if (WIKI.models) {
await WIKI.models.unsubscribeToNotifications()
if (WIKI.models.knex) {
await WIKI.models.knex.destroy()
}
}
if (WIKI.asar) {
await WIKI.asar.unload()
}
if (WIKI.servers) {
await WIKI.servers.stopServers()
}
process.exit(0)
}
}

@ -12,7 +12,8 @@ class Job {
schedule = 'P1D',
repeat = false,
worker = false
}) {
}, queue) {
this.queue = queue
this.finished = Promise.resolve()
this.name = name
this.immediate = immediate
@ -27,6 +28,7 @@ class Job {
* @param {Object} data Job Data
*/
start(data) {
this.queue.jobs.push(this)
if (this.immediate) {
this.invoke(data)
} else {
@ -55,14 +57,22 @@ class Job {
`--job=${this.name}`,
`--data=${data}`
], {
cwd: WIKI.ROOTPATH
cwd: WIKI.ROOTPATH,
stdio: ['inherit', 'inherit', 'pipe', 'ipc']
})
const stderr = [];
proc.stderr.on('data', chunk => stderr.push(chunk))
this.finished = new Promise((resolve, reject) => {
proc.on('exit', (code, signal) => {
const data = Buffer.concat(stderr).toString()
if (code === 0) {
resolve()
resolve(data)
} else {
reject(signal)
const err = new Error(`Error when running job ${this.name}: ${data}`)
err.exitSignal = signal
err.exitCode = code
err.stderr = data
reject(err)
}
proc.kill()
})
@ -74,16 +84,20 @@ class Job {
} catch (err) {
WIKI.logger.warn(err)
}
if (this.repeat) {
if (this.repeat && this.queue.jobs.includes(this)) {
this.queue(data)
} else {
this.stop().catch(() => {})
}
}
/**
* Stop any future job invocation from occuring
*/
stop() {
async stop() {
clearTimeout(this.timeout)
this.queue.jobs = this.queue.jobs.filter(x => x !== this)
return this.finished
}
}
@ -110,16 +124,11 @@ module.exports = {
})
},
registerJob(opts, data) {
const job = new Job(opts)
const job = new Job(opts, this)
job.start(data)
if (job.repeat) {
this.jobs.push(job)
}
return job
},
stop() {
this.jobs.forEach(job => {
job.stop()
})
async stop() {
return Promise.all(this.jobs.map(job => job.stop()))
}
}

@ -14,6 +14,11 @@ WIKI.logger = require('./logger').init('JOB')
const args = require('yargs').argv
;(async () => {
await require(`../jobs/${args.job}`)(args.data)
process.exit(0)
try {
await require(`../jobs/${args.job}`)(args.data)
process.exit(0)
} catch (e) {
await new Promise(resolve => process.stderr.write(e.message, resolve))
process.exit(1)
}
})()

@ -33,3 +33,16 @@ WIKI.logger = require('./core/logger').init('MASTER')
// ----------------------------------------
WIKI.kernel.init()
// ----------------------------------------
// Register exit handler
// ----------------------------------------
process.on('SIGINT', () => {
WIKI.kernel.shutdown()
})
process.on('message', (msg) => {
if (msg === 'shutdown') {
WIKI.kernel.shutdown()
}
})

@ -74,5 +74,7 @@ module.exports = async (pageId) => {
} catch (err) {
WIKI.logger.error(`Rebuilding page tree: [ FAILED ]`)
WIKI.logger.error(err.message)
// exit process with error code
throw err
}
}

@ -90,5 +90,7 @@ module.exports = async (pageId) => {
} catch (err) {
WIKI.logger.error(`Rendering page ID ${pageId}: [ FAILED ]`)
WIKI.logger.error(err.message)
// exit process with error code
throw err
}
}

@ -9,27 +9,38 @@ const _ = require('lodash')
module.exports = {
init (passport, conf) {
passport.use('google',
new GoogleStrategy({
clientID: conf.clientId,
clientSecret: conf.clientSecret,
callbackURL: conf.callbackURL,
passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
picture: _.get(profile, 'photos[0].value', '')
}
})
cb(null, user)
} catch (err) {
cb(err, null)
const strategy = new GoogleStrategy({
clientID: conf.clientId,
clientSecret: conf.clientSecret,
callbackURL: conf.callbackURL,
passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => {
try {
if (conf.hostedDomain && conf.hostedDomain != profile._json.hd) {
throw new Error('Google authentication should have been performed with domain ' + conf.hostedDomain)
}
})
)
const user = await WIKI.models.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
picture: _.get(profile, 'photos[0].value', '')
}
})
cb(null, user)
} catch (err) {
cb(err, null)
}
})
if (conf.hostedDomain) {
strategy.authorizationParams = function(options) {
return {
hd: conf.hostedDomain
}
}
}
passport.use('google', strategy)
},
logout (conf) {
return '/'

@ -22,3 +22,8 @@ props:
title: Client Secret
hint: Application Client Secret
order: 2
hostedDomain:
type: String
title: Hosted Domain
hint: (optional) Only for G Suite hosted domain. Leave empty otherwise.
order: 3

@ -237,7 +237,7 @@ module.exports = {
// --------------------------------
$('body').contents().toArray().forEach(item => {
if (item.type === 'text' && item.parent.name === 'body') {
if (item && item.type === 'text' && item.parent.name === 'body') {
$(item).wrap('<div></div>')
}
})
@ -249,7 +249,7 @@ module.exports = {
function iterateMustacheNode (node) {
const list = $(node).contents().toArray()
list.forEach(item => {
if (item.type === 'text') {
if (item && item.type === 'text') {
const rawText = $(item).text().replace(/\r?\n|\r/g, '')
if (mustacheRegExp.test(rawText)) {
$(item).parent().attr('v-pre', true)

Loading…
Cancel
Save