feat: core improvements + local fs provider + UI fixes

This commit is contained in:
NGPixel 2018-07-29 22:23:33 -04:00
parent 803d86ff63
commit 2817c72ec3
65 changed files with 482 additions and 264 deletions

View File

@ -110,7 +110,7 @@ Vue.prototype.Velocity = Velocity
Vue.component('admin', () => import(/* webpackChunkName: "admin" */ './components/admin.vue')) Vue.component('admin', () => import(/* webpackChunkName: "admin" */ './components/admin.vue'))
Vue.component('editor', () => import(/* webpackChunkName: "editor" */ './components/editor.vue')) Vue.component('editor', () => import(/* webpackChunkName: "editor" */ './components/editor.vue'))
Vue.component('login', () => import(/* webpackMode: "eager" */ './components/login.vue')) Vue.component('login', () => import(/* webpackMode: "eager" */ './components/login.vue'))
Vue.component('nav-header', () => import(/* webpackMode: "eager" */ './components/nav-header.vue')) Vue.component('nav-header', () => import(/* webpackMode: "eager" */ './components/common/nav-header.vue'))
Vue.component('profile', () => import(/* webpackChunkName: "profile" */ './components/profile.vue')) Vue.component('profile', () => import(/* webpackChunkName: "profile" */ './components/profile.vue'))
Vue.component('setup', () => import(/* webpackChunkName: "setup" */ './components/setup.vue')) Vue.component('setup', () => import(/* webpackChunkName: "setup" */ './components/setup.vue'))
Vue.component('v-card-chin', () => import(/* webpackMode: "eager" */ './components/common/v-card-chin.vue')) Vue.component('v-card-chin', () => import(/* webpackMode: "eager" */ './components/common/v-card-chin.vue'))

View File

@ -13,14 +13,34 @@
v-toolbar-title v-toolbar-title
.subheading {{ $t('admin:general.siteInfo') }} .subheading {{ $t('admin:general.siteInfo') }}
v-subheader General v-subheader General
.px-3 .px-3.pb-3
v-text-field(label='Site Title', required, :counter='50', v-model='siteTitle', prepend-icon='public') v-text-field(label='Site Title', required, :counter='50', v-model='siteTitle', prepend-icon='public')
v-divider.mt-3 v-divider
v-subheader SEO v-subheader SEO
.px-3 .px-3.pb-3
v-text-field(label='Site Description', :counter='255', prepend-icon='public') v-text-field(label='Site Description', :counter='255', prepend-icon='public')
v-text-field(label='Site Keywords', :counter='255', prepend-icon='public') v-text-field(label='Site Keywords', :counter='255', prepend-icon='public')
v-select(label='Meta Robots', chips, tags, :items='metaRobots', v-model='metaRobotsSelection', prepend-icon='public') v-select(label='Meta Robots', chips, tags, :items='metaRobots', v-model='metaRobotsSelection', prepend-icon='public')
v-divider
v-subheader Analytics
.px-3.pb-3
v-text-field(
label='Google Analytics ID'
:counter='255'
prepend-icon='public'
persistent-hint
hint='Property tracking ID for Google Analytics.'
)
v-divider
v-subheader Footer Copyright
.px-3.pb-3
v-text-field(
label='Company / Organization Name'
:counter='255'
prepend-icon='public'
persistent-hint
hint='Name to use when displaying copyright notice in the footer. Leave empty to hide.'
)
v-card-chin v-card-chin
v-spacer v-spacer
v-btn(color='primary') v-btn(color='primary')

View File

@ -4,10 +4,22 @@
v-flex(xs12) v-flex(xs12)
.headline.primary--text Statistics .headline.primary--text Statistics
.subheading.grey--text Useful information about your wiki .subheading.grey--text Useful information about your wiki
.pa-3
fingerprint-spinner(
:animation-duration='1500'
:size='128'
color='#e91e63'
)
.caption.pink--text.mt-3 Compiling latest data...
</template> </template>
<script> <script>
import { FingerprintSpinner } from 'epic-spinners'
export default { export default {
components: {
FingerprintSpinner
},
data() { data() {
return {} return {}
} }

View File

@ -18,7 +18,6 @@
:key='tgt.key' :key='tgt.key'
:label='tgt.title' :label='tgt.title'
color='primary' color='primary'
:disabled='tgt.key === `local`'
hide-details hide-details
) )
@ -30,26 +29,38 @@
template(v-else, v-for='cfg in tgt.config') template(v-else, v-for='cfg in tgt.config')
v-select( v-select(
v-if='cfg.value.type === "string" && cfg.value.enum' v-if='cfg.value.type === "string" && cfg.value.enum'
outline
background-color='grey lighten-2'
:items='cfg.value.enum' :items='cfg.value.enum'
:key='cfg.key' :key='cfg.key'
:label='cfg.key | startCase' :label='cfg.value.title'
v-model='cfg.value.value' v-model='cfg.value.value'
prepend-icon='settings_applications' prepend-icon='settings_applications'
:hint='cfg.value.hint ? cfg.value.hint : ""'
persistent-hint
:class='cfg.value.hint ? "mb-2" : ""'
) )
v-switch( v-switch(
v-else-if='cfg.value.type === "boolean"' v-else-if='cfg.value.type === "boolean"'
:key='cfg.key' :key='cfg.key'
:label='cfg.key | startCase' :label='cfg.value.title'
v-model='cfg.value.value' v-model='cfg.value.value'
color='primary' color='primary'
prepend-icon='settings_applications' prepend-icon='settings_applications'
:hint='cfg.value.hint ? cfg.value.hint : ""'
persistent-hint
) )
v-text-field( v-text-field(
v-else v-else
outline
background-color='grey lighten-2'
:key='cfg.key' :key='cfg.key'
:label='cfg.key | startCase' :label='cfg.value.title'
v-model='cfg.value.value' v-model='cfg.value.value'
prepend-icon='settings_applications' prepend-icon='settings_applications'
:hint='cfg.value.hint ? cfg.value.hint : ""'
persistent-hint
:class='cfg.value.hint ? "mb-2" : ""'
) )
v-divider.mt-3 v-divider.mt-3
v-subheader.pl-0 Sync Direction v-subheader.pl-0 Sync Direction

View File

@ -36,12 +36,18 @@
v-subheader Rescan Modules v-subheader Rescan Modules
v-card-text.pt-0.pl-4 v-card-text.pt-0.pl-4
.body-1 Look for new modules on disk. Existing configurations will be merged. .body-1 Look for new modules on disk. Existing configurations will be merged.
v-btn(depressed).ml-0 v-select.mt-3(
v-icon(left, color='grey') youtube_searched_for v-model='rescanModuleType'
span Authentication :items='moduleTypes'
v-btn(depressed).ml-0 label='Modules Type'
v-icon(left, color='grey') youtube_searched_for outline
span Storage background-color='grey lighten-1'
hide-details
dense
)
v-btn.ml-0(color='primary', depressed, dark)
v-icon(left) chevron_right
span Rescan
v-flex(xs12, sm6) v-flex(xs12, sm6)
v-card v-card
v-toolbar(:color='$vuetify.dark ? "" : "grey darken-3"', dark, dense, flat) v-toolbar(:color='$vuetify.dark ? "" : "grey darken-3"', dark, dense, flat)
@ -58,19 +64,20 @@
.subheading Graph Endpoint .subheading Graph Endpoint
v-card-text v-card-text
.body-1 The Graph API Endpoint from which remote resources like locales, themes and plugins are fetched. .body-1 The Graph API Endpoint from which remote resources like locales, themes and plugins are fetched.
.caption Do not change unless you know what you're doing! .caption.red--text Do not change unless you know what you're doing!
v-text-field.my-2.grey.lighten-3(solo, flat, label='Graph Endpoint', value='https://graph.requarks.io') v-text-field.my-2(outline, hide-details, background-color='grey lighten-1', label='Graph Endpoint', value='https://graph.requarks.io')
v-btn.ml-0(color='primary', depressed, dark) v-btn.ml-0(color='primary', depressed, dark)
v-icon(left) chevron_right v-icon(left) chevron_right
span Save span Save
v-tab-item(key='telemetry', :transition='false', :reverse-transition='false') v-tab-item(key='telemetry', :transition='false', :reverse-transition='false')
v-card.pa-3 v-card
v-form v-form
v-card-text
v-subheader What is telemetry? v-subheader What is telemetry?
.body-1.pl-3 Telemetry allows the developers of Wiki.js to improve the software by collecting basic anonymized data about its usage and the host info. #[br] This is entirely optional and #[strong absolutely no] private data (such as content or personal data) is collected. .body-1.pl-3 Telemetry allows the developers of Wiki.js to improve the software by collecting basic anonymized data about its usage and the host info. #[br] This is entirely optional and #[strong absolutely no] private data (such as content or personal data) is collected.
.body-1.pt-3.pl-3 For maximum privacy, a random client ID is generated every time Wiki.js is started. This ID is used to group requests together while keeping complete anonymity. .body-1.pt-3.pl-3 For maximum privacy, a random client ID is generated every time Wiki.js is started. This ID is used to group requests together while keeping complete anonymity.
v-divider v-divider.my-3
v-subheader What is collected? v-subheader What is collected?
.body-1.pl-3 When telemetry is enabled, only the following data is transmitted: .body-1.pl-3 When telemetry is enabled, only the following data is transmitted:
v-list(dense) v-list(dense)
@ -87,10 +94,10 @@
v-list-tile-avatar: v-icon info_outline v-list-tile-avatar: v-icon info_outline
v-list-tile-content: v-list-tile-title.caption Setup analytics (step reached) v-list-tile-content: v-list-tile-title.caption Setup analytics (step reached)
.body-2.pl-3 .body-2.pl-3
v-divider v-divider.my-3
v-subheader Settings v-subheader Settings
.pl-3 .pl-3
v-switch( v-switch.mt-0(
v-model='telemetry', v-model='telemetry',
label='Enable Telemetry', label='Enable Telemetry',
:value='true', :value='true',
@ -100,8 +107,7 @@
) )
.subheading.mt-3.grey--text.text--darken-1 Client ID .subheading.mt-3.grey--text.text--darken-1 Client ID
.body-1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx .body-1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
v-divider v-card-chin
v-card-actions
v-btn(color='primary') v-btn(color='primary')
v-icon(left) chevron_right v-icon(left) chevron_right
| Save Changes | Save Changes
@ -117,13 +123,13 @@
v-btn.ml-3.mt-3(depressed, dark, color='grey darken-2', href='https://github.com/Requarks/wiki/issues', target='_blank') v-btn.ml-3.mt-3(depressed, dark, color='grey darken-2', href='https://github.com/Requarks/wiki/issues', target='_blank')
icon-github-circle.mr-3(fillColor='#FFFFFF') icon-github-circle.mr-3(fillColor='#FFFFFF')
span Submit an issue span Submit an issue
v-divider v-divider.my-3
v-subheader Suggest a New Feature / Enhancement v-subheader Suggest a New Feature / Enhancement
.body-1.pl-3 Have an idea for a new feature or something that could be improved? .body-1.pl-3 Have an idea for a new feature or something that could be improved?
v-btn.ml-3.mt-3(depressed, dark, color='indigo', href='https://requests.requarks.io/wiki', target='_blank') v-btn.ml-3.mt-3(depressed, dark, color='indigo', href='https://requests.requarks.io/wiki', target='_blank')
v-icon(left) lightbulb_outline v-icon(left) lightbulb_outline
span Submit an idea span Submit an idea
v-divider v-divider.my-3
v-subheader Questions / Comments v-subheader Questions / Comments
.body-1.pl-3 Join our gitter channel. We are very active and friendly! .body-1.pl-3 Join our gitter channel. We are very active and friendly!
v-btn.ml-3.mt-3(depressed, dark, color='pink', href='https://gitter.im/Requarks/wiki', target='_blank') v-btn.ml-3.mt-3(depressed, dark, color='pink', href='https://gitter.im/Requarks/wiki', target='_blank')
@ -144,6 +150,15 @@ export default {
data() { data() {
return { return {
tab: '0', tab: '0',
moduleTypes: [
{ text: 'Authentication', value: 'authentication' },
{ text: 'Editor', value: 'editor' },
{ text: 'Logging', value: 'logging' },
{ text: 'Rendering', value: 'renderer' },
{ text: 'Search Engine', value: 'search' },
{ text: 'Storage', value: 'storage' }
],
rescanModuleType: 'authentication',
telemetry: true telemetry: true
} }
}, },

View File

@ -1,5 +1,5 @@
<template lang='pug'> <template lang='pug'>
v-toolbar(color='black', dark, app, clipped-left, fixed, flat, dense) v-toolbar(color='black', dark, app, clipped-left, fixed, flat, :dense='dense')
v-menu(open-on-hover, offset-y, bottom, left, nudge-top='-18', min-width='250') v-menu(open-on-hover, offset-y, bottom, left, nudge-top='-18', min-width='250')
v-toolbar-side-icon(slot='activator') v-toolbar-side-icon(slot='activator')
v-icon view_module v-icon view_module
@ -41,15 +41,15 @@
v-if='searchIsShown', v-if='searchIsShown',
v-model='search', v-model='search',
clearable, clearable,
color='blue', color='white',
label='Search...', label='Search...',
single-line, single-line,
solo
flat
hide-details, hide-details,
append-icon='search', prepend-inner-icon='search',
:append-icon-cb='searchEnter',
:loading='searchIsLoading', :loading='searchIsLoading',
@keyup.enter='searchEnter', @keyup.enter='searchEnter'
@keyup.esc='searchToggle'
) )
v-progress-linear( v-progress-linear(
indeterminate, indeterminate,
@ -58,11 +58,9 @@
color='blue' color='blue'
) )
v-spacer v-spacer
v-progress-circular.mr-3(indeterminate, color='blue', :size='22', :width='2' v-show='isLoading') .navHeaderLoading.mr-3
v-progress-circular(indeterminate, color='blue', :size='22', :width='2' v-show='isLoading')
slot(name='actions') slot(name='actions')
transition(name='navHeaderSearch')
v-btn(icon, @click='searchToggle', v-if='!searchIsShown')
v-icon(color='grey') search
v-btn(icon, href='/a') v-btn(icon, href='/a')
v-icon(color='grey') settings v-icon(color='grey') settings
v-menu(offset-y, min-width='300') v-menu(offset-y, min-width='300')
@ -90,11 +88,21 @@ import { mapGetters } from 'vuex'
/* global siteConfig */ /* global siteConfig */
export default { export default {
props: {
dense: {
type: Boolean,
default: false
},
hideSearch: {
type: Boolean,
default: false
}
},
data() { data() {
return { return {
menuIsShown: true, menuIsShown: true,
searchIsLoading: false, searchIsLoading: false,
searchIsShown: false, searchIsShown: true,
search: '' search: ''
} }
}, },
@ -102,16 +110,12 @@ export default {
...mapGetters(['isLoading']), ...mapGetters(['isLoading']),
title() { return siteConfig.title } title() { return siteConfig.title }
}, },
methods: { created() {
searchToggle() { if (this.hideSearch || this.dense) {
this.searchIsLoading = false this.searchIsShown = false
this.searchIsShown = !this.searchIsShown
if (this.searchIsShown) {
this.$nextTick(() => {
this.$refs.searchField.focus()
})
} }
}, },
methods: {
searchEnter() { searchEnter() {
this.searchIsLoading = true this.searchIsLoading = true
} }
@ -130,7 +134,10 @@ export default {
} }
&-enter, &-leave-to { &-enter, &-leave-to {
opacity: 0; opacity: 0;
transform: translateY(-25px); transform: scale(.7, .7);
} }
} }
.navHeaderLoading { // To avoid search bar jumping
width: 22px;
}
</style> </style>

View File

@ -1,6 +1,6 @@
<template lang="pug"> <template lang="pug">
.editor .editor
nav-header nav-header(dense)
template(slot='actions') template(slot='actions')
v-btn(outline, color='green', @click.native.stop='save') v-btn(outline, color='green', @click.native.stop='save')
v-icon(color='green', left) check v-icon(color='green', left) check

View File

