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 */
|
||||
|
||||
module.exports = {
|
||||
numWorkers: 1,
|
||||
workers: [],
|
||||
init() {
|
||||
if (cluster.isMaster) {
|
||||
WIKI.logger.info('=======================================')
|
||||
WIKI.logger.info('= Wiki.js =============================')
|
||||
WIKI.logger.info('=======================================')
|
||||
async init() {
|
||||
WIKI.logger.info('=======================================')
|
||||
WIKI.logger.info('= Wiki.js =============================')
|
||||
WIKI.logger.info('=======================================')
|
||||
|
||||
WIKI.redis = require('./redis').init()
|
||||
WIKI.queue = require('./queue').init()
|
||||
WIKI.db = require('./db').init()
|
||||
WIKI.redis = require('./redis').init()
|
||||
WIKI.queue = require('./queue').init()
|
||||
|
||||
this.setWorkerLimit()
|
||||
this.bootMaster()
|
||||
} else {
|
||||
this.bootWorker()
|
||||
}
|
||||
await this.preBootMaster()
|
||||
this.bootMaster()
|
||||
},
|
||||
/**
|
||||
* Pre-Master Boot Sequence
|
||||
*/
|
||||
preBootMaster() {
|
||||
return Promise.mapSeries([
|
||||
() => { return WIKI.db.onReady },
|
||||
() => { return WIKI.configSvc.loadFromDb() },
|
||||
() => { return WIKI.queue.clean() }
|
||||
], fn => { return fn() })
|
||||
async preBootMaster() {
|
||||
try {
|
||||
await WIKI.db.onReady
|
||||
await WIKI.configSvc.loadFromDb()
|
||||
await WIKI.queue.clean()
|
||||
} catch (err) {
|
||||
WIKI.logger.error(err)
|
||||
process.exit(1)
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Boot Master Process
|
||||
*/
|
||||
bootMaster() {
|
||||
this.preBootMaster().then(sequenceResults => {
|
||||
if (_.every(sequenceResults, rs => rs === true) && WIKI.config.configMode !== 'setup') {
|
||||
this.postBootMaster()
|
||||
} else {
|
||||
WIKI.logger.info('Starting configuration manager...')
|
||||
async bootMaster() {
|
||||
try {
|
||||
if (WIKI.config.setup) {
|
||||
WIKI.logger.info('Starting setup wizard...')
|
||||
require('../setup')()
|
||||
} else {
|
||||
await require('../master')()
|
||||
this.postBootMaster()
|
||||
}
|
||||
return true
|
||||
}).catch(err => {
|
||||
} catch (err) {
|
||||
WIKI.logger.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Post-Master Boot Sequence
|
||||
*/
|
||||
async postBootMaster() {
|
||||
await require('../master')()
|
||||
|
||||
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
|
||||
}
|
||||
await WIKI.auth.activateStrategies()
|
||||
await WIKI.queue.start()
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
block body
|
||||
body(class='is-error')
|
||||
.container
|
||||
a(href='/'): img(src=config.site.path + '/images/logo.png')
|
||||
h1= message
|
||||
h2= t('errors:generic')
|
||||
a.button.is-amber.is-inverted.is-featured(href=config.site.path+ '/')= t('errors:actions.gohome')
|
||||
#app.is-fullscreen
|
||||
v-app(dark)
|
||||
.app-error
|
||||
v-container
|
||||
.pt-5
|
||||
v-layout(row)
|
||||
v-flex(xs10)
|
||||
a(href='/'): img(src='/svg/logo-wikijs.svg')
|
||||
v-flex(xs2).text-xs-right
|
||||
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
|
||||
h3= t('errors:debugmsg')
|
||||
pre: code #{error.stack}
|
||||
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