Unverified Commit 10cc2ef4 authored by Nicolas Giard's avatar Nicolas Giard Committed by GitHub

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

parent 5c6ae08b
......@@ -129,6 +129,5 @@ bodyParserLimit: 5mb
scheduler:
# Maximum number of workers to run background cpu-intensive jobs.
# Make sure your PostgreSQL server can handle an extra connection
# for each worker!
workers: 3
# Leave 'auto' to use number of CPU cores as maximum.
workers: auto
......@@ -80,6 +80,7 @@ defaults:
maintainerEmail: security@requarks.io
jobs:
- task: background
identifier: purge-uploads
pattern: '*/15 * * * *'
payload:
name: purgeUploads
......
......@@ -10,7 +10,7 @@ const path = require('path')
const bruteforce = new ExpressBrute(new BruteKnex({
createTable: true,
knex: WIKI.models.knex
knex: WIKI.db.knex
}), {
freeRetries: 5,
minWait: 5 * 60 * 1000, // 5 minutes
......@@ -26,7 +26,7 @@ const bruteforce = new ExpressBrute(new BruteKnex({
router.get('/login', async (req, res, next) => {
// -> Bypass Login
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])
if (!stgInfo.useForm) {
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) => {
try {
await WIKI.models.users.login({
await WIKI.db.users.login({
strategy: req.params.strategy
}, { req, res })
} catch (err) {
......@@ -56,7 +56,7 @@ router.all('/login/:strategy/callback', async (req, res, next) => {
if (req.method !== 'GET' && req.method !== 'POST') { return next() }
try {
const authResult = await WIKI.models.users.login({
const authResult = await WIKI.db.users.login({
strategy: req.params.strategy
}, { req, res })
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
*/
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) => {
if (err) { return next(err) }
res.clearCookie('jwt')
......@@ -95,7 +95,7 @@ router.get('/logout', async (req, res, next) => {
*/
router.get('/register', async (req, res, next) => {
_.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) {
res.sendFile(path.join(WIKI.ROOTPATH, 'assets/index.html'))
} else {
......@@ -108,13 +108,13 @@ router.get('/register', async (req, res, next) => {
*/
router.get('/verify/:token', bruteforce.prevent, async (req, res, next) => {
try {
const usr = await WIKI.models.userKeys.validateToken({ kind: 'verify', token: req.params.token })
await WIKI.models.users.query().patch({ isVerified: true }).where('id', usr.id)
const usr = await WIKI.db.userKeys.validateToken({ kind: 'verify', token: req.params.token })
await WIKI.db.users.query().patch({ isVerified: true }).where('id', usr.id)
req.brute.reset()
if (WIKI.config.auth.enforce2FA) {
res.redirect('/login')
} 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.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) => {
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) {
throw new Error('Invalid Token')
}
req.brute.reset()
const changePwdContinuationToken = await WIKI.models.userKeys.generateToken({
const changePwdContinuationToken = await WIKI.db.userKeys.generateToken({
userId: usr.id,
kind: 'changePwd'
})
......
......@@ -6,8 +6,6 @@ const CleanCSS = require('clean-css')
const moment = require('moment')
const path = require('path')
/* global WIKI */
const tmplCreateRegex = /^[0-9]+(,[0-9]+)?$/
const siteAssetsPath = path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, 'assets')
......@@ -27,7 +25,7 @@ router.get('/robots.txt', (req, res, next) => {
* Health Endpoint
*/
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()
} else {
res.status(200).json({ ok: true }).end()
......@@ -38,7 +36,7 @@ router.get('/healthz', (req, res, next) => {
* Site Asset
*/
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) {
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 page = await WIKI.models.pages.getPageFromDb({
const page = await WIKI.db.pages.getPageFromDb({
path: pageArgs.path,
locale: pageArgs.locale,
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)
res.attachment(fileName)
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))
} else {
res.send(pageHelper.injectPageMetadata(page))
......@@ -176,7 +174,7 @@ router.get(['/_edit', '/_edit/*'], async (req, res, next) => {
}
// -> Get page data from DB
let page = await WIKI.models.pages.getPageFromDb({
let page = await WIKI.db.pages.getPageFromDb({
path: pageArgs.path,
locale: pageArgs.locale,
userId: req.user.id,
......@@ -255,7 +253,7 @@ router.get(['/_edit', '/_edit/*'], async (req, res, next) => {
if (tmplVersionId > 0) {
// -> 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) {
_.set(res.locals, 'pageMeta.title', 'Page Not Found')
return res.status(404).render('notfound', { action: 'template' })
......@@ -270,7 +268,7 @@ router.get(['/_edit', '/_edit/*'], async (req, res, next) => {
page.description = pageVersion.description
} else {
// -> From Page Live
const pageOriginal = await WIKI.models.pages.query().findById(tmplPageId)
const pageOriginal = await WIKI.db.pages.query().findById(tmplPageId)
if (!pageOriginal) {
_.set(res.locals, 'pageMeta.title', 'Page Not Found')
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.rtl', req.i18n.dir() === 'rtl')
const page = await WIKI.models.pages.getPageFromDb({
const page = await WIKI.db.pages.getPageFromDb({
path: pageArgs.path,
locale: pageArgs.locale,
userId: req.user.id,
......@@ -345,7 +343,7 @@ router.get(['/i', '/i/:id'], async (req, res, next) => {
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) {
_.set(res.locals, 'pageMeta.title', 'Page Not Found')
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 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,
locale: pageArgs.locale,
userId: req.user.id,
......@@ -410,7 +408,7 @@ router.get(['/s', '/s/*'], async (req, res, next) => {
if (page) {
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.description', pageVersion.description)
res.render('source', {
......@@ -446,7 +444,7 @@ router.get('/_userav/:uid', async (req, res, next) => {
if (!WIKI.auth.checkAccess(req.user, ['read:pages'])) {
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) {
res.set('Content-Type', 'image/jpeg')
res.send(av)
......@@ -472,7 +470,7 @@ router.get('/*', async (req, res, next) => {
try {
// -> Get Page from cache
const page = await WIKI.models.pages.getPage({
const page = await WIKI.db.pages.getPage({
path: pageArgs.path,
locale: pageArgs.locale,
userId: req.user.id
......@@ -519,7 +517,7 @@ router.get('/*', async (req, res, next) => {
// -> Build sidebar navigation
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++}`,
k: n.kind,
l: n.label,
......@@ -595,7 +593,7 @@ router.get('/*', async (req, res, next) => {
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 qs = require('querystring')
/* global WIKI */
/**
* Let's Encrypt Challenge
*/
......
......@@ -5,8 +5,6 @@ const multer = require('multer')
const path = require('path')
const sanitize = require('sanitize-filename')
/* global WIKI */
/**
* Upload files
*/
......@@ -66,7 +64,7 @@ router.post('/u', (req, res, next) => {
let hierarchy = []
if (folderId) {
try {
hierarchy = await WIKI.models.assetFolders.getHierarchy(folderId)
hierarchy = await WIKI.db.assetFolders.getHierarchy(folderId)
} catch (err) {
return res.status(400).json({
succeeded: false,
......@@ -88,7 +86,7 @@ router.post('/u', (req, res, next) => {
}
// Process upload file
await WIKI.models.assets.upload({
await WIKI.db.assets.upload({
...fileMeta,
mode: 'upload',
folderId: folderId,
......
const chalk = require('chalk')
const os = require('node:os')
/* global WIKI */
module.exports = () => {
WIKI.servers.ws.on('connection', (socket) => {
// TODO: Validate token + permissions
......
......@@ -3,8 +3,6 @@ const path = require('path')
const UINT64 = require('cuint').UINT64
const fs = require('fs')
/* global WIKI */
/**
* Based of express-serve-asar (https://github.com/toyobayashi/express-serve-asar)
* by Fenglin Li (https://github.com/toyobayashi)
......
......@@ -10,8 +10,6 @@ const pem2jwk = require('pem-jwk').pem2jwk
const securityHelper = require('../helpers/security')
/* global WIKI */
module.exports = {
strategies: {},
guest: {
......@@ -33,7 +31,7 @@ module.exports = {
passport.deserializeUser(async (id, done) => {
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')
})
if (user) {
......@@ -75,7 +73,7 @@ module.exports = {
}))
// 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) {
try {
const strategy = require(`../modules/authentication/${stg.module}/authentication.js`)
......@@ -144,7 +142,7 @@ module.exports = {
if (mustRevalidate) {
const jwtPayload = jwt.decode(securityHelper.extractJWT(req))
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.permissions = user.getPermissions()
user.groups = user.getGroups()
......@@ -162,7 +160,7 @@ module.exports = {
return next()
}
} else if (user) {
user = await WIKI.models.users.getById(user.id)
user = await WIKI.db.users.getById(user.id)
user.permissions = user.getPermissions()
user.groups = user.getGroups()
user.strategyId = strategyId
......@@ -170,7 +168,7 @@ module.exports = {
} else {
// JWT is NOT valid, set as guest
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 })
}
req.user = WIKI.auth.guest
......@@ -349,7 +347,7 @@ module.exports = {
* Reload Groups from DB
*/
async reloadGroups () {
const groupsArray = await WIKI.models.groups.query()
const groupsArray = await WIKI.db.groups.query()
this.groups = _.keyBy(groupsArray, 'id')
WIKI.auth.guest.cacheExpiration = DateTime.utc().minus({ days: 1 })
},
......@@ -358,7 +356,7 @@ module.exports = {
* Reload valid API Keys from DB
*/
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')
},
......@@ -405,14 +403,14 @@ module.exports = {
*/
async resetGuestUser() {
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',
email: 'guest@example.com'
}).orWhere('id', 2)
const guestUser = await WIKI.models.users.query().insert({
const guestUser = await WIKI.db.users.query().insert({
id: 2,
provider: 'local',
email: 'guest@example.com',
......
......@@ -5,8 +5,6 @@ const fs = require('fs')
const path = require('path')
const yaml = require('js-yaml')
/* global WIKI */
module.exports = {
/**
* Load root config from disk
......@@ -52,10 +50,18 @@ module.exports = {
appconfig = _.defaultsDeep(appconfig, appdata.defaults.config)
// Override port
if (appconfig.port < 1 || process.env.HEROKU) {
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'))
// Load DB Password from Docker Secret File
......@@ -81,12 +87,12 @@ module.exports = {
* Load config from DB
*/
async loadFromDb() {
let conf = await WIKI.models.settings.getConfig()
let conf = await WIKI.db.settings.getConfig()
if (conf) {
WIKI.config = _.defaultsDeep(conf, WIKI.config)
} else {
WIKI.logger.warn('DB Configuration is empty or incomplete. Switching to Setup mode...')
WIKI.config.setup = true
WIKI.logger.warn('Missing DB Configuration!')
process.exit(1)
}
},
/**
......@@ -102,9 +108,9 @@ module.exports = {
if (!_.isPlainObject(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) {
await WIKI.models.settings.query().insert({ key, value })
await WIKI.db.settings.query().insert({ key, value })
}
}
if (propagate) {
......@@ -121,7 +127,7 @@ module.exports = {
* Apply Dev Flags
*/
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 migrateFromLegacy = require('../db/legacy')
/* global WIKI */
/**
* 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
this.onReady = Promise.each(initTasksQueue, t => t()).return(true)
this.onReady = (async () => {
await initTasks.connect()
await initTasks.migrateFromLegacy()
await initTasks.syncSchemas()
})()
return {
...this,
......@@ -187,7 +181,7 @@ module.exports = {
WIKI.auth.subscribeToEvents()
WIKI.configSvc.subscribeToEvents()
WIKI.models.pages.subscribeToEvents()
WIKI.db.pages.subscribeToEvents()
WIKI.logger.info(`PG PubSub Listener initialized successfully: [ OK ]`)
},
......@@ -208,7 +202,7 @@ module.exports = {
* @param {object} value Payload of the event
*/
notifyViaDB (event, value) {
WIKI.models.listener.publish('wiki', {
WIKI.db.listener.publish('wiki', {
source: WIKI.INSTANCE_ID,
event,
value
......
const fs = require('fs-extra')
const path = require('path')
/* global WIKI */
module.exports = {
ext: {},
async init () {
......
......@@ -3,8 +3,6 @@ const EventEmitter = require('eventemitter2').EventEmitter2
let isShuttingDown = false
/* global WIKI */
module.exports = {
async init() {
WIKI.logger.info('=======================================')
......@@ -12,10 +10,10 @@ module.exports = {
WIKI.logger.info('=======================================')
WIKI.logger.info('Initializing...')
WIKI.models = require('./db').init()
WIKI.db = require('./db').init()
try {
await WIKI.models.onReady
await WIKI.db.onReady
await WIKI.configSvc.loadFromDb()
await WIKI.configSvc.applyFlags()
} catch (err) {
......@@ -64,21 +62,21 @@ module.exports = {
* Post-Web Boot Sequence
*/
async postBootWeb() {
await WIKI.models.analytics.refreshProvidersFromDisk()
await WIKI.models.authentication.refreshStrategiesFromDisk()
await WIKI.models.commentProviders.refreshProvidersFromDisk()
await WIKI.models.renderers.refreshRenderersFromDisk()
await WIKI.models.storage.refreshTargetsFromDisk()
await WIKI.db.analytics.refreshProvidersFromDisk()
await WIKI.db.authentication.refreshStrategiesFromDisk()
await WIKI.db.commentProviders.refreshProvidersFromDisk()
await WIKI.db.renderers.refreshRenderersFromDisk()
await WIKI.db.storage.refreshTargetsFromDisk()
await WIKI.extensions.init()
await WIKI.auth.activateStrategies()
await WIKI.models.commentProviders.initProvider()
await WIKI.models.sites.reloadCache()
await WIKI.models.storage.initTargets()
await WIKI.db.commentProviders.initProvider()
await WIKI.db.sites.reloadCache()
await WIKI.db.storage.initTargets()
await WIKI.scheduler.start()
await WIKI.models.subscribeToNotifications()
await WIKI.db.subscribeToNotifications()
},
/**
* Graceful shutdown
......@@ -93,9 +91,9 @@ module.exports = {
await WIKI.scheduler.stop()
}
if (WIKI.models) {
await WIKI.models.unsubscribeToNotifications()
if (WIKI.models.knex) {
await WIKI.models.knex.destroy()
await WIKI.db.unsubscribeToNotifications()
if (WIKI.db.knex) {
await WIKI.db.knex.destroy()
}
}
if (WIKI.asar) {
......
......@@ -6,8 +6,6 @@ const CSR = require('@root/csr')
const PEM = require('@root/pem')
const punycode = require('punycode/')
/* global WIKI */
module.exports = {
apiDirectory: WIKI.dev ? 'https://acme-staging-v02.api.letsencrypt.org/directory' : 'https://acme-v02.api.letsencrypt.org/directory',
acme: null,
......
const chalk = require('chalk')
const EventEmitter = require('events')
/* global WIKI */
const LEVELS = ['error', 'warn', 'info', 'debug']
const LEVELSIGNORED = ['verbose', 'silly']
const LEVELCOLORS = {
......
......@@ -3,8 +3,6 @@ const _ = require('lodash')
const fs = require('fs-extra')
const path = require('path')
/* global WIKI */
module.exports = {
transport: null,
templates: {},
......
const { run, parseCronItems, Logger } = require('graphile-worker')
const { Pool } = require('pg')
const { DynamicThreadPool } = require('poolifier')
const { v4: uuid } = require('uuid')
const os = require('node:os')
......@@ -21,49 +19,46 @@ module.exports = {
},
async start () {
WIKI.logger.info('Starting Scheduler...')
this.runner = await run({
pgPool: new Pool({
...(typeof WIKI.models.config === 'string') ? {
connectionString: WIKI.models.config
} : WIKI.models.config,
max: this.maxWorkers + 2
}),
schema: WIKI.config.db.schemas.scheduler,
concurrency: this.maxWorkers,
noHandleSignals: true,
logger: new Logger(scope => {
return (level, message, meta) => {
const prefix = (scope?.workerId) ? `[${scope.workerId}] ` : ''
WIKI.logger[level](`${prefix}${message}`, meta)
}
}),
parsedCronItems: parseCronItems(WIKI.data.jobs.map(j => ({
...j,
identifier: uuid()
}))),
taskList: {
simple: async (payload, helpers) => {
// TODO: Handle task
},
background: async (payload, helpers) => {
try {
await this.pool.execute({
id: helpers.job.id,
name: payload.name,
data: payload.data
})
} catch (err) {
helpers.logger.warn(`Failed job: ${err.message}`)
throw err
}
}
}
})
// this.runner = await run({
// pgPool: new Pool({
// ...(typeof WIKI.db.config === 'string') ? {
// connectionString: WIKI.db.config
// } : WIKI.db.config,
// max: this.maxWorkers + 2
// }),
// schema: WIKI.config.db.schemas.scheduler,
// concurrency: this.maxWorkers,
// noHandleSignals: true,
// logger: new Logger(scope => {
// return (level, message, meta) => {
// const prefix = (scope?.workerId) ? `[${scope.workerId}] ` : ''
// WIKI.logger[level](`${prefix}${message}`, meta)
// }
// }),
// parsedCronItems: parseCronItems(WIKI.data.jobs),
// taskList: {
// simple: async (payload, helpers) => {
// // TODO: Handle task
// },
// background: async (payload, helpers) => {
// try {
// await this.pool.execute({
// id: helpers.job.id,
// name: payload.name,
// data: payload.data
// })
// } catch (err) {
// helpers.logger.warn(`Failed job: ${err.message}`)
// throw err
// }
// }
// }
// })
WIKI.logger.info('Scheduler: [ STARTED ]')
},
async stop () {
WIKI.logger.info('Stopping Scheduler...')
await this.runner.stop()
// await this.runner.stop()
WIKI.logger.info('Scheduler: [ STOPPED ]')
}
}
......@@ -8,8 +8,6 @@ const io = require('socket.io')
const { ApolloServerPluginLandingPageGraphQLPlayground, ApolloServerPluginLandingPageProductionDefault } = require('apollo-server-core')
const { graphqlUploadExpress } = require('graphql-upload')
/* global WIKI */
module.exports = {
graph: null,
http: null,
......
......@@ -2,8 +2,6 @@ const fs = require('fs-extra')
const path = require('path')
const _ = require('lodash')
/* global WIKI */
module.exports = {
async init () {
if (!WIKI.config.offline) {
......@@ -45,9 +43,9 @@ module.exports = {
_.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) {
await WIKI.models.locales.query().update({
await WIKI.db.locales.query().update({
code: locale.code,
strings: lcObj,
isRTL: locale.isRTL,
......@@ -55,7 +53,7 @@ module.exports = {
nativeName: locale.nativeName
}).where('code', locale.code)
} else {
await WIKI.models.locales.query().insert({
await WIKI.db.locales.query().insert({
code: locale.code,
strings: lcObj,
isRTL: locale.isRTL,
......
const fs = require('fs-extra')
const path = require('path')
/* global WIKI */
module.exports = {
updates: {
channel: 'BETA',
......
const _ = require('lodash')
/* global WIKI */
module.exports = {
async migrate (knex) {
const migrationsTableExists = await knex.schema.hasTable('migrations')
......
......@@ -3,8 +3,6 @@ const bcrypt = require('bcryptjs-then')
const crypto = require('crypto')
const pem2jwk = require('pem-jwk').pem2jwk
/* global WIKI */
exports.up = async knex => {
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('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 -----------------------------
.createTable('locales', table => {
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.')
}
......
......@@ -4,8 +4,6 @@ const semver = require('semver')
const baseMigrationPath = path.join(WIKI.SERVERPATH, 'db/migrations')
/* global WIKI */
module.exports = {
/**
* Gets the migration names
......
......@@ -6,8 +6,6 @@ const { makeExecutableSchema } = require('@graphql-tools/schema')
const { defaultKeyGenerator, rateLimitDirective } = require('graphql-rate-limit-directive')
const { GraphQLUpload } = require('graphql-upload')
/* global WIKI */
// Rate Limiter
const { rateLimitDirectiveTypeDefs, rateLimitDirectiveTransformer } = rateLimitDirective({
......
const _ = require('lodash')
const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = {
Query: {
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 => {
const providerInfo = _.find(WIKI.data.analytics, ['key', stg.key]) || {}
return {
......@@ -31,7 +29,7 @@ module.exports = {
async updateAnalyticsProviders(obj, args, context) {
try {
for (let str of args.providers) {
await WIKI.models.analytics.query().patch({
await WIKI.db.analytics.query().patch({
isEnabled: str.isEnabled,
config: _.reduce(str.config, (result, value, key) => {
_.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 assetHelper = require('../../helpers/asset')
/* global WIKI */
module.exports = {
Query: {
async assets(obj, args, context) {
......@@ -14,9 +12,9 @@ module.exports = {
if (args.kind !== 'ALL') {
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 results = await WIKI.models.assets.query().where(cond)
const results = await WIKI.db.assets.query().where(cond)
return _.filter(results, r => {
const path = folderPath ? `${folderPath}/${r.filename}` : r.filename
return WIKI.auth.checkAccess(context.req.user, ['read:assets'], { path })
......@@ -26,10 +24,10 @@ module.exports = {
}))
},
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
})
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('/')
return _.filter(results, r => {
const path = parentPath ? `${parentPath}/${r.slug}` : r.slug
......@@ -45,12 +43,12 @@ module.exports = {
try {
const folderSlug = sanitize(args.slug).toLowerCase()
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,
slug: folderSlug
}).first()
if (!result) {
await WIKI.models.assetFolders.query().insert({
await WIKI.db.assetFolders.query().insert({
slug: folderSlug,
name: folderSlug,
parentId: parentFolderId
......@@ -72,7 +70,7 @@ module.exports = {
try {
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) {
// Check for extension mismatch
if (!_.endsWith(filename, asset.ext)) {
......@@ -85,7 +83,7 @@ module.exports = {
}
// Check for collision
const assetCollision = await WIKI.models.assets.query().where({
const assetCollision = await WIKI.db.assets.query().where({
filename,
folderId: asset.folderId
}).first()
......@@ -96,7 +94,7 @@ module.exports = {
// Get asset folder path
let hierarchy = []
if (asset.folderId) {
hierarchy = await WIKI.models.assetFolders.getHierarchy(asset.folderId)
hierarchy = await WIKI.db.assetFolders.getHierarchy(asset.folderId)
}
// Check source asset permissions
......@@ -113,7 +111,7 @@ module.exports = {
// Update filename + hash
const fileHash = assetHelper.generateHash(assetTargetPath)
await WIKI.models.assets.query().patch({
await WIKI.db.assets.query().patch({
filename: filename,
hash: fileHash
}).findById(args.id)
......@@ -122,7 +120,7 @@ module.exports = {
await asset.deleteAssetCache()
// Rename in Storage
await WIKI.models.storage.assetEvent({
await WIKI.db.storage.assetEvent({
event: 'renamed',
asset: {
...asset,
......@@ -149,7 +147,7 @@ module.exports = {
*/
async deleteAsset(obj, args, context) {
try {
const asset = await WIKI.models.assets.query().findById(args.id)
const asset = await WIKI.db.assets.query().findById(args.id)
if (asset) {
// Check permissions
const assetPath = await asset.getAssetPath()
......@@ -157,12 +155,12 @@ module.exports = {
throw new WIKI.Error.AssetDeleteForbidden()
}
await WIKI.models.knex('assetData').where('id', args.id).del()
await WIKI.models.assets.query().deleteById(args.id)
await WIKI.db.knex('assetData').where('id', args.id).del()
await WIKI.db.assets.query().deleteById(args.id)
await asset.deleteAssetCache()
// Delete from Storage
await WIKI.models.storage.assetEvent({
await WIKI.db.storage.assetEvent({
event: 'deleted',
asset: {
...asset,
......@@ -188,7 +186,7 @@ module.exports = {
*/
async flushTempUploads(obj, args, context) {
try {
await WIKI.models.assets.flushTempUploads()
await WIKI.db.assets.flushTempUploads()
return {
responseResult: graphHelper.generateSuccess('Temporary Uploads have been flushed successfully.')
}
......
const _ = require('lodash')
const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = {
Query: {
/**
* List of API Keys
*/
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 => ({
id: k.id,
name: k.name,
......@@ -39,14 +37,14 @@ module.exports = {
* Fetch active authentication strategies
*/
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
*/
async authSiteStrategies (obj, args, context, info) {
const site = await WIKI.models.sites.query().findById(args.siteId)
const activeStrategies = await WIKI.models.authentication.getStrategies({ enabledOnly: true })
const site = await WIKI.db.sites.query().findById(args.siteId)
const activeStrategies = await WIKI.db.authentication.getStrategies({ enabledOnly: true })
return activeStrategies.map(str => {
const siteAuth = _.find(site.config.authStrategies, ['id', str.id]) || {}
return {
......@@ -64,7 +62,7 @@ module.exports = {
*/
async createApiKey (obj, args, context) {
try {
const key = await WIKI.models.apiKeys.createNewKey(args)
const key = await WIKI.db.apiKeys.createNewKey(args)
await WIKI.auth.reloadApiKeys()
WIKI.events.outbound.emit('reloadApiKeys')
return {
......@@ -81,7 +79,7 @@ module.exports = {
*/
async login (obj, args, context) {
try {
const authResult = await WIKI.models.users.login(args, context)
const authResult = await WIKI.db.users.login(args, context)
return {
...authResult,
operation: graphHelper.generateSuccess('Login success')
......@@ -101,7 +99,7 @@ module.exports = {
*/
async loginTFA (obj, args, context) {
try {
const authResult = await WIKI.models.users.loginTFA(args, context)
const authResult = await WIKI.db.users.loginTFA(args, context)
return {
...authResult,
responseResult: graphHelper.generateSuccess('TFA success')
......@@ -115,7 +113,7 @@ module.exports = {
*/
async changePassword (obj, args, context) {
try {
const authResult = await WIKI.models.users.loginChangePassword(args, context)
const authResult = await WIKI.db.users.loginChangePassword(args, context)
return {
...authResult,
responseResult: graphHelper.generateSuccess('Password changed successfully')
......@@ -129,7 +127,7 @@ module.exports = {
*/
async forgotPassword (obj, args, context) {
try {
await WIKI.models.users.loginForgotPassword(args, context)
await WIKI.db.users.loginForgotPassword(args, context)
return {
responseResult: graphHelper.generateSuccess('Password reset request processed.')
}
......@@ -142,7 +140,7 @@ module.exports = {
*/
async register (obj, args, context) {
try {
await WIKI.models.users.register({ ...args, verify: true }, context)
await WIKI.db.users.register({ ...args, verify: true }, context)
return {
responseResult: graphHelper.generateSuccess('Registration success')
}
......@@ -169,7 +167,7 @@ module.exports = {
*/
async revokeApiKey (obj, args, context) {
try {
await WIKI.models.apiKeys.query().findById(args.id).patch({
await WIKI.db.apiKeys.query().findById(args.id).patch({
isRevoked: true
})
await WIKI.auth.reloadApiKeys()
......@@ -186,7 +184,7 @@ module.exports = {
*/
async updateAuthStrategies (obj, args, context) {
try {
const previousStrategies = await WIKI.models.authentication.getStrategies()
const previousStrategies = await WIKI.db.authentication.getStrategies()
for (const str of args.strategies) {
const newStr = {
displayName: str.displayName,
......@@ -202,13 +200,13 @@ module.exports = {
}
if (_.some(previousStrategies, ['key', str.key])) {
await WIKI.models.authentication.query().patch({
await WIKI.db.authentication.query().patch({
key: str.key,
strategyKey: str.strategyKey,
...newStr
}).where('key', str.key)
} else {
await WIKI.models.authentication.query().insert({
await WIKI.db.authentication.query().insert({
key: str.key,
strategyKey: str.strategyKey,
...newStr
......@@ -217,11 +215,11 @@ module.exports = {
}
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) {
throw new Error(`Cannot delete ${str.displayName} as 1 or more users are still using it.`)
} else {
await WIKI.models.authentication.query().delete().where('key', str.key)
await WIKI.db.authentication.query().delete().where('key', str.key)
}
}
......
const _ = require('lodash')
const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = {
Query: {
/**
* Fetch list of Comments Providers
*/
async commentsProviders(obj, args, context, info) {
const providers = await WIKI.models.commentProviders.getProviders()
const providers = await WIKI.db.commentProviders.getProviders()
return providers.map(provider => {
const providerInfo = _.find(WIKI.data.commentProviders, ['key', provider.key]) || {}
return {
......@@ -34,10 +32,10 @@ module.exports = {
* Fetch list of comments for a page
*/
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 (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 => ({
...c,
authorName: c.name,
......@@ -59,7 +57,7 @@ module.exports = {
if (!cm || !cm.pageId) {
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 (WIKI.auth.checkAccess(context.req.user, ['read:comments'], {
path: page.path,
......@@ -86,7 +84,7 @@ module.exports = {
*/
async createComment (obj, args, context) {
try {
const cmId = await WIKI.models.comments.postNewComment({
const cmId = await WIKI.db.comments.postNewComment({
...args,
user: context.req.user,
ip: context.req.ip
......@@ -104,7 +102,7 @@ module.exports = {
*/
async updateComment (obj, args, context) {
try {
const cmRender = await WIKI.models.comments.updateComment({
const cmRender = await WIKI.db.comments.updateComment({
...args,
user: context.req.user,
ip: context.req.ip
......@@ -122,7 +120,7 @@ module.exports = {
*/
async deleteComment (obj, args, context) {
try {
await WIKI.models.comments.deleteComment({
await WIKI.db.comments.deleteComment({
id: args.id,
user: context.req.user,
ip: context.req.ip
......@@ -140,7 +138,7 @@ module.exports = {
async updateCommentsProviders(obj, args, context) {
try {
for (let provider of args.providers) {
await WIKI.models.commentProviders.query().patch({
await WIKI.db.commentProviders.query().patch({
isEnabled: provider.isEnabled,
config: _.reduce(provider.config, (result, value, key) => {
_.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null))
......@@ -148,7 +146,7 @@ module.exports = {
}, {})
}).where('key', provider.key)
}
await WIKI.models.commentProviders.initProvider()
await WIKI.db.commentProviders.initProvider()
return {
responseResult: graphHelper.generateSuccess('Comment Providers updated successfully')
}
......
......@@ -3,24 +3,22 @@ const safeRegex = require('safe-regex')
const _ = require('lodash')
const { v4: uuid } = require('uuid')
/* global WIKI */
module.exports = {
Query: {
/**
* FETCH ALL GROUPS
*/
async groups () {
return WIKI.models.groups.query().select(
return WIKI.db.groups.query().select(
'groups.*',
WIKI.models.groups.relatedQuery('users').count().as('userCount')
WIKI.db.groups.relatedQuery('users').count().as('userCount')
)
},
/**
* FETCH A SINGLE GROUP
*/
async groupById(obj, args) {
return WIKI.models.groups.query().findById(args.id)
return WIKI.db.groups.query().findById(args.id)
}
},
Mutation: {
......@@ -34,7 +32,7 @@ module.exports = {
}
// 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) {
throw new Error('Invalid Group ID')
}
......@@ -51,13 +49,13 @@ module.exports = {
}
// 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) {
throw new Error('Invalid User ID')
}
// Check for existing relation
const relExist = await WIKI.models.knex('userGroups').where({
const relExist = await WIKI.db.knex('userGroups').where({
userId: args.userId,
groupId: args.groupId
}).first()
......@@ -80,7 +78,7 @@ module.exports = {
* CREATE NEW GROUP
*/
async createGroup (obj, args, { req }) {
const group = await WIKI.models.groups.query().insertAndFetch({
const group = await WIKI.db.groups.query().insertAndFetch({
name: args.name,
permissions: JSON.stringify(WIKI.data.groups.defaultPermissions),
rules: JSON.stringify(WIKI.data.groups.defaultRules.map(r => ({
......@@ -104,7 +102,7 @@ module.exports = {
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.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'g' })
......@@ -126,11 +124,11 @@ module.exports = {
if (args.userId === 1 && args.groupId === 1) {
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) {
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) {
throw new Error('Invalid User ID')
}
......@@ -179,7 +177,7 @@ module.exports = {
}
// Update group
await WIKI.models.groups.query().patch({
await WIKI.db.groups.query().patch({
name: args.name,
redirectOnLogin: args.redirectOnLogin,
permissions: JSON.stringify(args.permissions),
......
const graphHelper = require('../../helpers/graph')
const _ = require('lodash')
/* global WIKI */
module.exports = {
Query: {
async hooks () {
return WIKI.models.hooks.query().orderBy('name')
return WIKI.db.hooks.query().orderBy('name')
},
async hookById (obj, args) {
return WIKI.models.hooks.query().findById(args.id)
return WIKI.db.hooks.query().findById(args.id)
}
},
Mutation: {
......@@ -29,7 +27,7 @@ module.exports = {
throw new WIKI.Error.Custom('HookCreateInvalidURL', 'Invalid Hook URL')
}
// -> 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.`)
return {
......@@ -46,7 +44,7 @@ module.exports = {
async updateHook (obj, args) {
try {
// -> Load hook
const hook = await WIKI.models.hooks.query().findById(args.id)
const hook = await WIKI.db.hooks.query().findById(args.id)
if (!hook) {
throw new WIKI.Error.Custom('HookInvalidId', 'Invalid Hook ID')
}
......@@ -61,7 +59,7 @@ module.exports = {
throw new WIKI.Error.Custom('HookInvalidURL', 'URL is invalid.')
}
// -> 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.`)
return {
......@@ -76,7 +74,7 @@ module.exports = {
*/
async deleteHook (obj, args) {
try {
await WIKI.models.hooks.deleteHook(args.id)
await WIKI.db.hooks.deleteHook(args.id)
WIKI.logger.debug(`Hook ${args.id} deleted successfully.`)
return {
operation: graphHelper.generateSuccess('Hook deleted successfully')
......
const graphHelper = require('../../helpers/graph')
const _ = require('lodash')
/* global WIKI */
module.exports = {
Query: {
async locales(obj, args, context, info) {
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
return _.map(remoteLocales, rl => {
let isInstalled = _.some(localLocales, ['code', rl.code])
......@@ -44,7 +42,7 @@ module.exports = {
WIKI.config.lang.namespacing = args.namespacing
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
await WIKI.configSvc.saveToDb(['lang'])
......
const _ = require('lodash')
const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = {
Query: {
async mailConfig(obj, args, context, info) {
......
const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = {
Query: {
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) {
return WIKI.config.nav
......@@ -14,7 +12,7 @@ module.exports = {
Mutation: {
async updateNavigationTree (obj, args, context) {
try {
await WIKI.models.navigation.query().patch({
await WIKI.db.navigation.query().patch({
config: args.tree
}).where('key', 'site')
for (const tree of args.tree) {
......
const _ = require('lodash')
const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = {
Query: {
async renderers(obj, args, context, info) {
let renderers = await WIKI.models.renderers.getRenderers()
let renderers = await WIKI.db.renderers.getRenderers()
renderers = renderers.map(rdr => {
const rendererInfo = _.find(WIKI.data.renderers, ['key', rdr.key]) || {}
return {
......@@ -35,7 +33,7 @@ module.exports = {
async updateRenderers(obj, args, context) {
try {
for (let rdr of args.renderers) {
await WIKI.models.renderers.query().patch({
await WIKI.db.renderers.query().patch({
isEnabled: rdr.isEnabled,
config: _.reduce(rdr.config, (result, value, key) => {
_.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null))
......
const graphHelper = require('../../helpers/graph')
/* global WIKI */
module.exports = {
Mutation: {
async rebuildSearchIndex (obj, args, context) {
......
......@@ -5,12 +5,10 @@ const path = require('path')
const fs = require('fs-extra')
const { v4: uuid } = require('uuid')
/* global WIKI */
module.exports = {
Query: {
async sites () {
const sites = await WIKI.models.sites.query().orderBy('hostname')
const sites = await WIKI.db.sites.query().orderBy('hostname')
return sites.map(s => ({
...s.config,
id: s.id,
......@@ -20,7 +18,7 @@ module.exports = {
}))
},
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 ? {
...site.config,
id: site.id,
......@@ -30,11 +28,11 @@ module.exports = {
} : null
},
async siteByHostname (obj, args) {
let site = await WIKI.models.sites.query().where({
let site = await WIKI.db.sites.query().where({
hostname: args.hostname
}).first()
if (!site && !args.exact) {
site = await WIKI.models.sites.query().where({
site = await WIKI.db.sites.query().where({
hostname: '*'
}).first()
}
......@@ -62,7 +60,7 @@ module.exports = {
}
// -> Check for duplicate catch-all
if (args.hostname === '*') {
const site = await WIKI.models.sites.query().where({
const site = await WIKI.db.sites.query().where({
hostname: args.hostname
}).first()
if (site) {
......@@ -70,7 +68,7 @@ module.exports = {
}
}
// -> Create site
const newSite = await WIKI.models.sites.createSite(args.hostname, {
const newSite = await WIKI.db.sites.createSite(args.hostname, {
title: args.title
})
return {
......@@ -88,7 +86,7 @@ module.exports = {
async updateSite (obj, args) {
try {
// -> Load site
const site = await WIKI.models.sites.query().findById(args.id)
const site = await WIKI.db.sites.query().findById(args.id)
if (!site) {
throw new WIKI.Error.Custom('SiteInvalidId', 'Invalid Site ID')
}
......@@ -98,7 +96,7 @@ module.exports = {
}
// -> Check for duplicate catch-all
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) {
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)
}
// -> Update site
await WIKI.models.sites.updateSite(args.id, {
await WIKI.db.sites.updateSite(args.id, {
hostname: args.patch.hostname ?? site.hostname,
isEnabled: args.patch.isEnabled ?? site.isEnabled,
config: _.defaultsDeep(_.omit(args.patch, ['hostname', 'isEnabled']), site.config)
......@@ -132,12 +130,12 @@ module.exports = {
async deleteSite (obj, args) {
try {
// -> 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) {
throw new WIKI.Error.Custom('SiteDeleteLastSite', 'Cannot delete the last site. At least 1 site must exists at all times.')
}
// -> Delete site
await WIKI.models.sites.deleteSite(args.id)
await WIKI.db.sites.deleteSite(args.id)
return {
operation: graphHelper.generateSuccess('Site deleted successfully')
}
......@@ -175,16 +173,16 @@ module.exports = {
height: 72
})
// -> 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) {
site.config.assets.logo = uuid()
}
site.config.assets.logoExt = destFormat
await WIKI.models.sites.query().findById(args.id).patch({ config: site.config })
await WIKI.models.sites.reloadCache()
await WIKI.db.sites.query().findById(args.id).patch({ config: site.config })
await WIKI.db.sites.reloadCache()
// -> Save image data to DB
const imgBuffer = await fs.readFile(destPath)
await WIKI.models.knex('assetData').insert({
await WIKI.db.knex('assetData').insert({
id: site.config.assets.logo,
data: imgBuffer
}).onConflict('id').merge()
......@@ -227,16 +225,16 @@ module.exports = {
height: 64
})
// -> 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) {
site.config.assets.favicon = uuid()
}
site.config.assets.faviconExt = destFormat
await WIKI.models.sites.query().findById(args.id).patch({ config: site.config })
await WIKI.models.sites.reloadCache()
await WIKI.db.sites.query().findById(args.id).patch({ config: site.config })
await WIKI.db.sites.reloadCache()
// -> Save image data to DB
const imgBuffer = await fs.readFile(destPath)
await WIKI.models.knex('assetData').insert({
await WIKI.db.knex('assetData').insert({
id: site.config.assets.favicon,
data: imgBuffer
}).onConflict('id').merge()
......@@ -277,15 +275,15 @@ module.exports = {
width: 1920
})
// -> 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) {
site.config.assets.loginBg = uuid()
await WIKI.models.sites.query().findById(args.id).patch({ config: site.config })
await WIKI.models.sites.reloadCache()
await WIKI.db.sites.query().findById(args.id).patch({ config: site.config })
await WIKI.db.sites.reloadCache()
}
// -> Save image data to DB
const imgBuffer = await fs.readFile(destPath)
await WIKI.models.knex('assetData').insert({
await WIKI.db.knex('assetData').insert({
id: site.config.assets.loginBg,
data: imgBuffer
}).onConflict('id').merge()
......
......@@ -2,12 +2,10 @@ const _ = require('lodash')
const graphHelper = require('../../helpers/graph')
const { v4: uuid } = require('uuid')
/* global WIKI */
module.exports = {
Query: {
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 => {
// const targetInfo = _.find(WIKI.data.storage, ['module', tgt.key]) || {}
// return {
......@@ -101,7 +99,7 @@ module.exports = {
async updateStorageTargets (obj, args, context) {
WIKI.logger.debug(`Updating storage targets for site ${args.siteId}...`)
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) {
const md = _.find(WIKI.storage.defs, ['key', tgt.module])
if (!md) {
......@@ -124,7 +122,7 @@ module.exports = {
// -> Target doesn't exist yet in the DB, let's create it
if (!dbTarget) {
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,
module: tgt.module,
siteId: args.siteId,
......@@ -147,7 +145,7 @@ module.exports = {
})
} else {
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,
contentTypes: {
activeTypes: tgt.contentTypes ?? dbTarget?.contentTypes?.activeTypes ?? [],
......@@ -164,7 +162,7 @@ module.exports = {
}).where('id', tgt.id)
}
}
// await WIKI.models.storage.initTargets()
// await WIKI.db.storage.initTargets()
return {
status: graphHelper.generateSuccess('Storage targets updated successfully')
}
......@@ -174,7 +172,7 @@ module.exports = {
},
async setupStorageTarget (obj, args, context) {
try {
const tgt = await WIKI.models.storage.query().findById(args.targetId)
const tgt = await WIKI.db.storage.query().findById(args.targetId)
if (!tgt) {
throw new Error('Not storage target matching this ID')
}
......@@ -182,7 +180,7 @@ module.exports = {
if (!md) {
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.')
}
const result = await WIKI.storage.modules[md.key].setup(args.targetId, args.state)
......@@ -197,7 +195,7 @@ module.exports = {
},
async destroyStorageTargetSetup (obj, args, context) {
try {
const tgt = await WIKI.models.storage.query().findById(args.targetId)
const tgt = await WIKI.db.storage.query().findById(args.targetId)
if (!tgt) {
throw new Error('Not storage target matching this ID')
}
......@@ -205,7 +203,7 @@ module.exports = {
if (!md) {
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.')
}
await WIKI.storage.modules[md.key].setupDestroy(args.targetId)
......@@ -219,7 +217,7 @@ module.exports = {
},
async executeStorageAction (obj, args, context) {
try {
await WIKI.models.storage.executeAction(args.targetKey, args.handler)
await WIKI.db.storage.executeAction(args.targetKey, args.handler)
return {
status: graphHelper.generateSuccess('Action completed.')
}
......
......@@ -9,8 +9,6 @@ const { DateTime } = require('luxon')
const graphHelper = require('../../helpers/graph')
const cronParser = require('cron-parser')
/* global WIKI */
module.exports = {
Query: {
systemFlags () {
......@@ -183,19 +181,19 @@ module.exports = {
return process.cwd()
},
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)
},
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)
},
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)
},
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)
}
}
......
const graphHelper = require('../../helpers/graph')
const _ = require('lodash')
/* global WIKI */
module.exports = {
Query: {
/**
......@@ -22,7 +20,7 @@ module.exports = {
}
// -> Fetch Users
return WIKI.models.users.query()
return WIKI.db.users.query()
.select('id', 'email', 'name', 'isSystem', 'isActive', 'createdAt', 'lastLoginAt')
.where(builder => {
if (args.filter) {
......@@ -38,7 +36,7 @@ module.exports = {
* FETCH A SINGLE USER
*/
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) {
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) {
// 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) {
// throw new WIKI.Error.AuthAccountBanned()
// }
......@@ -80,7 +78,7 @@ module.exports = {
// return usr
// },
async lastLogins (obj, args, context, info) {
return WIKI.models.users.query()
return WIKI.db.users.query()
.select('id', 'name', 'lastLoginAt')
.whereNotNull('lastLoginAt')
.orderBy('lastLoginAt', 'desc')
......@@ -90,7 +88,7 @@ module.exports = {
Mutation: {
async createUser (obj, args) {
try {
await WIKI.models.users.createNewUser({ ...args, passwordRaw: args.password, isVerified: true })
await WIKI.db.users.createNewUser({ ...args, passwordRaw: args.password, isVerified: true })
return {
operation: graphHelper.generateSuccess('User created successfully')
......@@ -104,7 +102,7 @@ module.exports = {
if (args.id <= 2) {
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.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'u' })
......@@ -122,7 +120,7 @@ module.exports = {
},
async updateUser (obj, args) {
try {
await WIKI.models.users.updateUser(args.id, args.patch)
await WIKI.db.users.updateUser(args.id, args.patch)
return {
operation: graphHelper.generateSuccess('User updated successfully')
......@@ -133,7 +131,7 @@ module.exports = {
},
async verifyUser (obj, args) {
try {
await WIKI.models.users.query().patch({ isVerified: true }).findById(args.id)
await WIKI.db.users.query().patch({ isVerified: true }).findById(args.id)
return {
operation: graphHelper.generateSuccess('User verified successfully')
......@@ -144,7 +142,7 @@ module.exports = {
},
async activateUser (obj, args) {
try {
await WIKI.models.users.query().patch({ isActive: true }).findById(args.id)
await WIKI.db.users.query().patch({ isActive: true }).findById(args.id)
return {
operation: graphHelper.generateSuccess('User activated successfully')
......@@ -158,7 +156,7 @@ module.exports = {
if (args.id <= 2) {
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.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'u' })
......@@ -172,7 +170,7 @@ module.exports = {
},
async enableUserTFA (obj, args) {
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 {
operation: graphHelper.generateSuccess('User 2FA enabled successfully')
......@@ -183,7 +181,7 @@ module.exports = {
},
async disableUserTFA (obj, args) {
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 {
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) {
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) {
throw new WIKI.Error.AuthAccountBanned()
}
......@@ -216,7 +214,7 @@ module.exports = {
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,
meta: {
...usr.meta,
......@@ -245,7 +243,7 @@ module.exports = {
if (!context.req.user || context.req.user.id < 1 || context.req.user.id === 2) {
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) {
throw new WIKI.Error.AuthAccountBanned()
}
......@@ -261,12 +259,12 @@ module.exports = {
throw new WIKI.Error.AuthPasswordInvalid()
}
await WIKI.models.users.updateUser({
await WIKI.db.users.updateUser({
id: usr.id,
newPassword: args.new
})
const newToken = await WIKI.models.users.refreshToken(usr)
const newToken = await WIKI.db.users.refreshToken(usr)
return {
responseResult: graphHelper.generateSuccess('Password changed successfully'),
......@@ -288,7 +286,7 @@ module.exports = {
// return usrGroups.map(g => g.name)
// },
// 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)
// }
// }
......
......@@ -14,8 +14,6 @@ const contentToExt = {
}
const extToContent = _.invert(contentToExt)
/* global WIKI */
module.exports = {
/**
* Parse raw url path and make it safe
......
......@@ -15,7 +15,6 @@ if (!semver.satisfies(process.version, '>=18')) {
let WIKI = {
IS_DEBUG: process.env.NODE_ENV === 'development',
IS_MASTER: true,
ROOTPATH: process.cwd(),
INSTANCE_ID: nanoid(10),
SERVERPATH: path.join(process.cwd(), 'server'),
......
const _ = require('lodash')
/* global WIKI */
/**
* SEO Middleware
*
......
......@@ -5,8 +5,6 @@ const _ = require('lodash')
const yaml = require('js-yaml')
const commonHelper = require('../helpers/common')
/* global WIKI */
/**
* Analytics model
*/
......@@ -31,7 +29,7 @@ module.exports = class Analytics extends Model {
}
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'])
}
......@@ -69,7 +67,7 @@ module.exports = class Analytics extends Model {
bodyStart: '',
bodyEnd: ''
}
const providers = await WIKI.models.analytics.getProviders(true)
const providers = await WIKI.db.analytics.getProviders(true)
for (let provider of providers) {
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 }) {
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,
key: 'pending',
expiration: DateTime.utc().plus(ms(expiration)).toISO(),
......@@ -65,7 +65,7 @@ module.exports = class ApiKey extends Model {
issuer: 'urn:wiki.js'
})
await WIKI.models.apiKeys.query().findById(entry.id).patch({
await WIKI.db.apiKeys.query().findById(entry.id).patch({
key,
isRevoked: false
})
......
const Model = require('objection').Model
const _ = require('lodash')
/* global WIKI */
/**
* Users model
*/
......@@ -42,13 +40,13 @@ module.exports = class AssetFolder extends Model {
static async getHierarchy (folderId) {
let hier
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 => {
sqb.select('a.id', 'a.name', 'a.slug', 'a.parentId').from('assetFolders AS a').join('ancestors', 'ancestors.parentId', 'a.id')
})
}).select('*').from('ancestors')
} 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 => {
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
*/
static async getAllPaths () {
const all = await WIKI.models.assetFolders.query()
const all = await WIKI.db.assetFolders.query()
let folders = {}
all.forEach(fld => {
_.set(folders, fld.id, fld.slug)
......
......@@ -69,7 +69,7 @@ module.exports = class Asset extends Model {
async getAssetPath() {
let hierarchy = []
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
}
......@@ -83,7 +83,7 @@ module.exports = class Asset extends Model {
const fileHash = assetHelper.generateHash(opts.assetPath)
// Check for existing asset
let asset = await WIKI.models.assets.query().where({
let asset = await WIKI.db.assets.query().where({
hash: fileHash,
folderId: opts.folderId
}).first()
......@@ -124,8 +124,8 @@ module.exports = class Asset extends Model {
if (opts.mode === 'upload') {
assetRow.authorId = opts.user.id
}
await WIKI.models.assets.query().patch(assetRow).findById(asset.id)
await WIKI.models.knex('assetData').where({
await WIKI.db.assets.query().patch(assetRow).findById(asset.id)
await WIKI.db.knex('assetData').where({
id: asset.id
}).update({
data: fileBuffer
......@@ -133,8 +133,8 @@ module.exports = class Asset extends Model {
} else {
// Create asset entry
assetRow.authorId = opts.user.id
asset = await WIKI.models.assets.query().insert(assetRow)
await WIKI.models.knex('assetData').insert({
asset = await WIKI.db.assets.query().insert(assetRow)
await WIKI.db.knex('assetData').insert({
id: asset.id,
data: fileBuffer
})
......@@ -149,7 +149,7 @@ module.exports = class Asset extends Model {
// Add to Storage
if (!opts.skipStorage) {
await WIKI.models.storage.assetEvent({
await WIKI.db.storage.assetEvent({
event: 'uploaded',
asset: {
...asset,
......@@ -177,13 +177,13 @@ module.exports = class Asset extends Model {
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
}
if (await WIKI.models.assets.getAssetFromStorage(assetPath, res)) {
if (await WIKI.db.assets.getAssetFromStorage(assetPath, res)) {
return
}
await WIKI.models.assets.getAssetFromDb(assetPath, fileHash, cachePath, res)
await WIKI.db.assets.getAssetFromDb(assetPath, fileHash, cachePath, res)
} catch (err) {
if (err.code === `ECONNABORTED` || err.code === `EPIPE`) {
return
......@@ -206,13 +206,13 @@ module.exports = class Asset extends Model {
}
static async getAssetFromStorage(assetPath, res) {
const localLocations = await WIKI.models.storage.getLocalLocations({
const localLocations = await WIKI.db.storage.getLocalLocations({
asset: {
path: assetPath
}
})
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) {
return true
}
......@@ -221,9 +221,9 @@ module.exports = class Asset extends Model {
}
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) {
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.send(assetData.data)
await fs.outputFile(cachePath, assetData.data)
......
......@@ -5,8 +5,6 @@ const _ = require('lodash')
const yaml = require('js-yaml')
const commonHelper = require('../helpers/common')
/* global WIKI */
/**
* Authentication model
*/
......@@ -32,11 +30,11 @@ module.exports = class Authentication extends Model {
}
static async getStrategy(key) {
return WIKI.models.authentication.query().findOne({ key })
return WIKI.db.authentication.query().findOne({ key })
}
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 => ({
...str,
domainWhitelist: _.get(str.domainWhitelist, 'v', []),
......
......@@ -5,8 +5,6 @@ const _ = require('lodash')
const yaml = require('js-yaml')
const commonHelper = require('../helpers/common')
/* global WIKI */
/**
* CommentProvider model
*/
......@@ -31,11 +29,11 @@ module.exports = class CommentProvider extends Model {
}
static async getProvider(key) {
return WIKI.models.commentProviders.query().findOne({ key })
return WIKI.db.commentProviders.query().findOne({ key })
}
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'])
}
......@@ -61,7 +59,7 @@ module.exports = class CommentProvider extends Model {
}
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) {
WIKI.data.commentProvider = {
..._.find(WIKI.data.commentProviders, ['key', commentProvider.module]),
......
......@@ -2,8 +2,6 @@ const Model = require('objection').Model
const validate = require('validate.js')
const _ = require('lodash')
/* global WIKI */
/**
* Comments model
*/
......@@ -95,7 +93,7 @@ module.exports = class Comment extends Model {
}
// -> Load Page
const page = await WIKI.models.pages.getPageFromDb(pageId)
const page = await WIKI.db.pages.getPageFromDb(pageId)
if (page) {
if (!WIKI.auth.checkAccess(user, ['write:comments'], {
path: page.path,
......@@ -132,7 +130,7 @@ module.exports = class Comment extends Model {
if (!pageId) {
throw new WIKI.Error.CommentNotFound()
}
const page = await WIKI.models.pages.getPageFromDb(pageId)
const page = await WIKI.db.pages.getPageFromDb(pageId)
if (page) {
if (!WIKI.auth.checkAccess(user, ['manage:comments'], {
path: page.path,
......@@ -165,7 +163,7 @@ module.exports = class Comment extends Model {
if (!pageId) {
throw new WIKI.Error.CommentNotFound()
}
const page = await WIKI.models.pages.getPageFromDb(pageId)
const page = await WIKI.db.pages.getPageFromDb(pageId)
if (page) {
if (!WIKI.auth.checkAccess(user, ['manage:comments'], {
path: page.path,
......
const Model = require('objection').Model
/* global WIKI */
/**
* Editor model
*/
......@@ -26,7 +24,7 @@ module.exports = class Editor extends Model {
}
static async getEditors() {
return WIKI.models.editors.query()
return WIKI.db.editors.query()
}
static async getDefaultEditor(contentType) {
......
const Model = require('objection').Model
/* global WIKI */
/**
* Hook model
*/
......@@ -17,7 +15,7 @@ module.exports = class Hook extends Model {
}
static async createHook (data) {
return WIKI.models.hooks.query().insertAndFetch({
return WIKI.db.hooks.query().insertAndFetch({
name: data.name,
events: data.events,
url: data.url,
......@@ -31,7 +29,7 @@ module.exports = class Hook extends Model {
}
static async updateHook (id, patch) {
return WIKI.models.hooks.query().findById(id).patch({
return WIKI.db.hooks.query().findById(id).patch({
...patch,
state: 'pending',
lastErrorMessage: null
......@@ -39,6 +37,6 @@ module.exports = class Hook extends Model {
}
static async deleteHook (id) {
return WIKI.models.hooks.query().deleteById(id)
return WIKI.db.hooks.query().deleteById(id)
}
}
const Model = require('objection').Model
/* global WIKI */
/**
* Locales model
*/
......@@ -50,7 +48,7 @@ module.exports = class Locale extends Model {
// 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 (cache) {
// await WIKI.cache.set('nav:locales', navLocales, 300)
......
const Model = require('objection').Model
const _ = require('lodash')
/* global WIKI */
/**
* Navigation model
*/
......@@ -26,10 +24,10 @@ module.exports = class Navigation extends Model {
if (cache) {
const navTreeCached = await WIKI.cache.get(`nav:sidebar:${locale}`)
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) {
// Check for pre-2.3 format
if (_.has(navTree.config[0], 'kind')) {
......@@ -51,7 +49,7 @@ module.exports = class Navigation extends Model {
if (bypassAuth) {
return locale === 'all' ? navTree.config : WIKI.cache.get(`nav:sidebar:${locale}`)
} 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 {
WIKI.logger.warn('Site Navigation is missing or corrupted.')
......
......@@ -2,8 +2,6 @@ const Model = require('objection').Model
const _ = require('lodash')
const { DateTime, Duration } = require('luxon')
/* global WIKI */
/**
* Page History model
*/
......@@ -89,7 +87,7 @@ module.exports = class PageHistory extends Model {
* Create Page Version
*/
static async addVersion(opts) {
await WIKI.models.pageHistory.query().insert({
await WIKI.db.pageHistory.query().insert({
pageId: opts.id,
authorId: opts.authorId,
content: opts.content,
......@@ -113,7 +111,7 @@ module.exports = class PageHistory extends Model {
* Get Page Version
*/
static async getVersion({ pageId, versionId }) {
const version = await WIKI.models.pageHistory.query()
const version = await WIKI.db.pageHistory.query()
.column([
'pageHistory.path',
'pageHistory.title',
......@@ -156,7 +154,7 @@ module.exports = class PageHistory extends Model {
* Get History Trail of a Page
*/
static async getHistory({ pageId, offsetPage = 0, offsetSize = 100 }) {
const history = await WIKI.models.pageHistory.query()
const history = await WIKI.db.pageHistory.query()
.column([
'pageHistory.id',
'pageHistory.path',
......@@ -178,7 +176,7 @@ module.exports = class PageHistory extends Model {
const upperLimit = (offsetPage + 1) * offsetSize
if (history.total >= upperLimit) {
prevPh = await WIKI.models.pageHistory.query()
prevPh = await WIKI.db.pageHistory.query()
.column([
'pageHistory.id',
'pageHistory.path',
......@@ -238,6 +236,6 @@ module.exports = class PageHistory extends Model {
static async purge (olderThan) {
const dur = Duration.fromISO(olderThan)
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()
}
}
......@@ -6,8 +6,6 @@ const yaml = require('js-yaml')
const DepGraph = require('dependency-graph').DepGraph
const commonHelper = require('../helpers/common')
/* global WIKI */
/**
* Renderer model
*/
......@@ -32,7 +30,7 @@ module.exports = class Renderer extends Model {
}
static async getRenderers() {
return WIKI.models.renderers.query()
return WIKI.db.renderers.query()
}
static async fetchDefinitions() {
......@@ -57,16 +55,16 @@ module.exports = class Renderer extends Model {
}
static async refreshRenderersFromDisk() {
// const dbRenderers = await WIKI.models.renderers.query()
// const dbRenderers = await WIKI.db.renderers.query()
// -> Fetch definitions from disk
await WIKI.models.renderers.fetchDefinitions()
await WIKI.db.renderers.fetchDefinitions()
// TODO: Merge existing configs with updated modules
}
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) {
const renderers = renderersDb.map(rdr => {
const renderer = _.find(WIKI.data.renderers, ['key', rdr.key])
......
const Model = require('objection').Model
const _ = require('lodash')
/* global WIKI */
/**
* Settings model
*/
......@@ -26,7 +24,7 @@ module.exports = class Setting extends Model {
}
static async getConfig() {
const settings = await WIKI.models.settings.query()
const settings = await WIKI.db.settings.query()
if (settings.length > 0) {
return _.reduce(settings, (res, val, key) => {
_.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 _ = require('lodash')
/* global WIKI */
/**
* Site model
*/
......@@ -30,7 +28,7 @@ module.exports = class Site extends Model {
static async getSiteByHostname ({ hostname, forceReload = false }) {
if (forceReload) {
await WIKI.models.sites.reloadCache()
await WIKI.db.sites.reloadCache()
}
const siteId = WIKI.sitesMappings[hostname] || WIKI.sitesMappings['*']
if (siteId) {
......@@ -41,7 +39,7 @@ module.exports = class Site extends Model {
static async reloadCache () {
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.sitesMappings = {}
for (const site of sites) {
......@@ -51,7 +49,7 @@ module.exports = class Site extends Model {
}
static async createSite (hostname, config) {
const newSite = await WIKI.models.sites.query().insertAndFetch({
const newSite = await WIKI.db.sites.query().insertAndFetch({
hostname,
isEnabled: true,
config: _.defaultsDeep(config, {
......@@ -114,7 +112,7 @@ module.exports = class Site extends Model {
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',
siteId: newSite.id,
isEnabled: true,
......@@ -135,11 +133,11 @@ module.exports = class Site extends Model {
}
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) {
await WIKI.models.storage.query().delete().where('siteId', id)
return WIKI.models.sites.query().deleteById(id)
await WIKI.db.storage.query().delete().where('siteId', id)
return WIKI.db.sites.query().deleteById(id)
}
}
......@@ -5,8 +5,6 @@ const _ = require('lodash')
const yaml = require('js-yaml')
const commonHelper = require('../helpers/common')
/* global WIKI */
/**
* Storage model
*/
......@@ -31,7 +29,7 @@ module.exports = class Storage extends Model {
}
static async getTargets ({ siteId }) {
return WIKI.models.storage.query().where(builder => {
return WIKI.db.storage.query().where(builder => {
if (siteId) {
builder.where('siteId', siteId)
}
......@@ -85,7 +83,7 @@ module.exports = class Storage extends Model {
* Initialize active storage targets
*/
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))
try {
// -> Stop and delete existing jobs
......@@ -109,7 +107,7 @@ module.exports = class Storage extends Model {
// await target.fn.init()
// // -> Save succeeded init state
// await WIKI.models.storage.query().patch({
// await WIKI.db.storage.query().patch({
// state: {
// status: 'operational',
// message: '',
......@@ -138,7 +136,7 @@ module.exports = class Storage extends Model {
// }
// } catch (err) {
// // -> Save initialization error
// await WIKI.models.storage.query().patch({
// await WIKI.db.storage.query().patch({
// state: {
// status: 'error',
// message: err.message,
......
const Model = require('objection').Model
const _ = require('lodash')
/* global WIKI */
/**
* Tags model
*/
......@@ -50,7 +48,7 @@ module.exports = class Tag extends Model {
}
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
......@@ -61,11 +59,11 @@ module.exports = class Tag extends Model {
const newTags = _.filter(tags, t => !_.some(existingTags, ['tag', t])).map(t => ({ tag: t }))
if (newTags.length > 0) {
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)
} else {
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)
}
}
......
......@@ -46,7 +46,7 @@ module.exports = class UserKey extends Model {
static async generateToken ({ userId, kind, meta }, context) {
const token = await nanoid()
await WIKI.models.userKeys.query().insert({
await WIKI.db.userKeys.query().insert({
kind,
token,
meta,
......@@ -57,10 +57,10 @@ module.exports = class UserKey extends Model {
}
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 (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)) {
throw new WIKI.Error.AuthValidationTokenInvalid()
......@@ -75,6 +75,6 @@ module.exports = class UserKey extends Model {
}
static async destroyToken ({ token }) {
return WIKI.models.userKeys.query().findOne({ token }).delete()
return WIKI.db.userKeys.query().findOne({ token }).delete()
}
}
......@@ -17,7 +17,7 @@ module.exports = {
passReqToCallback: true
}, async (req, accessToken, refreshToken, extraParams, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile
})
......
const _ = require('lodash')
/* global WIKI */
// ------------------------------------
// Azure AD Account
// ------------------------------------
......@@ -39,7 +37,7 @@ module.exports = {
}, async (req, iss, sub, profile, cb) => {
const usrEmail = _.get(profile, '_json.email', null) || _.get(profile, '_json.preferred_username')
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
id: profile.oid,
......
......@@ -15,7 +15,7 @@ module.exports = {
passReqToCallback: true
}, async (req, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile
})
......
......@@ -22,7 +22,7 @@ module.exports = {
if (conf.guildId && !_.some(profile.guilds, { id: conf.guildId })) {
throw new WIKI.Error.AuthLoginFailed()
}
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
......
......@@ -18,7 +18,7 @@ module.exports = {
passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
......
......@@ -19,7 +19,7 @@ module.exports = {
passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
......
......@@ -27,7 +27,7 @@ module.exports = {
passport.use(conf.key,
new GitHubStrategy(githubConfig, async (req, accessToken, refreshToken, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
......
......@@ -19,7 +19,7 @@ module.exports = {
passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
......
......@@ -19,7 +19,7 @@ module.exports = {
if (conf.hostedDomain && conf.hostedDomain != profile._json.hd) {
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,
profile: {
...profile,
......
const _ = require('lodash')
/* global WIKI */
// ------------------------------------
// Keycloak Account
// ------------------------------------
......@@ -27,7 +25,7 @@ module.exports = {
displayName = profile.fullName
}
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
id: profile.keycloakId,
......
......@@ -31,7 +31,7 @@ module.exports = {
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,
profile: {
id: userId,
......
......@@ -15,7 +15,7 @@ module.exports = {
passwordField: 'password'
}, async (uEmail, uPassword, done) => {
try {
const user = await WIKI.models.users.query().findOne({
const user = await WIKI.db.users.query().findOne({
email: uEmail.toLowerCase()
})
if (user) {
......
......@@ -18,7 +18,7 @@ module.exports = {
passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
......
const _ = require('lodash')
/* global WIKI */
// ------------------------------------
// OAuth2 Account
// ------------------------------------
......@@ -21,7 +19,7 @@ module.exports = {
scope: conf.scope
}, async (req, accessToken, refreshToken, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
......
const _ = require('lodash')
/* global WIKI */
// ------------------------------------
// OpenID Connect Account
// ------------------------------------
......@@ -22,7 +20,7 @@ module.exports = {
passReqToCallback: true
}, async (req, iss, sub, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
......
......@@ -20,7 +20,7 @@ module.exports = {
passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
......
const _ = require('lodash')
/* global WIKI */
// ------------------------------------
// Rocket.chat Account
// ------------------------------------
......@@ -43,7 +41,7 @@ module.exports = {
passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile
})
......
const _ = require('lodash')
/* global WIKI */
// ------------------------------------
// SAML Account
// ------------------------------------
......@@ -47,7 +45,7 @@ module.exports = {
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,
profile: {
id: userId,
......
......@@ -19,7 +19,7 @@ module.exports = {
passReqToCallback: true
}, async (req, accessToken, refreshToken, { user: userProfile }, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
...userProfile,
......
......@@ -17,7 +17,7 @@ module.exports = {
passReqToCallback: true
}, async (req, accessToken, refreshToken, profile, cb) => {
try {
const user = await WIKI.models.users.processProfile({
const user = await WIKI.db.users.processProfile({
providerKey: req.params.strategy,
profile: {
...profile,
......
......@@ -6,8 +6,6 @@ const _ = require('lodash')
const { AkismetClient } = require('akismet-api')
const moment = require('moment')
/* global WIKI */
const window = new JSDOM('').window
const DOMPurify = createDOMPurify(window)
......@@ -108,14 +106,14 @@ module.exports = {
// -> Check for minimum delay between posts
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)) {
throw new Error('Your administrator has set a time limit before you can post another comment. Try again later.')
}
}
// -> 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 cm.id
......@@ -125,7 +123,7 @@ module.exports = {
*/
async update ({ id, content, user }) {
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
})
return renderedContent
......@@ -134,26 +132,26 @@ module.exports = {
* Delete an existing comment by ID
*/
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
*/
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
},
/**
* Get a comment by 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
*/
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)
}
}
......@@ -4,8 +4,6 @@ const util = require('util')
const exec = util.promisify(require('child_process').exec)
const fs = require('fs-extra')
/* global WIKI */
module.exports = {
key: 'puppeteer',
title: 'Puppeteer',
......
......@@ -5,8 +5,6 @@ const util = require('util')
const exec = util.promisify(require('child_process').exec)
const { pipeline } = require('stream/promises')
/* global WIKI */
module.exports = {
key: 'sharp',
title: 'Sharp',
......
......@@ -6,8 +6,6 @@ const URL = require('url').URL
const mustacheRegExp = /(\{|&#x7b;?){2}(.+?)(\}|&#x7d;?){2}/i
/* global WIKI */
module.exports = {
async render() {
const $ = cheerio.load(this.input, {
......@@ -133,7 +131,7 @@ module.exports = {
if (internalRefs.length > 0) {
// -> 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) => {
if (idx < 1) {
builder.where(ref)
......@@ -168,14 +166,14 @@ module.exports = {
})
if (missingLinks.length > 0) {
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,
path: lnk.path,
localeCode: lnk.localeCode
})))
} else {
for (const lnk of missingLinks) {
await WIKI.models.pageLinks.query().insert({
await WIKI.db.pageLinks.query().insert({
pageId: this.page.id,
path: lnk.path,
localeCode: lnk.localeCode
......@@ -191,7 +189,7 @@ module.exports = {
return nLink.localeCode === pLink.localeCode && nLink.path === pLink.path
})
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'))
}
}
......
const katex = require('katex')
const chemParse = require('./mhchem')
/* global WIKI */
// ------------------------------------
// Markdown - KaTeX Renderer
// ------------------------------------
......
const mjax = require('mathjax')
/* global WIKI */
// ------------------------------------
// Markdown - MathJax Renderer
// ------------------------------------
......
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
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.`)
}
}
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
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
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.`)
}
}
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: {}
/* 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
}
}
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
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: {}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment