mirror of https://github.com/Requarks/wiki.git
NGPixel
6 years ago
27 changed files with 556 additions and 283 deletions
Split View
Diff Options
-
2client/components/nav-header.vue
-
11client/components/profile.vue
-
25client/components/profile/preferences.vue
-
100client/components/profile/profile.vue
-
12client/components/setup.vue
-
1client/scss/app.scss
-
64client/scss/pages/_error.scss
-
26config.sample.yml
-
9server/app/data.yml
-
68server/core/auth.js
-
41server/core/config.js
-
26server/core/db.js
-
94server/core/kernel.js
-
5server/core/localization.js
-
41server/db/migrations/2.0.0.js
-
64server/db/models/authentication.js
-
62server/db/models/editors.js
-
18server/db/models/settings.js
-
3server/db/models/users.js
-
11server/index.js
-
9server/jobs/fetch-graph-locale.js
-
9server/jobs/sync-graph-locales.js
-
2server/master.js
-
10server/modules/editor/markdown.js
-
74server/setup.js
-
33server/views/error.pug
-
19wiki.js
@ -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') |
|||
|
|||
if error.stack |
|||
h3= t('errors:debugmsg') |
|||
pre: code #{error.stack} |
|||
#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 |
|||
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} |
Write
Preview
Loading…
Cancel
Save