mirror of
https://github.com/requarks/wiki.git
synced 2026-08-26 13:17:10 -05:00
fix: add permissions to resolvers
This commit is contained in:
@@ -105,6 +105,8 @@ export default {
|
||||
* @param {Express Next Callback} next
|
||||
*/
|
||||
authenticate (req, res, next) {
|
||||
req.isAuthenticated = false
|
||||
|
||||
WIKI.auth.passport.authenticate('jwt', { session: false }, async (err, user, info) => {
|
||||
if (err) { return next() }
|
||||
let mustRevalidate = false
|
||||
@@ -170,6 +172,7 @@ export default {
|
||||
WIKI.auth.guest.cacheExpiration = DateTime.utc().plus({ minutes: 1 })
|
||||
}
|
||||
req.user = WIKI.auth.guest
|
||||
req.isAuthenticated = false
|
||||
return next()
|
||||
}
|
||||
|
||||
@@ -203,6 +206,7 @@ export default {
|
||||
// JWT is valid
|
||||
req.logIn(user, { session: false }, (errc) => {
|
||||
if (errc) { return next(errc) }
|
||||
req.isAuthenticated = true
|
||||
next()
|
||||
})
|
||||
})(req, res, next)
|
||||
@@ -223,7 +227,7 @@ export default {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check Global Permissions
|
||||
// Check Permissions
|
||||
if (_.intersection(userPermissions, permissions).length < 1) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@ export default {
|
||||
* List of API Keys
|
||||
*/
|
||||
async apiKeys (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['read:api', 'manage:api'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
const keys = await WIKI.db.apiKeys.query().orderBy(['isRevoked', 'name'])
|
||||
return keys.map(k => ({
|
||||
id: k.id,
|
||||
@@ -31,7 +35,11 @@ export default {
|
||||
/**
|
||||
* Current API State
|
||||
*/
|
||||
apiState () {
|
||||
apiState (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['read:api', 'manage:api', 'read:dashboard'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return WIKI.config.api.isEnabled
|
||||
},
|
||||
/**
|
||||
@@ -82,6 +90,10 @@ export default {
|
||||
*/
|
||||
async createApiKey (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:api'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
const key = await WIKI.db.apiKeys.createNewKey(args)
|
||||
await WIKI.auth.reloadApiKeys()
|
||||
WIKI.events.outbound.emit('reloadApiKeys')
|
||||
@@ -136,7 +148,7 @@ export default {
|
||||
try {
|
||||
const userId = context.req.user?.id
|
||||
if (!userId) {
|
||||
throw new Error('ERR_USER_NOT_AUTHENTICATED')
|
||||
throw new Error('ERR_NOT_AUTHENTICATED')
|
||||
}
|
||||
|
||||
const usr = await WIKI.db.users.query().findById(userId)
|
||||
@@ -182,7 +194,7 @@ export default {
|
||||
try {
|
||||
const userId = context.req.user?.id
|
||||
if (!userId) {
|
||||
throw new Error('ERR_USER_NOT_AUTHENTICATED')
|
||||
throw new Error('ERR_NOT_AUTHENTICATED')
|
||||
}
|
||||
|
||||
const usr = await WIKI.db.users.query().findById(userId)
|
||||
@@ -224,7 +236,7 @@ export default {
|
||||
try {
|
||||
const userId = context.req.user?.id
|
||||
if (!userId) {
|
||||
throw new Error('ERR_USER_NOT_AUTHENTICATED')
|
||||
throw new Error('ERR_NOT_AUTHENTICATED')
|
||||
}
|
||||
|
||||
const usr = await WIKI.db.users.query().findById(userId)
|
||||
@@ -283,7 +295,7 @@ export default {
|
||||
try {
|
||||
const userId = context.req.user?.id
|
||||
if (!userId) {
|
||||
throw new Error('ERR_USER_NOT_AUTHENTICATED')
|
||||
throw new Error('ERR_NOT_AUTHENTICATED')
|
||||
}
|
||||
|
||||
const usr = await WIKI.db.users.query().findById(userId)
|
||||
@@ -346,7 +358,7 @@ export default {
|
||||
try {
|
||||
const userId = context.req.user?.id
|
||||
if (!userId) {
|
||||
throw new Error('ERR_USER_NOT_AUTHENTICATED')
|
||||
throw new Error('ERR_NOT_AUTHENTICATED')
|
||||
}
|
||||
|
||||
const usr = await WIKI.db.users.query().findById(userId)
|
||||
@@ -584,7 +596,7 @@ export default {
|
||||
*/
|
||||
async revokeApiKey (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:api'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@ export default {
|
||||
Mutation: {
|
||||
async setBlocksState(obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:blocks'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
// TODO: update blocks state
|
||||
return {
|
||||
operation: generateSuccess('Blocks state updated successfully')
|
||||
|
||||
@@ -3,10 +3,18 @@ import _ from 'lodash-es'
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
async hooks () {
|
||||
async hooks (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['read:webhooks', 'write:webhooks', 'manage:webhooks'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return WIKI.db.hooks.query().orderBy('name')
|
||||
},
|
||||
async hookById (obj, args) {
|
||||
async hookById (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['read:webhooks', 'write:webhooks', 'manage:webhooks'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return WIKI.db.hooks.query().findById(args.id)
|
||||
}
|
||||
},
|
||||
@@ -14,8 +22,12 @@ export default {
|
||||
/**
|
||||
* CREATE HOOK
|
||||
*/
|
||||
async createHook (obj, args) {
|
||||
async createHook (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['write:webhooks', 'manage:webhooks'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
// -> Validate inputs
|
||||
if (!args.name || args.name.length < 1) {
|
||||
throw new WIKI.Error.Custom('HookCreateInvalidName', 'Invalid Hook Name')
|
||||
@@ -41,8 +53,12 @@ export default {
|
||||
/**
|
||||
* UPDATE HOOK
|
||||
*/
|
||||
async updateHook (obj, args) {
|
||||
async updateHook (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:webhooks'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
// -> Load hook
|
||||
const hook = await WIKI.db.hooks.query().findById(args.id)
|
||||
if (!hook) {
|
||||
@@ -72,8 +88,12 @@ export default {
|
||||
/**
|
||||
* DELETE HOOK
|
||||
*/
|
||||
async deleteHook (obj, args) {
|
||||
async deleteHook (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:webhooks'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
await WIKI.db.hooks.deleteHook(args.id)
|
||||
WIKI.logger.debug(`Hook ${args.id} deleted successfully.`)
|
||||
return {
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import { generateError, generateSuccess } from '../../helpers/graph.mjs'
|
||||
import _ from 'lodash-es'
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
async locales(obj, args, context, info) {
|
||||
@@ -9,45 +6,5 @@ export default {
|
||||
localeStrings (obj, args, context, info) {
|
||||
return WIKI.db.locales.getStrings(args.locale)
|
||||
}
|
||||
},
|
||||
Mutation: {
|
||||
async downloadLocale(obj, args, context) {
|
||||
try {
|
||||
const job = await WIKI.scheduler.registerJob({
|
||||
name: 'fetch-graph-locale',
|
||||
immediate: true
|
||||
}, args.locale)
|
||||
await job.finished
|
||||
return {
|
||||
responseResult: generateSuccess('Locale downloaded successfully')
|
||||
}
|
||||
} catch (err) {
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async updateLocale(obj, args, context) {
|
||||
try {
|
||||
WIKI.config.lang.code = args.locale
|
||||
WIKI.config.lang.autoUpdate = args.autoUpdate
|
||||
WIKI.config.lang.namespacing = args.namespacing
|
||||
WIKI.config.lang.namespaces = _.union(args.namespaces, [args.locale])
|
||||
|
||||
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'])
|
||||
|
||||
await WIKI.lang.setCurrentLocale(args.locale)
|
||||
await WIKI.lang.refreshNamespaces()
|
||||
|
||||
await WIKI.cache.del('nav:locales')
|
||||
|
||||
return {
|
||||
responseResult: generateSuccess('Locale config updated')
|
||||
}
|
||||
} catch (err) {
|
||||
return generateError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,11 @@ import { generateError, generateSuccess } from '../../helpers/graph.mjs'
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
async mailConfig(obj, args, context, info) {
|
||||
async mailConfig(obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return {
|
||||
...WIKI.config.mail,
|
||||
pass: WIKI.config.mail.pass.length > 0 ? '********' : ''
|
||||
@@ -13,6 +17,10 @@ export default {
|
||||
Mutation: {
|
||||
async sendMailTest(obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
if (_.isEmpty(args.recipientEmail) || args.recipientEmail.length < 6) {
|
||||
throw new WIKI.Error.MailInvalidRecipient()
|
||||
}
|
||||
@@ -36,6 +44,10 @@ export default {
|
||||
},
|
||||
async updateMailConfig(obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
WIKI.config.mail = {
|
||||
senderName: args.senderName,
|
||||
senderEmail: args.senderEmail,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import _ from 'lodash-es'
|
||||
import { generateError, generateSuccess } from '../../helpers/graph.mjs'
|
||||
import { parsePath }from '../../helpers/page.mjs'
|
||||
import { parsePath } from '../../helpers/page.mjs'
|
||||
import tsquery from 'pg-tsquery'
|
||||
|
||||
const tsq = tsquery()
|
||||
@@ -247,12 +247,19 @@ export default {
|
||||
siteId: args.siteId
|
||||
})
|
||||
if (page) {
|
||||
return {
|
||||
...page,
|
||||
...page.config,
|
||||
scriptCss: page.scripts?.css,
|
||||
scriptJsLoad: page.scripts?.jsLoad,
|
||||
scriptJsUnload: page.scripts?.jsUnload
|
||||
if (WIKI.auth.checkAccess(context.req.user, ['read:pages'], {
|
||||
path: page.path,
|
||||
locale: page.locale
|
||||
})) {
|
||||
return {
|
||||
...page,
|
||||
...page.config,
|
||||
scriptCss: page.scripts?.css,
|
||||
scriptJsLoad: page.scripts?.jsLoad,
|
||||
scriptJsUnload: page.scripts?.jsUnload
|
||||
}
|
||||
} else {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
} else {
|
||||
throw new Error('ERR_PAGE_NOT_FOUND')
|
||||
@@ -265,17 +272,17 @@ export default {
|
||||
async pathFromAlias (obj, args, context, info) {
|
||||
const alias = args.alias?.trim()
|
||||
if (!alias) {
|
||||
throw new Error('ERR_ALIAS_MISSING')
|
||||
throw new Error('ERR_PAGE_ALIAS_MISSING')
|
||||
}
|
||||
if (!WIKI.sites[args.siteId]) {
|
||||
throw new Error('ERR_INVALID_SITE_ID')
|
||||
throw new Error('ERR_INVALID_SITE')
|
||||
}
|
||||
const page = await WIKI.db.pages.query().findOne({
|
||||
alias: args.alias,
|
||||
siteId: args.siteId
|
||||
}).select('id', 'path', 'locale')
|
||||
if (!page) {
|
||||
throw new Error('ERR_ALIAS_NOT_FOUND')
|
||||
throw new Error('ERR_PAGE_ALIAS_NOT_FOUND')
|
||||
}
|
||||
return {
|
||||
id: page.id,
|
||||
@@ -287,7 +294,7 @@ export default {
|
||||
* FETCH TAGS
|
||||
*/
|
||||
async tags (obj, args, context, info) {
|
||||
if (!args.siteId) { throw new Error('Missing Site ID')}
|
||||
if (!args.siteId) { throw new Error('Missing Site ID') }
|
||||
const tags = await WIKI.db.knex('tags').where('siteId', args.siteId).orderBy('tag')
|
||||
// TODO: check permissions
|
||||
return tags
|
||||
@@ -670,19 +677,29 @@ export default {
|
||||
}
|
||||
},
|
||||
Page: {
|
||||
icon (obj) {
|
||||
return obj.icon || 'las la-file-alt'
|
||||
icon (page) {
|
||||
return page.icon || 'las la-file-alt'
|
||||
},
|
||||
password (obj) {
|
||||
return obj.password ? '********' : ''
|
||||
password (page) {
|
||||
return page.password ? '********' : ''
|
||||
},
|
||||
// async tags (obj) {
|
||||
// return WIKI.db.pages.relatedQuery('tags').for(obj.id)
|
||||
content (page, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['read:source', 'write:pages', 'manage:pages'], {
|
||||
path: page.path,
|
||||
locale: page.locale
|
||||
})) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return page.content
|
||||
},
|
||||
// async tags (page) {
|
||||
// return WIKI.db.pages.relatedQuery('tags').for(page.id)
|
||||
// },
|
||||
tocDepth (obj) {
|
||||
tocDepth (page) {
|
||||
return {
|
||||
min: obj.extra?.tocDepth?.min ?? 1,
|
||||
max: obj.extra?.tocDepth?.max ?? 2
|
||||
min: page.extra?.tocDepth?.min ?? 1,
|
||||
max: page.extra?.tocDepth?.max ?? 2
|
||||
}
|
||||
}
|
||||
// comments(pg) {
|
||||
|
||||
@@ -49,8 +49,12 @@ export default {
|
||||
/**
|
||||
* CREATE SITE
|
||||
*/
|
||||
async createSite (obj, args) {
|
||||
async createSite (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['write:sites', 'manage:sites'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
// -> Validate inputs
|
||||
if (!args.hostname || args.hostname.length < 1 || !/^(\\*)|([a-z0-9\-.:]+)$/.test(args.hostname)) {
|
||||
throw new WIKI.Error.Custom('SiteCreateInvalidHostname', 'Invalid Site Hostname')
|
||||
@@ -83,8 +87,12 @@ export default {
|
||||
/**
|
||||
* UPDATE SITE
|
||||
*/
|
||||
async updateSite (obj, args) {
|
||||
async updateSite (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:sites'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
// -> Load site
|
||||
const site = await WIKI.db.sites.query().findById(args.id)
|
||||
if (!site) {
|
||||
@@ -127,8 +135,12 @@ export default {
|
||||
/**
|
||||
* DELETE SITE
|
||||
*/
|
||||
async deleteSite (obj, args) {
|
||||
async deleteSite (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:sites'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
// -> Ensure site isn't last one
|
||||
const sitesCount = await WIKI.db.sites.query().count('id').first()
|
||||
if (sitesCount?.count && _.toNumber(sitesCount?.count) <= 1) {
|
||||
@@ -149,6 +161,10 @@ export default {
|
||||
*/
|
||||
async uploadSiteLogo (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:sites'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
const { filename, mimetype, createReadStream } = await args.image
|
||||
WIKI.logger.info(`Processing site logo ${filename} of type ${mimetype}...`)
|
||||
if (!WIKI.extensions.ext.sharp.isInstalled) {
|
||||
@@ -208,6 +224,10 @@ export default {
|
||||
*/
|
||||
async uploadSiteFavicon (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:sites'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
const { filename, mimetype, createReadStream } = await args.image
|
||||
WIKI.logger.info(`Processing site favicon ${filename} of type ${mimetype}...`)
|
||||
if (!WIKI.extensions.ext.sharp.isInstalled) {
|
||||
@@ -268,6 +288,10 @@ export default {
|
||||
*/
|
||||
async uploadSiteLoginBg (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:sites'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
const { filename, mimetype, createReadStream } = await args.image
|
||||
WIKI.logger.info(`Processing site login bg ${filename} of type ${mimetype}...`)
|
||||
if (!WIKI.extensions.ext.sharp.isInstalled) {
|
||||
|
||||
@@ -12,18 +12,44 @@ const getos = util.promisify(getosSync)
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
/**
|
||||
* System Flags
|
||||
*/
|
||||
systemFlags () {
|
||||
return WIKI.config.flags
|
||||
},
|
||||
async systemInfo () { return {} },
|
||||
async systemExtensions () {
|
||||
/**
|
||||
* System Info
|
||||
*/
|
||||
async systemInfo (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['read:dashboard', 'manage:sites'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return {}
|
||||
},
|
||||
/**
|
||||
* System Extensions
|
||||
*/
|
||||
async systemExtensions (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
const exts = Object.values(WIKI.extensions.ext).map(ext => _.pick(ext, ['key', 'title', 'description', 'isInstalled', 'isInstallable']))
|
||||
for (const ext of exts) {
|
||||
ext.isCompatible = await WIKI.extensions.ext[ext.key].isCompatible()
|
||||
}
|
||||
return exts
|
||||
},
|
||||
async systemInstances () {
|
||||
/**
|
||||
* List System Instances
|
||||
*/
|
||||
async systemInstances (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
const instRaw = await WIKI.db.knex('pg_stat_activity')
|
||||
.select([
|
||||
'usename',
|
||||
@@ -56,10 +82,24 @@ export default {
|
||||
}
|
||||
return _.values(insts)
|
||||
},
|
||||
systemSecurity () {
|
||||
/**
|
||||
* System Security Settings
|
||||
*/
|
||||
systemSecurity (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return WIKI.config.security
|
||||
},
|
||||
async systemJobs (obj, args) {
|
||||
/**
|
||||
* List System Jobs
|
||||
*/
|
||||
async systemJobs (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
const results = args.states?.length > 0 ?
|
||||
await WIKI.db.knex('jobHistory').whereIn('state', args.states.map(s => s.toLowerCase())).orderBy('startedAt', 'desc') :
|
||||
await WIKI.db.knex('jobHistory').orderBy('startedAt', 'desc')
|
||||
@@ -68,16 +108,37 @@ export default {
|
||||
state: r.state.toUpperCase()
|
||||
}))
|
||||
},
|
||||
async systemJobsScheduled (obj, args) {
|
||||
/**
|
||||
* List Scheduled Jobs
|
||||
*/
|
||||
async systemJobsScheduled (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return WIKI.db.knex('jobSchedule').orderBy('task')
|
||||
},
|
||||
async systemJobsUpcoming (obj, args) {
|
||||
/**
|
||||
* List Upcoming Jobs
|
||||
*/
|
||||
async systemJobsUpcoming (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return WIKI.db.knex('jobs').orderBy([
|
||||
{ column: 'waitUntil', order: 'asc', nulls: 'first' },
|
||||
{ column: 'createdAt', order: 'asc' }
|
||||
])
|
||||
},
|
||||
systemSearch () {
|
||||
/**
|
||||
* Search Settings
|
||||
*/
|
||||
systemSearch (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return {
|
||||
...WIKI.config.search,
|
||||
dictOverrides: JSON.stringify(WIKI.config.search.dictOverrides, null, 2)
|
||||
@@ -86,8 +147,13 @@ export default {
|
||||
},
|
||||
Mutation: {
|
||||
async cancelJob (obj, args, context) {
|
||||
WIKI.logger.info(`Admin requested cancelling job ${args.id}...`)
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
WIKI.logger.info(`Admin requested cancelling job ${args.id}...`)
|
||||
|
||||
const result = await WIKI.db.knex('jobs')
|
||||
.where('id', args.id)
|
||||
.del()
|
||||
@@ -100,12 +166,18 @@ export default {
|
||||
operation: generateSuccess('Cancelled job successfully.')
|
||||
}
|
||||
} catch (err) {
|
||||
WIKI.logger.warn(err)
|
||||
if (err.message !== 'ERR_FORBIDDEN') {
|
||||
WIKI.logger.warn(err)
|
||||
}
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async checkForUpdates (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['read:dashboard', 'manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
const renderJob = await WIKI.scheduler.addJob({
|
||||
task: 'checkVersion',
|
||||
maxRetries: 0,
|
||||
@@ -119,15 +191,28 @@ export default {
|
||||
latestDate: WIKI.config.update.versionDate
|
||||
}
|
||||
} catch (err) {
|
||||
WIKI.logger.warn(err)
|
||||
if (err.message !== 'ERR_FORBIDDEN') {
|
||||
WIKI.logger.warn(err)
|
||||
}
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async disconnectWS (obj, args, context) {
|
||||
WIKI.servers.ws.disconnectSockets(true)
|
||||
WIKI.logger.info('All active websocket connections have been terminated.')
|
||||
return {
|
||||
operation: generateSuccess('All websocket connections closed successfully.')
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
WIKI.servers.ws.disconnectSockets(true)
|
||||
WIKI.logger.info('All active websocket connections have been terminated.')
|
||||
return {
|
||||
operation: generateSuccess('All websocket connections closed successfully.')
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.message !== 'ERR_FORBIDDEN') {
|
||||
WIKI.logger.warn(err)
|
||||
}
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async installExtension (obj, args, context) {
|
||||
@@ -143,6 +228,10 @@ export default {
|
||||
},
|
||||
async rebuildSearchIndex (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
await WIKI.scheduler.addJob({
|
||||
task: 'rebuildSearchIndex',
|
||||
maxRetries: 0
|
||||
@@ -155,8 +244,13 @@ export default {
|
||||
}
|
||||
},
|
||||
async retryJob (obj, args, context) {
|
||||
WIKI.logger.info(`Admin requested rescheduling of job ${args.id}...`)
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
WIKI.logger.info(`Admin requested rescheduling of job ${args.id}...`)
|
||||
|
||||
const job = await WIKI.db.knex('jobHistory')
|
||||
.where('id', args.id)
|
||||
.first()
|
||||
@@ -188,34 +282,61 @@ export default {
|
||||
}
|
||||
},
|
||||
async updateSystemFlags (obj, args, context) {
|
||||
WIKI.config.flags = {
|
||||
...WIKI.config.flags,
|
||||
...args.flags
|
||||
}
|
||||
await WIKI.configSvc.applyFlags()
|
||||
await WIKI.configSvc.saveToDb(['flags'])
|
||||
return {
|
||||
operation: generateSuccess('System Flags applied successfully')
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
WIKI.config.flags = {
|
||||
...WIKI.config.flags,
|
||||
...args.flags
|
||||
}
|
||||
await WIKI.configSvc.applyFlags()
|
||||
await WIKI.configSvc.saveToDb(['flags'])
|
||||
return {
|
||||
operation: generateSuccess('System Flags applied successfully')
|
||||
}
|
||||
} catch (err) {
|
||||
WIKI.logger.warn(err)
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async updateSystemSearch (obj, args, context) {
|
||||
WIKI.config.search = {
|
||||
...WIKI.config.search,
|
||||
termHighlighting: args.termHighlighting ?? WIKI.config.search.termHighlighting,
|
||||
dictOverrides: args.dictOverrides ? JSON.parse(args.dictOverrides) : WIKI.config.search.dictOverrides
|
||||
}
|
||||
// TODO: broadcast config update
|
||||
await WIKI.configSvc.saveToDb(['search'])
|
||||
return {
|
||||
operation: generateSuccess('System Search configuration applied successfully')
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
WIKI.config.search = {
|
||||
...WIKI.config.search,
|
||||
termHighlighting: args.termHighlighting ?? WIKI.config.search.termHighlighting,
|
||||
dictOverrides: args.dictOverrides ? JSON.parse(args.dictOverrides) : WIKI.config.search.dictOverrides
|
||||
}
|
||||
// TODO: broadcast config update
|
||||
await WIKI.configSvc.saveToDb(['search'])
|
||||
return {
|
||||
operation: generateSuccess('System Search configuration applied successfully')
|
||||
}
|
||||
} catch (err) {
|
||||
WIKI.logger.warn(err)
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async updateSystemSecurity (obj, args, context) {
|
||||
WIKI.config.security = _.defaultsDeep(_.omit(args, ['__typename']), WIKI.config.security)
|
||||
// TODO: broadcast config update
|
||||
await WIKI.configSvc.saveToDb(['security'])
|
||||
return {
|
||||
operation: generateSuccess('System Security configuration applied successfully')
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
WIKI.config.security = _.defaultsDeep(_.omit(args, ['__typename']), WIKI.config.security)
|
||||
// TODO: broadcast config update
|
||||
await WIKI.configSvc.saveToDb(['security'])
|
||||
return {
|
||||
operation: generateSuccess('System Security configuration applied successfully')
|
||||
}
|
||||
} catch (err) {
|
||||
WIKI.logger.warn(err)
|
||||
return generateError(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -310,12 +431,16 @@ export default {
|
||||
const total = await WIKI.db.pages.query().count('* as total').first()
|
||||
return _.toSafeInteger(total.total)
|
||||
},
|
||||
async tagsTotal () {
|
||||
const total = await WIKI.db.tags.query().count('* as total').first()
|
||||
return _.toSafeInteger(total.total)
|
||||
},
|
||||
async usersTotal () {
|
||||
const total = await WIKI.db.users.query().count('* as total').first()
|
||||
return _.toSafeInteger(total.total)
|
||||
},
|
||||
async tagsTotal () {
|
||||
const total = await WIKI.db.tags.query().count('* as total').first()
|
||||
async loginsPastDay () {
|
||||
const total = await WIKI.db.users.query().count('* as total').whereRaw('"lastLoginAt" >= NOW() - INTERVAL \'1 DAY\'').first()
|
||||
return _.toSafeInteger(total.total)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ export default {
|
||||
.first()
|
||||
|
||||
if (!folder) {
|
||||
throw new Error('ERR_FOLDER_NOT_EXIST')
|
||||
throw new Error('ERR_INVALID_FOLDER')
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -158,7 +158,7 @@ export default {
|
||||
.first()
|
||||
|
||||
if (!folder) {
|
||||
throw new Error('ERR_FOLDER_NOT_EXIST')
|
||||
throw new Error('ERR_INVALID_FOLDER')
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
+106
-92
@@ -3,6 +3,7 @@ import _, { isNil } from 'lodash-es'
|
||||
import path from 'node:path'
|
||||
import fs from 'fs-extra'
|
||||
import { DateTime } from 'luxon'
|
||||
import bcrypt from 'bcryptjs'
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
@@ -10,6 +11,10 @@ export default {
|
||||
* FETCH ALL USERS
|
||||
*/
|
||||
async users (obj, args, context, info) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['read:users', 'write:users', 'manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
// -> Sanitize limit
|
||||
let limit = args.pageSize ?? 20
|
||||
if (limit < 1 || limit > 1000) {
|
||||
@@ -39,6 +44,12 @@ export default {
|
||||
* FETCH A SINGLE USER
|
||||
*/
|
||||
async userById (obj, args, context, info) {
|
||||
if (!context.req.isAuthenticated || context.req.user.id !== args.id) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['read:users', 'write:users', 'manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
}
|
||||
|
||||
const usr = await WIKI.db.users.query().findById(args.id)
|
||||
|
||||
if (!usr) {
|
||||
@@ -69,31 +80,20 @@ export default {
|
||||
|
||||
return usr
|
||||
},
|
||||
// async profile (obj, args, context, info) {
|
||||
// if (!context.req.user || context.req.user.id < 1 || context.req.user.id === 2) {
|
||||
// throw new WIKI.Error.AuthRequired()
|
||||
// }
|
||||
// const usr = await WIKI.db.users.query().findById(context.req.user.id)
|
||||
// if (!usr.isActive) {
|
||||
// throw new WIKI.Error.AuthAccountBanned()
|
||||
// }
|
||||
|
||||
// const providerInfo = _.get(WIKI.auth.strategies, usr.providerKey, {})
|
||||
|
||||
// usr.providerName = providerInfo.displayName || 'Unknown'
|
||||
// usr.lastLoginAt = usr.lastLoginAt || usr.updatedAt
|
||||
// usr.password = ''
|
||||
// usr.providerId = ''
|
||||
// usr.tfaSecret = ''
|
||||
|
||||
// return usr
|
||||
// },
|
||||
|
||||
async userDefaults (obj, args, context) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['read:users', 'write:users', 'manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return WIKI.config.userDefaults
|
||||
},
|
||||
|
||||
async lastLogins (obj, args, context, info) {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['read:dashboard', 'read:users', 'write:users', 'manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
return WIKI.db.users.query()
|
||||
.select('id', 'name', 'lastLoginAt')
|
||||
.whereNotNull('lastLoginAt')
|
||||
@@ -114,8 +114,12 @@ export default {
|
||||
}
|
||||
},
|
||||
Mutation: {
|
||||
async createUser (obj, args) {
|
||||
async createUser (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['write:users', 'manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
await WIKI.db.users.createNewUser({ ...args, isVerified: true })
|
||||
|
||||
return {
|
||||
@@ -125,8 +129,12 @@ export default {
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async deleteUser (obj, args) {
|
||||
async deleteUser (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
if (args.id <= 2) {
|
||||
throw new WIKI.Error.UserDeleteProtected()
|
||||
}
|
||||
@@ -146,8 +154,12 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
async updateUser (obj, args) {
|
||||
async updateUser (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
await WIKI.db.users.updateUser(args.id, args.patch)
|
||||
|
||||
return {
|
||||
@@ -157,8 +169,12 @@ export default {
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async verifyUser (obj, args) {
|
||||
async verifyUser (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
await WIKI.db.users.query().patch({ isVerified: true }).findById(args.id)
|
||||
|
||||
return {
|
||||
@@ -168,8 +184,12 @@ export default {
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async activateUser (obj, args) {
|
||||
async activateUser (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
await WIKI.db.users.query().patch({ isActive: true }).findById(args.id)
|
||||
|
||||
return {
|
||||
@@ -179,8 +199,12 @@ export default {
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async deactivateUser (obj, args) {
|
||||
async deactivateUser (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
if (args.id <= 2) {
|
||||
throw new Error('Cannot deactivate system accounts.')
|
||||
}
|
||||
@@ -196,8 +220,12 @@ export default {
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async enableUserTFA (obj, args) {
|
||||
async enableUserTFA (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
await WIKI.db.users.query().patch({ tfaIsActive: true, tfaSecret: null }).findById(args.id)
|
||||
|
||||
return {
|
||||
@@ -207,8 +235,12 @@ export default {
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
async disableUserTFA (obj, args) {
|
||||
async disableUserTFA (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
await WIKI.db.users.query().patch({ tfaIsActive: false, tfaSecret: null }).findById(args.id)
|
||||
|
||||
return {
|
||||
@@ -220,13 +252,17 @@ export default {
|
||||
},
|
||||
async changeUserPassword (obj, args, context) {
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
if (args.newPassword?.length < 8) {
|
||||
throw new Error('ERR_PASSWORD_TOO_SHORT')
|
||||
}
|
||||
|
||||
const usr = await WIKI.db.users.query().findById(args.id)
|
||||
if (!usr) {
|
||||
throw new Error('ERR_USER_NOT_FOUND')
|
||||
throw new Error('ERR_INVALID_USER')
|
||||
}
|
||||
const localAuth = await WIKI.db.authentication.getStrategy('local')
|
||||
|
||||
@@ -249,22 +285,22 @@ export default {
|
||||
async updateProfile (obj, args, context) {
|
||||
try {
|
||||
if (!context.req.user || context.req.user.id === WIKI.auth.guest.id) {
|
||||
throw new WIKI.Error.AuthRequired()
|
||||
throw new Error('ERR_NOT_AUTHENTICATED')
|
||||
}
|
||||
const usr = await WIKI.db.users.query().findById(context.req.user.id)
|
||||
if (!usr.isActive) {
|
||||
throw new WIKI.Error.AuthAccountBanned()
|
||||
throw new Error('ERR_INACTIVE_USER')
|
||||
}
|
||||
if (!usr.isVerified) {
|
||||
throw new WIKI.Error.AuthAccountNotVerified()
|
||||
throw new Error('ERR_USER_NOT_VERIFIED')
|
||||
}
|
||||
|
||||
if (args.dateFormat && !['', 'DD/MM/YYYY', 'DD.MM.YYYY', 'MM/DD/YYYY', 'YYYY-MM-DD', 'YYYY/MM/DD'].includes(args.dateFormat)) {
|
||||
throw new WIKI.Error.InputInvalid()
|
||||
throw new Error('ERR_INVALID_INPUT')
|
||||
}
|
||||
|
||||
if (args.appearance && !['site', 'light', 'dark'].includes(args.appearance)) {
|
||||
throw new WIKI.Error.InputInvalid()
|
||||
throw new Error('ERR_INVALID_INPUT')
|
||||
}
|
||||
|
||||
await WIKI.db.users.query().findById(usr.id).patch({
|
||||
@@ -292,47 +328,19 @@ export default {
|
||||
return generateError(err)
|
||||
}
|
||||
},
|
||||
// async changePassword (obj, args, context) {
|
||||
// try {
|
||||
// if (!context.req.user || context.req.user.id < 1 || context.req.user.id === 2) {
|
||||
// throw new WIKI.Error.AuthRequired()
|
||||
// }
|
||||
// const usr = await WIKI.db.users.query().findById(context.req.user.id)
|
||||
// if (!usr.isActive) {
|
||||
// throw new WIKI.Error.AuthAccountBanned()
|
||||
// }
|
||||
// if (!usr.isVerified) {
|
||||
// throw new WIKI.Error.AuthAccountNotVerified()
|
||||
// }
|
||||
// if (usr.providerKey !== 'local') {
|
||||
// throw new WIKI.Error.AuthProviderInvalid()
|
||||
// }
|
||||
// try {
|
||||
// await usr.verifyPassword(args.current)
|
||||
// } catch (err) {
|
||||
// throw new WIKI.Error.AuthPasswordInvalid()
|
||||
// }
|
||||
|
||||
// await WIKI.db.users.updateUser({
|
||||
// id: usr.id,
|
||||
// newPassword: args.new
|
||||
// })
|
||||
|
||||
// const newToken = await WIKI.db.users.refreshToken(usr)
|
||||
|
||||
// return {
|
||||
// responseResult: generateSuccess('Password changed successfully'),
|
||||
// jwt: newToken.token
|
||||
// }
|
||||
// } catch (err) {
|
||||
// return generateError(err)
|
||||
// }
|
||||
// },
|
||||
/**
|
||||
* UPLOAD USER AVATAR
|
||||
*/
|
||||
async uploadUserAvatar (obj, args) {
|
||||
async uploadUserAvatar (obj, args, context) {
|
||||
try {
|
||||
if (!context.req.user || context.req.user.id === WIKI.auth.guest.id) {
|
||||
throw new Error('ERR_NOT_AUTHENTICATED')
|
||||
}
|
||||
const usr = await WIKI.db.users.query().findById(context.req.user.id)
|
||||
if (!usr) {
|
||||
throw new Error('ERR_INVALID_USER')
|
||||
}
|
||||
|
||||
const { filename, mimetype, createReadStream } = await args.image
|
||||
const lowercaseFilename = filename.toLowerCase()
|
||||
WIKI.logger.debug(`Processing user ${args.id} avatar ${lowercaseFilename} of type ${mimetype}...`)
|
||||
@@ -358,7 +366,7 @@ export default {
|
||||
height: 180
|
||||
})
|
||||
// -> Set avatar flag for this user in the DB
|
||||
await WIKI.db.users.query().findById(args.id).patch({ hasAvatar: true })
|
||||
usr.$query().patch({ hasAvatar: true })
|
||||
// -> Save image data to DB
|
||||
const imgBuffer = await fs.readFile(destPath)
|
||||
await WIKI.db.knex('userAvatars').insert({
|
||||
@@ -377,10 +385,18 @@ export default {
|
||||
/**
|
||||
* CLEAR USER AVATAR
|
||||
*/
|
||||
async clearUserAvatar (obj, args) {
|
||||
async clearUserAvatar (obj, args, context) {
|
||||
try {
|
||||
if (!context.req.user || context.req.user.id === WIKI.auth.guest.id) {
|
||||
throw new Error('ERR_NOT_AUTHENTICATED')
|
||||
}
|
||||
const usr = await WIKI.db.users.query().findById(context.req.user.id)
|
||||
if (!usr) {
|
||||
throw new Error('ERR_INVALID_USER')
|
||||
}
|
||||
|
||||
WIKI.logger.debug(`Clearing user ${args.id} avatar...`)
|
||||
await WIKI.db.users.query().findById(args.id).patch({ hasAvatar: false })
|
||||
usr.$query.patch({ hasAvatar: false })
|
||||
await WIKI.db.knex('userAvatars').where({ id: args.id }).del()
|
||||
WIKI.logger.debug(`Cleared user ${args.id} avatar successfully.`)
|
||||
return {
|
||||
@@ -395,19 +411,27 @@ export default {
|
||||
* UPDATE USER DEFAULTS
|
||||
*/
|
||||
async updateUserDefaults (obj, args, context) {
|
||||
WIKI.config.userDefaults = {
|
||||
timezone: args.timezone,
|
||||
dateFormat: args.dateFormat,
|
||||
timeFormat: args.timeFormat
|
||||
}
|
||||
await WIKI.configSvc.saveToDb(['userDefaults'])
|
||||
return {
|
||||
operation: generateSuccess('User defaults saved successfully')
|
||||
try {
|
||||
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) {
|
||||
throw new Error('ERR_FORBIDDEN')
|
||||
}
|
||||
|
||||
WIKI.config.userDefaults = {
|
||||
timezone: args.timezone,
|
||||
dateFormat: args.dateFormat,
|
||||
timeFormat: args.timeFormat
|
||||
}
|
||||
await WIKI.configSvc.saveToDb(['userDefaults'])
|
||||
return {
|
||||
operation: generateSuccess('User defaults saved successfully')
|
||||
}
|
||||
} catch (err) {
|
||||
return generateError(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
User: {
|
||||
async auth (usr) {
|
||||
async auth (usr, args, context) {
|
||||
const authStrategies = await WIKI.db.authentication.getStrategies({ enabledOnly: true })
|
||||
return _.transform(usr.auth, (result, value, key) => {
|
||||
const authStrategy = _.find(authStrategies, ['id', key])
|
||||
@@ -432,14 +456,4 @@ export default {
|
||||
return usr.$relatedQuery('groups')
|
||||
}
|
||||
}
|
||||
// UserProfile: {
|
||||
// async groups (usr) {
|
||||
// const usrGroups = await usr.$relatedQuery('groups')
|
||||
// return usrGroups.map(g => g.name)
|
||||
// },
|
||||
// async pagesTotal (usr) {
|
||||
// const result = await WIKI.db.pages.query().count('* as total').where('creatorId', usr.id).first()
|
||||
// return _.toSafeInteger(result.total)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -7,19 +7,6 @@ extend type Query {
|
||||
localeStrings(locale: String!): JSON
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
downloadLocale(
|
||||
locale: String!
|
||||
): DefaultResponse
|
||||
|
||||
updateLocale(
|
||||
locale: String!
|
||||
autoUpdate: Boolean!
|
||||
namespacing: Boolean!
|
||||
namespaces: [String]!
|
||||
): DefaultResponse
|
||||
}
|
||||
|
||||
# -----------------------------------------------
|
||||
# TYPES
|
||||
# -----------------------------------------------
|
||||
|
||||
@@ -86,6 +86,7 @@ type SystemInfo {
|
||||
isSchedulerHealthy: Boolean
|
||||
latestVersion: String
|
||||
latestVersionReleaseDate: Date
|
||||
loginsPastDay: Int
|
||||
nodeVersion: String
|
||||
operatingSystem: String
|
||||
pagesTotal: Int
|
||||
|
||||
@@ -227,7 +227,7 @@ export class Page extends Model {
|
||||
static async createPage(opts) {
|
||||
// -> Validate site
|
||||
if (!WIKI.sites[opts.siteId]) {
|
||||
throw new Error('ERR_INVALID_SITE_ID')
|
||||
throw new Error('ERR_INVALID_SITE')
|
||||
}
|
||||
|
||||
// -> Remove trailing slash
|
||||
|
||||
+12
-12
@@ -77,7 +77,7 @@ export class Tree extends Model {
|
||||
if (id) {
|
||||
const parent = await WIKI.db.knex('tree').where('id', id).first()
|
||||
if (!parent) {
|
||||
throw new Error('ERR_NONEXISTING_FOLDER_ID')
|
||||
throw new Error('ERR_INVALID_FOLDER')
|
||||
}
|
||||
return parent
|
||||
} else {
|
||||
@@ -105,7 +105,7 @@ export class Tree extends Model {
|
||||
siteId
|
||||
})
|
||||
} else {
|
||||
throw new Error('ERR_NONEXISTING_FOLDER_PATH')
|
||||
throw new Error('ERR_INVALID_FOLDER')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,7 +150,7 @@ export class Tree extends Model {
|
||||
siteId,
|
||||
tags,
|
||||
meta,
|
||||
navigationId: siteId,
|
||||
navigationId: siteId
|
||||
}).returning('*')
|
||||
|
||||
return pageEntry[0]
|
||||
@@ -215,12 +215,12 @@ export class Tree extends Model {
|
||||
static async createFolder ({ parentId, parentPath, pathName, title, locale, siteId }) {
|
||||
// Validate path name
|
||||
if (!rePathName.test(pathName)) {
|
||||
throw new Error('ERR_INVALID_PATH_NAME')
|
||||
throw new Error('ERR_INVALID_PATH')
|
||||
}
|
||||
|
||||
// Validate title
|
||||
if (!reTitle.test(title)) {
|
||||
throw new Error('ERR_INVALID_TITLE')
|
||||
throw new Error('ERR_FOLDER_TITLE_INVALID')
|
||||
}
|
||||
|
||||
parentPath = encodeTreePath(parentPath)
|
||||
@@ -236,7 +236,7 @@ export class Tree extends Model {
|
||||
if (parentId) {
|
||||
parent = await WIKI.db.knex('tree').where('id', parentId).first()
|
||||
if (!parent) {
|
||||
throw new Error('ERR_NONEXISTING_PARENT_ID')
|
||||
throw new Error('ERR_FOLDER_PARENT_INVALID')
|
||||
}
|
||||
parentPath = parent.folderPath ? `${decodeFolderPath(parent.folderPath)}.${parent.fileName}` : parent.fileName
|
||||
} else if (parentPath) {
|
||||
@@ -254,7 +254,7 @@ export class Tree extends Model {
|
||||
type: 'folder'
|
||||
}).first()
|
||||
if (existingFolder) {
|
||||
throw new Error('ERR_FOLDER_ALREADY_EXISTS')
|
||||
throw new Error('ERR_FOLDER_DUPLICATE')
|
||||
}
|
||||
|
||||
// Ensure all ancestors exist
|
||||
@@ -338,17 +338,17 @@ export class Tree extends Model {
|
||||
// Get folder
|
||||
const folder = await WIKI.db.knex('tree').where('id', folderId).first()
|
||||
if (!folder) {
|
||||
throw new Error('ERR_NONEXISTING_FOLDER_ID')
|
||||
throw new Error('ERR_INVALID_FOLDER')
|
||||
}
|
||||
|
||||
// Validate path name
|
||||
if (!rePathName.test(pathName)) {
|
||||
throw new Error('ERR_INVALID_PATH_NAME')
|
||||
throw new Error('ERR_INVALID_PATH')
|
||||
}
|
||||
|
||||
// Validate title
|
||||
if (!reTitle.test(title)) {
|
||||
throw new Error('ERR_INVALID_TITLE')
|
||||
throw new Error('ERR_FOLDER_TITLE_INVALID')
|
||||
}
|
||||
|
||||
WIKI.logger.debug(`Renaming folder ${folder.id} path to ${pathName}...`)
|
||||
@@ -364,7 +364,7 @@ export class Tree extends Model {
|
||||
type: 'folder'
|
||||
}).first()
|
||||
if (existingFolder) {
|
||||
throw new Error('ERR_FOLDER_ALREADY_EXISTS')
|
||||
throw new Error('ERR_FOLDER_DUPLICATE')
|
||||
}
|
||||
|
||||
// Build new paths
|
||||
@@ -406,7 +406,7 @@ export class Tree extends Model {
|
||||
// Get folder
|
||||
const folder = await WIKI.db.knex('tree').where('id', folderId).first()
|
||||
if (!folder) {
|
||||
throw new Error('ERR_NONEXISTING_FOLDER_ID')
|
||||
throw new Error('ERR_INVALID_FOLDER')
|
||||
}
|
||||
const folderPath = folder.folderPath ? `${folder.folderPath}.${folder.fileName}` : folder.fileName
|
||||
WIKI.logger.debug(`Deleting folder ${folder.id} at path ${folderPath}...`)
|
||||
|
||||
@@ -451,7 +451,7 @@ export class User extends Model {
|
||||
})
|
||||
|
||||
if (strategyId !== expectedStrategyId) {
|
||||
throw new Error('ERR_UNEXPECTED_STRATEGY_ID')
|
||||
throw new Error('ERR_INVALID_STRATEGY')
|
||||
}
|
||||
|
||||
if (user) {
|
||||
@@ -461,11 +461,11 @@ export class User extends Model {
|
||||
}
|
||||
return WIKI.db.users.afterLoginChecks(user, strategyId, context, { siteId, skipTFA: true })
|
||||
} else {
|
||||
throw new Error('ERR_INCORRECT_TFA_TOKEN')
|
||||
throw new Error('ERR_TFA_INCORRECT_TOKEN')
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Error('ERR_INVALID_TFA_REQUEST')
|
||||
throw new Error('ERR_TFA_INVALID_REQUEST')
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -481,7 +481,7 @@ export class User extends Model {
|
||||
})
|
||||
|
||||
if (strategyId !== expectedStrategyId) {
|
||||
throw new Error('ERR_UNEXPECTED_STRATEGY_ID')
|
||||
throw new Error('ERR_INVALID_STRATEGY')
|
||||
}
|
||||
|
||||
if (user) {
|
||||
@@ -503,12 +503,12 @@ export class User extends Model {
|
||||
static async changePassword ({ strategyId, siteId, currentPassword, newPassword }, context) {
|
||||
const userId = context.req.user?.id
|
||||
if (!userId) {
|
||||
throw new Error('ERR_USER_NOT_AUTHENTICATED')
|
||||
throw new Error('ERR_NOT_AUTHENTICATED')
|
||||
}
|
||||
|
||||
const user = await WIKI.db.users.query().findById(userId)
|
||||
if (!user) {
|
||||
throw new Error('ERR_USER_NOT_FOUND')
|
||||
throw new Error('ERR_INVALID_USER')
|
||||
}
|
||||
|
||||
if (!newPassword || newPassword.length < 8) {
|
||||
@@ -516,7 +516,7 @@ export class User extends Model {
|
||||
}
|
||||
|
||||
if (!user.auth[strategyId]?.password) {
|
||||
throw new Error('ERR_UNEXPECTED_STRATEGY_ID')
|
||||
throw new Error('ERR_INVALID_STRATEGY')
|
||||
}
|
||||
|
||||
if (await bcrypt.compare(currentPassword, user.auth[strategyId].password) !== true) {
|
||||
@@ -627,7 +627,7 @@ export class User extends Model {
|
||||
// Check if email already exists
|
||||
const usr = await WIKI.db.users.query().findOne({ email })
|
||||
if (usr) {
|
||||
throw new Error('ERR_ACCOUNT_ALREADY_EXIST')
|
||||
throw new Error('ERR_DUPLICATE_ACCOUNT_EMAIL')
|
||||
}
|
||||
|
||||
WIKI.logger.debug(`Creating new user account for ${email}...`)
|
||||
|
||||
@@ -21,9 +21,9 @@ export default {
|
||||
if (user) {
|
||||
const authStrategyData = user.auth[strategyId]
|
||||
if (!authStrategyData) {
|
||||
throw new Error('ERR_INVALID_STRATEGY_ID')
|
||||
throw new Error('ERR_INVALID_STRATEGY')
|
||||
} else if (await bcrypt.compare(uPassword, authStrategyData.password) !== true) {
|
||||
throw new Error('ERR_AUTH_FAILED')
|
||||
throw new Error('ERR_LOGIN_FAILED')
|
||||
} else if (!user.isActive) {
|
||||
throw new Error('ERR_INACTIVE_USER')
|
||||
} else if (authStrategyData.restrictLogin) {
|
||||
@@ -34,7 +34,7 @@ export default {
|
||||
done(null, user)
|
||||
}
|
||||
} else {
|
||||
throw new Error('ERR_AUTH_FAILED')
|
||||
throw new Error('ERR_LOGIN_FAILED')
|
||||
}
|
||||
} catch (err) {
|
||||
done(err, null)
|
||||
|
||||
Reference in New Issue
Block a user