mirror of https://github.com/requarks/wiki
parent
b1499d1d64
commit
416755f17a
@ -0,0 +1,64 @@
|
|||||||
|
.app-error {
|
||||||
|
background: linear-gradient(to bottom, mc('grey', '900') 0%, mc('grey', '800') 100%);
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: mc('grey', '50');
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 250px;
|
||||||
|
filter: grayscale(50%) brightness(120%);
|
||||||
|
animation: errorlogo 5s linear infinite;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
|
||||||
|
@include until($tablet) {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes errorlogo {
|
||||||
|
0% {
|
||||||
|
filter: blur(0) grayscale(50%) brightness(200%) hue-rotate(110deg);
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
filter: blur(0) grayscale(50%) brightness(200%) hue-rotate(110deg) invert(100%);
|
||||||
|
}
|
||||||
|
15% {
|
||||||
|
filter: blur(0) grayscale(50%) brightness(200%) hue-rotate(110deg) invert(0%);
|
||||||
|
}
|
||||||
|
30% {
|
||||||
|
filter: blur(0) grayscale(50%) brightness(200%) hue-rotate(110deg);
|
||||||
|
}
|
||||||
|
32% {
|
||||||
|
filter: blur(0) grayscale(50%) brightness(200%) hue-rotate(2700deg) invert(100%);
|
||||||
|
}
|
||||||
|
34% {
|
||||||
|
filter: blur(0) grayscale(100%) brightness(50%) hue-rotate(110deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
filter: blur(0) grayscale(100%) brightness(200%) hue-rotate(110deg) sepia(0%);
|
||||||
|
}
|
||||||
|
55% {
|
||||||
|
filter: blur(0) grayscale(100%) brightness(100%) hue-rotate(110deg) sepia(100%);
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
filter: blur(0) grayscale(50%) brightness(200%) hue-rotate(110deg) sepia(0%);
|
||||||
|
}
|
||||||
|
90% {
|
||||||
|
filter: blur(0) grayscale(50%) brightness(200%) hue-rotate(110deg);
|
||||||
|
}
|
||||||
|
95% {
|
||||||
|
filter: blur(5px) grayscale(50%) brightness(200%) hue-rotate(720deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
filter: blur(0) grayscale(50%) brightness(200%) hue-rotate(110deg) invert(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
color: mc('grey', '500');
|
||||||
|
font-size: .8rem;
|
||||||
|
}
|
||||||
|
}
|
@ -1,89 +1,53 @@
|
|||||||
const _ = require('lodash')
|
|
||||||
const cluster = require('cluster')
|
|
||||||
const Promise = require('bluebird')
|
|
||||||
|
|
||||||
/* global WIKI */
|
/* global WIKI */
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
numWorkers: 1,
|
async init() {
|
||||||
workers: [],
|
WIKI.logger.info('=======================================')
|
||||||
init() {
|
WIKI.logger.info('= Wiki.js =============================')
|
||||||
if (cluster.isMaster) {
|
WIKI.logger.info('=======================================')
|
||||||
WIKI.logger.info('=======================================')
|
|
||||||
WIKI.logger.info('= Wiki.js =============================')
|
|
||||||
WIKI.logger.info('=======================================')
|
|
||||||
|
|
||||||
WIKI.redis = require('./redis').init()
|
WIKI.db = require('./db').init()
|
||||||
WIKI.queue = require('./queue').init()
|
WIKI.redis = require('./redis').init()
|
||||||
|
WIKI.queue = require('./queue').init()
|
||||||
|
|
||||||
this.setWorkerLimit()
|
await this.preBootMaster()
|
||||||
this.bootMaster()
|
this.bootMaster()
|
||||||
} else {
|
|
||||||
this.bootWorker()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Pre-Master Boot Sequence
|
* Pre-Master Boot Sequence
|
||||||
*/
|
*/
|
||||||
preBootMaster() {
|
async preBootMaster() {
|
||||||
return Promise.mapSeries([
|
try {
|
||||||
() => { return WIKI.db.onReady },
|
await WIKI.db.onReady
|
||||||
() => { return WIKI.configSvc.loadFromDb() },
|
await WIKI.configSvc.loadFromDb()
|
||||||
() => { return WIKI.queue.clean() }
|
await WIKI.queue.clean()
|
||||||
], fn => { return fn() })
|
} catch (err) {
|
||||||
|
WIKI.logger.error(err)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Boot Master Process
|
* Boot Master Process
|
||||||
*/
|
*/
|
||||||
bootMaster() {
|
async bootMaster() {
|
||||||
this.preBootMaster().then(sequenceResults => {
|
try {
|
||||||
if (_.every(sequenceResults, rs => rs === true) && WIKI.config.configMode !== 'setup') {
|
if (WIKI.config.setup) {
|
||||||
this.postBootMaster()
|
WIKI.logger.info('Starting setup wizard...')
|
||||||
} else {
|
|
||||||
WIKI.logger.info('Starting configuration manager...')
|
|
||||||
require('../setup')()
|
require('../setup')()
|
||||||
|
} else {
|
||||||
|
await require('../master')()
|
||||||
|
this.postBootMaster()
|
||||||
}
|
}
|
||||||
return true
|
} catch (err) {
|
||||||
}).catch(err => {
|
|
||||||
WIKI.logger.error(err)
|
WIKI.logger.error(err)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Post-Master Boot Sequence
|
* Post-Master Boot Sequence
|
||||||
*/
|
*/
|
||||||
async postBootMaster() {
|
async postBootMaster() {
|
||||||
await require('../master')()
|
await WIKI.auth.activateStrategies()
|
||||||
|
await WIKI.queue.start()
|
||||||
WIKI.queue.start()
|
|
||||||
|
|
||||||
cluster.on('exit', (worker, code, signal) => {
|
|
||||||
if (!global.DEV) {
|
|
||||||
WIKI.logger.info(`Background Worker #${worker.id} was terminated.`)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Boot Worker Process
|
|
||||||
*/
|
|
||||||
bootWorker() {
|
|
||||||
WIKI.logger.info(`Background Worker #${cluster.worker.id} is initializing...`)
|
|
||||||
require('../worker')
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Spawn new Worker process
|
|
||||||
*/
|
|
||||||
spawnWorker() {
|
|
||||||
this.workers.push(cluster.fork())
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Set Worker count based on config + system capabilities
|
|
||||||
*/
|
|
||||||
setWorkerLimit() {
|
|
||||||
const numCPUs = require('os').cpus().length
|
|
||||||
this.numWorkers = (WIKI.config.workers > 0) ? WIKI.config.workers : numCPUs
|
|
||||||
if (this.numWorkers > numCPUs) {
|
|
||||||
this.numWorkers = numCPUs
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
const Model = require('objection').Model
|
||||||
|
const autoload = require('auto-load')
|
||||||
|
const path = require('path')
|
||||||
|
const _ = require('lodash')
|
||||||
|
|
||||||
|
/* global WIKI */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication model
|
||||||
|
*/
|
||||||
|
module.exports = class Authentication extends Model {
|
||||||
|
static get tableName() { return 'authentication' }
|
||||||
|
|
||||||
|
static get jsonSchema () {
|
||||||
|
return {
|
||||||
|
type: 'object',
|
||||||
|
required: ['key', 'title', 'isEnabled', 'useForm'],
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
id: {type: 'integer'},
|
||||||
|
key: {type: 'string'},
|
||||||
|
title: {type: 'string'},
|
||||||
|
isEnabled: {type: 'boolean'},
|
||||||
|
useForm: {type: 'boolean'},
|
||||||
|
config: {type: 'object'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getEnabledStrategies() {
|
||||||
|
return WIKI.db.authentication.query().where({ isEnabled: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
static async refreshStrategiesFromDisk() {
|
||||||
|
try {
|
||||||
|
const dbStrategies = await WIKI.db.authentication.query()
|
||||||
|
const diskStrategies = autoload(path.join(WIKI.SERVERPATH, 'modules/authentication'))
|
||||||
|
let newStrategies = []
|
||||||
|
_.forOwn(diskStrategies, (strategy, strategyKey) => {
|
||||||
|
if (!_.some(dbStrategies, ['key', strategy.key])) {
|
||||||
|
newStrategies.push({
|
||||||
|
key: strategy.key,
|
||||||
|
title: strategy.title,
|
||||||
|
isEnabled: false,
|
||||||
|
useForm: strategy.useForm,
|
||||||
|
config: _.reduce(strategy.props, (result, value, key) => {
|
||||||
|
_.set(result, value, '')
|
||||||
|
return result
|
||||||
|
}, {})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (newStrategies.length > 0) {
|
||||||
|
await WIKI.db.authentication.query().insert(newStrategies)
|
||||||
|
WIKI.logger.info(`Loaded ${newStrategies.length} new authentication strategies: [ OK ]`)
|
||||||
|
} else {
|
||||||
|
WIKI.logger.info(`No new authentication strategies found: [ SKIPPED ]`)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
WIKI.logger.error(`Failed to scan or load new authentication providers: [ FAILED ]`)
|
||||||
|
WIKI.logger.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
const Model = require('objection').Model
|
||||||
|
const autoload = require('auto-load')
|
||||||
|
const path = require('path')
|
||||||
|
const _ = require('lodash')
|
||||||
|
|
||||||
|
/* global WIKI */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor model
|
||||||
|
*/
|
||||||
|
module.exports = class Editor extends Model {
|
||||||
|
static get tableName() { return 'editors' }
|
||||||
|
|
||||||
|
static get jsonSchema () {
|
||||||
|
return {
|
||||||
|
type: 'object',
|
||||||
|
required: ['key', 'title', 'isEnabled'],
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
id: {type: 'integer'},
|
||||||
|
key: {type: 'string'},
|
||||||
|
title: {type: 'string'},
|
||||||
|
isEnabled: {type: 'boolean'},
|
||||||
|
config: {type: 'object'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getEnabledEditors() {
|
||||||
|
return WIKI.db.editors.query().where({ isEnabled: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
static async refreshEditorsFromDisk() {
|
||||||
|
try {
|
||||||
|
const dbEditors = await WIKI.db.editors.query()
|
||||||
|
const diskEditors = autoload(path.join(WIKI.SERVERPATH, 'modules/editor'))
|
||||||
|
let newEditors = []
|
||||||
|
_.forOwn(diskEditors, (strategy, strategyKey) => {
|
||||||
|
if (!_.some(dbEditors, ['key', strategy.key])) {
|
||||||
|
newEditors.push({
|
||||||
|
key: strategy.key,
|
||||||
|
title: strategy.title,
|
||||||
|
isEnabled: false,
|
||||||
|
config: _.reduce(strategy.props, (result, value, key) => {
|
||||||
|
_.set(result, value, '')
|
||||||
|
return result
|
||||||
|
}, {})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (newEditors.length > 0) {
|
||||||
|
await WIKI.db.editors.query().insert(newEditors)
|
||||||
|
WIKI.logger.info(`Loaded ${newEditors.length} new editors: [ OK ]`)
|
||||||
|
} else {
|
||||||
|
WIKI.logger.info(`No new editors found: [ SKIPPED ]`)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
WIKI.logger.error(`Failed to scan or load new editors: [ FAILED ]`)
|
||||||
|
WIKI.logger.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// ------------------------------------
|
||||||
|
// Markdown Editor (default)
|
||||||
|
// ------------------------------------
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
key: 'markdown',
|
||||||
|
title: 'Markdown (default)',
|
||||||
|
props: [],
|
||||||
|
init (conf) {}
|
||||||
|
}
|
@ -1,13 +1,26 @@
|
|||||||
extends ./master.pug
|
extends ./master.pug
|
||||||
|
|
||||||
block body
|
block body
|
||||||
body(class='is-error')
|
#app.is-fullscreen
|
||||||
.container
|
v-app(dark)
|
||||||
a(href='/'): img(src=config.site.path + '/images/logo.png')
|
.app-error
|
||||||
h1= message
|
v-container
|
||||||
h2= t('errors:generic')
|
.pt-5
|
||||||
a.button.is-amber.is-inverted.is-featured(href=config.site.path+ '/')= t('errors:actions.gohome')
|
v-layout(row)
|
||||||
|
v-flex(xs10)
|
||||||
if error.stack
|
a(href='/'): img(src='/svg/logo-wikijs.svg')
|
||||||
h3= t('errors:debugmsg')
|
v-flex(xs2).text-xs-right
|
||||||
pre: code #{error.stack}
|
v-btn(href='/', depressed, color='red darken-3')
|
||||||
|
v-icon(left) home
|
||||||
|
span Home
|
||||||
|
v-alert(color='grey', outline, :value='true', icon='error')
|
||||||
|
strong.red--text.text--lighten-3 Oops, something went wrong...
|
||||||
|
.body-1.red--text.text--lighten-2= message
|
||||||
|
|
||||||
|
if error.stack
|
||||||
|
v-expansion-panel.mt-5
|
||||||
|
v-expansion-panel-content.red.darken-3(:value='true')
|
||||||
|
div(slot='header') View Debug Trace
|
||||||
|
v-card(color='grey darken-4')
|
||||||
|
v-card-text
|
||||||
|
pre: code #{error.stack}
|
||||||
|
Loading…
Reference in new issue