@ -57,6 +57,7 @@
:items='namespaces' :items='namespaces'
v-model='locale' v-model='locale'
hide-details hide-details
:disabled='mode !== "create"'
) )
v-flex(xs12, md10) v-flex(xs12, md10)
v-text-field( v-text-field(
@ -68,6 +69,7 @@
hint='Do not include any leading or trailing slashes.' hint='Do not include any leading or trailing slashes.'
persistent-hint persistent-hint
@click:append='showPathSelector' @click:append='showPathSelector'
:disabled='mode !== "create"'
) )
v-combobox( v-combobox(
background-color='grey lighten-2' background-color='grey lighten-2'
@ -186,7 +188,7 @@
<script> <script>
import _ from 'lodash' import _ from 'lodash'
import { sync } from 'vuex-pathify' import { sync, get } from 'vuex-pathify'
export default { export default {
data() { data() {
@ -204,6 +206,7 @@ export default {
} }
}, },
computed: { computed: {
mode: get('editor/mode'),
title: sync('editor/title'), title: sync('editor/title'),
description: sync('editor/description'), description: sync('editor/description'),
locale: sync('editor/locale'), locale: sync('editor/locale'),

View File

@ -3,7 +3,7 @@
@import "base/base"; @import "base/base";
@import 'base/icons'; @import 'base/icons';
// @import "../libs/animate/animate"; @import "../libs/animate/animate";
@import 'components/markdown-content'; @import 'components/markdown-content';
@import 'components/btn'; @import 'components/btn';

View File

@ -33,11 +33,28 @@
} }
} }
&::after {
content: '';
display: block;
width: 95vw;
height: 95vh;
border: 3px dotted rgba(255,255,255,.2);
border-radius: 50px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
z-index: 1;
}
img { img {
width: 500px; width: 500px;
filter: grayscale(100%) brightness(160%); filter: grayscale(100%) brightness(160%);
margin-bottom: 3rem; margin-bottom: 3rem;
z-index: 2; z-index: 2;
animation-duration: 3s;
@include until($tablet) { @include until($tablet) {
width: 300px; width: 300px;
@ -52,7 +69,7 @@
margin-bottom: 3rem; margin-bottom: 3rem;
z-index: 2; z-index: 2;
} }
.button { .v-btn {
z-index: 2; z-index: 2;
} }
} }

View File

@ -17,7 +17,7 @@ module.exports = {
}) })
passport.deserializeUser(function (id, done) { passport.deserializeUser(function (id, done) {
WIKI.db.users.query().findById(id).then((user) => { WIKI.models.users.query().findById(id).then((user) => {
if (user) { if (user) {
done(null, user) done(null, user)
} else { } else {
@ -40,7 +40,7 @@ module.exports = {
_.forEach(currentStrategies, stg => { passport.unuse(stg) }) _.forEach(currentStrategies, stg => { passport.unuse(stg) })
// Load enabled strategies // Load enabled strategies
const enabledStrategies = await WIKI.db.authentication.getStrategies() const enabledStrategies = await WIKI.models.authentication.getStrategies()
for (let idx in enabledStrategies) { for (let idx in enabledStrategies) {
const stg = enabledStrategies[idx] const stg = enabledStrategies[idx]
if (!stg.isEnabled) { continue } if (!stg.isEnabled) { continue }

View File

@ -52,7 +52,7 @@ module.exports = {
* Load config from DB * Load config from DB
*/ */
async loadFromDb() { async loadFromDb() {
let conf = await WIKI.db.settings.getConfig() let conf = await WIKI.models.settings.getConfig()
if (conf) { if (conf) {
WIKI.config = _.defaultsDeep(conf, WIKI.config) WIKI.config = _.defaultsDeep(conf, WIKI.config)
} else { } else {
@ -73,9 +73,9 @@ module.exports = {
if (!_.isPlainObject(value)) { if (!_.isPlainObject(value)) {
value = { v: value } value = { v: value }
} }
let affectedRows = await WIKI.db.settings.query().patch({ value }).where('key', key) let affectedRows = await WIKI.models.settings.query().patch({ value }).where('key', key)
if (affectedRows === 0 && value) { if (affectedRows === 0 && value) {
await WIKI.db.settings.query().insert({ key, value }) await WIKI.models.settings.query().insert({ key, value })
} }
} }
} catch (err) { } catch (err) {

View File

@ -74,7 +74,7 @@ module.exports = {
// Load DB Models // Load DB Models
const models = autoload(path.join(WIKI.SERVERPATH, 'db/models')) const models = autoload(path.join(WIKI.SERVERPATH, 'models'))
// Set init tasks // Set init tasks

View File

@ -6,7 +6,7 @@ module.exports = {
WIKI.logger.info('= Wiki.js =============================') WIKI.logger.info('= Wiki.js =============================')
WIKI.logger.info('=======================================') WIKI.logger.info('=======================================')
WIKI.db = require('./db').init() WIKI.models = require('./db').init()
WIKI.redis = require('./redis').init() WIKI.redis = require('./redis').init()
WIKI.queue = require('./queue').init() WIKI.queue = require('./queue').init()
@ -18,7 +18,7 @@ module.exports = {
*/ */
async preBootMaster() { async preBootMaster() {
try { try {
await WIKI.db.onReady await WIKI.models.onReady
await WIKI.configSvc.loadFromDb() await WIKI.configSvc.loadFromDb()
await WIKI.queue.clean() await WIKI.queue.clean()
} catch (err) { } catch (err) {
@ -48,6 +48,7 @@ module.exports = {
*/ */
async postBootMaster() { async postBootMaster() {
await WIKI.auth.activateStrategies() await WIKI.auth.activateStrategies()
await WIKI.models.storage.refreshTargetsFromDisk()
await WIKI.queue.start() await WIKI.queue.start()
} }
} }

View File

@ -52,7 +52,7 @@ module.exports = {
} }
}, },
async loadLocale(locale, opts = { silent: false }) { async loadLocale(locale, opts = { silent: false }) {
const res = await WIKI.db.locales.query().findOne('code', locale) const res = await WIKI.models.locales.query().findOne('code', locale)
if (res) { if (res) {
if (_.isPlainObject(res.strings)) { if (_.isPlainObject(res.strings)) {
_.forOwn(res.strings, (data, ns) => { _.forOwn(res.strings, (data, ns) => {

View File

@ -45,7 +45,7 @@ module.exports = {
$not: 'guest' $not: 'guest'
} }
}).toArray() }).toArray()
await WIKI.db.User.bulkCreate(_.map(userData, usr => { await WIKI.models.User.bulkCreate(_.map(userData, usr => {
return { return {
email: usr.email, email: usr.email,
name: usr.name || 'Imported User', name: usr.name || 'Imported User',

View File

@ -79,6 +79,7 @@ exports.up = knex => {
table.string('publishStartDate') table.string('publishStartDate')
table.string('publishEndDate') table.string('publishEndDate')
table.text('content') table.text('content')
table.string('contentType').notNullable()
table.string('createdAt').notNullable() table.string('createdAt').notNullable()
}) })
// PAGES ------------------------------- // PAGES -------------------------------
@ -92,6 +93,7 @@ exports.up = knex => {
table.string('publishStartDate') table.string('publishStartDate')
table.string('publishEndDate') table.string('publishEndDate')
table.text('content') table.text('content')
table.string('contentType').notNullable()
table.string('createdAt').notNullable() table.string('createdAt').notNullable()
table.string('updatedAt').notNullable() table.string('updatedAt').notNullable()
}) })

View File

@ -16,7 +16,7 @@ module.exports = {
}, },
AuthenticationQuery: { AuthenticationQuery: {
async strategies(obj, args, context, info) { async strategies(obj, args, context, info) {
let strategies = await WIKI.db.authentication.getStrategies() let strategies = await WIKI.models.authentication.getStrategies()
strategies = strategies.map(stg => ({ strategies = strategies.map(stg => ({
...stg, ...stg,
config: _.sortBy(_.transform(stg.config, (res, value, key) => { config: _.sortBy(_.transform(stg.config, (res, value, key) => {
@ -31,7 +31,7 @@ module.exports = {
AuthenticationMutation: { AuthenticationMutation: {
async login(obj, args, context) { async login(obj, args, context) {
try { try {
let authResult = await WIKI.db.users.login(args, context) let authResult = await WIKI.models.users.login(args, context)
return { return {
...authResult, ...authResult,
responseResult: graphHelper.generateSuccess('Login success') responseResult: graphHelper.generateSuccess('Login success')
@ -42,7 +42,7 @@ module.exports = {
}, },
async loginTFA(obj, args, context) { async loginTFA(obj, args, context) {
try { try {
let authResult = await WIKI.db.users.loginTFA(args, context) let authResult = await WIKI.models.users.loginTFA(args, context)
return { return {
...authResult, ...authResult,
responseResult: graphHelper.generateSuccess('TFA success') responseResult: graphHelper.generateSuccess('TFA success')
@ -54,7 +54,7 @@ module.exports = {
async updateStrategies(obj, args, context) { async updateStrategies(obj, args, context) {
try { try {
for (let str of args.strategies) { for (let str of args.strategies) {
await WIKI.db.authentication.query().patch({ await WIKI.models.authentication.query().patch({
isEnabled: str.isEnabled, isEnabled: str.isEnabled,
config: _.reduce(str.config, (result, value, key) => { config: _.reduce(str.config, (result, value, key) => {
_.set(result, `${value.key}.value`, value.value) _.set(result, `${value.key}.value`, value.value)

View File

@ -4,19 +4,19 @@
module.exports = { module.exports = {
Query: { Query: {
comments(obj, args, context, info) { comments(obj, args, context, info) {
return WIKI.db.Comment.findAll({ where: args }) return WIKI.models.Comment.findAll({ where: args })
} }
}, },
Mutation: { Mutation: {
createComment(obj, args) { createComment(obj, args) {
return WIKI.db.Comment.create({ return WIKI.models.Comment.create({
content: args.content, content: args.content,
author: args.userId, author: args.userId,
document: args.documentId document: args.documentId
}) })
}, },
deleteComment(obj, args) { deleteComment(obj, args) {
return WIKI.db.Comment.destroy({ return WIKI.models.Comment.destroy({
where: { where: {
id: args.id id: args.id
}, },
@ -24,7 +24,7 @@ module.exports = {
}) })
}, },
modifyComment(obj, args) { modifyComment(obj, args) {
return WIKI.db.Comment.update({ return WIKI.models.Comment.update({
content: args.content content: args.content
}, { }, {
where: { id: args.id } where: { id: args.id }

View File

@ -4,15 +4,15 @@
module.exports = { module.exports = {
Query: { Query: {
documents(obj, args, context, info) { documents(obj, args, context, info) {
return WIKI.db.Document.findAll({ where: args }) return WIKI.models.Document.findAll({ where: args })
} }
}, },
Mutation: { Mutation: {
createDocument(obj, args) { createDocument(obj, args) {
return WIKI.db.Document.create(args) return WIKI.models.Document.create(args)
}, },
deleteDocument(obj, args) { deleteDocument(obj, args) {
return WIKI.db.Document.destroy({ return WIKI.models.Document.destroy({
where: { where: {
id: args.id id: args.id
}, },
@ -20,7 +20,7 @@ module.exports = {
}) })
}, },
modifyDocument(obj, args) { modifyDocument(obj, args) {
return WIKI.db.Document.update({ return WIKI.models.Document.update({
title: args.title, title: args.title,
subtitle: args.subtitle subtitle: args.subtitle
}, { }, {
@ -28,7 +28,7 @@ module.exports = {
}) })
}, },
moveDocument(obj, args) { moveDocument(obj, args) {
return WIKI.db.Document.update({ return WIKI.models.Document.update({
path: args.path path: args.path
}, { }, {
where: { id: args.id } where: { id: args.id }

View File

@ -6,16 +6,16 @@ const gql = require('graphql')
module.exports = { module.exports = {
Query: { Query: {
files(obj, args, context, info) { files(obj, args, context, info) {
return WIKI.db.File.findAll({ where: args }) return WIKI.models.File.findAll({ where: args })
} }
}, },
Mutation: { Mutation: {
uploadFile(obj, args) { uploadFile(obj, args) {
// todo // todo
return WIKI.db.File.create(args) return WIKI.models.File.create(args)
}, },
deleteFile(obj, args) { deleteFile(obj, args) {
return WIKI.db.File.destroy({ return WIKI.models.File.destroy({
where: { where: {
id: args.id id: args.id
}, },
@ -23,18 +23,18 @@ module.exports = {
}) })
}, },
renameFile(obj, args) { renameFile(obj, args) {
return WIKI.db.File.update({ return WIKI.models.File.update({
filename: args.filename filename: args.filename
}, { }, {
where: { id: args.id } where: { id: args.id }
}) })
}, },
moveFile(obj, args) { moveFile(obj, args) {
return WIKI.db.File.findById(args.fileId).then(fl => { return WIKI.models.File.findById(args.fileId).then(fl => {
if (!fl) { if (!fl) {
throw new gql.GraphQLError('Invalid File ID') throw new gql.GraphQLError('Invalid File ID')
} }
return WIKI.db.Folder.findById(args.folderId).then(fld => { return WIKI.models.Folder.findById(args.folderId).then(fld => {
if (!fld) { if (!fld) {
throw new gql.GraphQLError('Invalid Folder ID') throw new gql.GraphQLError('Invalid Folder ID')
} }

View File

@ -4,15 +4,15 @@
module.exports = { module.exports = {
Query: { Query: {
folders(obj, args, context, info) { folders(obj, args, context, info) {
return WIKI.db.Folder.findAll({ where: args }) return WIKI.models.Folder.findAll({ where: args })
} }
}, },
Mutation: { Mutation: {
createFolder(obj, args) { createFolder(obj, args) {
return WIKI.db.Folder.create(args) return WIKI.models.Folder.create(args)
}, },
deleteFolder(obj, args) { deleteFolder(obj, args) {
return WIKI.db.Folder.destroy({ return WIKI.models.Folder.destroy({
where: { where: {
id: args.id id: args.id
}, },
@ -20,7 +20,7 @@ module.exports = {
}) })
}, },
renameFolder(obj, args) { renameFolder(obj, args) {
return WIKI.db.Folder.update({ return WIKI.models.Folder.update({
name: args.name name: args.name
}, { }, {
where: { id: args.id } where: { id: args.id }

View File

@ -13,22 +13,22 @@ module.exports = {
}, },
GroupQuery: { GroupQuery: {
async list(obj, args, context, info) { async list(obj, args, context, info) {
return WIKI.db.groups.query().select( return WIKI.models.groups.query().select(
'groups.*', 'groups.*',
WIKI.db.groups.relatedQuery('users').count().as('userCount') WIKI.models.groups.relatedQuery('users').count().as('userCount')
) )
}, },
async single(obj, args, context, info) { async single(obj, args, context, info) {
return WIKI.db.groups.query().findById(args.id) return WIKI.models.groups.query().findById(args.id)
} }
}, },
GroupMutation: { GroupMutation: {
async assignUser(obj, args) { async assignUser(obj, args) {
const grp = await WIKI.db.groups.query().findById(args.groupId) const grp = await WIKI.models.groups.query().findById(args.groupId)
if (!grp) { if (!grp) {
throw new gql.GraphQLError('Invalid Group ID') throw new gql.GraphQLError('Invalid Group ID')
} }
const usr = await WIKI.db.users.query().findById(args.userId) const usr = await WIKI.models.users.query().findById(args.userId)
if (!usr) { if (!usr) {
throw new gql.GraphQLError('Invalid User ID') throw new gql.GraphQLError('Invalid User ID')
} }
@ -38,7 +38,7 @@ module.exports = {
} }
}, },
async create(obj, args) { async create(obj, args) {
const group = await WIKI.db.groups.query().insertAndFetch({ const group = await WIKI.models.groups.query().insertAndFetch({
name: args.name name: args.name
}) })
return { return {
@ -47,17 +47,17 @@ module.exports = {
} }
}, },
async delete(obj, args) { async delete(obj, args) {
await WIKI.db.groups.query().deleteById(args.id) await WIKI.models.groups.query().deleteById(args.id)
return { return {
responseResult: graphHelper.generateSuccess('Group has been deleted.') responseResult: graphHelper.generateSuccess('Group has been deleted.')
} }
}, },
async unassignUser(obj, args) { async unassignUser(obj, args) {
const grp = await WIKI.db.groups.query().findById(args.groupId) const grp = await WIKI.models.groups.query().findById(args.groupId)
if (!grp) { if (!grp) {
throw new gql.GraphQLError('Invalid Group ID') throw new gql.GraphQLError('Invalid Group ID')
} }
const usr = await WIKI.db.users.query().findById(args.userId) const usr = await WIKI.models.users.query().findById(args.userId)
if (!usr) { if (!usr) {
throw new gql.GraphQLError('Invalid User ID') throw new gql.GraphQLError('Invalid User ID')
} }
@ -67,7 +67,7 @@ module.exports = {
} }
}, },
async update(obj, args) { async update(obj, args) {
await WIKI.db.groups.query().patch({ name: args.name }).where('id', args.id) await WIKI.models.groups.query().patch({ name: args.name }).where('id', args.id)
return { return {
responseResult: graphHelper.generateSuccess('Group has been updated.') responseResult: graphHelper.generateSuccess('Group has been updated.')
} }

View File

@ -13,7 +13,7 @@ module.exports = {
LocalizationQuery: { LocalizationQuery: {
async locales(obj, args, context, info) { async locales(obj, args, context, info) {
let remoteLocales = await WIKI.redis.get('locales') let remoteLocales = await WIKI.redis.get('locales')
let localLocales = await WIKI.db.locales.query().select('id', 'code', 'isRTL', 'name', 'nativeName', 'createdAt', 'updatedAt') let localLocales = await WIKI.models.locales.query().select('id', 'code', 'isRTL', 'name', 'nativeName', 'createdAt', 'updatedAt')
remoteLocales = (remoteLocales) ? JSON.parse(remoteLocales) : localLocales remoteLocales = (remoteLocales) ? JSON.parse(remoteLocales) : localLocales
return _.map(remoteLocales, rl => { return _.map(remoteLocales, rl => {
let isInstalled = _.some(localLocales, ['code', rl.code]) let isInstalled = _.some(localLocales, ['code', rl.code])

View File

@ -11,18 +11,18 @@ module.exports = {
}, },
PageQuery: { PageQuery: {
async list(obj, args, context, info) { async list(obj, args, context, info) {
return WIKI.db.pages.query().select( return WIKI.models.pages.query().select(
'pages.*', 'pages.*',
WIKI.db.pages.relatedQuery('users').count().as('userCount') WIKI.models.pages.relatedQuery('users').count().as('userCount')
) )
}, },
async single(obj, args, context, info) { async single(obj, args, context, info) {
return WIKI.db.pages.query().findById(args.id) return WIKI.models.pages.query().findById(args.id)
} }
}, },
PageMutation: { PageMutation: {
async create(obj, args, context) { async create(obj, args, context) {
const page = await WIKI.db.pages.createPage({ const page = await WIKI.models.pages.createPage({
...args, ...args,
authorId: context.req.user.id authorId: context.req.user.id
}) })
@ -32,13 +32,13 @@ module.exports = {
} }
}, },
async delete(obj, args) { async delete(obj, args) {
await WIKI.db.groups.query().deleteById(args.id) await WIKI.models.groups.query().deleteById(args.id)
return { return {
responseResult: graphHelper.generateSuccess('Page has been deleted.') responseResult: graphHelper.generateSuccess('Page has been deleted.')
} }
}, },
async update(obj, args, context) { async update(obj, args, context) {
const page = await WIKI.db.pages.updatePage({ const page = await WIKI.models.pages.updatePage({
...args, ...args,
authorId: context.req.user.id authorId: context.req.user.id
}) })

View File

@ -6,16 +6,16 @@ const gql = require('graphql')
module.exports = { module.exports = {
Query: { Query: {
rights(obj, args, context, info) { rights(obj, args, context, info) {
return WIKI.db.Right.findAll({ where: args }) return WIKI.models.Right.findAll({ where: args })
} }
}, },
Mutation: { Mutation: {
addRightToGroup(obj, args) { addRightToGroup(obj, args) {
return WIKI.db.Group.findById(args.groupId).then(grp => { return WIKI.models.Group.findById(args.groupId).then(grp => {
if (!grp) { if (!grp) {
throw new gql.GraphQLError('Invalid Group ID') throw new gql.GraphQLError('Invalid Group ID')
} }
return WIKI.db.Right.create({ return WIKI.models.Right.create({
path: args.path, path: args.path,
role: args.role, role: args.role,
exact: args.exact, exact: args.exact,
@ -25,7 +25,7 @@ module.exports = {
}) })
}, },
removeRightFromGroup(obj, args) { removeRightFromGroup(obj, args) {
return WIKI.db.Right.destroy({ return WIKI.models.Right.destroy({
where: { where: {
id: args.rightId id: args.rightId
}, },
@ -33,7 +33,7 @@ module.exports = {
}) })
}, },
modifyRight(obj, args) { modifyRight(obj, args) {
return WIKI.db.Right.update({ return WIKI.models.Right.update({
path: args.path, path: args.path,
role: args.role, role: args.role,
exact: args.exact, exact: args.exact,

View File

@ -6,7 +6,7 @@ const _ = require('lodash')
module.exports = { module.exports = {
Query: { Query: {
settings(obj, args, context, info) { settings(obj, args, context, info) {
return WIKI.db.Setting.findAll({ where: args, raw: true }).then(entries => { return WIKI.models.Setting.findAll({ where: args, raw: true }).then(entries => {
return _.map(entries, entry => { return _.map(entries, entry => {
entry.config = JSON.stringify(entry.config) entry.config = JSON.stringify(entry.config)
return entry return entry
@ -16,7 +16,7 @@ module.exports = {
}, },
Mutation: { Mutation: {
setConfigEntry(obj, args) { setConfigEntry(obj, args) {
return WIKI.db.Setting.update({ return WIKI.models.Setting.update({
value: args.value value: args.value
}, { where: { key: args.key } }) }, { where: { key: args.key } })
} }

View File

@ -12,13 +12,24 @@ module.exports = {
}, },
StorageQuery: { StorageQuery: {
async targets(obj, args, context, info) { async targets(obj, args, context, info) {
let targets = await WIKI.db.storage.getTargets() let targets = await WIKI.models.storage.getTargets()
targets = targets.map(tgt => ({ targets = targets.map(tgt => {
const targetInfo = _.find(WIKI.data.storage, ['key', tgt.key]) || {}
console.info(targetInfo)
return {
...tgt, ...tgt,
config: _.sortBy(_.transform(tgt.config, (res, value, key) => { config: _.sortBy(_.transform(tgt.config, (res, value, key) => {
res.push({ key, value: JSON.stringify(value) }) const configData = _.get(targetInfo.props, key, {})
res.push({
key,
value: JSON.stringify({
...configData,
value
})
})
}, []), 'key') }, []), 'key')
})) }
})
if (args.filter) { targets = graphHelper.filter(targets, args.filter) } if (args.filter) { targets = graphHelper.filter(targets, args.filter) }
if (args.orderBy) { targets = graphHelper.orderBy(targets, args.orderBy) } if (args.orderBy) { targets = graphHelper.orderBy(targets, args.orderBy) }
return targets return targets
@ -28,11 +39,11 @@ module.exports = {
async updateTargets(obj, args, context) { async updateTargets(obj, args, context) {
try { try {
for (let tgt of args.targets) { for (let tgt of args.targets) {
await WIKI.db.storage.query().patch({ await WIKI.models.storage.query().patch({
isEnabled: tgt.isEnabled, isEnabled: tgt.isEnabled,
mode: tgt.mode, mode: tgt.mode,
config: _.reduce(tgt.config, (result, value, key) => { config: _.reduce(tgt.config, (result, value, key) => {
_.set(result, `${value.key}.value`, value.value) _.set(result, `${value.key}`, value.value)
return result return result
}, {}) }, {})
}).where('key', tgt.key) }).where('key', tgt.key)

View File

@ -33,7 +33,7 @@ module.exports = {
configFile: path.join(process.cwd(), 'config.yml'), configFile: path.join(process.cwd(), 'config.yml'),
currentVersion: WIKI.version, currentVersion: WIKI.version,
dbType: _.get(dbTypes, WIKI.config.db.type, 'Unknown DB'), dbType: _.get(dbTypes, WIKI.config.db.type, 'Unknown DB'),
dbVersion: _.get(WIKI.db, 'knex.client.version', 'Unknown version'), dbVersion: _.get(WIKI.models, 'knex.client.version', 'Unknown version'),
dbHost: WIKI.config.db.host, dbHost: WIKI.config.db.host,
latestVersion: WIKI.version, // TODO latestVersion: WIKI.version, // TODO
latestVersionReleaseDate: new Date(), // TODO latestVersionReleaseDate: new Date(), // TODO

View File

@ -6,16 +6,16 @@ const gql = require('graphql')
module.exports = { module.exports = {
Query: { Query: {
tags(obj, args, context, info) { tags(obj, args, context, info) {
return WIKI.db.Tag.findAll({ where: args }) return WIKI.models.Tag.findAll({ where: args })
} }
}, },
Mutation: { Mutation: {
assignTagToDocument(obj, args) { assignTagToDocument(obj, args) {
return WIKI.db.Tag.findById(args.tagId).then(tag => { return WIKI.models.Tag.findById(args.tagId).then(tag => {
if (!tag) { if (!tag) {
throw new gql.GraphQLError('Invalid Tag ID') throw new gql.GraphQLError('Invalid Tag ID')
} }
return WIKI.db.Document.findById(args.documentId).then(doc => { return WIKI.models.Document.findById(args.documentId).then(doc => {
if (!doc) { if (!doc) {
throw new gql.GraphQLError('Invalid Document ID') throw new gql.GraphQLError('Invalid Document ID')
} }
@ -24,10 +24,10 @@ module.exports = {
}) })
}, },
createTag(obj, args) { createTag(obj, args) {
return WIKI.db.Tag.create(args) return WIKI.models.Tag.create(args)
}, },
deleteTag(obj, args) { deleteTag(obj, args) {
return WIKI.db.Tag.destroy({ return WIKI.models.Tag.destroy({
where: { where: {
id: args.id id: args.id
}, },
@ -35,11 +35,11 @@ module.exports = {
}) })
}, },
removeTagFromDocument(obj, args) { removeTagFromDocument(obj, args) {
return WIKI.db.Tag.findById(args.tagId).then(tag => { return WIKI.models.Tag.findById(args.tagId).then(tag => {
if (!tag) { if (!tag) {
throw new gql.GraphQLError('Invalid Tag ID') throw new gql.GraphQLError('Invalid Tag ID')
} }
return WIKI.db.Document.findById(args.documentId).then(doc => { return WIKI.models.Document.findById(args.documentId).then(doc => {
if (!doc) { if (!doc) {
throw new gql.GraphQLError('Invalid Document ID') throw new gql.GraphQLError('Invalid Document ID')
} }
@ -48,7 +48,7 @@ module.exports = {
}) })
}, },
renameTag(obj, args) { renameTag(obj, args) {
return WIKI.db.Group.update({ return WIKI.models.Group.update({
key: args.key key: args.key
}, { }, {
where: { id: args.id } where: { id: args.id }

View File

@ -10,18 +10,18 @@ module.exports = {
}, },
UserQuery: { UserQuery: {
async list(obj, args, context, info) { async list(obj, args, context, info) {
return WIKI.db.users.query() return WIKI.models.users.query()
.select('id', 'email', 'name', 'provider', 'role', 'createdAt', 'updatedAt') .select('id', 'email', 'name', 'provider', 'role', 'createdAt', 'updatedAt')
}, },
async search(obj, args, context, info) { async search(obj, args, context, info) {
return WIKI.db.users.query() return WIKI.models.users.query()
.where('email', 'like', `%${args.query}%`) .where('email', 'like', `%${args.query}%`)
.orWhere('name', 'like', `%${args.query}%`) .orWhere('name', 'like', `%${args.query}%`)
.limit(10) .limit(10)
.select('id', 'email', 'name', 'provider', 'role', 'createdAt', 'updatedAt') .select('id', 'email', 'name', 'provider', 'role', 'createdAt', 'updatedAt')
}, },
async single(obj, args, context, info) { async single(obj, args, context, info) {
let usr = await WIKI.db.users.query().findById(args.id) let usr = await WIKI.models.users.query().findById(args.id)
usr.password = '' usr.password = ''
usr.tfaSecret = '' usr.tfaSecret = ''
return usr return usr
@ -29,13 +29,13 @@ module.exports = {
}, },
UserMutation: { UserMutation: {
create(obj, args) { create(obj, args) {
return WIKI.db.users.query().insertAndFetch(args) return WIKI.models.users.query().insertAndFetch(args)
}, },
delete(obj, args) { delete(obj, args) {
return WIKI.db.users.query().deleteById(args.id) return WIKI.models.users.query().deleteById(args.id)
}, },
update(obj, args) { update(obj, args) {
return WIKI.db.users.query().patch({ return WIKI.models.users.query().patch({
email: args.email, email: args.email,
name: args.name, name: args.name,
provider: args.provider, provider: args.provider,

View File

@ -5,7 +5,7 @@ const { createApolloFetch } = require('apollo-fetch')
/* global WIKI */ /* global WIKI */
WIKI.redis = require('../core/redis').init() WIKI.redis = require('../core/redis').init()
WIKI.db = require('../core/db').init() WIKI.models = require('../core/db').init()
module.exports = async (job) => { module.exports = async (job) => {
WIKI.logger.info(`Fetching locale ${job.data.locale} from Graph endpoint...`) WIKI.logger.info(`Fetching locale ${job.data.locale} from Graph endpoint...`)
@ -39,8 +39,8 @@ module.exports = async (job) => {
const locales = await WIKI.redis.get('locales') const locales = await WIKI.redis.get('locales')
if (locales) { if (locales) {
const currentLocale = _.find(JSON.parse(locales), ['code', job.data.locale]) || {} const currentLocale = _.find(JSON.parse(locales), ['code', job.data.locale]) || {}
await WIKI.db.locales.query().delete().where('code', job.data.locale) await WIKI.models.locales.query().delete().where('code', job.data.locale)
await WIKI.db.locales.query().insert({ await WIKI.models.locales.query().insert({
code: job.data.locale, code: job.data.locale,
strings: lcObj, strings: lcObj,
isRTL: currentLocale.isRTL, isRTL: currentLocale.isRTL,

View File

@ -5,7 +5,7 @@ const { createApolloFetch } = require('apollo-fetch')
/* global WIKI */ /* global WIKI */
WIKI.redis = require('../core/redis').init() WIKI.redis = require('../core/redis').init()
WIKI.db = require('../core/db').init() WIKI.models = require('../core/db').init()
module.exports = async (job) => { module.exports = async (job) => {
WIKI.logger.info('Syncing locales with Graph endpoint...') WIKI.logger.info('Syncing locales with Graph endpoint...')
@ -59,7 +59,7 @@ module.exports = async (job) => {
_.set(lcObj, row.key.replace(':', '.'), row.value) _.set(lcObj, row.key.replace(':', '.'), row.value)
}) })
await WIKI.db.locales.query().update({ await WIKI.models.locales.query().update({
code: WIKI.config.lang.code, code: WIKI.config.lang.code,
strings: lcObj, strings: lcObj,
isRTL: currentLocale.isRTL, isRTL: currentLocale.isRTL,

View File

@ -3,7 +3,7 @@ const fs = require('fs-extra')
const path = require('path') const path = require('path')
const _ = require('lodash') const _ = require('lodash')
const yaml = require('js-yaml') const yaml = require('js-yaml')
const commonHelper = require('../../helpers/common') const commonHelper = require('../helpers/common')
/* global WIKI */ /* global WIKI */
@ -33,7 +33,7 @@ module.exports = class Authentication extends Model {
} }
static async getStrategies() { static async getStrategies() {
const strategies = await WIKI.db.authentication.query() const strategies = await WIKI.models.authentication.query()
return strategies.map(str => ({ return strategies.map(str => ({
...str, ...str,
domainWhitelist: _.get(str.domainWhitelist, 'v', []), domainWhitelist: _.get(str.domainWhitelist, 'v', []),
@ -43,7 +43,7 @@ module.exports = class Authentication extends Model {
static async refreshStrategiesFromDisk() { static async refreshStrategiesFromDisk() {
try { try {
const dbStrategies = await WIKI.db.authentication.query() const dbStrategies = await WIKI.models.authentication.query()
// -> Fetch definitions from disk // -> Fetch definitions from disk
const authDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/authentication')) const authDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/authentication'))
@ -86,7 +86,7 @@ module.exports = class Authentication extends Model {
} }
}) })
if (newStrategies.length > 0) { if (newStrategies.length > 0) {
await WIKI.db.authentication.query().insert(newStrategies) await WIKI.models.authentication.query().insert(newStrategies)
WIKI.logger.info(`Loaded ${newStrategies.length} new authentication strategies: [ OK ]`) WIKI.logger.info(`Loaded ${newStrategies.length} new authentication strategies: [ OK ]`)
} else { } else {
WIKI.logger.info(`No new authentication strategies found: [ SKIPPED ]`) WIKI.logger.info(`No new authentication strategies found: [ SKIPPED ]`)

View File

@ -27,12 +27,12 @@ module.exports = class Editor extends Model {
} }
static async getEnabledEditors() { static async getEnabledEditors() {
return WIKI.db.editors.query().where({ isEnabled: true }) return WIKI.models.editors.query().where({ isEnabled: true })
} }
static async refreshEditorsFromDisk() { static async refreshEditorsFromDisk() {
try { try {
const dbEditors = await WIKI.db.editors.query() const dbEditors = await WIKI.models.editors.query()
const diskEditors = autoload(path.join(WIKI.SERVERPATH, 'modules/editor')) const diskEditors = autoload(path.join(WIKI.SERVERPATH, 'modules/editor'))
let newEditors = [] let newEditors = []
_.forOwn(diskEditors, (strategy, strategyKey) => { _.forOwn(diskEditors, (strategy, strategyKey) => {
@ -49,7 +49,7 @@ module.exports = class Editor extends Model {
} }
}) })
if (newEditors.length > 0) { if (newEditors.length > 0) {
await WIKI.db.editors.query().insert(newEditors) await WIKI.models.editors.query().insert(newEditors)
WIKI.logger.info(`Loaded ${newEditors.length} new editors: [ OK ]`) WIKI.logger.info(`Loaded ${newEditors.length} new editors: [ OK ]`)
} else { } else {
WIKI.logger.info(`No new editors found: [ SKIPPED ]`) WIKI.logger.info(`No new editors found: [ SKIPPED ]`)

View File

@ -82,7 +82,7 @@ module.exports = class PageHistory extends Model {
} }
static async addVersion(opts) { static async addVersion(opts) {
await WIKI.db.pageHistory.query().insert({ await WIKI.models.pageHistory.query().insert({
pageId: opts.id, pageId: opts.id,
authorId: opts.authorId, authorId: opts.authorId,
content: opts.content, content: opts.content,

View File

@ -22,6 +22,7 @@ module.exports = class Page extends Model {
publishStartDate: {type: 'string'}, publishStartDate: {type: 'string'},
publishEndDate: {type: 'string'}, publishEndDate: {type: 'string'},
content: {type: 'string'}, content: {type: 'string'},
contentType: {type: 'string'},
createdAt: {type: 'string'}, createdAt: {type: 'string'},
updatedAt: {type: 'string'} updatedAt: {type: 'string'}
@ -87,7 +88,7 @@ module.exports = class Page extends Model {
} }
static async createPage(opts) { static async createPage(opts) {
const page = await WIKI.db.pages.query().insertAndFetch({ const page = await WIKI.models.pages.query().insertAndFetch({
authorId: opts.authorId, authorId: opts.authorId,
content: opts.content, content: opts.content,
creatorId: opts.authorId, creatorId: opts.authorId,
@ -101,7 +102,7 @@ module.exports = class Page extends Model {
publishStartDate: opts.publishStartDate, publishStartDate: opts.publishStartDate,
title: opts.title title: opts.title
}) })
await WIKI.db.storage.pageEvent({ await WIKI.models.storage.pageEvent({
event: 'created', event: 'created',
page page
}) })
@ -109,15 +110,21 @@ module.exports = class Page extends Model {
} }
static async updatePage(opts) { static async updatePage(opts) {
const ogPage = await WIKI.db.pages.query().findById(opts.id) const ogPage = await WIKI.models.pages.query().findById(opts.id)
if (!ogPage) { if (!ogPage) {
throw new Error('Invalid Page Id') throw new Error('Invalid Page Id')
} }
await WIKI.db.pageHistory.addVersion(ogPage) await WIKI.models.pageHistory.addVersion(ogPage)
const page = await WIKI.db.pages.query().patchAndFetch({ const page = await WIKI.models.pages.query().patchAndFetchById(ogPage.id, {
authorId: opts.authorId,
content: opts.content,
description: opts.description,
isPublished: opts.isPublished,
publishEndDate: opts.publishEndDate,
publishStartDate: opts.publishStartDate,
title: opts.title title: opts.title
}).where('id', opts.id) })
await WIKI.db.storage.pageEvent({ await WIKI.models.storage.pageEvent({
event: 'updated', event: 'updated',
page page
}) })

View File

@ -32,7 +32,7 @@ module.exports = class Setting extends Model {
} }
static async getConfig() { static async getConfig() {
const settings = await WIKI.db.settings.query() const settings = await WIKI.models.settings.query()
if (settings.length > 0) { if (settings.length > 0) {
return _.reduce(settings, (res, val, key) => { return _.reduce(settings, (res, val, key) => {
_.set(res, val.key, (val.value.v) ? val.value.v : val.value) _.set(res, val.key, (val.value.v) ? val.value.v : val.value)

View File

@ -3,7 +3,7 @@ const path = require('path')
const fs = require('fs-extra') const fs = require('fs-extra')
const _ = require('lodash') const _ = require('lodash')
const yaml = require('js-yaml') const yaml = require('js-yaml')
const commonHelper = require('../../helpers/common') const commonHelper = require('../helpers/common')
/* global WIKI */ /* global WIKI */
@ -30,12 +30,12 @@ module.exports = class Storage extends Model {
} }
static async getTargets() { static async getTargets() {
return WIKI.db.storage.query() return WIKI.models.storage.query()
} }
static async refreshTargetsFromDisk() { static async refreshTargetsFromDisk() {
try { try {
const dbTargets = await WIKI.db.storage.query() const dbTargets = await WIKI.models.storage.query()
// -> Fetch definitions from disk // -> Fetch definitions from disk
const storageDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/storage')) const storageDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/storage'))
@ -44,10 +44,29 @@ module.exports = class Storage extends Model {
const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/storage', dir, 'definition.yml'), 'utf8') const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/storage', dir, 'definition.yml'), 'utf8')
diskTargets.push(yaml.safeLoad(def)) diskTargets.push(yaml.safeLoad(def))
} }
WIKI.data.storage = diskTargets.map(target => ({
...target,
props: _.transform(target.props, (result, value, key) => {
let defaultValue = ''
if (_.isPlainObject(value)) {
defaultValue = !_.isNil(value.default) ? value.default : commonHelper.getTypeDefaultValue(value.type)
} else {
defaultValue = commonHelper.getTypeDefaultValue(value)
}
_.set(result, key, {
default: defaultValue,
type: (value.type || value).toLowerCase(),
title: value.title || _.startCase(key),
hint: value.hint || false,
enum: value.enum || false
})
return result
}, {})
}))
// -> Insert new targets // -> Insert new targets
let newTargets = [] let newTargets = []
_.forEach(diskTargets, target => { for (let target of WIKI.data.storage) {
if (!_.some(dbTargets, ['key', target.key])) { if (!_.some(dbTargets, ['key', target.key])) {
newTargets.push({ newTargets.push({
key: target.key, key: target.key,
@ -55,28 +74,25 @@ module.exports = class Storage extends Model {
isEnabled: false, isEnabled: false,
mode: 'push', mode: 'push',
config: _.transform(target.props, (result, value, key) => { config: _.transform(target.props, (result, value, key) => {
if (_.isPlainObject(value)) { _.set(result, key, value.default)
let cfgValue = {
type: value.type.toLowerCase(),
value: !_.isNil(value.default) ? value.default : commonHelper.getTypeDefaultValue(value.type)
}
if (_.isArray(value.enum)) {
cfgValue.enum = value.enum
}
_.set(result, key, cfgValue)
} else {
_.set(result, key, {
type: value.toLowerCase(),
value: commonHelper.getTypeDefaultValue(value)
})
}
return result return result
}, {}) }, {})
}) })
} else {
const targetConfig = _.get(_.find(dbTargets, ['key', target.key]), 'config', {})
await WIKI.models.storage.query().patch({
title: target.title,
config: _.transform(target.props, (result, value, key) => {
if (!_.has(result, key)) {
_.set(result, key, value.default)
}
return result
}, targetConfig)
}).where('key', target.key)
}
} }
})
if (newTargets.length > 0) { if (newTargets.length > 0) {
await WIKI.db.storage.query().insert(newTargets) await WIKI.models.storage.query().insert(newTargets)
WIKI.logger.info(`Loaded ${newTargets.length} new storage targets: [ OK ]`) WIKI.logger.info(`Loaded ${newTargets.length} new storage targets: [ OK ]`)
} else { } else {
WIKI.logger.info(`No new storage targets found: [ SKIPPED ]`) WIKI.logger.info(`No new storage targets found: [ SKIPPED ]`)
@ -87,8 +103,8 @@ module.exports = class Storage extends Model {
} }
} }
static async pageEvent(event, page) { static async pageEvent({ event, page }) {
const targets = await WIKI.db.storage.query().where('isEnabled', true) const targets = await WIKI.models.storage.query().where('isEnabled', true)
if (targets && targets.length > 0) { if (targets && targets.length > 0) {
_.forEach(targets, target => { _.forEach(targets, target => {
WIKI.queue.job.syncStorage.add({ WIKI.queue.job.syncStorage.add({

View File

@ -3,7 +3,7 @@
const bcrypt = require('bcryptjs-then') const bcrypt = require('bcryptjs-then')
const _ = require('lodash') const _ = require('lodash')
const tfa = require('node-2fa') const tfa = require('node-2fa')
const securityHelper = require('../../helpers/security') const securityHelper = require('../helpers/security')
const Model = require('objection').Model const Model = require('objection').Model
const bcryptRegexp = /^\$2[ayb]\$[0-9]{2}\$[A-Za-z0-9./]{53}$/ const bcryptRegexp = /^\$2[ayb]\$[0-9]{2}\$[A-Za-z0-9./]{53}$/
@ -151,7 +151,7 @@ module.exports = class User extends Model {
profile.provider = _.lowerCase(profile.provider) profile.provider = _.lowerCase(profile.provider)
primaryEmail = _.toLower(primaryEmail) primaryEmail = _.toLower(primaryEmail)
let user = await WIKI.db.users.query().findOne({ let user = await WIKI.models.users.query().findOne({
email: primaryEmail, email: primaryEmail,
provider: profile.provider provider: profile.provider
}) })
@ -163,7 +163,7 @@ module.exports = class User extends Model {
name: profile.displayName || _.split(primaryEmail, '@')[0] name: profile.displayName || _.split(primaryEmail, '@')[0]
}) })
} else { } else {
user = await WIKI.db.users.query().insertAndFetch({ user = await WIKI.models.users.query().insertAndFetch({
email: primaryEmail, email: primaryEmail,
provider: profile.provider, provider: profile.provider,
providerId: profile.id, providerId: profile.id,
@ -186,7 +186,7 @@ module.exports = class User extends Model {
// deny: false // deny: false
// }] // }]
// } // }
// return WIKI.db.users.query().insert(nUsr) // return WIKI.models.users.query().insert(nUsr)
// } // }
return user return user
@ -238,7 +238,7 @@ module.exports = class User extends Model {
if (result) { if (result) {
let userId = _.toSafeInteger(result) let userId = _.toSafeInteger(result)
if (userId && userId > 0) { if (userId && userId > 0) {
let user = await WIKI.db.users.query().findById(userId) let user = await WIKI.models.users.query().findById(userId)
if (user && user.verifyTFA(opts.securityCode)) { if (user && user.verifyTFA(opts.securityCode)) {
return Promise.fromCallback(clb => { return Promise.fromCallback(clb => {
context.req.logIn(user, clb) context.req.logIn(user, clb)

View File

@ -15,7 +15,7 @@ module.exports = {
clientSecret: conf.clientSecret, clientSecret: conf.clientSecret,
callbackURL: conf.callbackURL callbackURL: conf.callbackURL
}, function (accessToken, refreshToken, profile, cb) { }, function (accessToken, refreshToken, profile, cb) {
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -20,7 +20,7 @@ module.exports = {
let waadProfile = jwt.decode(params.id_token) let waadProfile = jwt.decode(params.id_token)
waadProfile.id = waadProfile.oid waadProfile.id = waadProfile.oid
waadProfile.provider = 'azure' waadProfile.provider = 'azure'
WIKI.db.users.processProfile(waadProfile).then((user) => { WIKI.models.users.processProfile(waadProfile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -13,7 +13,7 @@ module.exports = {
ssoBaseURL: conf.ssoBaseURL, ssoBaseURL: conf.ssoBaseURL,
serverBaseURL: conf.serverBaseURL serverBaseURL: conf.serverBaseURL
}, (profile, cb) => { }, (profile, cb) => {
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -15,7 +15,7 @@ module.exports = {
callbackURL: conf.callbackURL, callbackURL: conf.callbackURL,
scope: 'identify email' scope: 'identify email'
}, function (accessToken, refreshToken, profile, cb) { }, function (accessToken, refreshToken, profile, cb) {
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -15,7 +15,7 @@ module.exports = {
clientSecret: conf.clientSecret, clientSecret: conf.clientSecret,
callbackURL: conf.callbackURL callbackURL: conf.callbackURL
}, (accessToken, refreshToken, profile, cb) => { }, (accessToken, refreshToken, profile, cb) => {
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -15,7 +15,7 @@ module.exports = {
callbackURL: conf.callbackURL, callbackURL: conf.callbackURL,
profileFields: ['id', 'displayName', 'email'] profileFields: ['id', 'displayName', 'email']
}, function (accessToken, refreshToken, profile, cb) { }, function (accessToken, refreshToken, profile, cb) {
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -15,7 +15,7 @@ module.exports = {
callbackURL: conf.callbackURL, callbackURL: conf.callbackURL,
scope: ['user:email'] scope: ['user:email']
}, (accessToken, refreshToken, profile, cb) => { }, (accessToken, refreshToken, profile, cb) => {
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -14,7 +14,7 @@ module.exports = {
clientSecret: conf.clientSecret, clientSecret: conf.clientSecret,
callbackURL: conf.callbackURL callbackURL: conf.callbackURL
}, (accessToken, refreshToken, profile, cb) => { }, (accessToken, refreshToken, profile, cb) => {
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -29,7 +29,7 @@ module.exports = {
}, (profile, cb) => { }, (profile, cb) => {
profile.provider = 'ldap' profile.provider = 'ldap'
profile.id = profile.dn profile.id = profile.dn
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -13,7 +13,7 @@ module.exports = {
usernameField: 'email', usernameField: 'email',
passwordField: 'password' passwordField: 'password'
}, (uEmail, uPassword, done) => { }, (uEmail, uPassword, done) => {
WIKI.db.users.query().findOne({ WIKI.models.users.query().findOne({
email: uEmail, email: uEmail,
providerKey: 'local' providerKey: 'local'
}).then((user) => { }).then((user) => {

View File

@ -14,7 +14,7 @@ module.exports = {
clientSecret: conf.clientSecret, clientSecret: conf.clientSecret,
callbackURL: conf.callbackURL callbackURL: conf.callbackURL
}, function (accessToken, refreshToken, profile, cb) { }, function (accessToken, refreshToken, profile, cb) {
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -16,7 +16,7 @@ module.exports = {
clientSecret: conf.clientSecret, clientSecret: conf.clientSecret,
callbackURL: conf.callbackURL callbackURL: conf.callbackURL
}, (accessToken, refreshToken, profile, cb) => { }, (accessToken, refreshToken, profile, cb) => {
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -14,7 +14,7 @@ module.exports = {
clientSecret: conf.clientSecret, clientSecret: conf.clientSecret,
callbackURL: conf.callbackURL callbackURL: conf.callbackURL
}, (accessToken, refreshToken, profile, cb) => { }, (accessToken, refreshToken, profile, cb) => {
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -15,7 +15,7 @@ module.exports = {
callbackURL: conf.callbackURL, callbackURL: conf.callbackURL,
scope: 'user_read' scope: 'user_read'
}, function (accessToken, refreshToken, profile, cb) { }, function (accessToken, refreshToken, profile, cb) {
WIKI.db.users.processProfile(profile).then((user) => { WIKI.models.users.processProfile(profile).then((user) => {
return cb(null, user) || true return cb(null, user) || true
}).catch((err) => { }).catch((err) => {
return cb(err, null) || true return cb(err, null) || true

View File

@ -0,0 +1,7 @@
key: box
title: Box
author: requarks.io
props:
clientId: String
clientSecret: String
rootFolder: String

View File

@ -0,0 +1,23 @@
module.exports = {
async activated() {
},
async deactivated() {
},
async init() {
},
async created() {
},
async updated() {
},
async deleted() {
},
async renamed() {
}
}

View File

@ -1,5 +1,8 @@
key: disk key: disk
title: Local FS title: Local File System
author: requarks.io author: requarks.io
props: props:
path: String path:
type: String
title: Path
hint: Absolute path without a trailing slash (e.g. /home/wiki/backup, C:\wiki\backup)

View File

@ -1,23 +1,68 @@
module.exports = { const fs = require('fs-extra')
async activated() { const path = require('path')
},
async deactivated() {
},
async init() {
},
async created() {
},
async updated() {
},
async deleted() {
},
async renamed() {
/**
* Get file extension based on content type
*/
const getFileExtension = (contentType) => {
switch (contentType) {
case 'markdown':
return 'md'
case 'html':
return 'html'
default:
return 'txt'
}
}
/**
* Inject page metadata into contents
*/
const injectMetadata = (page) => {
let meta = [
['title', page.title],
['description', page.description]
]
let metaFormatted = ''
switch (page.contentType) {
case 'markdown':
metaFormatted = meta.map(mt => `[//]: # ${mt[0]}: ${mt[1]}`).join('\n')
break
case 'html':
metaFormatted = meta.map(mt => `<!-- ${mt[0]}: ${mt[1]} -->`).join('\n')
break
default:
metaFormatted = meta.map(mt => `#WIKI ${mt[0]}: ${mt[1]}`).join('\n')
break
}
return `${metaFormatted}\n\n${page.content}`
}
module.exports = {
async activated() {
// not used
},
async deactivated() {
// not used
},
async init() {
await fs.ensureDir(this.config.path)
},
async created() {
const filePath = path.join(this.config.path, `${this.page.path}.${getFileExtension(this.page.contentType)}`)
await fs.outputFile(filePath, injectMetadata(this.page), 'utf8')
},
async updated() {
const filePath = path.join(this.config.path, `${this.page.path}.${getFileExtension(this.page.contentType)}`)
await fs.outputFile(filePath, injectMetadata(this.page), 'utf8')
},
async deleted() {
const filePath = path.join(this.config.path, `${this.page.path}.${getFileExtension(this.page.contentType)}`)
await fs.unlink(filePath)
},
async renamed() {
const sourceFilePath = path.join(this.config.path, `${this.page.sourcePath}.${getFileExtension(this.page.contentType)}`)
const destinationFilePath = path.join(this.config.path, `${this.page.destinationPath}.${getFileExtension(this.page.contentType)}`)
await fs.move(sourceFilePath, destinationFilePath, { overwrite: true })
} }
} }

View File

@ -5,16 +5,32 @@ props:
authType: authType:
type: String type: String
default: 'ssh' default: 'ssh'
title: Authentication Type
hint: Use SSH for maximum security.
enum: enum:
- 'basic' - 'basic'
- 'ssh' - 'ssh'
repoUrl: String repoUrl:
type: String
title: Repository URI
hint: Git-compliant URI (e.g. git@github.com:org/repo.git for ssh, https://github.com/org/repo.git for basic)
branch: branch:
type: String type: String
default: 'master' default: 'master'
verifySSL: verifySSL:
type: Boolean type: Boolean
default: true default: true
sshPrivateKeyPath: String title: Verify SSL Certificate
basicUsername: String hint: Some hosts requires SSL certificate checking to be disabled. Leave enabled for proper security.
basicPassword: String sshPrivateKeyPath:
type: String
title: SSH Private Key Path
hint: SSH Authentication Only - Absolute path to the key. The key must NOT be passphrase-protected.
basicUsername:
type: String
title: Username
hint: Basic Authentication Only
basicPassword:
type: String
title: Password / PAT
hint: Basic Authentication Only

View File

@ -303,7 +303,7 @@ module.exports = () => {
// Create default locale // Create default locale
WIKI.logger.info('Installing default locale...') WIKI.logger.info('Installing default locale...')
await WIKI.db.locales.query().insert({ await WIKI.models.locales.query().insert({
code: 'en', code: 'en',
strings: require('./locales/default.json'), strings: require('./locales/default.json'),
isRTL: false, isRTL: false,
@ -312,23 +312,23 @@ module.exports = () => {
}) })
// Load authentication strategies + enable local // Load authentication strategies + enable local
await WIKI.db.authentication.refreshStrategiesFromDisk() await WIKI.models.authentication.refreshStrategiesFromDisk()
await WIKI.db.authentication.query().patch({ isEnabled: true }).where('key', 'local') await WIKI.models.authentication.query().patch({ isEnabled: true }).where('key', 'local')
// Load editors + enable default // Load editors + enable default
await WIKI.db.editors.refreshEditorsFromDisk() await WIKI.models.editors.refreshEditorsFromDisk()
await WIKI.db.editors.query().patch({ isEnabled: true }).where('key', 'markdown') await WIKI.models.editors.query().patch({ isEnabled: true }).where('key', 'markdown')
// Load storage targets // Load storage targets
await WIKI.db.storage.refreshTargetsFromDisk() await WIKI.models.storage.refreshTargetsFromDisk()
// Create root administrator // Create root administrator
WIKI.logger.info('Creating root administrator...') WIKI.logger.info('Creating root administrator...')
await WIKI.db.users.query().delete().where({ await WIKI.models.users.query().delete().where({
providerKey: 'local', providerKey: 'local',
email: req.body.adminEmail email: req.body.adminEmail
}) })
await WIKI.db.users.query().insert({ await WIKI.models.users.query().insert({
email: req.body.adminEmail, email: req.body.adminEmail,
provider: 'local', provider: 'local',
password: req.body.adminPassword, password: req.body.adminPassword,
@ -341,12 +341,12 @@ module.exports = () => {
// Create Guest account // Create Guest account
WIKI.logger.info('Creating guest account...') WIKI.logger.info('Creating guest account...')
const guestUsr = await WIKI.db.users.query().findOne({ const guestUsr = await WIKI.models.users.query().findOne({
providerKey: 'local', providerKey: 'local',
email: 'guest@example.com' email: 'guest@example.com'
}) })
if (!guestUsr) { if (!guestUsr) {
await WIKI.db.users.query().insert({ await WIKI.models.users.query().insert({
provider: 'local', provider: 'local',
email: 'guest@example.com', email: 'guest@example.com',
name: 'Guest', name: 'Guest',

View File

@ -4,7 +4,9 @@ block body
#app.is-fullscreen #app.is-fullscreen
v-app v-app
.onboarding .onboarding
img(src='/svg/logo-wikijs.svg', alt='Wiki.js') img.animated.zoomIn(src='/svg/logo-wikijs.svg', alt='Wiki.js')
h1= t('welcome.title') .headline= t('welcome.title')
h2= t('welcome.subtitle') .subheading.mt-3= t('welcome.subtitle')
v-btn(color='primary', href='/e/home')= t('welcome.createhome') v-btn.mt-5(color='primary', href='/e/home', large)
v-icon(left) add
span= t('welcome.createhome')

View File

@ -118,7 +118,7 @@ const init = {
}, },
async reload() { async reload() {
console.warn(chalk.yellow('--- Closing DB connections...')) console.warn(chalk.yellow('--- Closing DB connections...'))
await global.WIKI.db.knex.destroy() await global.WIKI.models.knex.destroy()
console.warn(chalk.yellow('--- Closing Redis connections...')) console.warn(chalk.yellow('--- Closing Redis connections...'))
await global.WIKI.redis.quit() await global.WIKI.redis.quit()
console.warn(chalk.yellow('--- Closing Server connections...')) console.warn(chalk.yellow('--- Closing Server connections...'))