chore: DB ref refactor + add scheduler db model + remove search modules (#5699)

pull/5702/head
Nicolas Giard 2 years ago committed by GitHub
parent 5c6ae08b84
commit 10cc2ef4b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -129,6 +129,5 @@ bodyParserLimit: 5mb
scheduler: scheduler:
# Maximum number of workers to run background cpu-intensive jobs. # Maximum number of workers to run background cpu-intensive jobs.
# Make sure your PostgreSQL server can handle an extra connection # Leave 'auto' to use number of CPU cores as maximum.
# for each worker! workers: auto
workers: 3

@ -80,6 +80,7 @@ defaults:
maintainerEmail: security@requarks.io maintainerEmail: security@requarks.io
jobs: jobs:
- task: background - task: background
identifier: purge-uploads
pattern: '*/15 * * * *' pattern: '*/15 * * * *'
payload: payload:
name: purgeUploads name: purgeUploads

@ -10,7 +10,7 @@ const path = require('path')
const bruteforce = new ExpressBrute(new BruteKnex({ const bruteforce = new ExpressBrute(new BruteKnex({
createTable: true, createTable: true,
knex: WIKI.models.knex knex: WIKI.db.knex
}), { }), {
freeRetries: 5, freeRetries: 5,
minWait: 5 * 60 * 1000, // 5 minutes minWait: 5 * 60 * 1000, // 5 minutes
@ -26,7 +26,7 @@ const bruteforce = new ExpressBrute(new BruteKnex({
router.get('/login', async (req, res, next) => { router.get('/login', async (req, res, next) => {
// -> Bypass Login // -> Bypass Login
if (WIKI.config.auth.autoLogin && !req.query.all) { if (WIKI.config.auth.autoLogin && !req.query.all) {
const stg = await WIKI.models.authentication.query().orderBy('order').first() const stg = await WIKI.db.authentication.query().orderBy('order').first()
const stgInfo = _.find(WIKI.data.authentication, ['key', stg.strategyKey]) const stgInfo = _.find(WIKI.data.authentication, ['key', stg.strategyKey])
if (!stgInfo.useForm) { if (!stgInfo.useForm) {
return res.redirect(`/login/${stg.key}`) return res.redirect(`/login/${stg.key}`)
@ -41,7 +41,7 @@ router.get('/login', async (req, res, next) => {
*/ */
router.get('/login/:strategy', async (req, res, next) => { router.get('/login/:strategy', async (req, res, next) => {
try { try {
await WIKI.models.users.login({ await WIKI.db.users.login({
strategy: req.params.strategy strategy: req.params.strategy
}, { req, res }) }, { req, res })
} catch (err) { } catch (err) {
@ -56,7 +56,7 @@ router.all('/login/:strategy/callback', async (req, res, next) => {
if (req.method !== 'GET' && req.method !== 'POST') { return next() } if (req.method !== 'GET' && req.method !== 'POST') { return next() }
try { try {
const authResult = await WIKI.models.users.login({ const authResult = await WIKI.db.users.login({
strategy: req.params.strategy strategy: req.params.strategy
}, { req, res }) }, { req, res })
res.cookie('jwt', authResult.jwt, { expires: moment().add(1, 'y').toDate() }) res.cookie('jwt', authResult.jwt, { expires: moment().add(1, 'y').toDate() })
@ -82,7 +82,7 @@ router.all('/login/:strategy/callback', async (req, res, next) => {
* Logout * Logout
*/ */
router.get('/logout', async (req, res, next) => { router.get('/logout', async (req, res, next) => {
const redirURL = await WIKI.models.users.logout({ req, res }) const redirURL = await WIKI.db.users.logout({ req, res })
req.logout((err) => { req.logout((err) => {
if (err) { return next(err) } if (err) { return next(err) }
res.clearCookie('jwt') res.clearCookie('jwt')
@ -95,7 +95,7 @@ router.get('/logout', async (req, res, next) => {
*/ */
router.get('/register', async (req, res, next) => { router.get('/register', async (req, res, next) => {
_.set(res.locals, 'pageMeta.title', 'Register') _.set(res.locals, 'pageMeta.title', 'Register')
const localStrg = await WIKI.models.authentication.getStrategy('local') const localStrg = await WIKI.db.authentication.getStrategy('local')
if (localStrg.selfRegistration) { if (localStrg.selfRegistration) {
res.sendFile(path.join(WIKI.ROOTPATH, 'assets/index.html')) res.sendFile(path.join(WIKI.ROOTPATH, 'assets/index.html'))
} else { } else {
@ -108,13 +108,13 @@ router.get('/register', async (req, res, next) => {
*/ */
router.get('/verify/:token', bruteforce.prevent, async (req, res, next) => { router.get('/verify/:token', bruteforce.prevent, async (req, res, next) => {
try { try {
const usr = await WIKI.models.userKeys.validateToken({ kind: 'verify', token: req.params.token }) const usr = await WIKI.db.userKeys.validateToken({ kind: 'verify', token: req.params.token })
await WIKI.models.users.query().patch({ isVerified: true }).where('id', usr.id) await WIKI.db.users.query().patch({ isVerified: true }).where('id', usr.id)
req.brute.reset() req.brute.reset()
if (WIKI.config.auth.enforce2FA) { if (WIKI.config.auth.enforce2FA) {
res.redirect('/login') res.redirect('/login')
} else { } else {
const result = await WIKI.models.users.refreshToken(usr) const result = await WIKI.db.users.refreshToken(usr)
res.cookie('jwt', result.token, { expires: moment().add(1, 'years').toDate() }) res.cookie('jwt', result.token, { expires: moment().add(1, 'years').toDate() })
res.redirect('/') res.redirect('/')
} }
@ -128,13 +128,13 @@ router.get('/verify/:token', bruteforce.prevent, async (req, res, next) => {
*/ */
router.get('/login-reset/:token', bruteforce.prevent, async (req, res, next) => { router.get('/login-reset/:token', bruteforce.prevent, async (req, res, next) => {
try { try {
const usr = await WIKI.models.userKeys.validateToken({ kind: 'resetPwd', token: req.params.token }) const usr = await WIKI.db.userKeys.validateToken({ kind: 'resetPwd', token: req.params.token })
if (!usr) { if (!usr) {
throw new Error('Invalid Token') throw new Error('Invalid Token')
} }
req.brute.reset() req.brute.reset()
const changePwdContinuationToken = await WIKI.models.userKeys.generateToken({ const changePwdContinuationToken = await WIKI.db.userKeys.generateToken({
userId: usr.id, userId: usr.id,
kind: 'changePwd' kind: 'changePwd'
}) })

@ -6,8 +6,6 @@ const CleanCSS = require('clean-css')
const moment = require('moment') const moment = require('moment')
const path = require('path') const path = require('path')
/* global WIKI */
const tmplCreateRegex = /^[0-9]+(,[0-9]+)?$/ const tmplCreateRegex = /^[0-9]+(,[0-9]+)?$/
const siteAssetsPath = path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, 'assets') const siteAssetsPath = path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, 'assets')
@ -27,7 +25,7 @@ router.get('/robots.txt', (req, res, next) => {
* Health Endpoint * Health Endpoint
*/ */
router.get('/healthz', (req, res, next) => { router.get('/healthz', (req, res, next) => {
if (WIKI.models.knex.client.pool.numFree() < 1 && WIKI.models.knex.client.pool.numUsed() < 1) { if (WIKI.db.knex.client.pool.numFree() < 1 && WIKI.db.knex.client.pool.numUsed() < 1) {
res.status(503).json({ ok: false }).end() res.status(503).json({ ok: false }).end()
} else { } else {
res.status(200).json({ ok: true }).end() res.status(200).json({ ok: true }).end()
@ -38,7 +36,7 @@ router.get('/healthz', (req, res, next) => {
* Site Asset * Site Asset
*/ */
router.get('/_site/:siteId?/:resource', async (req, res, next) => { router.get('/_site/:siteId?/:resource', async (req, res, next) => {
const site = req.params.siteId ? WIKI.sites[req.params.siteId] : await WIKI.models.sites.getSiteByHostname({ hostname: req.hostname }) const site = req.params.siteId ? WIKI.sites[req.params.siteId] : await WIKI.db.sites.getSiteByHostname({ hostname: req.hostname })
if (!site) { if (!site) {
return res.status(404).send('Site Not Found') return res.status(404).send('Site Not Found')
} }
@ -115,7 +113,7 @@ router.get(['/d', '/d/*'], async (req, res, next) => {
const versionId = (req.query.v) ? _.toSafeInteger(req.query.v) : 0 const versionId = (req.query.v) ? _.toSafeInteger(req.query.v) : 0
const page = await WIKI.models.pages.getPageFromDb({ const page = await WIKI.db.pages.getPageFromDb({
path: pageArgs.path, path: pageArgs.path,
locale: pageArgs.locale, locale: pageArgs.locale,
userId: req.user.id, userId: req.user.id,
@ -140,7 +138,7 @@ router.get(['/d', '/d/*'], async (req, res, next) => {
const fileName = _.last(page.path.split('/')) + '.' + pageHelper.getFileExtension(page.contentType) const fileName = _.last(page.path.split('/')) + '.' + pageHelper.getFileExtension(page.contentType)
res.attachment(fileName) res.attachment(fileName)
if (versionId > 0) { if (versionId > 0) {
const pageVersion = await WIKI.models.pageHistory.getVersion({ pageId: page.id, versionId }) const pageVersion = await WIKI.db.pageHistory.getVersion({ pageId: page.id, versionId })
res.send(pageHelper.injectPageMetadata(pageVersion)) res.send(pageHelper.injectPageMetadata(pageVersion))
} else { } else {
res.send(pageHelper.injectPageMetadata(page)) res.send(pageHelper.injectPageMetadata(page))
@ -176,7 +174,7 @@ router.get(['/_edit', '/_edit/*'], async (req, res, next) => {
} }
// -> Get page data from DB // -> Get page data from DB
let page = await WIKI.models.pages.getPageFromDb({ let page = await WIKI.db.pages.getPageFromDb({
path: pageArgs.path, path: pageArgs.path,
locale: pageArgs.locale, locale: pageArgs.locale,
userId: req.user.id, userId: req.user.id,
@ -255,7 +253,7 @@ router.get(['/_edit', '/_edit/*'], async (req, res, next) => {
if (tmplVersionId > 0) { if (tmplVersionId > 0) {
// -> From Page Version // -> From Page Version
const pageVersion = await WIKI.models.pageHistory.getVersion({ pageId: tmplPageId, versionId: tmplVersionId }) const pageVersion = await WIKI.db.pageHistory.getVersion({ pageId: tmplPageId, versionId: tmplVersionId })
if (!pageVersion) { if (!pageVersion) {
_.set(res.locals, 'pageMeta.title', 'Page Not Found') _.set(res.locals, 'pageMeta.title', 'Page Not Found')
return res.status(404).render('notfound', { action: 'template' }) return res.status(404).render('notfound', { action: 'template' })
@ -270,7 +268,7 @@ router.get(['/_edit', '/_edit/*'], async (req, res, next) => {
page.description = pageVersion.description page.description = pageVersion.description
} else { } else {
// -> From Page Live // -> From Page Live
const pageOriginal = await WIKI.models.pages.query().findById(tmplPageId) const pageOriginal = await WIKI.db.pages.query().findById(tmplPageId)
if (!pageOriginal) { if (!pageOriginal) {
_.set(res.locals, 'pageMeta.title', 'Page Not Found') _.set(res.locals, 'pageMeta.title', 'Page Not Found')
return res.status(404).render('notfound', { action: 'template' }) return res.status(404).render('notfound', { action: 'template' })
@ -305,7 +303,7 @@ router.get(['/h', '/h/*'], async (req, res, next) => {
_.set(res, 'locals.siteConfig.lang', pageArgs.locale) _.set(res, 'locals.siteConfig.lang', pageArgs.locale)
_.set(res, 'locals.siteConfig.rtl', req.i18n.dir() === 'rtl') _.set(res, 'locals.siteConfig.rtl', req.i18n.dir() === 'rtl')
const page = await WIKI.models.pages.getPageFromDb({ const page = await WIKI.db.pages.getPageFromDb({
path: pageArgs.path, path: pageArgs.path,
locale: pageArgs.locale, locale: pageArgs.locale,
userId: req.user.id, userId: req.user.id,
@ -345,7 +343,7 @@ router.get(['/i', '/i/:id'], async (req, res, next) => {
return res.redirect('/') return res.redirect('/')
} }
const page = await WIKI.models.pages.query().column(['path', 'localeCode', 'isPrivate', 'privateNS']).findById(pageId) const page = await WIKI.db.pages.query().column(['path', 'localeCode', 'isPrivate', 'privateNS']).findById(pageId)
if (!page) { if (!page) {
_.set(res.locals, 'pageMeta.title', 'Page Not Found') _.set(res.locals, 'pageMeta.title', 'Page Not Found')
return res.status(404).render('notfound', { action: 'view' }) return res.status(404).render('notfound', { action: 'view' })
@ -377,7 +375,7 @@ router.get(['/s', '/s/*'], async (req, res, next) => {
const pageArgs = pageHelper.parsePath(req.path, { stripExt: true }) const pageArgs = pageHelper.parsePath(req.path, { stripExt: true })
const versionId = (req.query.v) ? _.toSafeInteger(req.query.v) : 0 const versionId = (req.query.v) ? _.toSafeInteger(req.query.v) : 0
const page = await WIKI.models.pages.getPageFromDb({ const page = await WIKI.db.pages.getPageFromDb({
path: pageArgs.path, path: pageArgs.path,
locale: pageArgs.locale, locale: pageArgs.locale,
userId: req.user.id, userId: req.user.id,
@ -410,7 +408,7 @@ router.get(['/s', '/s/*'], async (req, res, next) => {
if (page) { if (page) {
if (versionId > 0) { if (versionId > 0) {
const pageVersion = await WIKI.models.pageHistory.getVersion({ pageId: page.id, versionId }) const pageVersion = await WIKI.db.pageHistory.getVersion({ pageId: page.id, versionId })
_.set(res.locals, 'pageMeta.title', pageVersion.title) _.set(res.locals, 'pageMeta.title', pageVersion.title)
_.set(res.locals, 'pageMeta.description', pageVersion.description) _.set(res.locals, 'pageMeta.description', pageVersion.description)
res.render('source', { res.render('source', {
@ -446,7 +444,7 @@ router.get('/_userav/:uid', async (req, res, next) => {
if (!WIKI.auth.checkAccess(req.user, ['read:pages'])) { if (!WIKI.auth.checkAccess(req.user, ['read:pages'])) {
return res.sendStatus(403) return res.sendStatus(403)
} }
const av = await WIKI.models.users.getUserAvatarData(req.params.uid) const av = await WIKI.db.users.getUserAvatarData(req.params.uid)
if (av) { if (av) {
res.set('Content-Type', 'image/jpeg') res.set('Content-Type', 'image/jpeg')
res.send(av) res.send(av)
@ -472,7 +470,7 @@ router.get('/*', async (req, res, next) => {
try { try {
// -> Get Page from cache // -> Get Page from cache
const page = await WIKI.models.pages.getPage({ const page = await WIKI.db.pages.getPage({
path: pageArgs.path, path: pageArgs.path,
locale: pageArgs.locale, locale: pageArgs.locale,
userId: req.user.id userId: req.user.id
@ -519,7 +517,7 @@ router.get('/*', async (req, res, next) => {
// -> Build sidebar navigation // -> Build sidebar navigation
let sdi = 1 let sdi = 1
const sidebar = (await WIKI.models.navigation.getTree({ cache: true, locale: pageArgs.locale, groups: req.user.groups })).map(n => ({ const sidebar = (await WIKI.db.navigation.getTree({ cache: true, locale: pageArgs.locale, groups: req.user.groups })).map(n => ({
i: `sdi-${sdi++}`, i: `sdi-${sdi++}`,
k: n.kind, k: n.kind,
l: n.label, l: n.label,
@ -595,7 +593,7 @@ router.get('/*', async (req, res, next) => {
return res.sendStatus(403) return res.sendStatus(403)
} }
await WIKI.models.assets.getAsset(pageArgs.path, res) await WIKI.db.assets.getAsset(pageArgs.path, res)
} }
}) })

@ -3,8 +3,6 @@ const router = express.Router()
const _ = require('lodash') const _ = require('lodash')
const qs = require('querystring') const qs = require('querystring')
/* global WIKI */
/** /**
* Let's Encrypt Challenge * Let's Encrypt Challenge
*/ */

@ -5,8 +5,6 @@ const multer = require('multer')
const path = require('path') const path = require('path')
const sanitize = require('sanitize-filename') const sanitize = require('sanitize-filename')
/* global WIKI */
/** /**
* Upload files * Upload files
*/ */
@ -66,7 +64,7 @@ router.post('/u', (req, res, next) => {
let hierarchy = [] let hierarchy = []
if (folderId) { if (folderId) {
try { try {
hierarchy = await WIKI.models.assetFolders.getHierarchy(folderId) hierarchy = await WIKI.db.assetFolders.getHierarchy(folderId)
} catch (err) { } catch (err) {
return res.status(400).json({ return res.status(400).json({
succeeded: false, succeeded: false,
@ -88,7 +86,7 @@ router.post('/u', (req, res, next) => {
} }
// Process upload file // Process upload file
await WIKI.models.assets.upload({ await WIKI.db.assets.upload({
...fileMeta, ...fileMeta,
mode: 'upload', mode: 'upload',
folderId: folderId, folderId: folderId,

@ -1,8 +1,6 @@
const chalk = require('chalk') const chalk = require('chalk')
const os = require('node:os') const os = require('node:os')
/* global WIKI */
module.exports = () => { module.exports = () => {
WIKI.servers.ws.on('connection', (socket) => { WIKI.servers.ws.on('connection', (socket) => {
// TODO: Validate token + permissions // TODO: Validate token + permissions

@ -3,8 +3,6 @@ const path = require('path')
const UINT64 = require('cuint').UINT64 const UINT64 = require('cuint').UINT64
const fs = require('fs') const fs = require('fs')
/* global WIKI */
/** /**
* Based of express-serve-asar (https://github.com/toyobayashi/express-serve-asar) * Based of express-serve-asar (https://github.com/toyobayashi/express-serve-asar)
* by Fenglin Li (https://github.com/toyobayashi) * by Fenglin Li (https://github.com/toyobayashi)

@ -10,8 +10,6 @@ const pem2jwk = require('pem-jwk').pem2jwk
const securityHelper = require('../helpers/security') const securityHelper = require('../helpers/security')
/* global WIKI */
module.exports = { module.exports = {
strategies: {}, strategies: {},
guest: { guest: {
@ -33,7 +31,7 @@ module.exports = {
passport.deserializeUser(async (id, done) => { passport.deserializeUser(async (id, done) => {
try { try {
const user = await WIKI.models.users.query().findById(id).withGraphFetched('groups').modifyGraph('groups', builder => { const user = await WIKI.db.users.query().findById(id).withGraphFetched('groups').modifyGraph('groups', builder => {
builder.select('groups.id', 'permissions') builder.select('groups.id', 'permissions')
}) })
if (user) { if (user) {
@ -75,7 +73,7 @@ module.exports = {
})) }))
// Load enabled strategies // Load enabled strategies
const enabledStrategies = await WIKI.models.authentication.getStrategies({ enabledOnly: true }) const enabledStrategies = await WIKI.db.authentication.getStrategies({ enabledOnly: true })
for (const stg of enabledStrategies) { for (const stg of enabledStrategies) {
try { try {
const strategy = require(`../modules/authentication/${stg.module}/authentication.js`) const strategy = require(`../modules/authentication/${stg.module}/authentication.js`)
@ -144,7 +142,7 @@ module.exports = {
if (mustRevalidate) { if (mustRevalidate) {
const jwtPayload = jwt.decode(securityHelper.extractJWT(req)) const jwtPayload = jwt.decode(securityHelper.extractJWT(req))
try { try {
const newToken = await WIKI.models.users.refreshToken(jwtPayload.id, jwtPayload.pvd) const newToken = await WIKI.db.users.refreshToken(jwtPayload.id, jwtPayload.pvd)
user = newToken.user user = newToken.user
user.permissions = user.getPermissions() user.permissions = user.getPermissions()
user.groups = user.getGroups() user.groups = user.getGroups()
@ -162,7 +160,7 @@ module.exports = {
return next() return next()
} }
} else if (user) { } else if (user) {
user = await WIKI.models.users.getById(user.id) user = await WIKI.db.users.getById(user.id)
user.permissions = user.getPermissions() user.permissions = user.getPermissions()
user.groups = user.getGroups() user.groups = user.getGroups()
user.strategyId = strategyId user.strategyId = strategyId
@ -170,7 +168,7 @@ module.exports = {
} else { } else {
// JWT is NOT valid, set as guest // JWT is NOT valid, set as guest
if (WIKI.auth.guest.cacheExpiration <= DateTime.utc()) { if (WIKI.auth.guest.cacheExpiration <= DateTime.utc()) {
WIKI.auth.guest = await WIKI.models.users.getGuestUser() WIKI.auth.guest = await WIKI.db.users.getGuestUser()
WIKI.auth.guest.cacheExpiration = DateTime.utc().plus({ minutes: 1 }) WIKI.auth.guest.cacheExpiration = DateTime.utc().plus({ minutes: 1 })
} }
req.user = WIKI.auth.guest req.user = WIKI.auth.guest
@ -349,7 +347,7 @@ module.exports = {
* Reload Groups from DB * Reload Groups from DB
*/ */
async reloadGroups () { async reloadGroups () {
const groupsArray = await WIKI.models.groups.query() const groupsArray = await WIKI.db.groups.query()
this.groups = _.keyBy(groupsArray, 'id') this.groups = _.keyBy(groupsArray, 'id')
WIKI.auth.guest.cacheExpiration = DateTime.utc().minus({ days: 1 }) WIKI.auth.guest.cacheExpiration = DateTime.utc().minus({ days: 1 })
}, },
@ -358,7 +356,7 @@ module.exports = {
* Reload valid API Keys from DB * Reload valid API Keys from DB
*/ */
async reloadApiKeys () { async reloadApiKeys () {
const keys = await WIKI.models.apiKeys.query().select('id').where('isRevoked', false).andWhere('expiration', '>', DateTime.utc().toISO()) const keys = await WIKI.db.apiKeys.query().select('id').where('isRevoked', false).andWhere('expiration', '>', DateTime.utc().toISO())
this.validApiKeys = _.map(keys, 'id') this.validApiKeys = _.map(keys, 'id')
}, },
@ -405,14 +403,14 @@ module.exports = {
*/ */
async resetGuestUser() { async resetGuestUser() {
WIKI.logger.info('Resetting guest account...') WIKI.logger.info('Resetting guest account...')
const guestGroup = await WIKI.models.groups.query().where('id', 2).first() const guestGroup = await WIKI.db.groups.query().where('id', 2).first()
await WIKI.models.users.query().delete().where({ await WIKI.db.users.query().delete().where({
providerKey: 'local', providerKey: 'local',
email: 'guest@example.com' email: 'guest@example.com'
}).orWhere('id', 2) }).orWhere('id', 2)
const guestUser = await WIKI.models.users.query().insert({ const guestUser = await WIKI.db.users.query().insert({
id: 2, id: 2,
provider: 'local', provider: 'local',
email: 'guest@example.com', email: 'guest@example.com',

@ -5,8 +5,6 @@ const fs = require('fs')
const path = require('path') const path = require('path')
const yaml = require('js-yaml') const yaml = require('js-yaml')
/* global WIKI */
module.exports = { module.exports = {
/** /**
* Load root config from disk * Load root config from disk
@ -52,10 +50,18 @@ module.exports = {
appconfig = _.defaultsDeep(appconfig, appdata.defaults.config) appconfig = _.defaultsDeep(appconfig, appdata.defaults.config)
// Override port
if (appconfig.port < 1 || process.env.HEROKU) { if (appconfig.port < 1 || process.env.HEROKU) {
appconfig.port = process.env.PORT || 80 appconfig.port = process.env.PORT || 80
} }
if (process.env.WIKI_PORT) {
appconfig.port = process.env.WIKI_PORT || 80
}
// Load package info
const packageInfo = require(path.join(WIKI.ROOTPATH, 'package.json')) const packageInfo = require(path.join(WIKI.ROOTPATH, 'package.json'))
// Load DB Password from Docker Secret File // Load DB Password from Docker Secret File
@ -81,12 +87,12 @@ module.exports = {
* Load config from DB * Load config from DB
*/ */
async loadFromDb() { async loadFromDb() {
let conf = await WIKI.models.settings.getConfig() let conf = await WIKI.db.settings.getConfig()
if (conf) { if (conf) {
WIKI.config = _.defaultsDeep(conf, WIKI.config) WIKI.config = _.defaultsDeep(conf, WIKI.config)
} else { } else {
WIKI.logger.warn('DB Configuration is empty or incomplete. Switching to Setup mode...') WIKI.logger.warn('Missing DB Configuration!')
WIKI.config.setup = true process.exit(1)
} }
}, },
/** /**
@ -102,9 +108,9 @@ module.exports = {
if (!_.isPlainObject(value)) { if (!_.isPlainObject(value)) {
value = { v: value } value = { v: value }
} }
let affectedRows = await WIKI.models.settings.query().patch({ value }).where('key', key) let affectedRows = await WIKI.db.settings.query().patch({ value }).where('key', key)
if (affectedRows === 0 && value) { if (affectedRows === 0 && value) {
await WIKI.models.settings.query().insert({ key, value }) await WIKI.db.settings.query().insert({ key, value })
} }
} }
if (propagate) { if (propagate) {
@ -121,7 +127,7 @@ module.exports = {
* Apply Dev Flags * Apply Dev Flags
*/ */
async applyFlags() { async applyFlags() {
WIKI.models.knex.client.config.debug = WIKI.config.flags.sqllog WIKI.db.knex.client.config.debug = WIKI.config.flags.sqllog
}, },
/** /**

@ -9,8 +9,6 @@ const Objection = require('objection')
const migrationSource = require('../db/migrator-source') const migrationSource = require('../db/migrator-source')
const migrateFromLegacy = require('../db/legacy') const migrateFromLegacy = require('../db/legacy')
/* global WIKI */
/** /**
* ORM DB module * ORM DB module
*/ */
@ -144,17 +142,13 @@ module.exports = {
} }
} }
let initTasksQueue = (WIKI.IS_MASTER) ? [
initTasks.connect,
initTasks.migrateFromLegacy,
initTasks.syncSchemas
] : [
() => { return Promise.resolve() }
]
// Perform init tasks // Perform init tasks
this.onReady = Promise.each(initTasksQueue, t => t()).return(true) this.onReady = (async () => {
await initTasks.connect()
await initTasks.migrateFromLegacy()
await initTasks.syncSchemas()
})()
return { return {
...this, ...this,
@ -187,7 +181,7 @@ module.exports = {
WIKI.auth.subscribeToEvents() WIKI.auth.subscribeToEvents()
WIKI.configSvc.subscribeToEvents() WIKI.configSvc.subscribeToEvents()
WIKI.models.pages.subscribeToEvents() WIKI.db.pages.subscribeToEvents()
WIKI.logger.info(`PG PubSub Listener initialized successfully: [ OK ]`) WIKI.logger.info(`PG PubSub Listener initialized successfully: [ OK ]`)
}, },
@ -208,7 +202,7 @@ module.exports = {
* @param {object} value Payload of the event * @param {object} value Payload of the event
*/ */
notifyViaDB (event, value) { notifyViaDB (event, value) {
WIKI.models.listener.publish('wiki', { WIKI.db.listener.publish('wiki', {
source: WIKI.INSTANCE_ID, source: WIKI.INSTANCE_ID,
event, event,
value value

@ -1,8 +1,6 @@
const fs = require('fs-extra') const fs = require('fs-extra')
const path = require('path') const path = require('path')
/* global WIKI */
module.exports = { module.exports = {
ext: {}, ext: {},
async init () { async init () {

@ -3,8 +3,6 @@ const EventEmitter = require('eventemitter2').EventEmitter2
let isShuttingDown = false let isShuttingDown = false
/* global WIKI */
module.exports = { module.exports = {
async init() { async init() {
WIKI.logger.info('=======================================') WIKI.logger.info('=======================================')
@ -12,10 +10,10 @@ module.exports = {
WIKI.logger.info('=======================================') WIKI.logger.info('=======================================')
WIKI.logger.info('Initializing...') WIKI.logger.info('Initializing...')
WIKI.models = require('./db').init() WIKI.db = require('./db').init()
try { try {
await WIKI.models.onReady await WIKI.db.onReady
await WIKI.configSvc.loadFromDb() await WIKI.configSvc.loadFromDb()
await WIKI.configSvc.applyFlags() await WIKI.configSvc.applyFlags()
} catch (err) { } catch (err) {
@ -64,21 +62,21 @@ module.exports = {
* Post-Web Boot Sequence * Post-Web Boot Sequence
*/ */
async postBootWeb() { async postBootWeb() {
await WIKI.models.analytics.refreshProvidersFromDisk() await WIKI.db.analytics.refreshProvidersFromDisk()
await WIKI.models.authentication.refreshStrategiesFromDisk() await WIKI.db.authentication.refreshStrategiesFromDisk()
await WIKI.models.commentProviders.refreshProvidersFromDisk() await WIKI.db.commentProviders.refreshProvidersFromDisk()
await WIKI.models.renderers.refreshRenderersFromDisk() await WIKI.db.renderers.refreshRenderersFromDisk()
await WIKI.models.storage.refreshTargetsFromDisk() await WIKI.db.storage.refreshTargetsFromDisk()
await WIKI.extensions.init() await WIKI.extensions.init()
await WIKI.auth.activateStrategies() await WIKI.auth.activateStrategies()
await WIKI.models.commentProviders.initProvider() await WIKI.db.commentProviders.initProvider()
await WIKI.models.sites.reloadCache() await WIKI.db.sites.reloadCache()
await WIKI.models.storage.initTargets() await WIKI.db.storage.initTargets()
await WIKI.scheduler.start() await WIKI.scheduler.start()
await WIKI.models.subscribeToNotifications() await WIKI.db.subscribeToNotifications()
}, },
/** /**
* Graceful shutdown * Graceful shutdown
@ -93,9 +91,9 @@ module.exports = {
await WIKI.scheduler.stop() await WIKI.scheduler.stop()
} }
if (WIKI.models) { if (WIKI.models) {
await WIKI.models.unsubscribeToNotifications() await WIKI.db.unsubscribeToNotifications()
if (WIKI.models.knex) { if (WIKI.db.knex) {
await WIKI.models.knex.destroy() await WIKI.db.knex.destroy()
} }
} }
if (WIKI.asar) { if (WIKI.asar) {

@ -6,8 +6,6 @@ const CSR = require('@root/csr')
const PEM = require('@root/pem') const PEM = require('@root/pem')
const punycode = require('punycode/') const punycode = require('punycode/')
/* global WIKI */
module.exports = { module.exports = {
apiDirectory: WIKI.dev ? 'https://acme-staging-v02.api.letsencrypt.org/directory' : 'https://acme-v02.api.letsencrypt.org/directory', apiDirectory: WIKI.dev ? 'https://acme-staging-v02.api.letsencrypt.org/directory' : 'https://acme-v02.api.letsencrypt.org/directory',
acme: null, acme: null,

@ -1,8 +1,6 @@
const chalk = require('chalk') const chalk = require('chalk')
const EventEmitter = require('events') const EventEmitter = require('events')
/* global WIKI */
const LEVELS = ['error', 'warn', 'info', 'debug'] const LEVELS = ['error', 'warn', 'info', 'debug']
const LEVELSIGNORED = ['verbose', 'silly'] const LEVELSIGNORED = ['verbose', 'silly']
const LEVELCOLORS = { const LEVELCOLORS = {

@ -3,8 +3,6 @@ const _ = require('lodash')
const fs = require('fs-extra') const fs = require('fs-extra')
const path = require('path') const path = require('path')
/* global WIKI */
module.exports = { module.exports = {
transport: null, transport: null,
templates: {}, templates: {},

@ -1,5 +1,3 @@
const { run, parseCronItems, Logger } = require('graphile-worker')
const { Pool } = require('pg')
const { DynamicThreadPool } = require('poolifier') const { DynamicThreadPool } = require('poolifier')
const { v4: uuid } = require('uuid') const { v4: uuid } = require('uuid')
const os = require('node:os') const os = require('node:os')
@ -21,49 +19,46 @@ module.exports = {
}, },
async start () { async start () {
WIKI.logger.info('Starting Scheduler...') WIKI.logger.info('Starting Scheduler...')
this.runner = await run({ // this.runner = await run({
pgPool: new Pool({ // pgPool: new Pool({
...(typeof WIKI.models.config === 'string') ? { // ...(typeof WIKI.db.config === 'string') ? {
connectionString: WIKI.models.config // connectionString: WIKI.db.config
} : WIKI.models.config, // } : WIKI.db.config,
max: this.maxWorkers + 2 // max: this.maxWorkers + 2
}), // }),
schema: WIKI.config.db.schemas.scheduler, // schema: WIKI.config.db.schemas.scheduler,
concurrency: this.maxWorkers, // concurrency: this.maxWorkers,
noHandleSignals: true, // noHandleSignals: true,
logger: new Logger(scope => { // logger: new Logger(scope => {
return (level, message, meta) => { // return (level, message, meta) => {
const prefix = (scope?.workerId) ? `[${scope.workerId}] ` : '' // const prefix = (scope?.workerId) ? `[${scope.workerId}] ` : ''
WIKI.logger[level](`${prefix}${message}`, meta) // WIKI.logger[level](`${prefix}${message}`, meta)
} // }
}), // }),
parsedCronItems: parseCronItems(WIKI.data.jobs.map(j => ({ // parsedCronItems: parseCronItems(WIKI.data.jobs),
...j, // taskList: {
identifier: uuid() // simple: async (payload, helpers) => {
}))), // // TODO: Handle task
taskList: { // },
simple: async (payload, helpers) => { // background: async (payload, helpers) => {
// TODO: Handle task // try {
}, // await this.pool.execute({
background: async (payload, helpers) => { // id: helpers.job.id,
try { // name: payload.name,
await this.pool.execute({ // data: payload.data
id: helpers.job.id, // })
name: payload.name, // } catch (err) {
data: payload.data // helpers.logger.warn(`Failed job: ${err.message}`)
}) // throw err
} catch (err) { // }
helpers.logger.warn(`Failed job: ${err.message}`) // }
throw err // }
} // })
}
}
})
WIKI.logger.info('Scheduler: [ STARTED ]') WIKI.logger.info('Scheduler: [ STARTED ]')
}, },
async stop () { async stop () {
WIKI.logger.info('Stopping Scheduler...') WIKI.logger.info('Stopping Scheduler...')
await this.runner.stop() // await this.runner.stop()
WIKI.logger.info('Scheduler: [ STOPPED ]') WIKI.logger.info('Scheduler: [ STOPPED ]')
} }
} }

@ -8,8 +8,6 @@ const io = require('socket.io')
const { ApolloServerPluginLandingPageGraphQLPlayground, ApolloServerPluginLandingPageProductionDefault } = require('apollo-server-core') const { ApolloServerPluginLandingPageGraphQLPlayground, ApolloServerPluginLandingPageProductionDefault } = require('apollo-server-core')
const { graphqlUploadExpress } = require('graphql-upload') const { graphqlUploadExpress } = require('graphql-upload')
/* global WIKI */
module.exports = { module.exports = {
graph: null, graph: null,
http: null, http: null,

@ -2,8 +2,6 @@ const fs = require('fs-extra')
const path = require('path') const path = require('path')
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
module.exports = { module.exports = {
async init () { async init () {
if (!WIKI.config.offline) { if (!WIKI.config.offline) {
@ -45,9 +43,9 @@ module.exports = {
_.set(lcObj, key.replace(':', '.'), value) _.set(lcObj, key.replace(':', '.'), value)
}) })
const localeDbExists = await WIKI.models.locales.query().select('code').where('code', locale.code).first() const localeDbExists = await WIKI.db.locales.query().select('code').where('code', locale.code).first()
if (localeDbExists) { if (localeDbExists) {
await WIKI.models.locales.query().update({ await WIKI.db.locales.query().update({
code: locale.code, code: locale.code,
strings: lcObj, strings: lcObj,
isRTL: locale.isRTL, isRTL: locale.isRTL,
@ -55,7 +53,7 @@ module.exports = {
nativeName: locale.nativeName nativeName: locale.nativeName
}).where('code', locale.code) }).where('code', locale.code)
} else { } else {
await WIKI.models.locales.query().insert({ await WIKI.db.locales.query().insert({
code: locale.code, code: locale.code,
strings: lcObj, strings: lcObj,
isRTL: locale.isRTL, isRTL: locale.isRTL,

@ -1,8 +1,6 @@
const fs = require('fs-extra') const fs = require('fs-extra')
const path = require('path') const path = require('path')
/* global WIKI */
module.exports = { module.exports = {
updates: { updates: {
channel: 'BETA', channel: 'BETA',

@ -1,7 +1,5 @@
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
module.exports = { module.exports = {
async migrate (knex) { async migrate (knex) {
const migrationsTableExists = await knex.schema.hasTable('migrations') const migrationsTableExists = await knex.schema.hasTable('migrations')

@ -3,8 +3,6 @@ const bcrypt = require('bcryptjs-then')
const crypto = require('crypto') const crypto = require('crypto')
const pem2jwk = require('pem-jwk').pem2jwk const pem2jwk = require('pem-jwk').pem2jwk
/* global WIKI */
exports.up = async knex => { exports.up = async knex => {
WIKI.logger.info('Running 3.0.0 database migration...') WIKI.logger.info('Running 3.0.0 database migration...')
@ -122,6 +120,35 @@ exports.up = async knex => {
table.timestamp('createdAt').notNullable().defaultTo(knex.fn.now()) table.timestamp('createdAt').notNullable().defaultTo(knex.fn.now())
table.timestamp('updatedAt').notNullable().defaultTo(knex.fn.now()) table.timestamp('updatedAt').notNullable().defaultTo(knex.fn.now())
}) })
// JOB SCHEDULE ------------------------
.createTable('jobSchedule', table => {
table.uuid('id').notNullable().primary().defaultTo(knex.raw('gen_random_uuid()'))
table.string('task').notNullable()
table.string('cron').notNullable()
table.string('type').notNullable().defaultTo('system')
table.jsonb('payload')
table.timestamp('createdAt').notNullable().defaultTo(knex.fn.now())
table.timestamp('updatedAt').notNullable().defaultTo(knex.fn.now())
})
// JOB HISTORY -------------------------
.createTable('jobHistory', table => {
table.uuid('id').notNullable().primary()
table.string('task').notNullable()
table.string('state').notNullable()
table.jsonb('payload')
table.string('lastErrorMessage')
table.timestamp('createdAt').notNullable()
table.timestamp('startedAt').notNullable()
table.timestamp('completedAt').notNullable().defaultTo(knex.fn.now())
})
// JOBS --------------------------------
.createTable('jobs', table => {
table.uuid('id').notNullable().primary().defaultTo(knex.raw('gen_random_uuid()'))
table.string('task').notNullable()
table.jsonb('payload')
table.timestamp('createdAt').notNullable().defaultTo(knex.fn.now())
table.timestamp('updatedAt').notNullable().defaultTo(knex.fn.now())
})
// LOCALES ----------------------------- // LOCALES -----------------------------
.createTable('locales', table => { .createTable('locales', table => {
table.string('code', 5).notNullable().primary() table.string('code', 5).notNullable().primary()
@ -636,6 +663,21 @@ exports.up = async knex => {
} }
}) })
// -> SCHEDULED JOBS
await knex('jobSchedule').insert([
{
task: 'update-locales',
cron: '0 0 * * *',
type: 'system'
},
{
task: 'check-version',
cron: '0 0 * * *',
type: 'system'
}
])
WIKI.logger.info('Completed 3.0.0 database migration.') WIKI.logger.info('Completed 3.0.0 database migration.')
} }

@ -4,8 +4,6 @@ const semver = require('semver')
const baseMigrationPath = path.join(WIKI.SERVERPATH, 'db/migrations') const baseMigrationPath = path.join(WIKI.SERVERPATH, 'db/migrations')
/* global WIKI */
module.exports = { module.exports = {
/** /**
* Gets the migration names * Gets the migration names

@ -6,8 +6,6 @@ const { makeExecutableSchema } = require('@graphql-tools/schema')
const { defaultKeyGenerator, rateLimitDirective } = require('graphql-rate-limit-directive') const { defaultKeyGenerator, rateLimitDirective } = require('graphql-rate-limit-directive')
const { GraphQLUpload } = require('graphql-upload') const { GraphQLUpload } = require('graphql-upload')
/* global WIKI */
// Rate Limiter // Rate Limiter
const { rateLimitDirectiveTypeDefs, rateLimitDirectiveTransformer } = rateLimitDirective({ const { rateLimitDirectiveTypeDefs, rateLimitDirectiveTransformer } = rateLimitDirective({

@ -1,12 +1,10 @@
const _ = require('lodash') const _ = require('lodash')
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
async analyticsProviders(obj, args, context, info) { async analyticsProviders(obj, args, context, info) {
let providers = await WIKI.models.analytics.getProviders(args.isEnabled) let providers = await WIKI.db.analytics.getProviders(args.isEnabled)
providers = providers.map(stg => { providers = providers.map(stg => {
const providerInfo = _.find(WIKI.data.analytics, ['key', stg.key]) || {} const providerInfo = _.find(WIKI.data.analytics, ['key', stg.key]) || {}
return { return {
@ -31,7 +29,7 @@ module.exports = {
async updateAnalyticsProviders(obj, args, context) { async updateAnalyticsProviders(obj, args, context) {
try { try {
for (let str of args.providers) { for (let str of args.providers) {
await WIKI.models.analytics.query().patch({ await WIKI.db.analytics.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}`, _.get(JSON.parse(value.value), 'v', null)) _.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null))

@ -3,8 +3,6 @@ const sanitize = require('sanitize-filename')
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
const assetHelper = require('../../helpers/asset') const assetHelper = require('../../helpers/asset')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
async assets(obj, args, context) { async assets(obj, args, context) {
@ -14,9 +12,9 @@ module.exports = {
if (args.kind !== 'ALL') { if (args.kind !== 'ALL') {
cond.kind = args.kind.toLowerCase() cond.kind = args.kind.toLowerCase()
} }
const folderHierarchy = await WIKI.models.assetFolders.getHierarchy(args.folderId) const folderHierarchy = await WIKI.db.assetFolders.getHierarchy(args.folderId)
const folderPath = folderHierarchy.map(h => h.slug).join('/') const folderPath = folderHierarchy.map(h => h.slug).join('/')
const results = await WIKI.models.assets.query().where(cond) const results = await WIKI.db.assets.query().where(cond)
return _.filter(results, r => { return _.filter(results, r => {
const path = folderPath ? `${folderPath}/${r.filename}` : r.filename const path = folderPath ? `${folderPath}/${r.filename}` : r.filename
return WIKI.auth.checkAccess(context.req.user, ['read:assets'], { path }) return WIKI.auth.checkAccess(context.req.user, ['read:assets'], { path })
@ -26,10 +24,10 @@ module.exports = {
})) }))
}, },
async assetsFolders(obj, args, context) { async assetsFolders(obj, args, context) {
const results = await WIKI.models.assetFolders.query().where({ const results = await WIKI.db.assetFolders.query().where({
parentId: args.parentFolderId === 0 ? null : args.parentFolderId parentId: args.parentFolderId === 0 ? null : args.parentFolderId
}) })
const parentHierarchy = await WIKI.models.assetFolders.getHierarchy(args.parentFolderId) const parentHierarchy = await WIKI.db.assetFolders.getHierarchy(args.parentFolderId)
const parentPath = parentHierarchy.map(h => h.slug).join('/') const parentPath = parentHierarchy.map(h => h.slug).join('/')
return _.filter(results, r => { return _.filter(results, r => {
const path = parentPath ? `${parentPath}/${r.slug}` : r.slug const path = parentPath ? `${parentPath}/${r.slug}` : r.slug
@ -45,12 +43,12 @@ module.exports = {
try { try {
const folderSlug = sanitize(args.slug).toLowerCase() const folderSlug = sanitize(args.slug).toLowerCase()
const parentFolderId = args.parentFolderId === 0 ? null : args.parentFolderId const parentFolderId = args.parentFolderId === 0 ? null : args.parentFolderId
const result = await WIKI.models.assetFolders.query().where({ const result = await WIKI.db.assetFolders.query().where({
parentId: parentFolderId, parentId: parentFolderId,
slug: folderSlug slug: folderSlug
}).first() }).first()
if (!result) { if (!result) {
await WIKI.models.assetFolders.query().insert({ await WIKI.db.assetFolders.query().insert({
slug: folderSlug, slug: folderSlug,
name: folderSlug, name: folderSlug,
parentId: parentFolderId parentId: parentFolderId
@ -72,7 +70,7 @@ module.exports = {
try { try {
const filename = sanitize(args.filename).toLowerCase() const filename = sanitize(args.filename).toLowerCase()
const asset = await WIKI.models.assets.query().findById(args.id) const asset = await WIKI.db.assets.query().findById(args.id)
if (asset) { if (asset) {
// Check for extension mismatch // Check for extension mismatch
if (!_.endsWith(filename, asset.ext)) { if (!_.endsWith(filename, asset.ext)) {
@ -85,7 +83,7 @@ module.exports = {
} }
// Check for collision // Check for collision
const assetCollision = await WIKI.models.assets.query().where({ const assetCollision = await WIKI.db.assets.query().where({
filename, filename,
folderId: asset.folderId folderId: asset.folderId
}).first() }).first()
@ -96,7 +94,7 @@ module.exports = {
// Get asset folder path // Get asset folder path
let hierarchy = [] let hierarchy = []
if (asset.folderId) { if (asset.folderId) {
hierarchy = await WIKI.models.assetFolders.getHierarchy(asset.folderId) hierarchy = await WIKI.db.assetFolders.getHierarchy(asset.folderId)
} }
// Check source asset permissions // Check source asset permissions
@ -113,7 +111,7 @@ module.exports = {
// Update filename + hash // Update filename + hash
const fileHash = assetHelper.generateHash(assetTargetPath) const fileHash = assetHelper.generateHash(assetTargetPath)
await WIKI.models.assets.query().patch({ await WIKI.db.assets.query().patch({
filename: filename, filename: filename,
hash: fileHash hash: fileHash
}).findById(args.id) }).findById(args.id)
@ -122,7 +120,7 @@ module.exports = {
await asset.deleteAssetCache() await asset.deleteAssetCache()
// Rename in Storage // Rename in Storage
await WIKI.models.storage.assetEvent({ await WIKI.db.storage.assetEvent({
event: 'renamed', event: 'renamed',
asset: { asset: {
...asset, ...asset,
@ -149,7 +147,7 @@ module.exports = {
*/ */
async deleteAsset(obj, args, context) { async deleteAsset(obj, args, context) {
try { try {
const asset = await WIKI.models.assets.query().findById(args.id) const asset = await WIKI.db.assets.query().findById(args.id)
if (asset) { if (asset) {
// Check permissions // Check permissions
const assetPath = await asset.getAssetPath() const assetPath = await asset.getAssetPath()
@ -157,12 +155,12 @@ module.exports = {
throw new WIKI.Error.AssetDeleteForbidden() throw new WIKI.Error.AssetDeleteForbidden()
} }
await WIKI.models.knex('assetData').where('id', args.id).del() await WIKI.db.knex('assetData').where('id', args.id).del()
await WIKI.models.assets.query().deleteById(args.id) await WIKI.db.assets.query().deleteById(args.id)
await asset.deleteAssetCache() await asset.deleteAssetCache()
// Delete from Storage // Delete from Storage
await WIKI.models.storage.assetEvent({ await WIKI.db.storage.assetEvent({
event: 'deleted', event: 'deleted',
asset: { asset: {
...asset, ...asset,
@ -188,7 +186,7 @@ module.exports = {
*/ */
async flushTempUploads(obj, args, context) { async flushTempUploads(obj, args, context) {
try { try {
await WIKI.models.assets.flushTempUploads() await WIKI.db.assets.flushTempUploads()
return { return {
responseResult: graphHelper.generateSuccess('Temporary Uploads have been flushed successfully.') responseResult: graphHelper.generateSuccess('Temporary Uploads have been flushed successfully.')
} }

@ -1,15 +1,13 @@
const _ = require('lodash') const _ = require('lodash')
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
/** /**
* List of API Keys * List of API Keys
*/ */
async apiKeys (obj, args, context) { async apiKeys (obj, args, context) {
const keys = await WIKI.models.apiKeys.query().orderBy(['isRevoked', 'name']) const keys = await WIKI.db.apiKeys.query().orderBy(['isRevoked', 'name'])
return keys.map(k => ({ return keys.map(k => ({
id: k.id, id: k.id,
name: k.name, name: k.name,
@ -39,14 +37,14 @@ module.exports = {
* Fetch active authentication strategies * Fetch active authentication strategies
*/ */
async authActiveStrategies (obj, args, context) { async authActiveStrategies (obj, args, context) {
return WIKI.models.authentication.getStrategies({ enabledOnly: args.enabledOnly }) return WIKI.db.authentication.getStrategies({ enabledOnly: args.enabledOnly })
}, },
/** /**
* Fetch site authentication strategies * Fetch site authentication strategies
*/ */
async authSiteStrategies (obj, args, context, info) { async authSiteStrategies (obj, args, context, info) {
const site = await WIKI.models.sites.query().findById(args.siteId) const site = await WIKI.db.sites.query().findById(args.siteId)
const activeStrategies = await WIKI.models.authentication.getStrategies({ enabledOnly: true }) const activeStrategies = await WIKI.db.authentication.getStrategies({ enabledOnly: true })
return activeStrategies.map(str => { return activeStrategies.map(str => {
const siteAuth = _.find(site.config.authStrategies, ['id', str.id]) || {} const siteAuth = _.find(site.config.authStrategies, ['id', str.id]) || {}
return { return {
@ -64,7 +62,7 @@ module.exports = {
*/ */
async createApiKey (obj, args, context) { async createApiKey (obj, args, context) {
try { try {
const key = await WIKI.models.apiKeys.createNewKey(args) const key = await WIKI.db.apiKeys.createNewKey(args)
await WIKI.auth.reloadApiKeys() await WIKI.auth.reloadApiKeys()
WIKI.events.outbound.emit('reloadApiKeys') WIKI.events.outbound.emit('reloadApiKeys')
return { return {
@ -81,7 +79,7 @@ module.exports = {
*/ */
async login (obj, args, context) { async login (obj, args, context) {
try { try {
const authResult = await WIKI.models.users.login(args, context) const authResult = await WIKI.db.users.login(args, context)
return { return {
...authResult, ...authResult,
operation: graphHelper.generateSuccess('Login success') operation: graphHelper.generateSuccess('Login success')
@ -101,7 +99,7 @@ module.exports = {
*/ */
async loginTFA (obj, args, context) { async loginTFA (obj, args, context) {
try { try {
const authResult = await WIKI.models.users.loginTFA(args, context) const authResult = await WIKI.db.users.loginTFA(args, context)
return { return {
...authResult, ...authResult,
responseResult: graphHelper.generateSuccess('TFA success') responseResult: graphHelper.generateSuccess('TFA success')
@ -115,7 +113,7 @@ module.exports = {
*/ */
async changePassword (obj, args, context) { async changePassword (obj, args, context) {
try { try {
const authResult = await WIKI.models.users.loginChangePassword(args, context) const authResult = await WIKI.db.users.loginChangePassword(args, context)
return { return {
...authResult, ...authResult,
responseResult: graphHelper.generateSuccess('Password changed successfully') responseResult: graphHelper.generateSuccess('Password changed successfully')
@ -129,7 +127,7 @@ module.exports = {
*/ */
async forgotPassword (obj, args, context) { async forgotPassword (obj, args, context) {
try { try {
await WIKI.models.users.loginForgotPassword(args, context) await WIKI.db.users.loginForgotPassword(args, context)
return { return {
responseResult: graphHelper.generateSuccess('Password reset request processed.') responseResult: graphHelper.generateSuccess('Password reset request processed.')
} }
@ -142,7 +140,7 @@ module.exports = {
*/ */
async register (obj, args, context) { async register (obj, args, context) {
try { try {
await WIKI.models.users.register({ ...args, verify: true }, context) await WIKI.db.users.register({ ...args, verify: true }, context)
return { return {
responseResult: graphHelper.generateSuccess('Registration success') responseResult: graphHelper.generateSuccess('Registration success')
} }
@ -169,7 +167,7 @@ module.exports = {
*/ */
async revokeApiKey (obj, args, context) { async revokeApiKey (obj, args, context) {
try { try {
await WIKI.models.apiKeys.query().findById(args.id).patch({ await WIKI.db.apiKeys.query().findById(args.id).patch({
isRevoked: true isRevoked: true
}) })
await WIKI.auth.reloadApiKeys() await WIKI.auth.reloadApiKeys()
@ -186,7 +184,7 @@ module.exports = {
*/ */
async updateAuthStrategies (obj, args, context) { async updateAuthStrategies (obj, args, context) {
try { try {
const previousStrategies = await WIKI.models.authentication.getStrategies() const previousStrategies = await WIKI.db.authentication.getStrategies()
for (const str of args.strategies) { for (const str of args.strategies) {
const newStr = { const newStr = {
displayName: str.displayName, displayName: str.displayName,
@ -202,13 +200,13 @@ module.exports = {
} }
if (_.some(previousStrategies, ['key', str.key])) { if (_.some(previousStrategies, ['key', str.key])) {
await WIKI.models.authentication.query().patch({ await WIKI.db.authentication.query().patch({
key: str.key, key: str.key,
strategyKey: str.strategyKey, strategyKey: str.strategyKey,
...newStr ...newStr
}).where('key', str.key) }).where('key', str.key)
} else { } else {
await WIKI.models.authentication.query().insert({ await WIKI.db.authentication.query().insert({
key: str.key, key: str.key,
strategyKey: str.strategyKey, strategyKey: str.strategyKey,
...newStr ...newStr
@ -217,11 +215,11 @@ module.exports = {
} }
for (const str of _.differenceBy(previousStrategies, args.strategies, 'key')) { for (const str of _.differenceBy(previousStrategies, args.strategies, 'key')) {
const hasUsers = await WIKI.models.users.query().count('* as total').where({ providerKey: str.key }).first() const hasUsers = await WIKI.db.users.query().count('* as total').where({ providerKey: str.key }).first()
if (_.toSafeInteger(hasUsers.total) > 0) { if (_.toSafeInteger(hasUsers.total) > 0) {
throw new Error(`Cannot delete ${str.displayName} as 1 or more users are still using it.`) throw new Error(`Cannot delete ${str.displayName} as 1 or more users are still using it.`)
} else { } else {
await WIKI.models.authentication.query().delete().where('key', str.key) await WIKI.db.authentication.query().delete().where('key', str.key)
} }
} }

@ -1,15 +1,13 @@
const _ = require('lodash') const _ = require('lodash')
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
/** /**
* Fetch list of Comments Providers * Fetch list of Comments Providers
*/ */
async commentsProviders(obj, args, context, info) { async commentsProviders(obj, args, context, info) {
const providers = await WIKI.models.commentProviders.getProviders() const providers = await WIKI.db.commentProviders.getProviders()
return providers.map(provider => { return providers.map(provider => {
const providerInfo = _.find(WIKI.data.commentProviders, ['key', provider.key]) || {} const providerInfo = _.find(WIKI.data.commentProviders, ['key', provider.key]) || {}
return { return {
@ -34,10 +32,10 @@ module.exports = {
* Fetch list of comments for a page * Fetch list of comments for a page
*/ */
async comments (obj, args, context) { async comments (obj, args, context) {
const page = await WIKI.models.pages.query().select('id').findOne({ localeCode: args.locale, path: args.path }) const page = await WIKI.db.pages.query().select('id').findOne({ localeCode: args.locale, path: args.path })
if (page) { if (page) {
if (WIKI.auth.checkAccess(context.req.user, ['read:comments'], args)) { if (WIKI.auth.checkAccess(context.req.user, ['read:comments'], args)) {
const comments = await WIKI.models.comments.query().where('pageId', page.id).orderBy('createdAt') const comments = await WIKI.db.comments.query().where('pageId', page.id).orderBy('createdAt')
return comments.map(c => ({ return comments.map(c => ({
...c, ...c,
authorName: c.name, authorName: c.name,
@ -59,7 +57,7 @@ module.exports = {
if (!cm || !cm.pageId) { if (!cm || !cm.pageId) {
throw new WIKI.Error.CommentNotFound() throw new WIKI.Error.CommentNotFound()
} }
const page = await WIKI.models.pages.query().select('localeCode', 'path').findById(cm.pageId) const page = await WIKI.db.pages.query().select('localeCode', 'path').findById(cm.pageId)
if (page) { if (page) {
if (WIKI.auth.checkAccess(context.req.user, ['read:comments'], { if (WIKI.auth.checkAccess(context.req.user, ['read:comments'], {
path: page.path, path: page.path,
@ -86,7 +84,7 @@ module.exports = {
*/ */
async createComment (obj, args, context) { async createComment (obj, args, context) {
try { try {
const cmId = await WIKI.models.comments.postNewComment({ const cmId = await WIKI.db.comments.postNewComment({
...args, ...args,
user: context.req.user, user: context.req.user,
ip: context.req.ip ip: context.req.ip
@ -104,7 +102,7 @@ module.exports = {
*/ */
async updateComment (obj, args, context) { async updateComment (obj, args, context) {
try { try {
const cmRender = await WIKI.models.comments.updateComment({ const cmRender = await WIKI.db.comments.updateComment({
...args, ...args,
user: context.req.user, user: context.req.user,
ip: context.req.ip ip: context.req.ip
@ -122,7 +120,7 @@ module.exports = {
*/ */
async deleteComment (obj, args, context) { async deleteComment (obj, args, context) {
try { try {
await WIKI.models.comments.deleteComment({ await WIKI.db.comments.deleteComment({
id: args.id, id: args.id,
user: context.req.user, user: context.req.user,
ip: context.req.ip ip: context.req.ip
@ -140,7 +138,7 @@ module.exports = {
async updateCommentsProviders(obj, args, context) { async updateCommentsProviders(obj, args, context) {
try { try {
for (let provider of args.providers) { for (let provider of args.providers) {
await WIKI.models.commentProviders.query().patch({ await WIKI.db.commentProviders.query().patch({
isEnabled: provider.isEnabled, isEnabled: provider.isEnabled,
config: _.reduce(provider.config, (result, value, key) => { config: _.reduce(provider.config, (result, value, key) => {
_.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null)) _.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null))
@ -148,7 +146,7 @@ module.exports = {
}, {}) }, {})
}).where('key', provider.key) }).where('key', provider.key)
} }
await WIKI.models.commentProviders.initProvider() await WIKI.db.commentProviders.initProvider()
return { return {
responseResult: graphHelper.generateSuccess('Comment Providers updated successfully') responseResult: graphHelper.generateSuccess('Comment Providers updated successfully')
} }

@ -3,24 +3,22 @@ const safeRegex = require('safe-regex')
const _ = require('lodash') const _ = require('lodash')
const { v4: uuid } = require('uuid') const { v4: uuid } = require('uuid')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
/** /**
* FETCH ALL GROUPS * FETCH ALL GROUPS
*/ */
async groups () { async groups () {
return WIKI.models.groups.query().select( return WIKI.db.groups.query().select(
'groups.*', 'groups.*',
WIKI.models.groups.relatedQuery('users').count().as('userCount') WIKI.db.groups.relatedQuery('users').count().as('userCount')
) )
}, },
/** /**
* FETCH A SINGLE GROUP * FETCH A SINGLE GROUP
*/ */
async groupById(obj, args) { async groupById(obj, args) {
return WIKI.models.groups.query().findById(args.id) return WIKI.db.groups.query().findById(args.id)
} }
}, },
Mutation: { Mutation: {
@ -34,7 +32,7 @@ module.exports = {
} }
// Check for valid group // Check for valid group
const grp = await WIKI.models.groups.query().findById(args.groupId) const grp = await WIKI.db.groups.query().findById(args.groupId)
if (!grp) { if (!grp) {
throw new Error('Invalid Group ID') throw new Error('Invalid Group ID')
} }
@ -51,13 +49,13 @@ module.exports = {
} }
// Check for valid user // Check for valid user
const usr = await WIKI.models.users.query().findById(args.userId) const usr = await WIKI.db.users.query().findById(args.userId)
if (!usr) { if (!usr) {
throw new Error('Invalid User ID') throw new Error('Invalid User ID')
} }
// Check for existing relation // Check for existing relation
const relExist = await WIKI.models.knex('userGroups').where({ const relExist = await WIKI.db.knex('userGroups').where({
userId: args.userId, userId: args.userId,
groupId: args.groupId groupId: args.groupId
}).first() }).first()
@ -80,7 +78,7 @@ module.exports = {
* CREATE NEW GROUP * CREATE NEW GROUP
*/ */
async createGroup (obj, args, { req }) { async createGroup (obj, args, { req }) {
const group = await WIKI.models.groups.query().insertAndFetch({ const group = await WIKI.db.groups.query().insertAndFetch({
name: args.name, name: args.name,
permissions: JSON.stringify(WIKI.data.groups.defaultPermissions), permissions: JSON.stringify(WIKI.data.groups.defaultPermissions),
rules: JSON.stringify(WIKI.data.groups.defaultRules.map(r => ({ rules: JSON.stringify(WIKI.data.groups.defaultRules.map(r => ({
@ -104,7 +102,7 @@ module.exports = {
throw new Error('Cannot delete this group.') throw new Error('Cannot delete this group.')
} }
await WIKI.models.groups.query().deleteById(args.id) await WIKI.db.groups.query().deleteById(args.id)
WIKI.auth.revokeUserTokens({ id: args.id, kind: 'g' }) WIKI.auth.revokeUserTokens({ id: args.id, kind: 'g' })
WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'g' }) WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'g' })
@ -126,11 +124,11 @@ module.exports = {
if (args.userId === 1 && args.groupId === 1) { if (args.userId === 1 && args.groupId === 1) {
throw new Error('Cannot unassign Administrator user from Administrators group.') throw new Error('Cannot unassign Administrator user from Administrators group.')
} }
const grp = await WIKI.models.groups.query().findById(args.groupId) const grp = await WIKI.db.groups.query().findById(args.groupId)
if (!grp) { if (!grp) {
throw new Error('Invalid Group ID') throw new Error('Invalid Group ID')
} }
const usr = await WIKI.models.users.query().findById(args.userId) const usr = await WIKI.db.users.query().findById(args.userId)
if (!usr) { if (!usr) {
throw new Error('Invalid User ID') throw new Error('Invalid User ID')
} }
@ -179,7 +177,7 @@ module.exports = {
} }
// Update group // Update group
await WIKI.models.groups.query().patch({ await WIKI.db.groups.query().patch({
name: args.name, name: args.name,
redirectOnLogin: args.redirectOnLogin, redirectOnLogin: args.redirectOnLogin,
permissions: JSON.stringify(args.permissions), permissions: JSON.stringify(args.permissions),

@ -1,15 +1,13 @@
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
async hooks () { async hooks () {
return WIKI.models.hooks.query().orderBy('name') return WIKI.db.hooks.query().orderBy('name')
}, },
async hookById (obj, args) { async hookById (obj, args) {
return WIKI.models.hooks.query().findById(args.id) return WIKI.db.hooks.query().findById(args.id)
} }
}, },
Mutation: { Mutation: {
@ -29,7 +27,7 @@ module.exports = {
throw new WIKI.Error.Custom('HookCreateInvalidURL', 'Invalid Hook URL') throw new WIKI.Error.Custom('HookCreateInvalidURL', 'Invalid Hook URL')
} }
// -> Create hook // -> Create hook
const newHook = await WIKI.models.hooks.createHook(args) const newHook = await WIKI.db.hooks.createHook(args)
WIKI.logger.debug(`New Hook ${newHook.id} created successfully.`) WIKI.logger.debug(`New Hook ${newHook.id} created successfully.`)
return { return {
@ -46,7 +44,7 @@ module.exports = {
async updateHook (obj, args) { async updateHook (obj, args) {
try { try {
// -> Load hook // -> Load hook
const hook = await WIKI.models.hooks.query().findById(args.id) const hook = await WIKI.db.hooks.query().findById(args.id)
if (!hook) { if (!hook) {
throw new WIKI.Error.Custom('HookInvalidId', 'Invalid Hook ID') throw new WIKI.Error.Custom('HookInvalidId', 'Invalid Hook ID')
} }
@ -61,7 +59,7 @@ module.exports = {
throw new WIKI.Error.Custom('HookInvalidURL', 'URL is invalid.') throw new WIKI.Error.Custom('HookInvalidURL', 'URL is invalid.')
} }
// -> Update hook // -> Update hook
await WIKI.models.hooks.query().findById(args.id).patch(args.patch) await WIKI.db.hooks.query().findById(args.id).patch(args.patch)
WIKI.logger.debug(`Hook ${args.id} updated successfully.`) WIKI.logger.debug(`Hook ${args.id} updated successfully.`)
return { return {
@ -76,7 +74,7 @@ module.exports = {
*/ */
async deleteHook (obj, args) { async deleteHook (obj, args) {
try { try {
await WIKI.models.hooks.deleteHook(args.id) await WIKI.db.hooks.deleteHook(args.id)
WIKI.logger.debug(`Hook ${args.id} deleted successfully.`) WIKI.logger.debug(`Hook ${args.id} deleted successfully.`)
return { return {
operation: graphHelper.generateSuccess('Hook deleted successfully') operation: graphHelper.generateSuccess('Hook deleted successfully')

@ -1,13 +1,11 @@
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
async locales(obj, args, context, info) { async locales(obj, args, context, info) {
let remoteLocales = await WIKI.cache.get('locales') let remoteLocales = await WIKI.cache.get('locales')
let localLocales = await WIKI.models.locales.query().select('code', 'isRTL', 'name', 'nativeName', 'createdAt', 'updatedAt', 'availability') let localLocales = await WIKI.db.locales.query().select('code', 'isRTL', 'name', 'nativeName', 'createdAt', 'updatedAt', 'availability')
remoteLocales = remoteLocales || localLocales remoteLocales = remoteLocales || localLocales
return _.map(remoteLocales, rl => { return _.map(remoteLocales, rl => {
let isInstalled = _.some(localLocales, ['code', rl.code]) let isInstalled = _.some(localLocales, ['code', rl.code])
@ -44,7 +42,7 @@ module.exports = {
WIKI.config.lang.namespacing = args.namespacing WIKI.config.lang.namespacing = args.namespacing
WIKI.config.lang.namespaces = _.union(args.namespaces, [args.locale]) WIKI.config.lang.namespaces = _.union(args.namespaces, [args.locale])
const newLocale = await WIKI.models.locales.query().select('isRTL').where('code', args.locale).first() const newLocale = await WIKI.db.locales.query().select('isRTL').where('code', args.locale).first()
WIKI.config.lang.rtl = newLocale.isRTL WIKI.config.lang.rtl = newLocale.isRTL
await WIKI.configSvc.saveToDb(['lang']) await WIKI.configSvc.saveToDb(['lang'])

@ -1,8 +1,6 @@
const _ = require('lodash') const _ = require('lodash')
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
async mailConfig(obj, args, context, info) { async mailConfig(obj, args, context, info) {

@ -1,11 +1,9 @@
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
async navigationTree (obj, args, context, info) { async navigationTree (obj, args, context, info) {
return WIKI.models.navigation.getTree({ cache: false, locale: 'all', bypassAuth: true }) return WIKI.db.navigation.getTree({ cache: false, locale: 'all', bypassAuth: true })
}, },
navigationConfig (obj, args, context, info) { navigationConfig (obj, args, context, info) {
return WIKI.config.nav return WIKI.config.nav
@ -14,7 +12,7 @@ module.exports = {
Mutation: { Mutation: {
async updateNavigationTree (obj, args, context) { async updateNavigationTree (obj, args, context) {
try { try {
await WIKI.models.navigation.query().patch({ await WIKI.db.navigation.query().patch({
config: args.tree config: args.tree
}).where('key', 'site') }).where('key', 'site')
for (const tree of args.tree) { for (const tree of args.tree) {

@ -1,20 +1,18 @@
const _ = require('lodash') const _ = require('lodash')
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
/** /**
* PAGE HISTORY * PAGE HISTORY
*/ */
async pageHistoryById (obj, args, context, info) { async pageHistoryById (obj, args, context, info) {
const page = await WIKI.models.pages.query().select('path', 'localeCode').findById(args.id) const page = await WIKI.db.pages.query().select('path', 'localeCode').findById(args.id)
if (WIKI.auth.checkAccess(context.req.user, ['read:history'], { if (WIKI.auth.checkAccess(context.req.user, ['read:history'], {
path: page.path, path: page.path,
locale: page.localeCode locale: page.localeCode
})) { })) {
return WIKI.models.pageHistory.getHistory({ return WIKI.db.pageHistory.getHistory({
pageId: args.id, pageId: args.id,
offsetPage: args.offsetPage || 0, offsetPage: args.offsetPage || 0,
offsetSize: args.offsetSize || 100 offsetSize: args.offsetSize || 100
@ -27,12 +25,12 @@ module.exports = {
* PAGE VERSION * PAGE VERSION
*/ */
async pageVersionById (obj, args, context, info) { async pageVersionById (obj, args, context, info) {
const page = await WIKI.models.pages.query().select('path', 'localeCode').findById(args.pageId) const page = await WIKI.db.pages.query().select('path', 'localeCode').findById(args.pageId)
if (WIKI.auth.checkAccess(context.req.user, ['read:history'], { if (WIKI.auth.checkAccess(context.req.user, ['read:history'], {
path: page.path, path: page.path,
locale: page.localeCode locale: page.localeCode
})) { })) {
return WIKI.models.pageHistory.getVersion({ return WIKI.db.pageHistory.getVersion({
pageId: args.pageId, pageId: args.pageId,
versionId: args.versionId versionId: args.versionId
}) })
@ -68,7 +66,7 @@ module.exports = {
* LIST PAGES * LIST PAGES
*/ */
async pages (obj, args, context, info) { async pages (obj, args, context, info) {
let results = await WIKI.models.pages.query().column([ let results = await WIKI.db.pages.query().column([
'pages.id', 'pages.id',
'path', 'path',
{ locale: 'localeCode' }, { locale: 'localeCode' },
@ -144,7 +142,7 @@ module.exports = {
* FETCH SINGLE PAGE * FETCH SINGLE PAGE
*/ */
async pageById (obj, args, context, info) { async pageById (obj, args, context, info) {
let page = await WIKI.models.pages.getPageFromDb(args.id) let page = await WIKI.db.pages.getPageFromDb(args.id)
if (page) { if (page) {
if (WIKI.auth.checkAccess(context.req.user, ['manage:pages', 'delete:pages'], { if (WIKI.auth.checkAccess(context.req.user, ['manage:pages', 'delete:pages'], {
path: page.path, path: page.path,
@ -166,7 +164,7 @@ module.exports = {
* FETCH TAGS * FETCH TAGS
*/ */
async tags (obj, args, context, info) { async tags (obj, args, context, info) {
const pages = await WIKI.models.pages.query() const pages = await WIKI.db.pages.query()
.column([ .column([
'path', 'path',
{ locale: 'localeCode' } { locale: 'localeCode' }
@ -185,7 +183,7 @@ module.exports = {
*/ */
async searchTags (obj, args, context, info) { async searchTags (obj, args, context, info) {
const query = _.trim(args.query) const query = _.trim(args.query)
const pages = await WIKI.models.pages.query() const pages = await WIKI.db.pages.query()
.column([ .column([
'path', 'path',
{ locale: 'localeCode' } { locale: 'localeCode' }
@ -220,7 +218,7 @@ module.exports = {
if (!args.locale) { args.locale = WIKI.config.lang.code } if (!args.locale) { args.locale = WIKI.config.lang.code }
if (args.path && !args.parent) { if (args.path && !args.parent) {
curPage = await WIKI.models.knex('pageTree').first('parent', 'ancestors').where({ curPage = await WIKI.db.knex('pageTree').first('parent', 'ancestors').where({
path: args.path, path: args.path,
localeCode: args.locale localeCode: args.locale
}) })
@ -231,7 +229,7 @@ module.exports = {
} }
} }
const results = await WIKI.models.knex('pageTree').where(builder => { const results = await WIKI.db.knex('pageTree').where(builder => {
builder.where('localeCode', args.locale) builder.where('localeCode', args.locale)
switch (args.mode) { switch (args.mode) {
case 'FOLDERS': case 'FOLDERS':
@ -268,14 +266,14 @@ module.exports = {
let results let results
if (WIKI.config.db.type === 'mysql' || WIKI.config.db.type === 'mariadb' || WIKI.config.db.type === 'sqlite') { if (WIKI.config.db.type === 'mysql' || WIKI.config.db.type === 'mariadb' || WIKI.config.db.type === 'sqlite') {
results = await WIKI.models.knex('pages') results = await WIKI.db.knex('pages')
.column({ id: 'pages.id' }, { path: 'pages.path' }, 'title', { link: 'pageLinks.path' }, { locale: 'pageLinks.localeCode' }) .column({ id: 'pages.id' }, { path: 'pages.path' }, 'title', { link: 'pageLinks.path' }, { locale: 'pageLinks.localeCode' })
.leftJoin('pageLinks', 'pages.id', 'pageLinks.pageId') .leftJoin('pageLinks', 'pages.id', 'pageLinks.pageId')
.where({ .where({
'pages.localeCode': args.locale 'pages.localeCode': args.locale
}) })
.unionAll( .unionAll(
WIKI.models.knex('pageLinks') WIKI.db.knex('pageLinks')
.column({ id: 'pages.id' }, { path: 'pages.path' }, 'title', { link: 'pageLinks.path' }, { locale: 'pageLinks.localeCode' }) .column({ id: 'pages.id' }, { path: 'pages.path' }, 'title', { link: 'pageLinks.path' }, { locale: 'pageLinks.localeCode' })
.leftJoin('pages', 'pageLinks.pageId', 'pages.id') .leftJoin('pages', 'pageLinks.pageId', 'pages.id')
.where({ .where({
@ -283,7 +281,7 @@ module.exports = {
}) })
) )
} else { } else {
results = await WIKI.models.knex('pages') results = await WIKI.db.knex('pages')
.column({ id: 'pages.id' }, { path: 'pages.path' }, 'title', { link: 'pageLinks.path' }, { locale: 'pageLinks.localeCode' }) .column({ id: 'pages.id' }, { path: 'pages.path' }, 'title', { link: 'pageLinks.path' }, { locale: 'pageLinks.localeCode' })
.fullOuterJoin('pageLinks', 'pages.id', 'pageLinks.pageId') .fullOuterJoin('pageLinks', 'pages.id', 'pageLinks.pageId')
.where({ .where({
@ -320,7 +318,7 @@ module.exports = {
* CHECK FOR EDITING CONFLICT * CHECK FOR EDITING CONFLICT
*/ */
async checkConflicts (obj, args, context, info) { async checkConflicts (obj, args, context, info) {
let page = await WIKI.models.pages.query().select('path', 'localeCode', 'updatedAt').findById(args.id) let page = await WIKI.db.pages.query().select('path', 'localeCode', 'updatedAt').findById(args.id)
if (page) { if (page) {
if (WIKI.auth.checkAccess(context.req.user, ['write:pages', 'manage:pages'], { if (WIKI.auth.checkAccess(context.req.user, ['write:pages', 'manage:pages'], {
path: page.path, path: page.path,
@ -338,7 +336,7 @@ module.exports = {
* FETCH LATEST VERSION FOR CONFLICT COMPARISON * FETCH LATEST VERSION FOR CONFLICT COMPARISON
*/ */
async checkConflictsLatest (obj, args, context, info) { async checkConflictsLatest (obj, args, context, info) {
let page = await WIKI.models.pages.getPageFromDb(args.id) let page = await WIKI.db.pages.getPageFromDb(args.id)
if (page) { if (page) {
if (WIKI.auth.checkAccess(context.req.user, ['write:pages', 'manage:pages'], { if (WIKI.auth.checkAccess(context.req.user, ['write:pages', 'manage:pages'], {
path: page.path, path: page.path,
@ -363,7 +361,7 @@ module.exports = {
*/ */
async createPage(obj, args, context) { async createPage(obj, args, context) {
try { try {
const page = await WIKI.models.pages.createPage({ const page = await WIKI.db.pages.createPage({
...args, ...args,
user: context.req.user user: context.req.user
}) })
@ -380,7 +378,7 @@ module.exports = {
*/ */
async updatePage(obj, args, context) { async updatePage(obj, args, context) {
try { try {
const page = await WIKI.models.pages.updatePage({ const page = await WIKI.db.pages.updatePage({
...args, ...args,
user: context.req.user user: context.req.user
}) })
@ -397,7 +395,7 @@ module.exports = {
*/ */
async convertPage(obj, args, context) { async convertPage(obj, args, context) {
try { try {
await WIKI.models.pages.convertPage({ await WIKI.db.pages.convertPage({
...args, ...args,
user: context.req.user user: context.req.user
}) })
@ -413,7 +411,7 @@ module.exports = {
*/ */
async renamePage(obj, args, context) { async renamePage(obj, args, context) {
try { try {
await WIKI.models.pages.movePage({ await WIKI.db.pages.movePage({
...args, ...args,
user: context.req.user user: context.req.user
}) })
@ -429,7 +427,7 @@ module.exports = {
*/ */
async deletePage(obj, args, context) { async deletePage(obj, args, context) {
try { try {
await WIKI.models.pages.deletePage({ await WIKI.db.pages.deletePage({
...args, ...args,
user: context.req.user user: context.req.user
}) })
@ -445,10 +443,10 @@ module.exports = {
*/ */
async deleteTag (obj, args, context) { async deleteTag (obj, args, context) {
try { try {
const tagToDel = await WIKI.models.tags.query().findById(args.id) const tagToDel = await WIKI.db.tags.query().findById(args.id)
if (tagToDel) { if (tagToDel) {
await tagToDel.$relatedQuery('pages').unrelate() await tagToDel.$relatedQuery('pages').unrelate()
await WIKI.models.tags.query().deleteById(args.id) await WIKI.db.tags.query().deleteById(args.id)
} else { } else {
throw new Error('This tag does not exist.') throw new Error('This tag does not exist.')
} }
@ -464,7 +462,7 @@ module.exports = {
*/ */
async updateTag (obj, args, context) { async updateTag (obj, args, context) {
try { try {
const affectedRows = await WIKI.models.tags.query() const affectedRows = await WIKI.db.tags.query()
.findById(args.id) .findById(args.id)
.patch({ .patch({
tag: _.trim(args.tag).toLowerCase(), tag: _.trim(args.tag).toLowerCase(),
@ -485,7 +483,7 @@ module.exports = {
*/ */
async flushCache(obj, args, context) { async flushCache(obj, args, context) {
try { try {
await WIKI.models.pages.flushCache() await WIKI.db.pages.flushCache()
WIKI.events.outbound.emit('flushCache') WIKI.events.outbound.emit('flushCache')
return { return {
responseResult: graphHelper.generateSuccess('Pages Cache has been flushed successfully.') responseResult: graphHelper.generateSuccess('Pages Cache has been flushed successfully.')
@ -499,7 +497,7 @@ module.exports = {
*/ */
async migrateToLocale(obj, args, context) { async migrateToLocale(obj, args, context) {
try { try {
const count = await WIKI.models.pages.migrateToLocale(args) const count = await WIKI.db.pages.migrateToLocale(args)
return { return {
responseResult: graphHelper.generateSuccess('Migrated content to target locale successfully.'), responseResult: graphHelper.generateSuccess('Migrated content to target locale successfully.'),
count count
@ -513,7 +511,7 @@ module.exports = {
*/ */
async rebuildPageTree(obj, args, context) { async rebuildPageTree(obj, args, context) {
try { try {
await WIKI.models.pages.rebuildTree() await WIKI.db.pages.rebuildTree()
return { return {
responseResult: graphHelper.generateSuccess('Page tree rebuilt successfully.') responseResult: graphHelper.generateSuccess('Page tree rebuilt successfully.')
} }
@ -526,11 +524,11 @@ module.exports = {
*/ */
async renderPage (obj, args, context) { async renderPage (obj, args, context) {
try { try {
const page = await WIKI.models.pages.query().findById(args.id) const page = await WIKI.db.pages.query().findById(args.id)
if (!page) { if (!page) {
throw new WIKI.Error.PageNotFound() throw new WIKI.Error.PageNotFound()
} }
await WIKI.models.pages.renderPage(page) await WIKI.db.pages.renderPage(page)
return { return {
responseResult: graphHelper.generateSuccess('Page rendered successfully.') responseResult: graphHelper.generateSuccess('Page rendered successfully.')
} }
@ -543,7 +541,7 @@ module.exports = {
*/ */
async restorePage (obj, args, context) { async restorePage (obj, args, context) {
try { try {
const page = await WIKI.models.pages.query().select('path', 'localeCode').findById(args.pageId) const page = await WIKI.db.pages.query().select('path', 'localeCode').findById(args.pageId)
if (!page) { if (!page) {
throw new WIKI.Error.PageNotFound() throw new WIKI.Error.PageNotFound()
} }
@ -555,12 +553,12 @@ module.exports = {
throw new WIKI.Error.PageRestoreForbidden() throw new WIKI.Error.PageRestoreForbidden()
} }
const targetVersion = await WIKI.models.pageHistory.getVersion({ pageId: args.pageId, versionId: args.versionId }) const targetVersion = await WIKI.db.pageHistory.getVersion({ pageId: args.pageId, versionId: args.versionId })
if (!targetVersion) { if (!targetVersion) {
throw new WIKI.Error.PageNotFound() throw new WIKI.Error.PageNotFound()
} }
await WIKI.models.pages.updatePage({ await WIKI.db.pages.updatePage({
...targetVersion, ...targetVersion,
id: targetVersion.pageId, id: targetVersion.pageId,
user: context.req.user, user: context.req.user,
@ -579,7 +577,7 @@ module.exports = {
*/ */
async purgePagesHistory (obj, args, context) { async purgePagesHistory (obj, args, context) {
try { try {
await WIKI.models.pageHistory.purge(args.olderThan) await WIKI.db.pageHistory.purge(args.olderThan)
return { return {
responseResult: graphHelper.generateSuccess('Page history purged successfully.') responseResult: graphHelper.generateSuccess('Page history purged successfully.')
} }
@ -590,7 +588,7 @@ module.exports = {
}, },
Page: { Page: {
async tags (obj) { async tags (obj) {
return WIKI.models.pages.relatedQuery('tags').for(obj.id) return WIKI.db.pages.relatedQuery('tags').for(obj.id)
} }
// comments(pg) { // comments(pg) {
// return pg.$relatedQuery('comments') // return pg.$relatedQuery('comments')

@ -1,12 +1,10 @@
const _ = require('lodash') const _ = require('lodash')
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
async renderers(obj, args, context, info) { async renderers(obj, args, context, info) {
let renderers = await WIKI.models.renderers.getRenderers() let renderers = await WIKI.db.renderers.getRenderers()
renderers = renderers.map(rdr => { renderers = renderers.map(rdr => {
const rendererInfo = _.find(WIKI.data.renderers, ['key', rdr.key]) || {} const rendererInfo = _.find(WIKI.data.renderers, ['key', rdr.key]) || {}
return { return {
@ -35,7 +33,7 @@ module.exports = {
async updateRenderers(obj, args, context) { async updateRenderers(obj, args, context) {
try { try {
for (let rdr of args.renderers) { for (let rdr of args.renderers) {
await WIKI.models.renderers.query().patch({ await WIKI.db.renderers.query().patch({
isEnabled: rdr.isEnabled, isEnabled: rdr.isEnabled,
config: _.reduce(rdr.config, (result, value, key) => { config: _.reduce(rdr.config, (result, value, key) => {
_.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null)) _.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null))

@ -1,7 +1,5 @@
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = { module.exports = {
Mutation: { Mutation: {
async rebuildSearchIndex (obj, args, context) { async rebuildSearchIndex (obj, args, context) {

@ -5,12 +5,10 @@ const path = require('path')
const fs = require('fs-extra') const fs = require('fs-extra')
const { v4: uuid } = require('uuid') const { v4: uuid } = require('uuid')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
async sites () { async sites () {
const sites = await WIKI.models.sites.query().orderBy('hostname') const sites = await WIKI.db.sites.query().orderBy('hostname')
return sites.map(s => ({ return sites.map(s => ({
...s.config, ...s.config,
id: s.id, id: s.id,
@ -20,7 +18,7 @@ module.exports = {
})) }))
}, },
async siteById (obj, args) { async siteById (obj, args) {
const site = await WIKI.models.sites.query().findById(args.id) const site = await WIKI.db.sites.query().findById(args.id)
return site ? { return site ? {
...site.config, ...site.config,
id: site.id, id: site.id,
@ -30,11 +28,11 @@ module.exports = {
} : null } : null
}, },
async siteByHostname (obj, args) { async siteByHostname (obj, args) {
let site = await WIKI.models.sites.query().where({ let site = await WIKI.db.sites.query().where({
hostname: args.hostname hostname: args.hostname
}).first() }).first()
if (!site && !args.exact) { if (!site && !args.exact) {
site = await WIKI.models.sites.query().where({ site = await WIKI.db.sites.query().where({
hostname: '*' hostname: '*'
}).first() }).first()
} }
@ -62,7 +60,7 @@ module.exports = {
} }
// -> Check for duplicate catch-all // -> Check for duplicate catch-all
if (args.hostname === '*') { if (args.hostname === '*') {
const site = await WIKI.models.sites.query().where({ const site = await WIKI.db.sites.query().where({
hostname: args.hostname hostname: args.hostname
}).first() }).first()
if (site) { if (site) {
@ -70,7 +68,7 @@ module.exports = {
} }
} }
// -> Create site // -> Create site
const newSite = await WIKI.models.sites.createSite(args.hostname, { const newSite = await WIKI.db.sites.createSite(args.hostname, {
title: args.title title: args.title
}) })
return { return {
@ -88,7 +86,7 @@ module.exports = {
async updateSite (obj, args) { async updateSite (obj, args) {
try { try {
// -> Load site // -> Load site
const site = await WIKI.models.sites.query().findById(args.id) const site = await WIKI.db.sites.query().findById(args.id)
if (!site) { if (!site) {
throw new WIKI.Error.Custom('SiteInvalidId', 'Invalid Site ID') throw new WIKI.Error.Custom('SiteInvalidId', 'Invalid Site ID')
} }
@ -98,7 +96,7 @@ module.exports = {
} }
// -> Check for duplicate catch-all // -> Check for duplicate catch-all
if (args.patch.hostname === '*' && site.hostname !== '*') { if (args.patch.hostname === '*' && site.hostname !== '*') {
const dupSite = await WIKI.models.sites.query().where({ hostname: '*' }).first() const dupSite = await WIKI.db.sites.query().where({ hostname: '*' }).first()
if (dupSite) { if (dupSite) {
throw new WIKI.Error.Custom('SiteUpdateDuplicateCatchAll', `Site ${dupSite.config.title} with a catch-all hostname already exists! Cannot have 2 catch-all hostnames.`) throw new WIKI.Error.Custom('SiteUpdateDuplicateCatchAll', `Site ${dupSite.config.title} with a catch-all hostname already exists! Cannot have 2 catch-all hostnames.`)
} }
@ -112,7 +110,7 @@ module.exports = {
args.patch.pageExtensions = args.patch.pageExtensions.split(',').map(ext => ext.trim().toLowerCase()).filter(ext => ext.length > 0) args.patch.pageExtensions = args.patch.pageExtensions.split(',').map(ext => ext.trim().toLowerCase()).filter(ext => ext.length > 0)
} }
// -> Update site // -> Update site
await WIKI.models.sites.updateSite(args.id, { await WIKI.db.sites.updateSite(args.id, {
hostname: args.patch.hostname ?? site.hostname, hostname: args.patch.hostname ?? site.hostname,
isEnabled: args.patch.isEnabled ?? site.isEnabled, isEnabled: args.patch.isEnabled ?? site.isEnabled,
config: _.defaultsDeep(_.omit(args.patch, ['hostname', 'isEnabled']), site.config) config: _.defaultsDeep(_.omit(args.patch, ['hostname', 'isEnabled']), site.config)
@ -132,12 +130,12 @@ module.exports = {
async deleteSite (obj, args) { async deleteSite (obj, args) {
try { try {
// -> Ensure site isn't last one // -> Ensure site isn't last one
const sitesCount = await WIKI.models.sites.query().count('id').first() const sitesCount = await WIKI.db.sites.query().count('id').first()
if (sitesCount?.count && _.toNumber(sitesCount?.count) <= 1) { if (sitesCount?.count && _.toNumber(sitesCount?.count) <= 1) {
throw new WIKI.Error.Custom('SiteDeleteLastSite', 'Cannot delete the last site. At least 1 site must exists at all times.') throw new WIKI.Error.Custom('SiteDeleteLastSite', 'Cannot delete the last site. At least 1 site must exists at all times.')
} }
// -> Delete site // -> Delete site
await WIKI.models.sites.deleteSite(args.id) await WIKI.db.sites.deleteSite(args.id)
return { return {
operation: graphHelper.generateSuccess('Site deleted successfully') operation: graphHelper.generateSuccess('Site deleted successfully')
} }
@ -175,16 +173,16 @@ module.exports = {
height: 72 height: 72
}) })
// -> Save logo meta to DB // -> Save logo meta to DB
const site = await WIKI.models.sites.query().findById(args.id) const site = await WIKI.db.sites.query().findById(args.id)
if (!site.config.assets.logo) { if (!site.config.assets.logo) {
site.config.assets.logo = uuid() site.config.assets.logo = uuid()
} }
site.config.assets.logoExt = destFormat site.config.assets.logoExt = destFormat
await WIKI.models.sites.query().findById(args.id).patch({ config: site.config }) await WIKI.db.sites.query().findById(args.id).patch({ config: site.config })
await WIKI.models.sites.reloadCache() await WIKI.db.sites.reloadCache()
// -> Save image data to DB // -> Save image data to DB
const imgBuffer = await fs.readFile(destPath) const imgBuffer = await fs.readFile(destPath)
await WIKI.models.knex('assetData').insert({ await WIKI.db.knex('assetData').insert({
id: site.config.assets.logo, id: site.config.assets.logo,
data: imgBuffer data: imgBuffer
}).onConflict('id').merge() }).onConflict('id').merge()
@ -227,16 +225,16 @@ module.exports = {
height: 64 height: 64
}) })
// -> Save favicon meta to DB // -> Save favicon meta to DB
const site = await WIKI.models.sites.query().findById(args.id) const site = await WIKI.db.sites.query().findById(args.id)
if (!site.config.assets.favicon) { if (!site.config.assets.favicon) {
site.config.assets.favicon = uuid() site.config.assets.favicon = uuid()
} }
site.config.assets.faviconExt = destFormat site.config.assets.faviconExt = destFormat
await WIKI.models.sites.query().findById(args.id).patch({ config: site.config }) await WIKI.db.sites.query().findById(args.id).patch({ config: site.config })
await WIKI.models.sites.reloadCache() await WIKI.db.sites.reloadCache()
// -> Save image data to DB // -> Save image data to DB
const imgBuffer = await fs.readFile(destPath) const imgBuffer = await fs.readFile(destPath)
await WIKI.models.knex('assetData').insert({ await WIKI.db.knex('assetData').insert({
id: site.config.assets.favicon, id: site.config.assets.favicon,
data: imgBuffer data: imgBuffer
}).onConflict('id').merge() }).onConflict('id').merge()
@ -277,15 +275,15 @@ module.exports = {
width: 1920 width: 1920
}) })
// -> Save login bg meta to DB // -> Save login bg meta to DB
const site = await WIKI.models.sites.query().findById(args.id) const site = await WIKI.db.sites.query().findById(args.id)
if (!site.config.assets.loginBg) { if (!site.config.assets.loginBg) {
site.config.assets.loginBg = uuid() site.config.assets.loginBg = uuid()
await WIKI.models.sites.query().findById(args.id).patch({ config: site.config }) await WIKI.db.sites.query().findById(args.id).patch({ config: site.config })
await WIKI.models.sites.reloadCache() await WIKI.db.sites.reloadCache()
} }
// -> Save image data to DB // -> Save image data to DB
const imgBuffer = await fs.readFile(destPath) const imgBuffer = await fs.readFile(destPath)
await WIKI.models.knex('assetData').insert({ await WIKI.db.knex('assetData').insert({
id: site.config.assets.loginBg, id: site.config.assets.loginBg,
data: imgBuffer data: imgBuffer
}).onConflict('id').merge() }).onConflict('id').merge()

@ -2,12 +2,10 @@ const _ = require('lodash')
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
const { v4: uuid } = require('uuid') const { v4: uuid } = require('uuid')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
async storageTargets (obj, args, context, info) { async storageTargets (obj, args, context, info) {
const dbTargets = await WIKI.models.storage.getTargets({ siteId: args.siteId }) const dbTargets = await WIKI.db.storage.getTargets({ siteId: args.siteId })
// targets = _.sortBy(targets.map(tgt => { // targets = _.sortBy(targets.map(tgt => {
// const targetInfo = _.find(WIKI.data.storage, ['module', tgt.key]) || {} // const targetInfo = _.find(WIKI.data.storage, ['module', tgt.key]) || {}
// return { // return {
@ -101,7 +99,7 @@ module.exports = {
async updateStorageTargets (obj, args, context) { async updateStorageTargets (obj, args, context) {
WIKI.logger.debug(`Updating storage targets for site ${args.siteId}...`) WIKI.logger.debug(`Updating storage targets for site ${args.siteId}...`)
try { try {
const dbTargets = await WIKI.models.storage.getTargets({ siteId: args.siteId }) const dbTargets = await WIKI.db.storage.getTargets({ siteId: args.siteId })
for (const tgt of args.targets) { for (const tgt of args.targets) {
const md = _.find(WIKI.storage.defs, ['key', tgt.module]) const md = _.find(WIKI.storage.defs, ['key', tgt.module])
if (!md) { if (!md) {
@ -124,7 +122,7 @@ module.exports = {
// -> Target doesn't exist yet in the DB, let's create it // -> Target doesn't exist yet in the DB, let's create it
if (!dbTarget) { if (!dbTarget) {
WIKI.logger.debug(`No existing DB configuration for module ${tgt.module}. Creating a new one...`) WIKI.logger.debug(`No existing DB configuration for module ${tgt.module}. Creating a new one...`)
await WIKI.models.storage.query().insert({ await WIKI.db.storage.query().insert({
id: tgt.id, id: tgt.id,
module: tgt.module, module: tgt.module,
siteId: args.siteId, siteId: args.siteId,
@ -147,7 +145,7 @@ module.exports = {
}) })
} else { } else {
WIKI.logger.debug(`Updating DB configuration for module ${tgt.module}...`) WIKI.logger.debug(`Updating DB configuration for module ${tgt.module}...`)
await WIKI.models.storage.query().patch({ await WIKI.db.storage.query().patch({
isEnabled: tgt.isEnabled ?? dbTarget.isEnabled ?? false, isEnabled: tgt.isEnabled ?? dbTarget.isEnabled ?? false,
contentTypes: { contentTypes: {
activeTypes: tgt.contentTypes ?? dbTarget?.contentTypes?.activeTypes ?? [], activeTypes: tgt.contentTypes ?? dbTarget?.contentTypes?.activeTypes ?? [],
@ -164,7 +162,7 @@ module.exports = {
}).where('id', tgt.id) }).where('id', tgt.id)
} }
} }
// await WIKI.models.storage.initTargets() // await WIKI.db.storage.initTargets()
return { return {
status: graphHelper.generateSuccess('Storage targets updated successfully') status: graphHelper.generateSuccess('Storage targets updated successfully')
} }
@ -174,7 +172,7 @@ module.exports = {
}, },
async setupStorageTarget (obj, args, context) { async setupStorageTarget (obj, args, context) {
try { try {
const tgt = await WIKI.models.storage.query().findById(args.targetId) const tgt = await WIKI.db.storage.query().findById(args.targetId)
if (!tgt) { if (!tgt) {
throw new Error('Not storage target matching this ID') throw new Error('Not storage target matching this ID')
} }
@ -182,7 +180,7 @@ module.exports = {
if (!md) { if (!md) {
throw new Error('No matching storage module installed.') throw new Error('No matching storage module installed.')
} }
if (!await WIKI.models.storage.ensureModule(md.key)) { if (!await WIKI.db.storage.ensureModule(md.key)) {
throw new Error('Failed to load storage module. Check logs for details.') throw new Error('Failed to load storage module. Check logs for details.')
} }
const result = await WIKI.storage.modules[md.key].setup(args.targetId, args.state) const result = await WIKI.storage.modules[md.key].setup(args.targetId, args.state)
@ -197,7 +195,7 @@ module.exports = {
}, },
async destroyStorageTargetSetup (obj, args, context) { async destroyStorageTargetSetup (obj, args, context) {
try { try {
const tgt = await WIKI.models.storage.query().findById(args.targetId) const tgt = await WIKI.db.storage.query().findById(args.targetId)
if (!tgt) { if (!tgt) {
throw new Error('Not storage target matching this ID') throw new Error('Not storage target matching this ID')
} }
@ -205,7 +203,7 @@ module.exports = {
if (!md) { if (!md) {
throw new Error('No matching storage module installed.') throw new Error('No matching storage module installed.')
} }
if (!await WIKI.models.storage.ensureModule(md.key)) { if (!await WIKI.db.storage.ensureModule(md.key)) {
throw new Error('Failed to load storage module. Check logs for details.') throw new Error('Failed to load storage module. Check logs for details.')
} }
await WIKI.storage.modules[md.key].setupDestroy(args.targetId) await WIKI.storage.modules[md.key].setupDestroy(args.targetId)
@ -219,7 +217,7 @@ module.exports = {
}, },
async executeStorageAction (obj, args, context) { async executeStorageAction (obj, args, context) {
try { try {
await WIKI.models.storage.executeAction(args.targetKey, args.handler) await WIKI.db.storage.executeAction(args.targetKey, args.handler)
return { return {
status: graphHelper.generateSuccess('Action completed.') status: graphHelper.generateSuccess('Action completed.')
} }

@ -9,8 +9,6 @@ const { DateTime } = require('luxon')
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
const cronParser = require('cron-parser') const cronParser = require('cron-parser')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
systemFlags () { systemFlags () {
@ -183,19 +181,19 @@ module.exports = {
return process.cwd() return process.cwd()
}, },
async groupsTotal () { async groupsTotal () {
const total = await WIKI.models.groups.query().count('* as total').first() const total = await WIKI.db.groups.query().count('* as total').first()
return _.toSafeInteger(total.total) return _.toSafeInteger(total.total)
}, },
async pagesTotal () { async pagesTotal () {
const total = await WIKI.models.pages.query().count('* as total').first() const total = await WIKI.db.pages.query().count('* as total').first()
return _.toSafeInteger(total.total) return _.toSafeInteger(total.total)
}, },
async usersTotal () { async usersTotal () {
const total = await WIKI.models.users.query().count('* as total').first() const total = await WIKI.db.users.query().count('* as total').first()
return _.toSafeInteger(total.total) return _.toSafeInteger(total.total)
}, },
async tagsTotal () { async tagsTotal () {
const total = await WIKI.models.tags.query().count('* as total').first() const total = await WIKI.db.tags.query().count('* as total').first()
return _.toSafeInteger(total.total) return _.toSafeInteger(total.total)
} }
} }

@ -1,8 +1,6 @@
const graphHelper = require('../../helpers/graph') const graphHelper = require('../../helpers/graph')
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
module.exports = { module.exports = {
Query: { Query: {
/** /**
@ -22,7 +20,7 @@ module.exports = {
} }
// -> Fetch Users // -> Fetch Users
return WIKI.models.users.query() return WIKI.db.users.query()
.select('id', 'email', 'name', 'isSystem', 'isActive', 'createdAt', 'lastLoginAt') .select('id', 'email', 'name', 'isSystem', 'isActive', 'createdAt', 'lastLoginAt')
.where(builder => { .where(builder => {
if (args.filter) { if (args.filter) {
@ -38,7 +36,7 @@ module.exports = {
* FETCH A SINGLE USER * FETCH A SINGLE USER
*/ */
async userById (obj, args, context, info) { async userById (obj, args, context, info) {
const usr = await WIKI.models.users.query().findById(args.id) const usr = await WIKI.db.users.query().findById(args.id)
if (!usr) { if (!usr) {
throw new Error('Invalid User') throw new Error('Invalid User')
@ -64,7 +62,7 @@ module.exports = {
// if (!context.req.user || context.req.user.id < 1 || context.req.user.id === 2) { // if (!context.req.user || context.req.user.id < 1 || context.req.user.id === 2) {
// throw new WIKI.Error.AuthRequired() // throw new WIKI.Error.AuthRequired()
// } // }
// const usr = await WIKI.models.users.query().findById(context.req.user.id) // const usr = await WIKI.db.users.query().findById(context.req.user.id)
// if (!usr.isActive) { // if (!usr.isActive) {
// throw new WIKI.Error.AuthAccountBanned() // throw new WIKI.Error.AuthAccountBanned()
// } // }
@ -80,7 +78,7 @@ module.exports = {
// return usr // return usr
// }, // },
async lastLogins (obj, args, context, info) { async lastLogins (obj, args, context, info) {
return WIKI.models.users.query() return WIKI.db.users.query()
.select('id', 'name', 'lastLoginAt') .select('id', 'name', 'lastLoginAt')
.whereNotNull('lastLoginAt') .whereNotNull('lastLoginAt')
.orderBy('lastLoginAt', 'desc') .orderBy('lastLoginAt', 'desc')
@ -90,7 +88,7 @@ module.exports = {
Mutation: { Mutation: {
async createUser (obj, args) { async createUser (obj, args) {
try { try {
await WIKI.models.users.createNewUser({ ...args, passwordRaw: args.password, isVerified: true }) await WIKI.db.users.createNewUser({ ...args, passwordRaw: args.password, isVerified: true })
return { return {
operation: graphHelper.generateSuccess('User created successfully') operation: graphHelper.generateSuccess('User created successfully')
@ -104,7 +102,7 @@ module.exports = {
if (args.id <= 2) { if (args.id <= 2) {
throw new WIKI.Error.UserDeleteProtected() throw new WIKI.Error.UserDeleteProtected()
} }
await WIKI.models.users.deleteUser(args.id, args.replaceId) await WIKI.db.users.deleteUser(args.id, args.replaceId)
WIKI.auth.revokeUserTokens({ id: args.id, kind: 'u' }) WIKI.auth.revokeUserTokens({ id: args.id, kind: 'u' })
WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'u' }) WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'u' })
@ -122,7 +120,7 @@ module.exports = {
}, },
async updateUser (obj, args) { async updateUser (obj, args) {
try { try {
await WIKI.models.users.updateUser(args.id, args.patch) await WIKI.db.users.updateUser(args.id, args.patch)
return { return {
operation: graphHelper.generateSuccess('User updated successfully') operation: graphHelper.generateSuccess('User updated successfully')
@ -133,7 +131,7 @@ module.exports = {
}, },
async verifyUser (obj, args) { async verifyUser (obj, args) {
try { try {
await WIKI.models.users.query().patch({ isVerified: true }).findById(args.id) await WIKI.db.users.query().patch({ isVerified: true }).findById(args.id)
return { return {
operation: graphHelper.generateSuccess('User verified successfully') operation: graphHelper.generateSuccess('User verified successfully')
@ -144,7 +142,7 @@ module.exports = {
}, },
async activateUser (obj, args) { async activateUser (obj, args) {
try { try {
await WIKI.models.users.query().patch({ isActive: true }).findById(args.id) await WIKI.db.users.query().patch({ isActive: true }).findById(args.id)
return { return {
operation: graphHelper.generateSuccess('User activated successfully') operation: graphHelper.generateSuccess('User activated successfully')
@ -158,7 +156,7 @@ module.exports = {
if (args.id <= 2) { if (args.id <= 2) {
throw new Error('Cannot deactivate system accounts.') throw new Error('Cannot deactivate system accounts.')
} }
await WIKI.models.users.query().patch({ isActive: false }).findById(args.id) await WIKI.db.users.query().patch({ isActive: false }).findById(args.id)
WIKI.auth.revokeUserTokens({ id: args.id, kind: 'u' }) WIKI.auth.revokeUserTokens({ id: args.id, kind: 'u' })
WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'u' }) WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'u' })
@ -172,7 +170,7 @@ module.exports = {
}, },
async enableUserTFA (obj, args) { async enableUserTFA (obj, args) {
try { try {
await WIKI.models.users.query().patch({ tfaIsActive: true, tfaSecret: null }).findById(args.id) await WIKI.db.users.query().patch({ tfaIsActive: true, tfaSecret: null }).findById(args.id)
return { return {
operation: graphHelper.generateSuccess('User 2FA enabled successfully') operation: graphHelper.generateSuccess('User 2FA enabled successfully')
@ -183,7 +181,7 @@ module.exports = {
}, },
async disableUserTFA (obj, args) { async disableUserTFA (obj, args) {
try { try {
await WIKI.models.users.query().patch({ tfaIsActive: false, tfaSecret: null }).findById(args.id) await WIKI.db.users.query().patch({ tfaIsActive: false, tfaSecret: null }).findById(args.id)
return { return {
operation: graphHelper.generateSuccess('User 2FA disabled successfully') operation: graphHelper.generateSuccess('User 2FA disabled successfully')
@ -200,7 +198,7 @@ module.exports = {
if (!context.req.user || context.req.user.id === WIKI.auth.guest.id) { if (!context.req.user || context.req.user.id === WIKI.auth.guest.id) {
throw new WIKI.Error.AuthRequired() throw new WIKI.Error.AuthRequired()
} }
const usr = await WIKI.models.users.query().findById(context.req.user.id) const usr = await WIKI.db.users.query().findById(context.req.user.id)
if (!usr.isActive) { if (!usr.isActive) {
throw new WIKI.Error.AuthAccountBanned() throw new WIKI.Error.AuthAccountBanned()
} }
@ -216,7 +214,7 @@ module.exports = {
throw new WIKI.Error.InputInvalid() throw new WIKI.Error.InputInvalid()
} }
await WIKI.models.users.query().findById(usr.id).patch({ await WIKI.db.users.query().findById(usr.id).patch({
name: args.name?.trim() ?? usr.name, name: args.name?.trim() ?? usr.name,
meta: { meta: {
...usr.meta, ...usr.meta,
@ -245,7 +243,7 @@ module.exports = {
if (!context.req.user || context.req.user.id < 1 || context.req.user.id === 2) { if (!context.req.user || context.req.user.id < 1 || context.req.user.id === 2) {
throw new WIKI.Error.AuthRequired() throw new WIKI.Error.AuthRequired()
} }
const usr = await WIKI.models.users.query().findById(context.req.user.id) const usr = await WIKI.db.users.query().findById(context.req.user.id)
if (!usr.isActive) { if (!usr.isActive) {
throw new WIKI.Error.AuthAccountBanned() throw new WIKI.Error.AuthAccountBanned()
} }
@ -261,12 +259,12 @@ module.exports = {
throw new WIKI.Error.AuthPasswordInvalid() throw new WIKI.Error.AuthPasswordInvalid()
} }
await WIKI.models.users.updateUser({ await WIKI.db.users.updateUser({
id: usr.id, id: usr.id,
newPassword: args.new newPassword: args.new
}) })
const newToken = await WIKI.models.users.refreshToken(usr) const newToken = await WIKI.db.users.refreshToken(usr)
return { return {
responseResult: graphHelper.generateSuccess('Password changed successfully'), responseResult: graphHelper.generateSuccess('Password changed successfully'),
@ -288,7 +286,7 @@ module.exports = {
// return usrGroups.map(g => g.name) // return usrGroups.map(g => g.name)
// }, // },
// async pagesTotal (usr) { // async pagesTotal (usr) {
// const result = await WIKI.models.pages.query().count('* as total').where('creatorId', usr.id).first() // const result = await WIKI.db.pages.query().count('* as total').where('creatorId', usr.id).first()
// return _.toSafeInteger(result.total) // return _.toSafeInteger(result.total)
// } // }
// } // }

@ -14,8 +14,6 @@ const contentToExt = {
} }
const extToContent = _.invert(contentToExt) const extToContent = _.invert(contentToExt)
/* global WIKI */
module.exports = { module.exports = {
/** /**
* Parse raw url path and make it safe * Parse raw url path and make it safe

@ -15,7 +15,6 @@ if (!semver.satisfies(process.version, '>=18')) {
let WIKI = { let WIKI = {
IS_DEBUG: process.env.NODE_ENV === 'development', IS_DEBUG: process.env.NODE_ENV === 'development',
IS_MASTER: true,
ROOTPATH: process.cwd(), ROOTPATH: process.cwd(),
INSTANCE_ID: nanoid(10), INSTANCE_ID: nanoid(10),
SERVERPATH: path.join(process.cwd(), 'server'), SERVERPATH: path.join(process.cwd(), 'server'),

@ -1,7 +1,5 @@
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
/** /**
* SEO Middleware * SEO Middleware
* *

@ -5,8 +5,6 @@ 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 */
/** /**
* Analytics model * Analytics model
*/ */
@ -31,7 +29,7 @@ module.exports = class Analytics extends Model {
} }
static async getProviders(isEnabled) { static async getProviders(isEnabled) {
const providers = await WIKI.models.analytics.query().where(_.isBoolean(isEnabled) ? { isEnabled } : {}) const providers = await WIKI.db.analytics.query().where(_.isBoolean(isEnabled) ? { isEnabled } : {})
return _.sortBy(providers, ['module']) return _.sortBy(providers, ['module'])
} }
@ -69,7 +67,7 @@ module.exports = class Analytics extends Model {
bodyStart: '', bodyStart: '',
bodyEnd: '' bodyEnd: ''
} }
const providers = await WIKI.models.analytics.getProviders(true) const providers = await WIKI.db.analytics.getProviders(true)
for (let provider of providers) { for (let provider of providers) {
const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/analytics', provider.key, 'code.yml'), 'utf8') const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/analytics', provider.key, 'code.yml'), 'utf8')

@ -43,7 +43,7 @@ module.exports = class ApiKey extends Model {
static async createNewKey ({ name, expiration, groups }) { static async createNewKey ({ name, expiration, groups }) {
console.info(DateTime.utc().plus(ms(expiration)).toISO()) console.info(DateTime.utc().plus(ms(expiration)).toISO())
const entry = await WIKI.models.apiKeys.query().insert({ const entry = await WIKI.db.apiKeys.query().insert({
name, name,
key: 'pending', key: 'pending',
expiration: DateTime.utc().plus(ms(expiration)).toISO(), expiration: DateTime.utc().plus(ms(expiration)).toISO(),
@ -65,7 +65,7 @@ module.exports = class ApiKey extends Model {
issuer: 'urn:wiki.js' issuer: 'urn:wiki.js'
}) })
await WIKI.models.apiKeys.query().findById(entry.id).patch({ await WIKI.db.apiKeys.query().findById(entry.id).patch({
key, key,
isRevoked: false isRevoked: false
}) })

@ -1,8 +1,6 @@
const Model = require('objection').Model const Model = require('objection').Model
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
/** /**
* Users model * Users model
*/ */
@ -42,13 +40,13 @@ module.exports = class AssetFolder extends Model {
static async getHierarchy (folderId) { static async getHierarchy (folderId) {
let hier let hier
if (WIKI.config.db.type === 'mssql') { if (WIKI.config.db.type === 'mssql') {
hier = await WIKI.models.knex.with('ancestors', qb => { hier = await WIKI.db.knex.with('ancestors', qb => {
qb.select('id', 'name', 'slug', 'parentId').from('assetFolders').where('id', folderId).unionAll(sqb => { qb.select('id', 'name', 'slug', 'parentId').from('assetFolders').where('id', folderId).unionAll(sqb => {
sqb.select('a.id', 'a.name', 'a.slug', 'a.parentId').from('assetFolders AS a').join('ancestors', 'ancestors.parentId', 'a.id') sqb.select('a.id', 'a.name', 'a.slug', 'a.parentId').from('assetFolders AS a').join('ancestors', 'ancestors.parentId', 'a.id')
}) })
}).select('*').from('ancestors') }).select('*').from('ancestors')
} else { } else {
hier = await WIKI.models.knex.withRecursive('ancestors', qb => { hier = await WIKI.db.knex.withRecursive('ancestors', qb => {
qb.select('id', 'name', 'slug', 'parentId').from('assetFolders').where('id', folderId).union(sqb => { qb.select('id', 'name', 'slug', 'parentId').from('assetFolders').where('id', folderId).union(sqb => {
sqb.select('a.id', 'a.name', 'a.slug', 'a.parentId').from('assetFolders AS a').join('ancestors', 'ancestors.parentId', 'a.id') sqb.select('a.id', 'a.name', 'a.slug', 'a.parentId').from('assetFolders AS a').join('ancestors', 'ancestors.parentId', 'a.id')
}) })
@ -62,7 +60,7 @@ module.exports = class AssetFolder extends Model {
* Get full folder paths * Get full folder paths
*/ */
static async getAllPaths () { static async getAllPaths () {
const all = await WIKI.models.assetFolders.query() const all = await WIKI.db.assetFolders.query()
let folders = {} let folders = {}
all.forEach(fld => { all.forEach(fld => {
_.set(folders, fld.id, fld.slug) _.set(folders, fld.id, fld.slug)

@ -69,7 +69,7 @@ module.exports = class Asset extends Model {
async getAssetPath() { async getAssetPath() {
let hierarchy = [] let hierarchy = []
if (this.folderId) { if (this.folderId) {
hierarchy = await WIKI.models.assetFolders.getHierarchy(this.folderId) hierarchy = await WIKI.db.assetFolders.getHierarchy(this.folderId)
} }
return (this.folderId) ? hierarchy.map(h => h.slug).join('/') + `/${this.filename}` : this.filename return (this.folderId) ? hierarchy.map(h => h.slug).join('/') + `/${this.filename}` : this.filename
} }
@ -83,7 +83,7 @@ module.exports = class Asset extends Model {
const fileHash = assetHelper.generateHash(opts.assetPath) const fileHash = assetHelper.generateHash(opts.assetPath)
// Check for existing asset // Check for existing asset
let asset = await WIKI.models.assets.query().where({ let asset = await WIKI.db.assets.query().where({
hash: fileHash, hash: fileHash,
folderId: opts.folderId folderId: opts.folderId
}).first() }).first()
@ -124,8 +124,8 @@ module.exports = class Asset extends Model {
if (opts.mode === 'upload') { if (opts.mode === 'upload') {
assetRow.authorId = opts.user.id assetRow.authorId = opts.user.id
} }
await WIKI.models.assets.query().patch(assetRow).findById(asset.id) await WIKI.db.assets.query().patch(assetRow).findById(asset.id)
await WIKI.models.knex('assetData').where({ await WIKI.db.knex('assetData').where({
id: asset.id id: asset.id
}).update({ }).update({
data: fileBuffer data: fileBuffer
@ -133,8 +133,8 @@ module.exports = class Asset extends Model {
} else { } else {
// Create asset entry // Create asset entry
assetRow.authorId = opts.user.id assetRow.authorId = opts.user.id
asset = await WIKI.models.assets.query().insert(assetRow) asset = await WIKI.db.assets.query().insert(assetRow)
await WIKI.models.knex('assetData').insert({ await WIKI.db.knex('assetData').insert({
id: asset.id, id: asset.id,
data: fileBuffer data: fileBuffer
}) })
@ -149,7 +149,7 @@ module.exports = class Asset extends Model {
// Add to Storage // Add to Storage
if (!opts.skipStorage) { if (!opts.skipStorage) {
await WIKI.models.storage.assetEvent({ await WIKI.db.storage.assetEvent({
event: 'uploaded', event: 'uploaded',
asset: { asset: {
...asset, ...asset,
@ -177,13 +177,13 @@ module.exports = class Asset extends Model {
res.set('Content-disposition', 'attachment; filename=' + encodeURIComponent(fileInfo.base)) res.set('Content-disposition', 'attachment; filename=' + encodeURIComponent(fileInfo.base))
} }
if (await WIKI.models.assets.getAssetFromCache(assetPath, cachePath, res)) { if (await WIKI.db.assets.getAssetFromCache(assetPath, cachePath, res)) {
return return
} }
if (await WIKI.models.assets.getAssetFromStorage(assetPath, res)) { if (await WIKI.db.assets.getAssetFromStorage(assetPath, res)) {
return return
} }
await WIKI.models.assets.getAssetFromDb(assetPath, fileHash, cachePath, res) await WIKI.db.assets.getAssetFromDb(assetPath, fileHash, cachePath, res)
} catch (err) { } catch (err) {
if (err.code === `ECONNABORTED` || err.code === `EPIPE`) { if (err.code === `ECONNABORTED` || err.code === `EPIPE`) {
return return
@ -206,13 +206,13 @@ module.exports = class Asset extends Model {
} }
static async getAssetFromStorage(assetPath, res) { static async getAssetFromStorage(assetPath, res) {
const localLocations = await WIKI.models.storage.getLocalLocations({ const localLocations = await WIKI.db.storage.getLocalLocations({
asset: { asset: {
path: assetPath path: assetPath
} }
}) })
for (let location of _.filter(localLocations, location => Boolean(location.path))) { for (let location of _.filter(localLocations, location => Boolean(location.path))) {
const assetExists = await WIKI.models.assets.getAssetFromCache(assetPath, location.path, res) const assetExists = await WIKI.db.assets.getAssetFromCache(assetPath, location.path, res)
if (assetExists) { if (assetExists) {
return true return true
} }
@ -221,9 +221,9 @@ module.exports = class Asset extends Model {
} }
static async getAssetFromDb(assetPath, fileHash, cachePath, res) { static async getAssetFromDb(assetPath, fileHash, cachePath, res) {
const asset = await WIKI.models.assets.query().where('hash', fileHash).first() const asset = await WIKI.db.assets.query().where('hash', fileHash).first()
if (asset) { if (asset) {
const assetData = await WIKI.models.knex('assetData').where('id', asset.id).first() const assetData = await WIKI.db.knex('assetData').where('id', asset.id).first()
res.type(asset.ext) res.type(asset.ext)
res.send(assetData.data) res.send(assetData.data)
await fs.outputFile(cachePath, assetData.data) await fs.outputFile(cachePath, assetData.data)

@ -5,8 +5,6 @@ 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 */
/** /**
* Authentication model * Authentication model
*/ */
@ -32,11 +30,11 @@ module.exports = class Authentication extends Model {
} }
static async getStrategy(key) { static async getStrategy(key) {
return WIKI.models.authentication.query().findOne({ key }) return WIKI.db.authentication.query().findOne({ key })
} }
static async getStrategies({ enabledOnly = false } = {}) { static async getStrategies({ enabledOnly = false } = {}) {
const strategies = await WIKI.models.authentication.query().where(enabledOnly ? { isEnabled: true } : {}) const strategies = await WIKI.db.authentication.query().where(enabledOnly ? { isEnabled: true } : {})
return strategies.map(str => ({ return strategies.map(str => ({
...str, ...str,
domainWhitelist: _.get(str.domainWhitelist, 'v', []), domainWhitelist: _.get(str.domainWhitelist, 'v', []),

@ -5,8 +5,6 @@ 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 */
/** /**
* CommentProvider model * CommentProvider model
*/ */
@ -31,11 +29,11 @@ module.exports = class CommentProvider extends Model {
} }
static async getProvider(key) { static async getProvider(key) {
return WIKI.models.commentProviders.query().findOne({ key }) return WIKI.db.commentProviders.query().findOne({ key })
} }
static async getProviders(isEnabled) { static async getProviders(isEnabled) {
const providers = await WIKI.models.commentProviders.query().where(_.isBoolean(isEnabled) ? { isEnabled } : {}) const providers = await WIKI.db.commentProviders.query().where(_.isBoolean(isEnabled) ? { isEnabled } : {})
return _.sortBy(providers, ['module']) return _.sortBy(providers, ['module'])
} }
@ -61,7 +59,7 @@ module.exports = class CommentProvider extends Model {
} }
static async initProvider() { static async initProvider() {
const commentProvider = await WIKI.models.commentProviders.query().findOne('isEnabled', true) const commentProvider = await WIKI.db.commentProviders.query().findOne('isEnabled', true)
if (commentProvider) { if (commentProvider) {
WIKI.data.commentProvider = { WIKI.data.commentProvider = {
..._.find(WIKI.data.commentProviders, ['key', commentProvider.module]), ..._.find(WIKI.data.commentProviders, ['key', commentProvider.module]),

@ -2,8 +2,6 @@ const Model = require('objection').Model
const validate = require('validate.js') const validate = require('validate.js')
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
/** /**
* Comments model * Comments model
*/ */
@ -95,7 +93,7 @@ module.exports = class Comment extends Model {
} }
// -> Load Page // -> Load Page
const page = await WIKI.models.pages.getPageFromDb(pageId) const page = await WIKI.db.pages.getPageFromDb(pageId)
if (page) { if (page) {
if (!WIKI.auth.checkAccess(user, ['write:comments'], { if (!WIKI.auth.checkAccess(user, ['write:comments'], {
path: page.path, path: page.path,
@ -132,7 +130,7 @@ module.exports = class Comment extends Model {
if (!pageId) { if (!pageId) {
throw new WIKI.Error.CommentNotFound() throw new WIKI.Error.CommentNotFound()
} }
const page = await WIKI.models.pages.getPageFromDb(pageId) const page = await WIKI.db.pages.getPageFromDb(pageId)
if (page) { if (page) {
if (!WIKI.auth.checkAccess(user, ['manage:comments'], { if (!WIKI.auth.checkAccess(user, ['manage:comments'], {
path: page.path, path: page.path,
@ -165,7 +163,7 @@ module.exports = class Comment extends Model {
if (!pageId) { if (!pageId) {
throw new WIKI.Error.CommentNotFound() throw new WIKI.Error.CommentNotFound()
} }
const page = await WIKI.models.pages.getPageFromDb(pageId) const page = await WIKI.db.pages.getPageFromDb(pageId)
if (page) { if (page) {
if (!WIKI.auth.checkAccess(user, ['manage:comments'], { if (!WIKI.auth.checkAccess(user, ['manage:comments'], {
path: page.path, path: page.path,

@ -1,7 +1,5 @@
const Model = require('objection').Model const Model = require('objection').Model
/* global WIKI */
/** /**
* Editor model * Editor model
*/ */
@ -26,7 +24,7 @@ module.exports = class Editor extends Model {
} }
static async getEditors() { static async getEditors() {
return WIKI.models.editors.query() return WIKI.db.editors.query()
} }
static async getDefaultEditor(contentType) { static async getDefaultEditor(contentType) {

@ -1,7 +1,5 @@
const Model = require('objection').Model const Model = require('objection').Model
/* global WIKI */
/** /**
* Hook model * Hook model
*/ */
@ -17,7 +15,7 @@ module.exports = class Hook extends Model {
} }
static async createHook (data) { static async createHook (data) {
return WIKI.models.hooks.query().insertAndFetch({ return WIKI.db.hooks.query().insertAndFetch({
name: data.name, name: data.name,
events: data.events, events: data.events,
url: data.url, url: data.url,
@ -31,7 +29,7 @@ module.exports = class Hook extends Model {
} }
static async updateHook (id, patch) { static async updateHook (id, patch) {
return WIKI.models.hooks.query().findById(id).patch({ return WIKI.db.hooks.query().findById(id).patch({
...patch, ...patch,
state: 'pending', state: 'pending',
lastErrorMessage: null lastErrorMessage: null
@ -39,6 +37,6 @@ module.exports = class Hook extends Model {
} }
static async deleteHook (id) { static async deleteHook (id) {
return WIKI.models.hooks.query().deleteById(id) return WIKI.db.hooks.query().deleteById(id)
} }
} }

@ -1,7 +1,5 @@
const Model = require('objection').Model const Model = require('objection').Model
/* global WIKI */
/** /**
* Locales model * Locales model
*/ */
@ -50,7 +48,7 @@ module.exports = class Locale extends Model {
// return navLocalesCached // return navLocalesCached
// } // }
// } // }
// const navLocales = await WIKI.models.locales.query().select('code', 'nativeName AS name').whereIn('code', WIKI.config.lang.namespaces).orderBy('code') // const navLocales = await WIKI.db.locales.query().select('code', 'nativeName AS name').whereIn('code', WIKI.config.lang.namespaces).orderBy('code')
// if (navLocales) { // if (navLocales) {
// if (cache) { // if (cache) {
// await WIKI.cache.set('nav:locales', navLocales, 300) // await WIKI.cache.set('nav:locales', navLocales, 300)

@ -1,8 +1,6 @@
const Model = require('objection').Model const Model = require('objection').Model
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
/** /**
* Navigation model * Navigation model
*/ */
@ -26,10 +24,10 @@ module.exports = class Navigation extends Model {
if (cache) { if (cache) {
const navTreeCached = await WIKI.cache.get(`nav:sidebar:${locale}`) const navTreeCached = await WIKI.cache.get(`nav:sidebar:${locale}`)
if (navTreeCached) { if (navTreeCached) {
return bypassAuth ? navTreeCached : WIKI.models.navigation.getAuthorizedItems(navTreeCached, groups) return bypassAuth ? navTreeCached : WIKI.db.navigation.getAuthorizedItems(navTreeCached, groups)
} }
} }
const navTree = await WIKI.models.navigation.query().findOne('key', `site`) const navTree = await WIKI.db.navigation.query().findOne('key', `site`)
if (navTree) { if (navTree) {
// Check for pre-2.3 format // Check for pre-2.3 format
if (_.has(navTree.config[0], 'kind')) { if (_.has(navTree.config[0], 'kind')) {
@ -51,7 +49,7 @@ module.exports = class Navigation extends Model {
if (bypassAuth) { if (bypassAuth) {
return locale === 'all' ? navTree.config : WIKI.cache.get(`nav:sidebar:${locale}`) return locale === 'all' ? navTree.config : WIKI.cache.get(`nav:sidebar:${locale}`)
} else { } else {
return locale === 'all' ? WIKI.models.navigation.getAuthorizedItems(navTree.config, groups) : WIKI.models.navigation.getAuthorizedItems(WIKI.cache.get(`nav:sidebar:${locale}`), groups) return locale === 'all' ? WIKI.db.navigation.getAuthorizedItems(navTree.config, groups) : WIKI.db.navigation.getAuthorizedItems(WIKI.cache.get(`nav:sidebar:${locale}`), groups)
} }
} else { } else {
WIKI.logger.warn('Site Navigation is missing or corrupted.') WIKI.logger.warn('Site Navigation is missing or corrupted.')

@ -2,8 +2,6 @@ const Model = require('objection').Model
const _ = require('lodash') const _ = require('lodash')
const { DateTime, Duration } = require('luxon') const { DateTime, Duration } = require('luxon')
/* global WIKI */
/** /**
* Page History model * Page History model
*/ */
@ -89,7 +87,7 @@ module.exports = class PageHistory extends Model {
* Create Page Version * Create Page Version
*/ */
static async addVersion(opts) { static async addVersion(opts) {
await WIKI.models.pageHistory.query().insert({ await WIKI.db.pageHistory.query().insert({
pageId: opts.id, pageId: opts.id,
authorId: opts.authorId, authorId: opts.authorId,
content: opts.content, content: opts.content,
@ -113,7 +111,7 @@ module.exports = class PageHistory extends Model {
* Get Page Version * Get Page Version
*/ */
static async getVersion({ pageId, versionId }) { static async getVersion({ pageId, versionId }) {
const version = await WIKI.models.pageHistory.query() const version = await WIKI.db.pageHistory.query()
.column([ .column([
'pageHistory.path', 'pageHistory.path',
'pageHistory.title', 'pageHistory.title',
@ -156,7 +154,7 @@ module.exports = class PageHistory extends Model {
* Get History Trail of a Page * Get History Trail of a Page
*/ */
static async getHistory({ pageId, offsetPage = 0, offsetSize = 100 }) { static async getHistory({ pageId, offsetPage = 0, offsetSize = 100 }) {
const history = await WIKI.models.pageHistory.query() const history = await WIKI.db.pageHistory.query()
.column([ .column([
'pageHistory.id', 'pageHistory.id',
'pageHistory.path', 'pageHistory.path',
@ -178,7 +176,7 @@ module.exports = class PageHistory extends Model {
const upperLimit = (offsetPage + 1) * offsetSize const upperLimit = (offsetPage + 1) * offsetSize
if (history.total >= upperLimit) { if (history.total >= upperLimit) {
prevPh = await WIKI.models.pageHistory.query() prevPh = await WIKI.db.pageHistory.query()
.column([ .column([
'pageHistory.id', 'pageHistory.id',
'pageHistory.path', 'pageHistory.path',
@ -238,6 +236,6 @@ module.exports = class PageHistory extends Model {
static async purge (olderThan) { static async purge (olderThan) {
const dur = Duration.fromISO(olderThan) const dur = Duration.fromISO(olderThan)
const olderThanISO = DateTime.utc().minus(dur) const olderThanISO = DateTime.utc().minus(dur)
await WIKI.models.pageHistory.query().where('versionDate', '<', olderThanISO.toISO()).del() await WIKI.db.pageHistory.query().where('versionDate', '<', olderThanISO.toISO()).del()
} }
} }

@ -13,8 +13,6 @@ const TurndownService = require('turndown')
const turndownPluginGfm = require('@joplin/turndown-plugin-gfm').gfm const turndownPluginGfm = require('@joplin/turndown-plugin-gfm').gfm
const cheerio = require('cheerio') const cheerio = require('cheerio')
/* global WIKI */
const frontmatterRegex = { const frontmatterRegex = {
html: /^(<!-{2}(?:\n|\r)([\w\W]+?)(?:\n|\r)-{2}>)?(?:\n|\r)*([\w\W]*)*/, html: /^(<!-{2}(?:\n|\r)([\w\W]+?)(?:\n|\r)-{2}>)?(?:\n|\r)*([\w\W]*)*/,
legacy: /^(<!-- TITLE: ?([\w\W]+?) ?-{2}>)?(?:\n|\r)?(<!-- SUBTITLE: ?([\w\W]+?) ?-{2}>)?(?:\n|\r)*([\w\W]*)*/i, legacy: /^(<!-- TITLE: ?([\w\W]+?) ?-{2}>)?(?:\n|\r)?(<!-- SUBTITLE: ?([\w\W]+?) ?-{2}>)?(?:\n|\r)*([\w\W]*)*/i,
@ -120,7 +118,7 @@ module.exports = class Page extends Model {
*/ */
static async beforeDelete({ asFindQuery }) { static async beforeDelete({ asFindQuery }) {
const page = await asFindQuery().select('id') const page = await asFindQuery().select('id')
await WIKI.models.comments.query().delete().where('pageId', page[0].id) await WIKI.db.comments.query().delete().where('pageId', page[0].id)
} }
/** /**
* Cache Schema * Cache Schema
@ -256,7 +254,7 @@ module.exports = class Page extends Model {
} }
// -> Check for duplicate // -> Check for duplicate
const dupCheck = await WIKI.models.pages.query().select('id').where('localeCode', opts.locale).where('path', opts.path).first() const dupCheck = await WIKI.db.pages.query().select('id').where('localeCode', opts.locale).where('path', opts.path).first()
if (dupCheck) { if (dupCheck) {
throw new WIKI.Error.PageDuplicateCreate() throw new WIKI.Error.PageDuplicateCreate()
} }
@ -289,7 +287,7 @@ module.exports = class Page extends Model {
} }
// -> Create page // -> Create page
await WIKI.models.pages.query().insert({ await WIKI.db.pages.query().insert({
authorId: opts.user.id, authorId: opts.user.id,
content: opts.content, content: opts.content,
creatorId: opts.user.id, creatorId: opts.user.id,
@ -310,7 +308,7 @@ module.exports = class Page extends Model {
css: scriptCss css: scriptCss
}) })
}) })
const page = await WIKI.models.pages.getPageFromDb({ const page = await WIKI.db.pages.getPageFromDb({
path: opts.path, path: opts.path,
locale: opts.locale, locale: opts.locale,
userId: opts.user.id userId: opts.user.id
@ -318,37 +316,37 @@ module.exports = class Page extends Model {
// -> Save Tags // -> Save Tags
if (opts.tags && opts.tags.length > 0) { if (opts.tags && opts.tags.length > 0) {
await WIKI.models.tags.associateTags({ tags: opts.tags, page }) await WIKI.db.tags.associateTags({ tags: opts.tags, page })
} }
// -> Render page to HTML // -> Render page to HTML
await WIKI.models.pages.renderPage(page) await WIKI.db.pages.renderPage(page)
// -> Rebuild page tree // -> Rebuild page tree
await WIKI.models.pages.rebuildTree() await WIKI.db.pages.rebuildTree()
// -> Add to Search Index // -> Add to Search Index
const pageContents = await WIKI.models.pages.query().findById(page.id).select('render') const pageContents = await WIKI.db.pages.query().findById(page.id).select('render')
page.safeContent = WIKI.models.pages.cleanHTML(pageContents.render) page.safeContent = WIKI.db.pages.cleanHTML(pageContents.render)
await WIKI.data.searchEngine.created(page) await WIKI.data.searchEngine.created(page)
// -> Add to Storage // -> Add to Storage
if (!opts.skipStorage) { if (!opts.skipStorage) {
await WIKI.models.storage.pageEvent({ await WIKI.db.storage.pageEvent({
event: 'created', event: 'created',
page page
}) })
} }
// -> Reconnect Links // -> Reconnect Links
await WIKI.models.pages.reconnectLinks({ await WIKI.db.pages.reconnectLinks({
locale: page.localeCode, locale: page.localeCode,
path: page.path, path: page.path,
mode: 'create' mode: 'create'
}) })
// -> Get latest updatedAt // -> Get latest updatedAt
page.updatedAt = await WIKI.models.pages.query().findById(page.id).select('updatedAt').then(r => r.updatedAt) page.updatedAt = await WIKI.db.pages.query().findById(page.id).select('updatedAt').then(r => r.updatedAt)
return page return page
} }
@ -361,7 +359,7 @@ module.exports = class Page extends Model {
*/ */
static async updatePage(opts) { static async updatePage(opts) {
// -> Fetch original page // -> Fetch original page
const ogPage = await WIKI.models.pages.query().findById(opts.id) const ogPage = await WIKI.db.pages.query().findById(opts.id)
if (!ogPage) { if (!ogPage) {
throw new Error('Invalid Page Id') throw new Error('Invalid Page Id')
} }
@ -380,7 +378,7 @@ module.exports = class Page extends Model {
} }
// -> Create version snapshot // -> Create version snapshot
await WIKI.models.pageHistory.addVersion({ await WIKI.db.pageHistory.addVersion({
...ogPage, ...ogPage,
action: opts.action ? opts.action : 'updated', action: opts.action ? opts.action : 'updated',
versionDate: ogPage.updatedAt versionDate: ogPage.updatedAt
@ -414,7 +412,7 @@ module.exports = class Page extends Model {
} }
// -> Update page // -> Update page
await WIKI.models.pages.query().patch({ await WIKI.db.pages.query().patch({
authorId: opts.user.id, authorId: opts.user.id,
content: opts.content, content: opts.content,
description: opts.description, description: opts.description,
@ -428,23 +426,23 @@ module.exports = class Page extends Model {
css: scriptCss css: scriptCss
}) })
}).where('id', ogPage.id) }).where('id', ogPage.id)
let page = await WIKI.models.pages.getPageFromDb(ogPage.id) let page = await WIKI.db.pages.getPageFromDb(ogPage.id)
// -> Save Tags // -> Save Tags
await WIKI.models.tags.associateTags({ tags: opts.tags, page }) await WIKI.db.tags.associateTags({ tags: opts.tags, page })
// -> Render page to HTML // -> Render page to HTML
await WIKI.models.pages.renderPage(page) await WIKI.db.pages.renderPage(page)
WIKI.events.outbound.emit('deletePageFromCache', page.hash) WIKI.events.outbound.emit('deletePageFromCache', page.hash)
// -> Update Search Index // -> Update Search Index
const pageContents = await WIKI.models.pages.query().findById(page.id).select('render') const pageContents = await WIKI.db.pages.query().findById(page.id).select('render')
page.safeContent = WIKI.models.pages.cleanHTML(pageContents.render) page.safeContent = WIKI.db.pages.cleanHTML(pageContents.render)
await WIKI.data.searchEngine.updated(page) await WIKI.data.searchEngine.updated(page)
// -> Update on Storage // -> Update on Storage
if (!opts.skipStorage) { if (!opts.skipStorage) {
await WIKI.models.storage.pageEvent({ await WIKI.db.storage.pageEvent({
event: 'updated', event: 'updated',
page page
}) })
@ -460,7 +458,7 @@ module.exports = class Page extends Model {
throw new WIKI.Error.PageMoveForbidden() throw new WIKI.Error.PageMoveForbidden()
} }
await WIKI.models.pages.movePage({ await WIKI.db.pages.movePage({
id: page.id, id: page.id,
destinationLocale: opts.locale, destinationLocale: opts.locale,
destinationPath: opts.path, destinationPath: opts.path,
@ -468,13 +466,13 @@ module.exports = class Page extends Model {
}) })
} else { } else {
// -> Update title of page tree entry // -> Update title of page tree entry
await WIKI.models.knex.table('pageTree').where({ await WIKI.db.knex.table('pageTree').where({
pageId: page.id pageId: page.id
}).update('title', page.title) }).update('title', page.title)
} }
// -> Get latest updatedAt // -> Get latest updatedAt
page.updatedAt = await WIKI.models.pages.query().findById(page.id).select('updatedAt').then(r => r.updatedAt) page.updatedAt = await WIKI.db.pages.query().findById(page.id).select('updatedAt').then(r => r.updatedAt)
return page return page
} }
@ -487,7 +485,7 @@ module.exports = class Page extends Model {
*/ */
static async convertPage(opts) { static async convertPage(opts) {
// -> Fetch original page // -> Fetch original page
const ogPage = await WIKI.models.pages.query().findById(opts.id) const ogPage = await WIKI.db.pages.query().findById(opts.id)
if (!ogPage) { if (!ogPage) {
throw new Error('Invalid Page Id') throw new Error('Invalid Page Id')
} }
@ -621,7 +619,7 @@ module.exports = class Page extends Model {
// -> Create version snapshot // -> Create version snapshot
if (shouldConvert) { if (shouldConvert) {
await WIKI.models.pageHistory.addVersion({ await WIKI.db.pageHistory.addVersion({
...ogPage, ...ogPage,
action: 'updated', action: 'updated',
versionDate: ogPage.updatedAt versionDate: ogPage.updatedAt
@ -629,18 +627,18 @@ module.exports = class Page extends Model {
} }
// -> Update page // -> Update page
await WIKI.models.pages.query().patch({ await WIKI.db.pages.query().patch({
contentType: targetContentType, contentType: targetContentType,
editor: opts.editor, editor: opts.editor,
...(convertedContent ? { content: convertedContent } : {}) ...(convertedContent ? { content: convertedContent } : {})
}).where('id', ogPage.id) }).where('id', ogPage.id)
const page = await WIKI.models.pages.getPageFromDb(ogPage.id) const page = await WIKI.db.pages.getPageFromDb(ogPage.id)
await WIKI.models.pages.deletePageFromCache(page.hash) await WIKI.db.pages.deletePageFromCache(page.hash)
WIKI.events.outbound.emit('deletePageFromCache', page.hash) WIKI.events.outbound.emit('deletePageFromCache', page.hash)
// -> Update on Storage // -> Update on Storage
await WIKI.models.storage.pageEvent({ await WIKI.db.storage.pageEvent({
event: 'updated', event: 'updated',
page page
}) })
@ -655,9 +653,9 @@ module.exports = class Page extends Model {
static async movePage(opts) { static async movePage(opts) {
let page let page
if (_.has(opts, 'id')) { if (_.has(opts, 'id')) {
page = await WIKI.models.pages.query().findById(opts.id) page = await WIKI.db.pages.query().findById(opts.id)
} else { } else {
page = await WIKI.models.pages.query().findOne({ page = await WIKI.db.pages.query().findOne({
path: opts.path, path: opts.path,
localeCode: opts.locale localeCode: opts.locale
}) })
@ -697,7 +695,7 @@ module.exports = class Page extends Model {
} }
// -> Check for existing page at destination path // -> Check for existing page at destination path
const destPage = await WIKI.models.pages.query().findOne({ const destPage = await WIKI.db.pages.query().findOne({
path: opts.destinationPath, path: opts.destinationPath,
localeCode: opts.destinationLocale localeCode: opts.destinationLocale
}) })
@ -706,7 +704,7 @@ module.exports = class Page extends Model {
} }
// -> Create version snapshot // -> Create version snapshot
await WIKI.models.pageHistory.addVersion({ await WIKI.db.pageHistory.addVersion({
...page, ...page,
action: 'moved', action: 'moved',
versionDate: page.updatedAt versionDate: page.updatedAt
@ -716,21 +714,21 @@ module.exports = class Page extends Model {
// -> Move page // -> Move page
const destinationTitle = (page.title === page.path ? opts.destinationPath : page.title) const destinationTitle = (page.title === page.path ? opts.destinationPath : page.title)
await WIKI.models.pages.query().patch({ await WIKI.db.pages.query().patch({
path: opts.destinationPath, path: opts.destinationPath,
localeCode: opts.destinationLocale, localeCode: opts.destinationLocale,
title: destinationTitle, title: destinationTitle,
hash: destinationHash hash: destinationHash
}).findById(page.id) }).findById(page.id)
await WIKI.models.pages.deletePageFromCache(page.hash) await WIKI.db.pages.deletePageFromCache(page.hash)
WIKI.events.outbound.emit('deletePageFromCache', page.hash) WIKI.events.outbound.emit('deletePageFromCache', page.hash)
// -> Rebuild page tree // -> Rebuild page tree
await WIKI.models.pages.rebuildTree() await WIKI.db.pages.rebuildTree()
// -> Rename in Search Index // -> Rename in Search Index
const pageContents = await WIKI.models.pages.query().findById(page.id).select('render') const pageContents = await WIKI.db.pages.query().findById(page.id).select('render')
page.safeContent = WIKI.models.pages.cleanHTML(pageContents.render) page.safeContent = WIKI.db.pages.cleanHTML(pageContents.render)
await WIKI.data.searchEngine.renamed({ await WIKI.data.searchEngine.renamed({
...page, ...page,
destinationPath: opts.destinationPath, destinationPath: opts.destinationPath,
@ -740,7 +738,7 @@ module.exports = class Page extends Model {
// -> Rename in Storage // -> Rename in Storage
if (!opts.skipStorage) { if (!opts.skipStorage) {
await WIKI.models.storage.pageEvent({ await WIKI.db.storage.pageEvent({
event: 'renamed', event: 'renamed',
page: { page: {
...page, ...page,
@ -755,7 +753,7 @@ module.exports = class Page extends Model {
} }
// -> Reconnect Links : Changing old links to the new path // -> Reconnect Links : Changing old links to the new path
await WIKI.models.pages.reconnectLinks({ await WIKI.db.pages.reconnectLinks({
sourceLocale: page.localeCode, sourceLocale: page.localeCode,
sourcePath: page.path, sourcePath: page.path,
locale: opts.destinationLocale, locale: opts.destinationLocale,
@ -764,7 +762,7 @@ module.exports = class Page extends Model {
}) })
// -> Reconnect Links : Validate invalid links to the new path // -> Reconnect Links : Validate invalid links to the new path
await WIKI.models.pages.reconnectLinks({ await WIKI.db.pages.reconnectLinks({
locale: opts.destinationLocale, locale: opts.destinationLocale,
path: opts.destinationPath, path: opts.destinationPath,
mode: 'create' mode: 'create'
@ -778,7 +776,7 @@ module.exports = class Page extends Model {
* @returns {Promise} Promise with no value * @returns {Promise} Promise with no value
*/ */
static async deletePage(opts) { static async deletePage(opts) {
const page = await WIKI.models.pages.getPageFromDb(_.has(opts, 'id') ? opts.id : opts) const page = await WIKI.db.pages.getPageFromDb(_.has(opts, 'id') ? opts.id : opts)
if (!page) { if (!page) {
throw new WIKI.Error.PageNotFound() throw new WIKI.Error.PageNotFound()
} }
@ -792,33 +790,33 @@ module.exports = class Page extends Model {
} }
// -> Create version snapshot // -> Create version snapshot
await WIKI.models.pageHistory.addVersion({ await WIKI.db.pageHistory.addVersion({
...page, ...page,
action: 'deleted', action: 'deleted',
versionDate: page.updatedAt versionDate: page.updatedAt
}) })
// -> Delete page // -> Delete page
await WIKI.models.pages.query().delete().where('id', page.id) await WIKI.db.pages.query().delete().where('id', page.id)
await WIKI.models.pages.deletePageFromCache(page.hash) await WIKI.db.pages.deletePageFromCache(page.hash)
WIKI.events.outbound.emit('deletePageFromCache', page.hash) WIKI.events.outbound.emit('deletePageFromCache', page.hash)
// -> Rebuild page tree // -> Rebuild page tree
await WIKI.models.pages.rebuildTree() await WIKI.db.pages.rebuildTree()
// -> Delete from Search Index // -> Delete from Search Index
await WIKI.data.searchEngine.deleted(page) await WIKI.data.searchEngine.deleted(page)
// -> Delete from Storage // -> Delete from Storage
if (!opts.skipStorage) { if (!opts.skipStorage) {
await WIKI.models.storage.pageEvent({ await WIKI.db.storage.pageEvent({
event: 'deleted', event: 'deleted',
page page
}) })
} }
// -> Reconnect Links // -> Reconnect Links
await WIKI.models.pages.reconnectLinks({ await WIKI.db.pages.reconnectLinks({
locale: page.localeCode, locale: page.localeCode,
path: page.path, path: page.path,
mode: 'delete' mode: 'delete'
@ -863,10 +861,10 @@ module.exports = class Page extends Model {
let affectedHashes = [] let affectedHashes = []
// -> Perform replace and return affected page hashes (POSTGRES only) // -> Perform replace and return affected page hashes (POSTGRES only)
if (WIKI.config.db.type === 'postgres') { if (WIKI.config.db.type === 'postgres') {
const qryHashes = await WIKI.models.pages.query() const qryHashes = await WIKI.db.pages.query()
.returning('hash') .returning('hash')
.patch({ .patch({
render: WIKI.models.knex.raw('REPLACE(??, ?, ?)', ['render', replaceArgs.from, replaceArgs.to]) render: WIKI.db.knex.raw('REPLACE(??, ?, ?)', ['render', replaceArgs.from, replaceArgs.to])
}) })
.whereIn('pages.id', function () { .whereIn('pages.id', function () {
this.select('pageLinks.pageId').from('pageLinks').where({ this.select('pageLinks.pageId').from('pageLinks').where({
@ -877,9 +875,9 @@ module.exports = class Page extends Model {
affectedHashes = qryHashes.map(h => h.hash) affectedHashes = qryHashes.map(h => h.hash)
} else { } else {
// -> Perform replace, then query affected page hashes (MYSQL, MARIADB, MSSQL, SQLITE only) // -> Perform replace, then query affected page hashes (MYSQL, MARIADB, MSSQL, SQLITE only)
await WIKI.models.pages.query() await WIKI.db.pages.query()
.patch({ .patch({
render: WIKI.models.knex.raw('REPLACE(??, ?, ?)', ['render', replaceArgs.from, replaceArgs.to]) render: WIKI.db.knex.raw('REPLACE(??, ?, ?)', ['render', replaceArgs.from, replaceArgs.to])
}) })
.whereIn('pages.id', function () { .whereIn('pages.id', function () {
this.select('pageLinks.pageId').from('pageLinks').where({ this.select('pageLinks.pageId').from('pageLinks').where({
@ -887,7 +885,7 @@ module.exports = class Page extends Model {
'pageLinks.localeCode': opts.locale 'pageLinks.localeCode': opts.locale
}) })
}) })
const qryHashes = await WIKI.models.pages.query() const qryHashes = await WIKI.db.pages.query()
.column('hash') .column('hash')
.whereIn('pages.id', function () { .whereIn('pages.id', function () {
this.select('pageLinks.pageId').from('pageLinks').where({ this.select('pageLinks.pageId').from('pageLinks').where({
@ -898,7 +896,7 @@ module.exports = class Page extends Model {
affectedHashes = qryHashes.map(h => h.hash) affectedHashes = qryHashes.map(h => h.hash)
} }
for (const hash of affectedHashes) { for (const hash of affectedHashes) {
await WIKI.models.pages.deletePageFromCache(hash) await WIKI.db.pages.deletePageFromCache(hash)
WIKI.events.outbound.emit('deletePageFromCache', hash) WIKI.events.outbound.emit('deletePageFromCache', hash)
} }
} }
@ -940,14 +938,14 @@ module.exports = class Page extends Model {
*/ */
static async getPage(opts) { static async getPage(opts) {
// -> Get from cache first // -> Get from cache first
let page = await WIKI.models.pages.getPageFromCache(opts) let page = await WIKI.db.pages.getPageFromCache(opts)
if (!page) { if (!page) {
// -> Get from DB // -> Get from DB
page = await WIKI.models.pages.getPageFromDb(opts) page = await WIKI.db.pages.getPageFromDb(opts)
if (page) { if (page) {
if (page.render) { if (page.render) {
// -> Save render to cache // -> Save render to cache
await WIKI.models.pages.savePageToCache(page) await WIKI.db.pages.savePageToCache(page)
} else { } else {
// -> No render? Possible duplicate issue // -> No render? Possible duplicate issue
/* TODO: Detect duplicate and delete */ /* TODO: Detect duplicate and delete */
@ -967,7 +965,7 @@ module.exports = class Page extends Model {
static async getPageFromDb(opts) { static async getPageFromDb(opts) {
const queryModeID = _.isNumber(opts) const queryModeID = _.isNumber(opts)
try { try {
return WIKI.models.pages.query() return WIKI.db.pages.query()
.column([ .column([
'pages.id', 'pages.id',
'pages.path', 'pages.path',
@ -1031,7 +1029,7 @@ module.exports = class Page extends Model {
*/ */
static async savePageToCache(page) { static async savePageToCache(page) {
const cachePath = path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, `cache/${page.hash}.bin`) const cachePath = path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, `cache/${page.hash}.bin`)
await fs.outputFile(cachePath, WIKI.models.pages.cacheSchema.encode({ await fs.outputFile(cachePath, WIKI.db.pages.cacheSchema.encode({
id: page.id, id: page.id,
authorId: page.authorId, authorId: page.authorId,
authorName: page.authorName, authorName: page.authorName,
@ -1067,7 +1065,7 @@ module.exports = class Page extends Model {
try { try {
const pageBuffer = await fs.readFile(cachePath) const pageBuffer = await fs.readFile(cachePath)
let page = WIKI.models.pages.cacheSchema.decode(pageBuffer) let page = WIKI.db.pages.cacheSchema.decode(pageBuffer)
return { return {
...page, ...page,
path: opts.path, path: opts.path,
@ -1108,7 +1106,7 @@ module.exports = class Page extends Model {
* @returns {Promise} Promise with no value * @returns {Promise} Promise with no value
*/ */
static async migrateToLocale({ sourceLocale, targetLocale }) { static async migrateToLocale({ sourceLocale, targetLocale }) {
return WIKI.models.pages.query() return WIKI.db.pages.query()
.patch({ .patch({
localeCode: targetLocale localeCode: targetLocale
}) })
@ -1142,10 +1140,10 @@ module.exports = class Page extends Model {
*/ */
static subscribeToEvents() { static subscribeToEvents() {
WIKI.events.inbound.on('deletePageFromCache', hash => { WIKI.events.inbound.on('deletePageFromCache', hash => {
WIKI.models.pages.deletePageFromCache(hash) WIKI.db.pages.deletePageFromCache(hash)
}) })
WIKI.events.inbound.on('flushCache', () => { WIKI.events.inbound.on('flushCache', () => {
WIKI.models.pages.flushCache() WIKI.db.pages.flushCache()
}) })
} }
} }

@ -6,8 +6,6 @@ const yaml = require('js-yaml')
const DepGraph = require('dependency-graph').DepGraph const DepGraph = require('dependency-graph').DepGraph
const commonHelper = require('../helpers/common') const commonHelper = require('../helpers/common')
/* global WIKI */
/** /**
* Renderer model * Renderer model
*/ */
@ -32,7 +30,7 @@ module.exports = class Renderer extends Model {
} }
static async getRenderers() { static async getRenderers() {
return WIKI.models.renderers.query() return WIKI.db.renderers.query()
} }
static async fetchDefinitions() { static async fetchDefinitions() {
@ -57,16 +55,16 @@ module.exports = class Renderer extends Model {
} }
static async refreshRenderersFromDisk() { static async refreshRenderersFromDisk() {
// const dbRenderers = await WIKI.models.renderers.query() // const dbRenderers = await WIKI.db.renderers.query()
// -> Fetch definitions from disk // -> Fetch definitions from disk
await WIKI.models.renderers.fetchDefinitions() await WIKI.db.renderers.fetchDefinitions()
// TODO: Merge existing configs with updated modules // TODO: Merge existing configs with updated modules
} }
static async getRenderingPipeline(contentType) { static async getRenderingPipeline(contentType) {
const renderersDb = await WIKI.models.renderers.query().where('isEnabled', true) const renderersDb = await WIKI.db.renderers.query().where('isEnabled', true)
if (renderersDb && renderersDb.length > 0) { if (renderersDb && renderersDb.length > 0) {
const renderers = renderersDb.map(rdr => { const renderers = renderersDb.map(rdr => {
const renderer = _.find(WIKI.data.renderers, ['key', rdr.key]) const renderer = _.find(WIKI.data.renderers, ['key', rdr.key])

@ -1,8 +1,6 @@
const Model = require('objection').Model const Model = require('objection').Model
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
/** /**
* Settings model * Settings model
*/ */
@ -26,7 +24,7 @@ module.exports = class Setting extends Model {
} }
static async getConfig() { static async getConfig() {
const settings = await WIKI.models.settings.query() const settings = await WIKI.db.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, (_.has(val.value, 'v')) ? val.value.v : val.value) _.set(res, val.key, (_.has(val.value, 'v')) ? val.value.v : val.value)

@ -3,8 +3,6 @@ const crypto = require('crypto')
const pem2jwk = require('pem-jwk').pem2jwk const pem2jwk = require('pem-jwk').pem2jwk
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
/** /**
* Site model * Site model
*/ */
@ -30,7 +28,7 @@ module.exports = class Site extends Model {
static async getSiteByHostname ({ hostname, forceReload = false }) { static async getSiteByHostname ({ hostname, forceReload = false }) {
if (forceReload) { if (forceReload) {
await WIKI.models.sites.reloadCache() await WIKI.db.sites.reloadCache()
} }
const siteId = WIKI.sitesMappings[hostname] || WIKI.sitesMappings['*'] const siteId = WIKI.sitesMappings[hostname] || WIKI.sitesMappings['*']
if (siteId) { if (siteId) {
@ -41,7 +39,7 @@ module.exports = class Site extends Model {
static async reloadCache () { static async reloadCache () {
WIKI.logger.info('Reloading site configurations...') WIKI.logger.info('Reloading site configurations...')
const sites = await WIKI.models.sites.query().orderBy('id') const sites = await WIKI.db.sites.query().orderBy('id')
WIKI.sites = _.keyBy(sites, 'id') WIKI.sites = _.keyBy(sites, 'id')
WIKI.sitesMappings = {} WIKI.sitesMappings = {}
for (const site of sites) { for (const site of sites) {
@ -51,7 +49,7 @@ module.exports = class Site extends Model {
} }
static async createSite (hostname, config) { static async createSite (hostname, config) {
const newSite = await WIKI.models.sites.query().insertAndFetch({ const newSite = await WIKI.db.sites.query().insertAndFetch({
hostname, hostname,
isEnabled: true, isEnabled: true,
config: _.defaultsDeep(config, { config: _.defaultsDeep(config, {
@ -114,7 +112,7 @@ module.exports = class Site extends Model {
WIKI.logger.debug(`Creating new DB storage for site ${newSite.id}`) WIKI.logger.debug(`Creating new DB storage for site ${newSite.id}`)
await WIKI.models.storage.query().insert({ await WIKI.db.storage.query().insert({
module: 'db', module: 'db',
siteId: newSite.id, siteId: newSite.id,
isEnabled: true, isEnabled: true,
@ -135,11 +133,11 @@ module.exports = class Site extends Model {
} }
static async updateSite (id, patch) { static async updateSite (id, patch) {
return WIKI.models.sites.query().findById(id).patch(patch) return WIKI.db.sites.query().findById(id).patch(patch)
} }
static async deleteSite (id) { static async deleteSite (id) {
await WIKI.models.storage.query().delete().where('siteId', id) await WIKI.db.storage.query().delete().where('siteId', id)
return WIKI.models.sites.query().deleteById(id) return WIKI.db.sites.query().deleteById(id)
} }
} }

@ -5,8 +5,6 @@ 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 */
/** /**
* Storage model * Storage model
*/ */
@ -31,7 +29,7 @@ module.exports = class Storage extends Model {
} }
static async getTargets ({ siteId }) { static async getTargets ({ siteId }) {
return WIKI.models.storage.query().where(builder => { return WIKI.db.storage.query().where(builder => {
if (siteId) { if (siteId) {
builder.where('siteId', siteId) builder.where('siteId', siteId)
} }
@ -85,7 +83,7 @@ module.exports = class Storage extends Model {
* Initialize active storage targets * Initialize active storage targets
*/ */
static async initTargets () { static async initTargets () {
const dbTargets = await WIKI.models.storage.query().where('isEnabled', true) const dbTargets = await WIKI.db.storage.query().where('isEnabled', true)
const activeModules = _.uniq(dbTargets.map(t => t.module)) const activeModules = _.uniq(dbTargets.map(t => t.module))
try { try {
// -> Stop and delete existing jobs // -> Stop and delete existing jobs
@ -109,7 +107,7 @@ module.exports = class Storage extends Model {
// await target.fn.init() // await target.fn.init()
// // -> Save succeeded init state // // -> Save succeeded init state
// await WIKI.models.storage.query().patch({ // await WIKI.db.storage.query().patch({
// state: { // state: {
// status: 'operational', // status: 'operational',
// message: '', // message: '',
@ -138,7 +136,7 @@ module.exports = class Storage extends Model {
// } // }
// } catch (err) { // } catch (err) {
// // -> Save initialization error // // -> Save initialization error
// await WIKI.models.storage.query().patch({ // await WIKI.db.storage.query().patch({
// state: { // state: {
// status: 'error', // status: 'error',
// message: err.message, // message: err.message,

@ -1,8 +1,6 @@
const Model = require('objection').Model const Model = require('objection').Model
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
/** /**
* Tags model * Tags model
*/ */
@ -50,7 +48,7 @@ module.exports = class Tag extends Model {
} }
static async associateTags ({ tags, page }) { static async associateTags ({ tags, page }) {
let existingTags = await WIKI.models.tags.query().column('id', 'tag') let existingTags = await WIKI.db.tags.query().column('id', 'tag')
// Format tags // Format tags
@ -61,11 +59,11 @@ module.exports = class Tag extends Model {
const newTags = _.filter(tags, t => !_.some(existingTags, ['tag', t])).map(t => ({ tag: t })) const newTags = _.filter(tags, t => !_.some(existingTags, ['tag', t])).map(t => ({ tag: t }))
if (newTags.length > 0) { if (newTags.length > 0) {
if (WIKI.config.db.type === 'postgres') { if (WIKI.config.db.type === 'postgres') {
const createdTags = await WIKI.models.tags.query().insert(newTags) const createdTags = await WIKI.db.tags.query().insert(newTags)
existingTags = _.concat(existingTags, createdTags) existingTags = _.concat(existingTags, createdTags)
} else { } else {
for (const newTag of newTags) { for (const newTag of newTags) {
const createdTag = await WIKI.models.tags.query().insert(newTag) const createdTag = await WIKI.db.tags.query().insert(newTag)
existingTags.push(createdTag) existingTags.push(createdTag)
} }
} }

@ -46,7 +46,7 @@ module.exports = class UserKey extends Model {
static async generateToken ({ userId, kind, meta }, context) { static async generateToken ({ userId, kind, meta }, context) {
const token = await nanoid() const token = await nanoid()
await WIKI.models.userKeys.query().insert({ await WIKI.db.userKeys.query().insert({
kind, kind,
token, token,
meta, meta,
@ -57,10 +57,10 @@ module.exports = class UserKey extends Model {
} }
static async validateToken ({ kind, token, skipDelete }, context) { static async validateToken ({ kind, token, skipDelete }, context) {
const res = await WIKI.models.userKeys.query().findOne({ kind, token }).withGraphJoined('user') const res = await WIKI.db.userKeys.query().findOne({ kind, token }).withGraphJoined('user')
if (res) { if (res) {
if (skipDelete !== true) { if (skipDelete !== true) {
await WIKI.models.userKeys.query().deleteById(res.id) await WIKI.db.userKeys.query().deleteById(res.id)
} }
if (DateTime.utc() > DateTime.fromISO(res.validUntil)) { if (DateTime.utc() > DateTime.fromISO(res.validUntil)) {
throw new WIKI.Error.AuthValidationTokenInvalid() throw new WIKI.Error.AuthValidationTokenInvalid()
@ -75,6 +75,6 @@ module.exports = class UserKey extends Model {
} }
static async destroyToken ({ token }) { static async destroyToken ({ token }) {
return WIKI.models.userKeys.query().findOne({ token }).delete() return WIKI.db.userKeys.query().findOne({ token }).delete()
} }
} }

@ -90,7 +90,7 @@ module.exports = class User extends Model {
name: WIKI.config.title, name: WIKI.config.title,
account: this.email account: this.email
}) })
await WIKI.models.users.query().findById(this.id).patch({ await WIKI.db.users.query().findById(this.id).patch({
tfaIsActive: false, tfaIsActive: false,
tfaSecret: tfaInfo.secret tfaSecret: tfaInfo.secret
}) })
@ -99,7 +99,7 @@ module.exports = class User extends Model {
} }
async enableTFA() { async enableTFA() {
return WIKI.models.users.query().findById(this.id).patch({ return WIKI.db.users.query().findById(this.id).patch({
tfaIsActive: true tfaIsActive: true
}) })
} }
@ -129,7 +129,7 @@ module.exports = class User extends Model {
// ------------------------------------------------ // ------------------------------------------------
static async getById(id) { static async getById(id) {
return WIKI.models.users.query().findById(id).withGraphFetched('groups').modifyGraph('groups', builder => { return WIKI.db.users.query().findById(id).withGraphFetched('groups').modifyGraph('groups', builder => {
builder.select('groups.id', 'permissions') builder.select('groups.id', 'permissions')
}) })
} }
@ -139,7 +139,7 @@ module.exports = class User extends Model {
provider.info = _.find(WIKI.data.authentication, ['key', provider.stategyKey]) provider.info = _.find(WIKI.data.authentication, ['key', provider.stategyKey])
// Find existing user // Find existing user
let user = await WIKI.models.users.query().findOne({ let user = await WIKI.db.users.query().findOne({
providerId: _.toString(profile.id), providerId: _.toString(profile.id),
providerKey providerKey
}) })
@ -164,7 +164,7 @@ module.exports = class User extends Model {
// Find pending social user // Find pending social user
if (!user) { if (!user) {
user = await WIKI.models.users.query().findOne({ user = await WIKI.db.users.query().findOne({
email: primaryEmail, email: primaryEmail,
providerId: null, providerId: null,
providerKey providerKey
@ -213,7 +213,7 @@ module.exports = class User extends Model {
}) })
if (pictureUrl === 'internal') { if (pictureUrl === 'internal') {
await WIKI.models.users.updateUserAvatarData(user.id, profile.picture) await WIKI.db.users.updateUserAvatarData(user.id, profile.picture)
} }
return user return user
@ -230,7 +230,7 @@ module.exports = class User extends Model {
} }
// Create account // Create account
user = await WIKI.models.users.query().insertAndFetch({ user = await WIKI.db.users.query().insertAndFetch({
providerKey: providerKey, providerKey: providerKey,
providerId: _.toString(profile.id), providerId: _.toString(profile.id),
email: primaryEmail, email: primaryEmail,
@ -250,7 +250,7 @@ module.exports = class User extends Model {
} }
if (pictureUrl === 'internal') { if (pictureUrl === 'internal') {
await WIKI.models.users.updateUserAvatarData(user.id, profile.picture) await WIKI.db.users.updateUserAvatarData(user.id, profile.picture)
} }
return user return user
@ -288,7 +288,7 @@ module.exports = class User extends Model {
if (!user) { return reject(new WIKI.Error.AuthLoginFailed()) } if (!user) { return reject(new WIKI.Error.AuthLoginFailed()) }
try { try {
const resp = await WIKI.models.users.afterLoginChecks(user, selStrategy.id, context, { const resp = await WIKI.db.users.afterLoginChecks(user, selStrategy.id, context, {
skipTFA: !strInfo.useForm, skipTFA: !strInfo.useForm,
skipChangePwd: !strInfo.useForm skipChangePwd: !strInfo.useForm
}) })
@ -326,7 +326,7 @@ module.exports = class User extends Model {
if (!skipTFA) { if (!skipTFA) {
if (authStr.tfaRequired && authStr.tfaSecret) { if (authStr.tfaRequired && authStr.tfaSecret) {
try { try {
const tfaToken = await WIKI.models.userKeys.generateToken({ const tfaToken = await WIKI.db.userKeys.generateToken({
kind: 'tfa', kind: 'tfa',
userId: user.id userId: user.id
}) })
@ -342,7 +342,7 @@ module.exports = class User extends Model {
} else if (WIKI.config.auth.enforce2FA || (authStr.tfaIsActive && !authStr.tfaSecret)) { } else if (WIKI.config.auth.enforce2FA || (authStr.tfaIsActive && !authStr.tfaSecret)) {
try { try {
const tfaQRImage = await user.generateTFA() const tfaQRImage = await user.generateTFA()
const tfaToken = await WIKI.models.userKeys.generateToken({ const tfaToken = await WIKI.db.userKeys.generateToken({
kind: 'tfaSetup', kind: 'tfaSetup',
userId: user.id userId: user.id
}) })
@ -362,7 +362,7 @@ module.exports = class User extends Model {
// Must Change Password? // Must Change Password?
if (!skipChangePwd && authStr.mustChangePwd) { if (!skipChangePwd && authStr.mustChangePwd) {
try { try {
const pwdChangeToken = await WIKI.models.userKeys.generateToken({ const pwdChangeToken = await WIKI.db.userKeys.generateToken({
kind: 'changePwd', kind: 'changePwd',
userId: user.id userId: user.id
}) })
@ -381,7 +381,7 @@ module.exports = class User extends Model {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
context.req.login(user, { session: false }, async errc => { context.req.login(user, { session: false }, async errc => {
if (errc) { return reject(errc) } if (errc) { return reject(errc) }
const jwtToken = await WIKI.models.users.refreshToken(user, strategyId) const jwtToken = await WIKI.db.users.refreshToken(user, strategyId)
resolve({ jwt: jwtToken.token, redirect }) resolve({ jwt: jwtToken.token, redirect })
}) })
}) })
@ -392,7 +392,7 @@ module.exports = class User extends Model {
*/ */
static async refreshToken(user, provider) { static async refreshToken(user, provider) {
if (_.isString(user)) { if (_.isString(user)) {
user = await WIKI.models.users.query().findById(user).withGraphFetched('groups').modifyGraph('groups', builder => { user = await WIKI.db.users.query().findById(user).withGraphFetched('groups').modifyGraph('groups', builder => {
builder.select('groups.id', 'permissions') builder.select('groups.id', 'permissions')
}) })
if (!user) { if (!user) {
@ -409,7 +409,7 @@ module.exports = class User extends Model {
// Update Last Login Date // Update Last Login Date
// -> Bypass Objection.js to avoid updating the updatedAt field // -> Bypass Objection.js to avoid updating the updatedAt field
await WIKI.models.knex('users').where('id', user.id).update({ lastLoginAt: new Date().toISOString() }) await WIKI.db.knex('users').where('id', user.id).update({ lastLoginAt: new Date().toISOString() })
return { return {
token: jwt.sign({ token: jwt.sign({
@ -435,7 +435,7 @@ module.exports = class User extends Model {
*/ */
static async loginTFA ({ securityCode, continuationToken, setup }, context) { static async loginTFA ({ securityCode, continuationToken, setup }, context) {
if (securityCode.length === 6 && continuationToken.length > 1) { if (securityCode.length === 6 && continuationToken.length > 1) {
const user = await WIKI.models.userKeys.validateToken({ const user = await WIKI.db.userKeys.validateToken({
kind: setup ? 'tfaSetup' : 'tfa', kind: setup ? 'tfaSetup' : 'tfa',
token: continuationToken, token: continuationToken,
skipDelete: setup skipDelete: setup
@ -445,7 +445,7 @@ module.exports = class User extends Model {
if (setup) { if (setup) {
await user.enableTFA() await user.enableTFA()
} }
return WIKI.models.users.afterLoginChecks(user, context, { skipTFA: true }) return WIKI.db.users.afterLoginChecks(user, context, { skipTFA: true })
} else { } else {
throw new WIKI.Error.AuthTFAFailed() throw new WIKI.Error.AuthTFAFailed()
} }
@ -461,13 +461,13 @@ module.exports = class User extends Model {
if (!newPassword || newPassword.length < 6) { if (!newPassword || newPassword.length < 6) {
throw new WIKI.Error.InputInvalid('Password must be at least 6 characters!') throw new WIKI.Error.InputInvalid('Password must be at least 6 characters!')
} }
const usr = await WIKI.models.userKeys.validateToken({ const usr = await WIKI.db.userKeys.validateToken({
kind: 'changePwd', kind: 'changePwd',
token: continuationToken token: continuationToken
}) })
if (usr) { if (usr) {
await WIKI.models.users.query().patch({ await WIKI.db.users.query().patch({
password: newPassword, password: newPassword,
mustChangePwd: false mustChangePwd: false
}).findById(usr.id) }).findById(usr.id)
@ -475,7 +475,7 @@ module.exports = class User extends Model {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
context.req.logIn(usr, { session: false }, async err => { context.req.logIn(usr, { session: false }, async err => {
if (err) { return reject(err) } if (err) { return reject(err) }
const jwtToken = await WIKI.models.users.refreshToken(usr) const jwtToken = await WIKI.db.users.refreshToken(usr)
resolve({ jwt: jwtToken.token }) resolve({ jwt: jwtToken.token })
}) })
}) })
@ -488,7 +488,7 @@ module.exports = class User extends Model {
* Send a password reset request * Send a password reset request
*/ */
static async loginForgotPassword ({ email }, context) { static async loginForgotPassword ({ email }, context) {
const usr = await WIKI.models.users.query().where({ const usr = await WIKI.db.users.query().where({
email, email,
providerKey: 'local' providerKey: 'local'
}).first() }).first()
@ -496,7 +496,7 @@ module.exports = class User extends Model {
WIKI.logger.debug(`Password reset attempt on nonexistant local account ${email}: [DISCARDED]`) WIKI.logger.debug(`Password reset attempt on nonexistant local account ${email}: [DISCARDED]`)
return return
} }
const resetToken = await WIKI.models.userKeys.generateToken({ const resetToken = await WIKI.db.userKeys.generateToken({
userId: usr.id, userId: usr.id,
kind: 'resetPwd' kind: 'resetPwd'
}) })
@ -585,7 +585,7 @@ module.exports = class User extends Model {
} }
// Check if email already exists // Check if email already exists
const usr = await WIKI.models.users.query().findOne({ email, providerKey }) const usr = await WIKI.db.users.query().findOne({ email, providerKey })
if (!usr) { if (!usr) {
// Create the account // Create the account
let newUsrData = { let newUsrData = {
@ -606,7 +606,7 @@ module.exports = class User extends Model {
newUsrData.mustChangePwd = (mustChangePassword === true) newUsrData.mustChangePwd = (mustChangePassword === true)
} }
const newUsr = await WIKI.models.users.query().insert(newUsrData) const newUsr = await WIKI.db.users.query().insert(newUsrData)
// Assign to group(s) // Assign to group(s)
if (groups.length > 0) { if (groups.length > 0) {
@ -640,11 +640,11 @@ module.exports = class User extends Model {
* @param {Object} param0 User ID and fields to update * @param {Object} param0 User ID and fields to update
*/ */
static async updateUser ({ id, email, name, newPassword, groups, location, jobTitle, timezone, dateFormat, appearance }) { static async updateUser ({ id, email, name, newPassword, groups, location, jobTitle, timezone, dateFormat, appearance }) {
const usr = await WIKI.models.users.query().findById(id) const usr = await WIKI.db.users.query().findById(id)
if (usr) { if (usr) {
let usrData = {} let usrData = {}
if (!_.isEmpty(email) && email !== usr.email) { if (!_.isEmpty(email) && email !== usr.email) {
const dupUsr = await WIKI.models.users.query().select('id').where({ const dupUsr = await WIKI.db.users.query().select('id').where({
email, email,
providerKey: usr.providerKey providerKey: usr.providerKey
}).first() }).first()
@ -691,7 +691,7 @@ module.exports = class User extends Model {
if (!_.isNil(appearance) && appearance !== usr.appearance) { if (!_.isNil(appearance) && appearance !== usr.appearance) {
usrData.appearance = appearance usrData.appearance = appearance
} }
await WIKI.models.users.query().patch(usrData).findById(id) await WIKI.db.users.query().patch(usrData).findById(id)
} else { } else {
throw new WIKI.Error.UserNotFound() throw new WIKI.Error.UserNotFound()
} }
@ -703,16 +703,16 @@ module.exports = class User extends Model {
* @param {*} id User ID * @param {*} id User ID
*/ */
static async deleteUser (id, replaceId) { static async deleteUser (id, replaceId) {
const usr = await WIKI.models.users.query().findById(id) const usr = await WIKI.db.users.query().findById(id)
if (usr) { if (usr) {
await WIKI.models.assets.query().patch({ authorId: replaceId }).where('authorId', id) await WIKI.db.assets.query().patch({ authorId: replaceId }).where('authorId', id)
await WIKI.models.comments.query().patch({ authorId: replaceId }).where('authorId', id) await WIKI.db.comments.query().patch({ authorId: replaceId }).where('authorId', id)
await WIKI.models.pageHistory.query().patch({ authorId: replaceId }).where('authorId', id) await WIKI.db.pageHistory.query().patch({ authorId: replaceId }).where('authorId', id)
await WIKI.models.pages.query().patch({ authorId: replaceId }).where('authorId', id) await WIKI.db.pages.query().patch({ authorId: replaceId }).where('authorId', id)
await WIKI.models.pages.query().patch({ creatorId: replaceId }).where('creatorId', id) await WIKI.db.pages.query().patch({ creatorId: replaceId }).where('creatorId', id)
await WIKI.models.userKeys.query().delete().where('userId', id) await WIKI.db.userKeys.query().delete().where('userId', id)
await WIKI.models.users.query().deleteById(id) await WIKI.db.users.query().deleteById(id)
} else { } else {
throw new WIKI.Error.UserNotFound() throw new WIKI.Error.UserNotFound()
} }
@ -725,7 +725,7 @@ module.exports = class User extends Model {
* @param {Object} context GraphQL Context * @param {Object} context GraphQL Context
*/ */
static async register ({ email, password, name, verify = false, bypassChecks = false }, context) { static async register ({ email, password, name, verify = false, bypassChecks = false }, context) {
const localStrg = await WIKI.models.authentication.getStrategy('local') const localStrg = await WIKI.db.authentication.getStrategy('local')
// Check if self-registration is enabled // Check if self-registration is enabled
if (localStrg.selfRegistration || bypassChecks) { if (localStrg.selfRegistration || bypassChecks) {
// Input sanitization // Input sanitization
@ -773,10 +773,10 @@ module.exports = class User extends Model {
} }
} }
// Check if email already exists // Check if email already exists
const usr = await WIKI.models.users.query().findOne({ email, providerKey: 'local' }) const usr = await WIKI.db.users.query().findOne({ email, providerKey: 'local' })
if (!usr) { if (!usr) {
// Create the account // Create the account
const newUsr = await WIKI.models.users.query().insert({ const newUsr = await WIKI.db.users.query().insert({
provider: 'local', provider: 'local',
email, email,
name, name,
@ -796,7 +796,7 @@ module.exports = class User extends Model {
if (verify) { if (verify) {
// Create verification token // Create verification token
const verificationToken = await WIKI.models.userKeys.generateToken({ const verificationToken = await WIKI.db.userKeys.generateToken({
kind: 'verify', kind: 'verify',
userId: newUsr.id userId: newUsr.id
}) })
@ -846,7 +846,7 @@ module.exports = class User extends Model {
} }
static async getGuestUser () { static async getGuestUser () {
const user = await WIKI.models.users.query().findById(WIKI.config.auth.guestUserId).withGraphJoined('groups').modifyGraph('groups', builder => { const user = await WIKI.db.users.query().findById(WIKI.config.auth.guestUserId).withGraphJoined('groups').modifyGraph('groups', builder => {
builder.select('groups.id', 'permissions') builder.select('groups.id', 'permissions')
}) })
if (!user) { if (!user) {
@ -858,7 +858,7 @@ module.exports = class User extends Model {
} }
static async getRootUser () { static async getRootUser () {
let user = await WIKI.models.users.query().findById(WIKI.config.auth.rootAdminUserId) let user = await WIKI.db.users.query().findById(WIKI.config.auth.rootAdminUserId)
if (!user) { if (!user) {
WIKI.logger.error('CRITICAL ERROR: Root Administrator user is missing!') WIKI.logger.error('CRITICAL ERROR: Root Administrator user is missing!')
process.exit(1) process.exit(1)
@ -876,15 +876,15 @@ module.exports = class User extends Model {
if (data.length > 1024 * 1024) { if (data.length > 1024 * 1024) {
throw new Error('Avatar image filesize is too large. 1MB max.') throw new Error('Avatar image filesize is too large. 1MB max.')
} }
const existing = await WIKI.models.knex('userAvatars').select('id').where('id', userId).first() const existing = await WIKI.db.knex('userAvatars').select('id').where('id', userId).first()
if (existing) { if (existing) {
await WIKI.models.knex('userAvatars').where({ await WIKI.db.knex('userAvatars').where({
id: userId id: userId
}).update({ }).update({
data data
}) })
} else { } else {
await WIKI.models.knex('userAvatars').insert({ await WIKI.db.knex('userAvatars').insert({
id: userId, id: userId,
data data
}) })
@ -896,7 +896,7 @@ module.exports = class User extends Model {
static async getUserAvatarData (userId) { static async getUserAvatarData (userId) {
try { try {
const usrData = await WIKI.models.knex('userAvatars').where('id', userId).first() const usrData = await WIKI.db.knex('userAvatars').where('id', userId).first()
if (usrData) { if (usrData) {
return usrData.data return usrData.data
} else { } else {

@ -17,7 +17,7 @@ module.exports = {
passReqToCallback: true passReqToCallback: true
}, async (req, accessToken, refreshToken, extraParams, profile, cb) => { }, async (req, accessToken, refreshToken, extraParams, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile profile
}) })

@ -1,7 +1,5 @@
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
// ------------------------------------ // ------------------------------------
// Azure AD Account // Azure AD Account
// ------------------------------------ // ------------------------------------
@ -39,7 +37,7 @@ module.exports = {
}, async (req, iss, sub, profile, cb) => { }, async (req, iss, sub, profile, cb) => {
const usrEmail = _.get(profile, '_json.email', null) || _.get(profile, '_json.preferred_username') const usrEmail = _.get(profile, '_json.email', null) || _.get(profile, '_json.preferred_username')
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
id: profile.oid, id: profile.oid,

@ -15,7 +15,7 @@ module.exports = {
passReqToCallback: true passReqToCallback: true
}, async (req, profile, cb) => { }, async (req, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile profile
}) })

@ -22,7 +22,7 @@ module.exports = {
if (conf.guildId && !_.some(profile.guilds, { id: conf.guildId })) { if (conf.guildId && !_.some(profile.guilds, { id: conf.guildId })) {
throw new WIKI.Error.AuthLoginFailed() throw new WIKI.Error.AuthLoginFailed()
} }
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...profile, ...profile,

@ -18,7 +18,7 @@ module.exports = {
passReqToCallback: true passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => { }, async (req, accessToken, refreshToken, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...profile, ...profile,

@ -19,7 +19,7 @@ module.exports = {
passReqToCallback: true passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => { }, async (req, accessToken, refreshToken, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...profile, ...profile,

@ -27,7 +27,7 @@ module.exports = {
passport.use(conf.key, passport.use(conf.key,
new GitHubStrategy(githubConfig, async (req, accessToken, refreshToken, profile, cb) => { new GitHubStrategy(githubConfig, async (req, accessToken, refreshToken, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...profile, ...profile,

@ -19,7 +19,7 @@ module.exports = {
passReqToCallback: true passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => { }, async (req, accessToken, refreshToken, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...profile, ...profile,

@ -19,7 +19,7 @@ module.exports = {
if (conf.hostedDomain && conf.hostedDomain != profile._json.hd) { if (conf.hostedDomain && conf.hostedDomain != profile._json.hd) {
throw new Error('Google authentication should have been performed with domain ' + conf.hostedDomain) throw new Error('Google authentication should have been performed with domain ' + conf.hostedDomain)
} }
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...profile, ...profile,

@ -1,7 +1,5 @@
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
// ------------------------------------ // ------------------------------------
// Keycloak Account // Keycloak Account
// ------------------------------------ // ------------------------------------
@ -27,7 +25,7 @@ module.exports = {
displayName = profile.fullName displayName = profile.fullName
} }
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
id: profile.keycloakId, id: profile.keycloakId,

@ -31,7 +31,7 @@ module.exports = {
throw new Error('Invalid Unique ID field mapping!') throw new Error('Invalid Unique ID field mapping!')
} }
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
id: userId, id: userId,

@ -15,7 +15,7 @@ module.exports = {
passwordField: 'password' passwordField: 'password'
}, async (uEmail, uPassword, done) => { }, async (uEmail, uPassword, done) => {
try { try {
const user = await WIKI.models.users.query().findOne({ const user = await WIKI.db.users.query().findOne({
email: uEmail.toLowerCase() email: uEmail.toLowerCase()
}) })
if (user) { if (user) {

@ -18,7 +18,7 @@ module.exports = {
passReqToCallback: true passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => { }, async (req, accessToken, refreshToken, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...profile, ...profile,

@ -1,7 +1,5 @@
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
// ------------------------------------ // ------------------------------------
// OAuth2 Account // OAuth2 Account
// ------------------------------------ // ------------------------------------
@ -21,7 +19,7 @@ module.exports = {
scope: conf.scope scope: conf.scope
}, async (req, accessToken, refreshToken, profile, cb) => { }, async (req, accessToken, refreshToken, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...profile, ...profile,

@ -1,7 +1,5 @@
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
// ------------------------------------ // ------------------------------------
// OpenID Connect Account // OpenID Connect Account
// ------------------------------------ // ------------------------------------
@ -22,7 +20,7 @@ module.exports = {
passReqToCallback: true passReqToCallback: true
}, async (req, iss, sub, profile, cb) => { }, async (req, iss, sub, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...profile, ...profile,

@ -20,7 +20,7 @@ module.exports = {
passReqToCallback: true passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => { }, async (req, accessToken, refreshToken, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...profile, ...profile,

@ -1,7 +1,5 @@
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
// ------------------------------------ // ------------------------------------
// Rocket.chat Account // Rocket.chat Account
// ------------------------------------ // ------------------------------------
@ -43,7 +41,7 @@ module.exports = {
passReqToCallback: true passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => { }, async (req, accessToken, refreshToken, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile profile
}) })

@ -1,7 +1,5 @@
const _ = require('lodash') const _ = require('lodash')
/* global WIKI */
// ------------------------------------ // ------------------------------------
// SAML Account // SAML Account
// ------------------------------------ // ------------------------------------
@ -47,7 +45,7 @@ module.exports = {
throw new Error('Invalid or Missing Unique ID field!') throw new Error('Invalid or Missing Unique ID field!')
} }
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
id: userId, id: userId,

@ -19,7 +19,7 @@ module.exports = {
passReqToCallback: true passReqToCallback: true
}, async (req, accessToken, refreshToken, { user: userProfile }, cb) => { }, async (req, accessToken, refreshToken, { user: userProfile }, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...userProfile, ...userProfile,

@ -17,7 +17,7 @@ module.exports = {
passReqToCallback: true passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => { }, async (req, accessToken, refreshToken, profile, cb) => {
try { try {
const user = await WIKI.models.users.processProfile({ const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy, providerKey: req.params.strategy,
profile: { profile: {
...profile, ...profile,

@ -6,8 +6,6 @@ const _ = require('lodash')
const { AkismetClient } = require('akismet-api') const { AkismetClient } = require('akismet-api')
const moment = require('moment') const moment = require('moment')
/* global WIKI */
const window = new JSDOM('').window const window = new JSDOM('').window
const DOMPurify = createDOMPurify(window) const DOMPurify = createDOMPurify(window)
@ -108,14 +106,14 @@ module.exports = {
// -> Check for minimum delay between posts // -> Check for minimum delay between posts
if (WIKI.data.commentProvider.config.minDelay > 0) { if (WIKI.data.commentProvider.config.minDelay > 0) {
const lastComment = await WIKI.models.comments.query().select('updatedAt').findOne('authorId', user.id).orderBy('updatedAt', 'desc') const lastComment = await WIKI.db.comments.query().select('updatedAt').findOne('authorId', user.id).orderBy('updatedAt', 'desc')
if (lastComment && moment().subtract(WIKI.data.commentProvider.config.minDelay, 'seconds').isBefore(lastComment.updatedAt)) { if (lastComment && moment().subtract(WIKI.data.commentProvider.config.minDelay, 'seconds').isBefore(lastComment.updatedAt)) {
throw new Error('Your administrator has set a time limit before you can post another comment. Try again later.') throw new Error('Your administrator has set a time limit before you can post another comment. Try again later.')
} }
} }
// -> Save Comment to DB // -> Save Comment to DB
const cm = await WIKI.models.comments.query().insert(newComment) const cm = await WIKI.db.comments.query().insert(newComment)
// -> Return Comment ID // -> Return Comment ID
return cm.id return cm.id
@ -125,7 +123,7 @@ module.exports = {
*/ */
async update ({ id, content, user }) { async update ({ id, content, user }) {
const renderedContent = DOMPurify.sanitize(mkdown.render(content)) const renderedContent = DOMPurify.sanitize(mkdown.render(content))
await WIKI.models.comments.query().findById(id).patch({ await WIKI.db.comments.query().findById(id).patch({
render: renderedContent render: renderedContent
}) })
return renderedContent return renderedContent
@ -134,26 +132,26 @@ module.exports = {
* Delete an existing comment by ID * Delete an existing comment by ID
*/ */
async remove ({ id, user }) { async remove ({ id, user }) {
return WIKI.models.comments.query().findById(id).delete() return WIKI.db.comments.query().findById(id).delete()
}, },
/** /**
* Get the page ID from a comment ID * Get the page ID from a comment ID
*/ */
async getPageIdFromCommentId (id) { async getPageIdFromCommentId (id) {
const result = await WIKI.models.comments.query().select('pageId').findById(id) const result = await WIKI.db.comments.query().select('pageId').findById(id)
return (result) ? result.pageId : false return (result) ? result.pageId : false
}, },
/** /**
* Get a comment by ID * Get a comment by ID
*/ */
async getCommentById (id) { async getCommentById (id) {
return WIKI.models.comments.query().findById(id) return WIKI.db.comments.query().findById(id)
}, },
/** /**
* Get the total comments count for a page ID * Get the total comments count for a page ID
*/ */
async count (pageId) { async count (pageId) {
const result = await WIKI.models.comments.query().count('* as total').where('pageId', pageId).first() const result = await WIKI.db.comments.query().count('* as total').where('pageId', pageId).first()
return _.toSafeInteger(result.total) return _.toSafeInteger(result.total)
} }
} }

@ -4,8 +4,6 @@ const util = require('util')
const exec = util.promisify(require('child_process').exec) const exec = util.promisify(require('child_process').exec)
const fs = require('fs-extra') const fs = require('fs-extra')
/* global WIKI */
module.exports = { module.exports = {
key: 'puppeteer', key: 'puppeteer',
title: 'Puppeteer', title: 'Puppeteer',

@ -5,8 +5,6 @@ const util = require('util')
const exec = util.promisify(require('child_process').exec) const exec = util.promisify(require('child_process').exec)
const { pipeline } = require('stream/promises') const { pipeline } = require('stream/promises')
/* global WIKI */
module.exports = { module.exports = {
key: 'sharp', key: 'sharp',
title: 'Sharp', title: 'Sharp',

@ -6,8 +6,6 @@ const URL = require('url').URL
const mustacheRegExp = /(\{|&#x7b;?){2}(.+?)(\}|&#x7d;?){2}/i const mustacheRegExp = /(\{|&#x7b;?){2}(.+?)(\}|&#x7d;?){2}/i
/* global WIKI */
module.exports = { module.exports = {
async render() { async render() {
const $ = cheerio.load(this.input, { const $ = cheerio.load(this.input, {
@ -133,7 +131,7 @@ module.exports = {
if (internalRefs.length > 0) { if (internalRefs.length > 0) {
// -> Find matching pages // -> Find matching pages
const results = await WIKI.models.pages.query().column('id', 'path', 'localeCode').where(builder => { const results = await WIKI.db.pages.query().column('id', 'path', 'localeCode').where(builder => {
internalRefs.forEach((ref, idx) => { internalRefs.forEach((ref, idx) => {
if (idx < 1) { if (idx < 1) {
builder.where(ref) builder.where(ref)
@ -168,14 +166,14 @@ module.exports = {
}) })
if (missingLinks.length > 0) { if (missingLinks.length > 0) {
if (WIKI.config.db.type === 'postgres') { if (WIKI.config.db.type === 'postgres') {
await WIKI.models.pageLinks.query().insert(missingLinks.map(lnk => ({ await WIKI.db.pageLinks.query().insert(missingLinks.map(lnk => ({
pageId: this.page.id, pageId: this.page.id,
path: lnk.path, path: lnk.path,
localeCode: lnk.localeCode localeCode: lnk.localeCode
}))) })))
} else { } else {
for (const lnk of missingLinks) { for (const lnk of missingLinks) {
await WIKI.models.pageLinks.query().insert({ await WIKI.db.pageLinks.query().insert({
pageId: this.page.id, pageId: this.page.id,
path: lnk.path, path: lnk.path,
localeCode: lnk.localeCode localeCode: lnk.localeCode
@ -191,7 +189,7 @@ module.exports = {
return nLink.localeCode === pLink.localeCode && nLink.path === pLink.path return nLink.localeCode === pLink.localeCode && nLink.path === pLink.path
}) })
if (outdatedLinks.length > 0) { if (outdatedLinks.length > 0) {
await WIKI.models.pageLinks.query().delete().whereIn('id', _.map(outdatedLinks, 'id')) await WIKI.db.pageLinks.query().delete().whereIn('id', _.map(outdatedLinks, 'id'))
} }
} }

@ -1,8 +1,6 @@
const katex = require('katex') const katex = require('katex')
const chemParse = require('./mhchem') const chemParse = require('./mhchem')
/* global WIKI */
// ------------------------------------ // ------------------------------------
// Markdown - KaTeX Renderer // Markdown - KaTeX Renderer
// ------------------------------------ // ------------------------------------

@ -1,7 +1,5 @@
const mjax = require('mathjax') const mjax = require('mathjax')
/* global WIKI */
// ------------------------------------ // ------------------------------------
// Markdown - MathJax Renderer // Markdown - MathJax Renderer
// ------------------------------------ // ------------------------------------

@ -1,24 +0,0 @@
key: algolia
title: Algolia
description: Algolia is a powerful search-as-a-service solution, made easy to use with API clients, UI libraries, and pre-built integrations.
author: requarks.io
logo: https://static.requarks.io/logo/algolia.svg
website: https://www.algolia.com/
isAvailable: true
props:
appId:
type: String
title: App ID
hint: Your Algolia Application ID, found under API Keys
order: 1
apiKey:
type: String
title: Admin API Key
hint: Your Algolia Admin API Key, found under API Keys.
order: 2
indexName:
type: String
title: Index Name
hint: The name of the index you created under Indices.
default: wiki
order: 3

@ -1,203 +0,0 @@
const _ = require('lodash')
const algoliasearch = require('algoliasearch')
const stream = require('stream')
const Promise = require('bluebird')
const pipeline = Promise.promisify(stream.pipeline)
/* global WIKI */
module.exports = {
async activate() {
// not used
},
async deactivate() {
// not used
},
/**
* INIT
*/
async init() {
WIKI.logger.info(`(SEARCH/ALGOLIA) Initializing...`)
this.client = algoliasearch(this.config.appId, this.config.apiKey)
this.index = this.client.initIndex(this.config.indexName)
// -> Create Search Index
WIKI.logger.info(`(SEARCH/ALGOLIA) Setting index configuration...`)
await this.index.setSettings({
searchableAttributes: [
'title',
'description',
'content'
],
attributesToRetrieve: [
'locale',
'path',
'title',
'description'
],
advancedSyntax: true
})
WIKI.logger.info(`(SEARCH/ALGOLIA) Initialization completed.`)
},
/**
* QUERY
*
* @param {String} q Query
* @param {Object} opts Additional options
*/
async query(q, opts) {
try {
const results = await this.index.search(q, {
hitsPerPage: 50
})
return {
results: _.map(results.hits, r => ({
id: r.objectID,
locale: r.locale,
path: r.path,
title: r.title,
description: r.description
})),
suggestions: [],
totalHits: results.nbHits
}
} catch (err) {
WIKI.logger.warn('Search Engine Error:')
WIKI.logger.warn(err)
}
},
/**
* CREATE
*
* @param {Object} page Page to create
*/
async created(page) {
await this.index.saveObject({
objectID: page.hash,
locale: page.localeCode,
path: page.path,
title: page.title,
description: page.description,
content: page.safeContent
})
},
/**
* UPDATE
*
* @param {Object} page Page to update
*/
async updated(page) {
await this.index.partialUpdateObject({
objectID: page.hash,
title: page.title,
description: page.description,
content: page.safeContent
})
},
/**
* DELETE
*
* @param {Object} page Page to delete
*/
async deleted(page) {
await this.index.deleteObject(page.hash)
},
/**
* RENAME
*
* @param {Object} page Page to rename
*/
async renamed(page) {
await this.index.deleteObject(page.hash)
await this.index.saveObject({
objectID: page.destinationHash,
locale: page.destinationLocaleCode,
path: page.destinationPath,
title: page.title,
description: page.description,
content: page.safeContent
})
},
/**
* REBUILD INDEX
*/
async rebuild() {
WIKI.logger.info(`(SEARCH/ALGOLIA) Rebuilding Index...`)
await this.index.clearObjects()
const MAX_DOCUMENT_BYTES = 10 * Math.pow(2, 10) // 10 KB
const MAX_INDEXING_BYTES = 10 * Math.pow(2, 20) - Buffer.from('[').byteLength - Buffer.from(']').byteLength // 10 MB
const MAX_INDEXING_COUNT = 1000
const COMMA_BYTES = Buffer.from(',').byteLength
let chunks = []
let bytes = 0
const processDocument = async (cb, doc) => {
try {
if (doc) {
const docBytes = Buffer.from(JSON.stringify(doc)).byteLength
// -> Document too large
if (docBytes >= MAX_DOCUMENT_BYTES) {
throw new Error('Document exceeds maximum size allowed by Algolia.')
}
// -> Current batch exceeds size hard limit, flush
if (docBytes + COMMA_BYTES + bytes >= MAX_INDEXING_BYTES) {
await flushBuffer()
}
if (chunks.length > 0) {
bytes += COMMA_BYTES
}
bytes += docBytes
chunks.push(doc)
// -> Current batch exceeds count soft limit, flush
if (chunks.length >= MAX_INDEXING_COUNT) {
await flushBuffer()
}
} else {
// -> End of stream, flush
await flushBuffer()
}
cb()
} catch (err) {
cb(err)
}
}
const flushBuffer = async () => {
WIKI.logger.info(`(SEARCH/ALGOLIA) Sending batch of ${chunks.length}...`)
try {
await this.index.saveObjects(
_.map(chunks, doc => ({
objectID: doc.id,
locale: doc.locale,
path: doc.path,
title: doc.title,
description: doc.description,
content: WIKI.models.pages.cleanHTML(doc.render)
}))
)
} catch (err) {
WIKI.logger.warn('(SEARCH/ALGOLIA) Failed to send batch to Algolia: ', err)
}
chunks.length = 0
bytes = 0
}
await pipeline(
WIKI.models.knex.column({ id: 'hash' }, 'path', { locale: 'localeCode' }, 'title', 'description', 'render').select().from('pages').where({
isPublished: true,
isPrivate: false
}).stream(),
new stream.Transform({
objectMode: true,
transform: async (chunk, enc, cb) => processDocument(cb, chunk),
flush: async (cb) => processDocument(cb)
})
)
WIKI.logger.info(`(SEARCH/ALGOLIA) Index rebuilt successfully.`)
}
}

@ -1,88 +0,0 @@
key: aws
title: AWS CloudSearch
description: Amazon CloudSearch is a managed service in the AWS Cloud that makes it simple and cost-effective to set up, manage, and scale a search solution for your website or application.
author: requarks.io
logo: https://static.requarks.io/logo/aws-cloudsearch.svg
website: https://aws.amazon.com/cloudsearch/
isAvailable: true
props:
domain:
type: String
title: Search Domain
hint: The name of your CloudSearch service.
order: 1
endpoint:
type: String
title: Document Endpoint
hint: The Document Endpoint specified in the domain AWS console dashboard.
order: 2
region:
type: String
title: Region
hint: The AWS datacenter region where the instance was created.
default: us-east-1
enum:
- ap-northeast-1
- ap-northeast-2
- ap-southeast-1
- ap-southeast-2
- eu-central-1
- eu-west-1
- sa-east-1
- us-east-1
- us-west-1
- us-west-2
order: 3
accessKeyId:
type: String
title: Access Key ID
hint: The Access Key ID with CloudSearchFullAccess role access to the CloudSearch instance.
order: 4
secretAccessKey :
type: String
title: Secret Access Key
hint: The Secret Access Key for the Access Key ID provided above.
order: 5
AnalysisSchemeLang:
type: String
title: Analysis Scheme Language
hint: The language used to analyse content.
default: en
enum:
- 'ar'
- 'bg'
- 'ca'
- 'cs'
- 'da'
- 'de'
- 'el'
- 'en'
- 'es'
- 'eu'
- 'fa'
- 'fi'
- 'fr'
- 'ga'
- 'gl'
- 'he'
- 'hi'
- 'hu'
- 'hy'
- 'id'
- 'it'
- 'ja'
- 'ko'
- 'lv'
- 'mul'
- 'nl'
- 'no'
- 'pt'
- 'ro'
- 'ru'
- 'sv'
- 'th'
- 'tr'
- 'zh-Hans'
- 'zh-Hant'
order: 6

@ -1,370 +0,0 @@
const _ = require('lodash')
const AWS = require('aws-sdk')
const stream = require('stream')
const Promise = require('bluebird')
const pipeline = Promise.promisify(stream.pipeline)
/* global WIKI */
module.exports = {
async activate() {
// not used
},
async deactivate() {
// not used
},
/**
* INIT
*/
async init() {
WIKI.logger.info(`(SEARCH/AWS) Initializing...`)
this.client = new AWS.CloudSearch({
apiVersion: '2013-01-01',
accessKeyId: this.config.accessKeyId,
secretAccessKey: this.config.secretAccessKey,
region: this.config.region
})
this.clientDomain = new AWS.CloudSearchDomain({
apiVersion: '2013-01-01',
endpoint: this.config.endpoint,
accessKeyId: this.config.accessKeyId,
secretAccessKey: this.config.secretAccessKey,
region: this.config.region
})
let rebuildIndex = false
// -> Define Analysis Schemes
const schemes = await this.client.describeAnalysisSchemes({
DomainName: this.config.domain,
AnalysisSchemeNames: ['default_anlscheme']
}).promise()
if (_.get(schemes, 'AnalysisSchemes', []).length < 1) {
WIKI.logger.info(`(SEARCH/AWS) Defining Analysis Scheme...`)
await this.client.defineAnalysisScheme({
DomainName: this.config.domain,
AnalysisScheme: {
AnalysisSchemeLanguage: this.config.AnalysisSchemeLang,
AnalysisSchemeName: 'default_anlscheme'
}
}).promise()
rebuildIndex = true
}
// -> Define Index Fields
const fields = await this.client.describeIndexFields({
DomainName: this.config.domain
}).promise()
if (_.get(fields, 'IndexFields', []).length < 1) {
WIKI.logger.info(`(SEARCH/AWS) Defining Index Fields...`)
await this.client.defineIndexField({
DomainName: this.config.domain,
IndexField: {
IndexFieldName: 'id',
IndexFieldType: 'literal'
}
}).promise()
await this.client.defineIndexField({
DomainName: this.config.domain,
IndexField: {
IndexFieldName: 'path',
IndexFieldType: 'literal'
}
}).promise()
await this.client.defineIndexField({
DomainName: this.config.domain,
IndexField: {
IndexFieldName: 'locale',
IndexFieldType: 'literal'
}
}).promise()
await this.client.defineIndexField({
DomainName: this.config.domain,
IndexField: {
IndexFieldName: 'title',
IndexFieldType: 'text',
TextOptions: {
ReturnEnabled: true,
AnalysisScheme: 'default_anlscheme'
}
}
}).promise()
await this.client.defineIndexField({
DomainName: this.config.domain,
IndexField: {
IndexFieldName: 'description',
IndexFieldType: 'text',
TextOptions: {
ReturnEnabled: true,
AnalysisScheme: 'default_anlscheme'
}
}
}).promise()
await this.client.defineIndexField({
DomainName: this.config.domain,
IndexField: {
IndexFieldName: 'content',
IndexFieldType: 'text',
TextOptions: {
ReturnEnabled: false,
AnalysisScheme: 'default_anlscheme'
}
}
}).promise()
rebuildIndex = true
}
// -> Define suggester
const suggesters = await this.client.describeSuggesters({
DomainName: this.config.domain,
SuggesterNames: ['default_suggester']
}).promise()
if (_.get(suggesters, 'Suggesters', []).length < 1) {
WIKI.logger.info(`(SEARCH/AWS) Defining Suggester...`)
await this.client.defineSuggester({
DomainName: this.config.domain,
Suggester: {
SuggesterName: 'default_suggester',
DocumentSuggesterOptions: {
SourceField: 'title',
FuzzyMatching: 'high'
}
}
}).promise()
rebuildIndex = true
}
// -> Rebuild Index
if (rebuildIndex) {
WIKI.logger.info(`(SEARCH/AWS) Requesting Index Rebuild...`)
await this.client.indexDocuments({
DomainName: this.config.domain
}).promise()
}
WIKI.logger.info(`(SEARCH/AWS) Initialization completed.`)
},
/**
* QUERY
*
* @param {String} q Query
* @param {Object} opts Additional options
*/
async query(q, opts) {
try {
let suggestions = []
const results = await this.clientDomain.search({
query: q,
partial: true,
size: 50
}).promise()
if (results.hits.found < 5) {
const suggestResults = await this.clientDomain.suggest({
query: q,
suggester: 'default_suggester',
size: 5
}).promise()
suggestions = suggestResults.suggest.suggestions.map(s => s.suggestion)
}
return {
results: _.map(results.hits.hit, r => ({
id: r.id,
path: _.head(r.fields.path),
locale: _.head(r.fields.locale),
title: _.head(r.fields.title) || '',
description: _.head(r.fields.description) || ''
})),
suggestions: suggestions,
totalHits: results.hits.found
}
} catch (err) {
WIKI.logger.warn('Search Engine Error:')
WIKI.logger.warn(err)
}
},
/**
* CREATE
*
* @param {Object} page Page to create
*/
async created(page) {
await this.clientDomain.uploadDocuments({
contentType: 'application/json',
documents: JSON.stringify([
{
type: 'add',
id: page.hash,
fields: {
locale: page.localeCode,
path: page.path,
title: page.title,
description: page.description,
content: page.safeContent
}
}
])
}).promise()
},
/**
* UPDATE
*
* @param {Object} page Page to update
*/
async updated(page) {
await this.clientDomain.uploadDocuments({
contentType: 'application/json',
documents: JSON.stringify([
{
type: 'add',
id: page.hash,
fields: {
locale: page.localeCode,
path: page.path,
title: page.title,
description: page.description,
content: page.safeContent
}
}
])
}).promise()
},
/**
* DELETE
*
* @param {Object} page Page to delete
*/
async deleted(page) {
await this.clientDomain.uploadDocuments({
contentType: 'application/json',
documents: JSON.stringify([
{
type: 'delete',
id: page.hash
}
])
}).promise()
},
/**
* RENAME
*
* @param {Object} page Page to rename
*/
async renamed(page) {
await this.clientDomain.uploadDocuments({
contentType: 'application/json',
documents: JSON.stringify([
{
type: 'delete',
id: page.hash
}
])
}).promise()
await this.clientDomain.uploadDocuments({
contentType: 'application/json',
documents: JSON.stringify([
{
type: 'add',
id: page.destinationHash,
fields: {
locale: page.destinationLocaleCode,
path: page.destinationPath,
title: page.title,
description: page.description,
content: page.safeContent
}
}
])
}).promise()
},
/**
* REBUILD INDEX
*/
async rebuild() {
WIKI.logger.info(`(SEARCH/AWS) Rebuilding Index...`)
const MAX_DOCUMENT_BYTES = Math.pow(2, 20)
const MAX_INDEXING_BYTES = 5 * Math.pow(2, 20) - Buffer.from('[').byteLength - Buffer.from(']').byteLength
const MAX_INDEXING_COUNT = 1000
const COMMA_BYTES = Buffer.from(',').byteLength
let chunks = []
let bytes = 0
const processDocument = async (cb, doc) => {
try {
if (doc) {
const docBytes = Buffer.from(JSON.stringify(doc)).byteLength
// -> Document too large
if (docBytes >= MAX_DOCUMENT_BYTES) {
throw new Error('Document exceeds maximum size allowed by AWS CloudSearch.')
}
// -> Current batch exceeds size hard limit, flush
if (docBytes + COMMA_BYTES + bytes >= MAX_INDEXING_BYTES) {
await flushBuffer()
}
if (chunks.length > 0) {
bytes += COMMA_BYTES
}
bytes += docBytes
chunks.push(doc)
// -> Current batch exceeds count soft limit, flush
if (chunks.length >= MAX_INDEXING_COUNT) {
await flushBuffer()
}
} else {
// -> End of stream, flush
await flushBuffer()
}
cb()
} catch (err) {
cb(err)
}
}
const flushBuffer = async () => {
WIKI.logger.info(`(SEARCH/AWS) Sending batch of ${chunks.length}...`)
try {
await this.clientDomain.uploadDocuments({
contentType: 'application/json',
documents: JSON.stringify(_.map(chunks, doc => ({
type: 'add',
id: doc.id,
fields: {
locale: doc.locale,
path: doc.path,
title: doc.title,
description: doc.description,
content: WIKI.models.pages.cleanHTML(doc.render)
}
})))
}).promise()
} catch (err) {
WIKI.logger.warn('(SEARCH/AWS) Failed to send batch to AWS CloudSearch: ', err)
}
chunks.length = 0
bytes = 0
}
await pipeline(
WIKI.models.knex.column({ id: 'hash' }, 'path', { locale: 'localeCode' }, 'title', 'description', 'render').select().from('pages').where({
isPublished: true,
isPrivate: false
}).stream(),
new stream.Transform({
objectMode: true,
transform: async (chunk, enc, cb) => processDocument(cb, chunk),
flush: async (cb) => processDocument(cb)
})
)
WIKI.logger.info(`(SEARCH/AWS) Requesting Index Rebuild...`)
await this.client.indexDocuments({
DomainName: this.config.domain
}).promise()
WIKI.logger.info(`(SEARCH/AWS) Index rebuilt successfully.`)
}
}

@ -1,24 +0,0 @@
key: azure
title: Azure Search
description: AI-Powered cloud search service for web and mobile app development.
author: requarks.io
logo: https://static.requarks.io/logo/azure.svg
website: https://azure.microsoft.com/services/search/
isAvailable: true
props:
serviceName:
type: String
title: Service Name
hint: The name of the Azure Search Service. Found under Properties.
order: 1
adminKey:
type: String
title: Admin API Key
hint: Either the primary or secondary admin key. Found under Keys.
order: 2
indexName:
type: String
title: Index Name
hint: 'Name to use when creating the index. (default: wiki)'
default: wiki
order: 3

@ -1,235 +0,0 @@
const _ = require('lodash')
const { SearchService, QueryType } = require('azure-search-client')
const request = require('request-promise')
const stream = require('stream')
const Promise = require('bluebird')
const pipeline = Promise.promisify(stream.pipeline)
/* global WIKI */
module.exports = {
async activate() {
// not used
},
async deactivate() {
// not used
},
/**
* INIT
*/
async init() {
WIKI.logger.info(`(SEARCH/AZURE) Initializing...`)
this.client = new SearchService(this.config.serviceName, this.config.adminKey)
// -> Create Search Index
const indexes = await this.client.indexes.list()
if (!_.find(_.get(indexes, 'result.value', []), ['name', this.config.indexName])) {
WIKI.logger.info(`(SEARCH/AZURE) Creating index...`)
await this.client.indexes.create({
name: this.config.indexName,
fields: [
{
name: 'id',
type: 'Edm.String',
key: true,
searchable: false
},
{
name: 'locale',
type: 'Edm.String',
searchable: false
},
{
name: 'path',
type: 'Edm.String',
searchable: false
},
{
name: 'title',
type: 'Edm.String',
searchable: true
},
{
name: 'description',
type: 'Edm.String',
searchable: true
},
{
name: 'content',
type: 'Edm.String',
searchable: true
}
],
scoringProfiles: [
{
name: 'fieldWeights',
text: {
weights: {
title: 4,
description: 3,
content: 1
}
}
}
],
suggesters: [
{
name: 'suggestions',
searchMode: 'analyzingInfixMatching',
sourceFields: ['title', 'description', 'content']
}
]
})
}
WIKI.logger.info(`(SEARCH/AZURE) Initialization completed.`)
},
/**
* QUERY
*
* @param {String} q Query
* @param {Object} opts Additional options
*/
async query(q, opts) {
try {
let suggestions = []
const results = await this.client.indexes.use(this.config.indexName).search({
count: true,
scoringProfile: 'fieldWeights',
search: q,
select: 'id, locale, path, title, description',
queryType: QueryType.simple,
top: 50
})
if (results.result.value.length < 5) {
// Using plain request, not yet available in library...
try {
const suggestResults = await request({
uri: `https://${this.config.serviceName}.search.windows.net/indexes/${this.config.indexName}/docs/autocomplete`,
method: 'post',
qs: {
'api-version': '2017-11-11-Preview'
},
headers: {
'api-key': this.config.adminKey,
'Content-Type': 'application/json'
},
json: true,
body: {
autocompleteMode: 'oneTermWithContext',
search: q,
suggesterName: 'suggestions'
}
})
suggestions = suggestResults.value.map(s => s.queryPlusText)
} catch (err) {
WIKI.logger.warn('Search Engine suggestion failure: ', err)
}
}
return {
results: results.result.value,
suggestions,
totalHits: results.result['@odata.count']
}
} catch (err) {
WIKI.logger.warn('Search Engine Error:')
WIKI.logger.warn(err)
}
},
/**
* CREATE
*
* @param {Object} page Page to create
*/
async created(page) {
await this.client.indexes.use(this.config.indexName).index([
{
id: page.hash,
locale: page.localeCode,
path: page.path,
title: page.title,
description: page.description,
content: page.safeContent
}
])
},
/**
* UPDATE
*
* @param {Object} page Page to update
*/
async updated(page) {
await this.client.indexes.use(this.config.indexName).index([
{
id: page.hash,
locale: page.localeCode,
path: page.path,
title: page.title,
description: page.description,
content: page.safeContent
}
])
},
/**
* DELETE
*
* @param {Object} page Page to delete
*/
async deleted(page) {
await this.client.indexes.use(this.config.indexName).index([
{
'@search.action': 'delete',
id: page.hash
}
])
},
/**
* RENAME
*
* @param {Object} page Page to rename
*/
async renamed(page) {
await this.client.indexes.use(this.config.indexName).index([
{
'@search.action': 'delete',
id: page.hash
}
])
await this.client.indexes.use(this.config.indexName).index([
{
id: page.destinationHash,
locale: page.destinationLocaleCode,
path: page.destinationPath,
title: page.title,
description: page.description,
content: page.safeContent
}
])
},
/**
* REBUILD INDEX
*/
async rebuild() {
WIKI.logger.info(`(SEARCH/AZURE) Rebuilding Index...`)
await pipeline(
WIKI.models.knex.column({ id: 'hash' }, 'path', { locale: 'localeCode' }, 'title', 'description', 'render').select().from('pages').where({
isPublished: true,
isPrivate: false
}).stream(),
new stream.Transform({
objectMode: true,
transform: (chunk, enc, cb) => {
cb(null, {
id: chunk.id,
path: chunk.path,
locale: chunk.locale,
title: chunk.title,
description: chunk.description,
content: WIKI.models.pages.cleanHTML(chunk.render)
})
}
}),
this.client.indexes.use(this.config.indexName).createIndexingStream()
)
WIKI.logger.info(`(SEARCH/AZURE) Index rebuilt successfully.`)
}
}

@ -1,8 +0,0 @@
key: db
title: Database - Basic
description: Default basic database-based search engine.
author: requarks.io
logo: https://static.requarks.io/logo/database.svg
website: https://www.requarks.io/
isAvailable: true
props: {}

@ -1,94 +0,0 @@
/* global WIKI */
module.exports = {
activate() {
// not used
},
deactivate() {
// not used
},
/**
* INIT
*/
init() {
// not used
},
/**
* QUERY
*
* @param {String} q Query
* @param {Object} opts Additional options
*/
async query(q, opts) {
const results = await WIKI.models.pages.query()
.column('pages.id', 'title', 'description', 'path', 'localeCode as locale')
.withGraphJoined('tags') // Adding page tags since they can be used to check resource access permissions
.modifyGraph('tags', builder => {
builder.select('tag')
})
.where(builder => {
builder.where('isPublished', true)
if (opts.locale) {
builder.andWhere('localeCode', opts.locale)
}
if (opts.path) {
builder.andWhere('path', 'like', `${opts.path}%`)
}
builder.andWhere(builderSub => {
if (WIKI.config.db.type === 'postgres') {
builderSub.where('title', 'ILIKE', `%${q}%`)
builderSub.orWhere('description', 'ILIKE', `%${q}%`)
builderSub.orWhere('path', 'ILIKE', `%${q.toLowerCase()}%`)
} else {
builderSub.where('title', 'LIKE', `%${q}%`)
builderSub.orWhere('description', 'LIKE', `%${q}%`)
builderSub.orWhere('path', 'LIKE', `%${q.toLowerCase()}%`)
}
})
})
.limit(WIKI.config.search.maxHits)
return {
results,
suggestions: [],
totalHits: results.length
}
},
/**
* CREATE
*
* @param {Object} page Page to create
*/
async created(page) {
// not used
},
/**
* UPDATE
*
* @param {Object} page Page to update
*/
async updated(page) {
// not used
},
/**
* DELETE
*
* @param {Object} page Page to delete
*/
async deleted(page) {
// not used
},
/**
* RENAME
*
* @param {Object} page Page to rename
*/
async renamed(page) {
// not used
},
/**
* REBUILD INDEX
*/
async rebuild() {
// not used
}
}

@ -1,47 +0,0 @@
key: elasticsearch
title: Elasticsearch
description: Elasticsearch is a distributed, RESTful search and analytics engine capable of solving a growing number of use cases.
author: requarks.io
logo: https://static.requarks.io/logo/elasticsearch.svg
website: https://www.elastic.co/products/elasticsearch
isAvailable: true
props:
apiVersion:
type: String
title: Elasticsearch Version
hint: Should match the version of the Elasticsearch nodes you are connecting to
order: 1
enum:
- '7.x'
- '6.x'
default: '6.x'
hosts:
type: String
title: Host(s)
hint: Comma-separated list of Elasticsearch hosts to connect to, including the port, username and password if necessary. (e.g. http://localhost:9200, https://user:pass@es1.example.com:9200)
order: 2
indexName:
type: String
title: Index Name
hint: The index name to use during creation
default: wiki
order: 3
analyzer:
type: String
title: Analyzer
hint: 'The token analyzer in elasticsearch'
default: simple
order: 4
sniffOnStart:
type: Boolean
title: Sniff on start
hint: 'Should Wiki.js attempt to detect the rest of the cluster on first connect? (Default: off)'
default: false
order: 5
sniffInterval:
type: Number
title: Sniff Interval
hint: '0 = disabled, Interval in seconds to check for updated list of nodes in cluster. (Default: 0)'
default: 0
order: 6

@ -1,353 +0,0 @@
const _ = require('lodash')
const stream = require('stream')
const Promise = require('bluebird')
const pipeline = Promise.promisify(stream.pipeline)
/* global WIKI */
module.exports = {
async activate() {
// not used
},
async deactivate() {
// not used
},
/**
* INIT
*/
async init() {
WIKI.logger.info(`(SEARCH/ELASTICSEARCH) Initializing...`)
switch (this.config.apiVersion) {
case '7.x':
const { Client: Client7 } = require('elasticsearch7')
this.client = new Client7({
nodes: this.config.hosts.split(',').map(_.trim),
sniffOnStart: this.config.sniffOnStart,
sniffInterval: (this.config.sniffInterval > 0) ? this.config.sniffInterval : false,
name: 'wiki-js'
})
break
case '6.x':
const { Client: Client6 } = require('elasticsearch6')
this.client = new Client6({
nodes: this.config.hosts.split(',').map(_.trim),
sniffOnStart: this.config.sniffOnStart,
sniffInterval: (this.config.sniffInterval > 0) ? this.config.sniffInterval : false,
name: 'wiki-js'
})
break
default:
throw new Error('Unsupported version of elasticsearch! Update your settings in the Administration Area.')
}
// -> Create Search Index
await this.createIndex()
WIKI.logger.info(`(SEARCH/ELASTICSEARCH) Initialization completed.`)
},
/**
* Create Index
*/
async createIndex() {
try {
const indexExists = await this.client.indices.exists({ index: this.config.indexName })
if (!indexExists.body) {
WIKI.logger.info(`(SEARCH/ELASTICSEARCH) Creating index...`)
try {
const idxBody = {
properties: {
suggest: { type: 'completion' },
title: { type: 'text', boost: 10.0 },
description: { type: 'text', boost: 3.0 },
content: { type: 'text', boost: 1.0 },
locale: { type: 'keyword' },
path: { type: 'text' },
tags: { type: 'text', boost: 8.0 }
}
}
await this.client.indices.create({
index: this.config.indexName,
body: {
mappings: (this.config.apiVersion === '6.x') ? {
_doc: idxBody
} : idxBody,
settings: {
analysis: {
analyzer: {
default: {
type: this.config.analyzer
}
}
}
}
}
})
} catch (err) {
WIKI.logger.error(`(SEARCH/ELASTICSEARCH) Create Index Error: `, _.get(err, 'meta.body.error', err))
}
}
} catch (err) {
WIKI.logger.error(`(SEARCH/ELASTICSEARCH) Index Check Error: `, _.get(err, 'meta.body.error', err))
}
},
/**
* QUERY
*
* @param {String} q Query
* @param {Object} opts Additional options
*/
async query(q, opts) {
try {
const results = await this.client.search({
index: this.config.indexName,
body: {
query: {
simple_query_string: {
query: `*${q}*`,
fields: ['title^20', 'description^3', 'tags^8', 'content^1'],
default_operator: 'and',
analyze_wildcard: true
}
},
from: 0,
size: 50,
_source: ['title', 'description', 'path', 'locale'],
suggest: {
suggestions: {
text: q,
completion: {
field: 'suggest',
size: 5,
skip_duplicates: true,
fuzzy: true
}
}
}
}
})
return {
results: _.get(results, 'body.hits.hits', []).map(r => ({
id: r._id,
locale: r._source.locale,
path: r._source.path,
title: r._source.title,
description: r._source.description
})),
suggestions: _.reject(_.get(results, 'suggest.suggestions', []).map(s => _.get(s, 'options[0].text', false)), s => !s),
totalHits: _.get(results, 'body.hits.total.value', _.get(results, 'body.hits.total', 0))
}
} catch (err) {
WIKI.logger.warn('Search Engine Error: ', _.get(err, 'meta.body.error', err))
}
},
/**
* Build tags field
* @param id
* @returns {Promise<*|*[]>}
*/
async buildTags(id) {
const tags = await WIKI.models.pages.query().findById(id).select('*').withGraphJoined('tags')
return (tags.tags && tags.tags.length > 0) ? tags.tags.map(function (tag) {
return tag.title
}) : []
},
/**
* Build suggest field
*/
buildSuggest(page) {
return _.reject(_.uniq(_.concat(
page.title.split(' ').map(s => ({
input: s,
weight: 10
})),
page.description.split(' ').map(s => ({
input: s,
weight: 3
})),
page.safeContent.split(' ').map(s => ({
input: s,
weight: 1
}))
)), ['input', ''])
},
/**
* CREATE
*
* @param {Object} page Page to create
*/
async created(page) {
await this.client.index({
index: this.config.indexName,
type: '_doc',
id: page.hash,
body: {
suggest: this.buildSuggest(page),
locale: page.localeCode,
path: page.path,
title: page.title,
description: page.description,
content: page.safeContent,
tags: await this.buildTags(page.id)
},
refresh: true
})
},
/**
* UPDATE
*
* @param {Object} page Page to update
*/
async updated(page) {
await this.client.index({
index: this.config.indexName,
type: '_doc',
id: page.hash,
body: {
suggest: this.buildSuggest(page),
locale: page.localeCode,
path: page.path,
title: page.title,
description: page.description,
content: page.safeContent,
tags: await this.buildTags(page.id)
},
refresh: true
})
},
/**
* DELETE
*
* @param {Object} page Page to delete
*/
async deleted(page) {
await this.client.delete({
index: this.config.indexName,
type: '_doc',
id: page.hash,
refresh: true
})
},
/**
* RENAME
*
* @param {Object} page Page to rename
*/
async renamed(page) {
await this.client.delete({
index: this.config.indexName,
type: '_doc',
id: page.hash,
refresh: true
})
await this.client.index({
index: this.config.indexName,
type: '_doc',
id: page.destinationHash,
body: {
suggest: this.buildSuggest(page),
locale: page.destinationLocaleCode,
path: page.destinationPath,
title: page.title,
description: page.description,
content: page.safeContent,
tags: await this.buildTags(page.id)
},
refresh: true
})
},
/**
* REBUILD INDEX
*/
async rebuild() {
WIKI.logger.info(`(SEARCH/ELASTICSEARCH) Rebuilding Index...`)
await this.client.indices.delete({ index: this.config.indexName })
await this.createIndex()
const MAX_INDEXING_BYTES = 10 * Math.pow(2, 20) - Buffer.from('[').byteLength - Buffer.from(']').byteLength // 10 MB
const MAX_INDEXING_COUNT = 1000
const COMMA_BYTES = Buffer.from(',').byteLength
let chunks = []
let bytes = 0
const processDocument = async (cb, doc) => {
try {
if (doc) {
const docBytes = Buffer.from(JSON.stringify(doc)).byteLength
doc['tags'] = await this.buildTags(doc.realId)
// -> Current batch exceeds size limit, flush
if (docBytes + COMMA_BYTES + bytes >= MAX_INDEXING_BYTES) {
await flushBuffer()
}
if (chunks.length > 0) {
bytes += COMMA_BYTES
}
bytes += docBytes
chunks.push(doc)
// -> Current batch exceeds count limit, flush
if (chunks.length >= MAX_INDEXING_COUNT) {
await flushBuffer()
}
} else {
// -> End of stream, flush
await flushBuffer()
}
cb()
} catch (err) {
cb(err)
}
}
const flushBuffer = async () => {
WIKI.logger.info(`(SEARCH/ELASTICSEARCH) Sending batch of ${chunks.length}...`)
try {
await this.client.bulk({
index: this.config.indexName,
body: _.reduce(chunks, (result, doc) => {
result.push({
index: {
_index: this.config.indexName,
_type: '_doc',
_id: doc.id
}
})
doc.safeContent = WIKI.models.pages.cleanHTML(doc.render)
result.push({
suggest: this.buildSuggest(doc),
tags: doc.tags,
locale: doc.locale,
path: doc.path,
title: doc.title,
description: doc.description,
content: doc.safeContent
})
return result
}, []),
refresh: true
})
} catch (err) {
WIKI.logger.warn('(SEARCH/ELASTICSEARCH) Failed to send batch to elasticsearch: ', err)
}
chunks.length = 0
bytes = 0
}
// Added real id in order to fetch page tags from the query
await pipeline(
WIKI.models.knex.column({ id: 'hash' }, 'path', { locale: 'localeCode' }, 'title', 'description', 'render', { realId: 'id' }).select().from('pages').where({
isPublished: true,
isPrivate: false
}).stream(),
new stream.Transform({
objectMode: true,
transform: async (chunk, enc, cb) => processDocument(cb, chunk),
flush: async (cb) => processDocument(cb)
})
)
WIKI.logger.info(`(SEARCH/ELASTICSEARCH) Index rebuilt successfully.`)
}
}

@ -1,8 +0,0 @@
key: manticore
title: Manticore Search
description: High performance full-text search engine with SQL and JSON support.
author: requarks.io
logo: https://static.requarks.io/logo/manticore.svg
website: https://manticoresearch.com/
isAvailable: false
props: {}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save