feat: add permission check to resolvers (wip)

vega
NGPixel 2 months ago
parent 1aa58546fe
commit 1c65d23408
No known key found for this signature in database
GPG Key ID: B755FB6870B30F63

@ -1,5 +1,3 @@
/* global WIKI */
import express from 'express' import express from 'express'
import ExpressBrute from 'express-brute' import ExpressBrute from 'express-brute'
import BruteKnex from '../helpers/brute-knex.mjs' import BruteKnex from '../helpers/brute-knex.mjs'

@ -475,6 +475,7 @@ export async function up (knex) {
private: certs.privateKey private: certs.privateKey
}, },
secret, secret,
rootAdminGroupId: groupAdminId,
rootAdminUserId: userAdminId, rootAdminUserId: userAdminId,
guestUserId: userGuestId guestUserId: userGuestId
} }

@ -4,6 +4,10 @@ import { generateError, generateSuccess } from '../../helpers/graph.mjs'
export default { export default {
Query: { Query: {
async analyticsProviders(obj, args, context, info) { async analyticsProviders(obj, args, context, info) {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
let providers = await WIKI.db.analytics.getProviders(args.isEnabled) let providers = await WIKI.db.analytics.getProviders(args.isEnabled)
providers = providers.map(stg => { providers = providers.map(stg => {
const providerInfo = find(WIKI.data.analytics, ['key', stg.key]) || {} const providerInfo = find(WIKI.data.analytics, ['key', stg.key]) || {}
@ -28,6 +32,10 @@ export default {
Mutation: { Mutation: {
async updateAnalyticsProviders(obj, args, context) { async updateAnalyticsProviders(obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
for (let str of args.providers) { for (let str of args.providers) {
await WIKI.db.analytics.query().patch({ await WIKI.db.analytics.query().patch({
isEnabled: str.isEnabled, isEnabled: str.isEnabled,

@ -10,6 +10,7 @@ import { pipeline } from 'node:stream/promises'
export default { export default {
Query: { Query: {
async assetById(obj, args, context) { async assetById(obj, args, context) {
// FIXME: Perm
const asset = await WIKI.db.assets.query().findById(args.id) const asset = await WIKI.db.assets.query().findById(args.id)
if (asset) { if (asset) {
return asset return asset
@ -145,6 +146,7 @@ export default {
*/ */
async uploadAssets(obj, args, context) { async uploadAssets(obj, args, context) {
try { try {
// FIXME: Perm
// -> Get Folder // -> Get Folder
let folder = {} let folder = {}
if (args.folderId || args.folderPath) { if (args.folderId || args.folderPath) {
@ -380,6 +382,10 @@ export default {
*/ */
async flushTempUploads(obj, args, context) { async flushTempUploads(obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
await WIKI.db.assets.flushTempUploads() await WIKI.db.assets.flushTempUploads()
return { return {
operation: generateSuccess('Temporary Uploads have been flushed successfully.') operation: generateSuccess('Temporary Uploads have been flushed successfully.')

@ -46,7 +46,11 @@ export default {
/** /**
* Fetch authentication strategies * Fetch authentication strategies
*/ */
async authStrategies () { async authStrategies (obj, args, context) {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
return WIKI.data.authentication.map(stg => ({ return WIKI.data.authentication.map(stg => ({
...stg, ...stg,
isAvailable: stg.isAvailable === true isAvailable: stg.isAvailable === true
@ -56,6 +60,10 @@ export default {
* Fetch active authentication strategies * Fetch active authentication strategies
*/ */
async authActiveStrategies (obj, args, context) { async authActiveStrategies (obj, args, context) {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
const strategies = await WIKI.db.authentication.getStrategies({ enabledOnly: args.enabledOnly }) const strategies = await WIKI.db.authentication.getStrategies({ enabledOnly: args.enabledOnly })
return strategies.map(a => { return strategies.map(a => {
const str = _.find(WIKI.data.authentication, ['key', a.module]) || {} const str = _.find(WIKI.data.authentication, ['key', a.module]) || {}

@ -7,6 +7,10 @@ export default {
* Fetch list of Comments Providers * Fetch list of Comments Providers
*/ */
async commentsProviders(obj, args, context, info) { async commentsProviders(obj, args, context, info) {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
const providers = await WIKI.db.commentProviders.getProviders() const providers = await WIKI.db.commentProviders.getProviders()
return providers.map(provider => { return providers.map(provider => {
const providerInfo = _.find(WIKI.data.commentProviders, ['key', provider.key]) || {} const providerInfo = _.find(WIKI.data.commentProviders, ['key', provider.key]) || {}
@ -137,6 +141,10 @@ export default {
*/ */
async updateCommentsProviders(obj, args, context) { async updateCommentsProviders(obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
for (let provider of args.providers) { for (let provider of args.providers) {
await WIKI.db.commentProviders.query().patch({ await WIKI.db.commentProviders.query().patch({
isEnabled: provider.isEnabled, isEnabled: provider.isEnabled,

@ -1,4 +1,4 @@
import { generateError, generateSuccess } from '../../helpers/graph.mjs' import { generateSuccess } from '../../helpers/graph.mjs'
import safeRegex from 'safe-regex' import safeRegex from 'safe-regex'
import _ from 'lodash-es' import _ from 'lodash-es'
import { v4 as uuid } from 'uuid' import { v4 as uuid } from 'uuid'
@ -8,7 +8,10 @@ export default {
/** /**
* FETCH ALL GROUPS * FETCH ALL GROUPS
*/ */
async groups () { async groups (obj, args, context) {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:groups', 'manage:users', 'manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
return WIKI.db.groups.query().select( return WIKI.db.groups.query().select(
'groups.*', 'groups.*',
WIKI.db.groups.relatedQuery('users').count().as('userCount') WIKI.db.groups.relatedQuery('users').count().as('userCount')
@ -17,7 +20,10 @@ export default {
/** /**
* FETCH A SINGLE GROUP * FETCH A SINGLE GROUP
*/ */
async groupById(obj, args) { async groupById(obj, args, context) {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:groups', 'manage:users', 'manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
return WIKI.db.groups.query().findById(args.id) return WIKI.db.groups.query().findById(args.id)
} }
}, },
@ -26,8 +32,12 @@ export default {
* ASSIGN USER TO GROUP * ASSIGN USER TO GROUP
*/ */
async assignUserToGroup (obj, args, { req }) { async assignUserToGroup (obj, args, { req }) {
if (!WIKI.auth.checkAccess(req.user, ['manage:groups', 'manage:users', 'manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
// Check for guest user // Check for guest user
if (args.userId === 2) { if (args.userId === WIKI.config.auth.guestUserId) {
throw new Error('Cannot assign the Guest user to a group.') throw new Error('Cannot assign the Guest user to a group.')
} }
@ -78,6 +88,10 @@ export default {
* CREATE NEW GROUP * CREATE NEW GROUP
*/ */
async createGroup (obj, args, { req }) { async createGroup (obj, args, { req }) {
if (!WIKI.auth.checkAccess(req.user, ['manage:groups', 'manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
const group = await WIKI.db.groups.query().insertAndFetch({ const group = await WIKI.db.groups.query().insertAndFetch({
name: args.name, name: args.name,
permissions: JSON.stringify(WIKI.data.groups.defaultPermissions), permissions: JSON.stringify(WIKI.data.groups.defaultPermissions),
@ -97,8 +111,12 @@ export default {
/** /**
* DELETE GROUP * DELETE GROUP
*/ */
async deleteGroup (obj, args) { async deleteGroup (obj, args, { req }) {
if (args.id === 1 || args.id === 2) { if (!WIKI.auth.checkAccess(req.user, ['manage:groups', 'manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
if (args.id === WIKI.data.systemIds.guestsGroupId || args.id === WIKI.data.systemIds.usersGroupId || args.id === WIKI.config.auth.rootAdminGroupId) {
throw new Error('Cannot delete this group.') throw new Error('Cannot delete this group.')
} }
@ -117,11 +135,15 @@ export default {
/** /**
* UNASSIGN USER FROM GROUP * UNASSIGN USER FROM GROUP
*/ */
async unassignUserFromGroup (obj, args) { async unassignUserFromGroup (obj, args, { req }) {
if (!WIKI.auth.checkAccess(req.user, ['manage:groups', 'manage:users', 'manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
if (args.userId === 2) { if (args.userId === 2) {
throw new Error('Cannot unassign Guest user') throw new Error('Cannot unassign Guest user')
} }
if (args.userId === 1 && args.groupId === 1) { if (args.userId === WIKI.config.auth.guestUserId && args.groupId === WIKI.data.systemIds.guestsGroupId) {
throw new Error('Cannot unassign Administrator user from Administrators group.') throw new Error('Cannot unassign Administrator user from Administrators group.')
} }
const grp = await WIKI.db.groups.query().findById(args.groupId) const grp = await WIKI.db.groups.query().findById(args.groupId)
@ -145,6 +167,10 @@ export default {
* UPDATE GROUP * UPDATE GROUP
*/ */
async updateGroup (obj, args, { req }) { async updateGroup (obj, args, { req }) {
if (!WIKI.auth.checkAccess(req.user, ['manage:groups', 'manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}
// Check for unsafe regex page rules // Check for unsafe regex page rules
if (_.some(args.pageRules, pr => { if (_.some(args.pageRules, pr => {
return pr.match === 'REGEX' && !safeRegex(pr.path) return pr.match === 'REGEX' && !safeRegex(pr.path)

@ -11,7 +11,7 @@ export default {
* FETCH ALL USERS * FETCH ALL USERS
*/ */
async users (obj, args, context, info) { async users (obj, args, context, info) {
if (!WIKI.auth.checkAccess(context.req.user, ['read:users', 'write:users', 'manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['read:users', 'write:users', 'manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
@ -51,7 +51,7 @@ export default {
*/ */
async userById (obj, args, context, info) { async userById (obj, args, context, info) {
if (!context.req.isAuthenticated || context.req.user.id !== args.id) { if (!context.req.isAuthenticated || context.req.user.id !== args.id) {
if (!WIKI.auth.checkAccess(context.req.user, ['read:users', 'write:users', 'manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['read:users', 'write:users', 'manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
} }
@ -88,7 +88,7 @@ export default {
}, },
async userDefaults (obj, args, context) { async userDefaults (obj, args, context) {
if (!WIKI.auth.checkAccess(context.req.user, ['read:users', 'write:users', 'manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['read:users', 'write:users', 'manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
@ -134,7 +134,7 @@ export default {
Mutation: { Mutation: {
async createUser (obj, args, context) { async createUser (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['write:users', 'manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['write:users', 'manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
@ -149,7 +149,7 @@ export default {
}, },
async deleteUser (obj, args, context) { async deleteUser (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
@ -174,7 +174,7 @@ export default {
}, },
async updateUser (obj, args, context) { async updateUser (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
@ -189,7 +189,7 @@ export default {
}, },
async verifyUser (obj, args, context) { async verifyUser (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
@ -204,7 +204,7 @@ export default {
}, },
async activateUser (obj, args, context) { async activateUser (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
@ -219,7 +219,7 @@ export default {
}, },
async deactivateUser (obj, args, context) { async deactivateUser (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
@ -240,7 +240,7 @@ export default {
}, },
async enableUserTFA (obj, args, context) { async enableUserTFA (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
@ -255,7 +255,7 @@ export default {
}, },
async disableUserTFA (obj, args, context) { async disableUserTFA (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
@ -270,7 +270,7 @@ export default {
}, },
async changeUserPassword (obj, args, context) { async changeUserPassword (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }
@ -430,7 +430,7 @@ export default {
*/ */
async updateUserDefaults (obj, args, context) { async updateUserDefaults (obj, args, context) {
try { try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:users'])) { if (!WIKI.auth.checkAccess(context.req.user, ['manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN') throw new Error('ERR_FORBIDDEN')
} }

@ -188,7 +188,7 @@ q-layout.admin(view='hHh Lpr lff')
q-item-section {{ t('admin.metrics.title') }} q-item-section {{ t('admin.metrics.title') }}
q-item-section(side) q-item-section(side)
status-light(:color='adminStore.info.isMetricsEnabled ? `positive` : `negative`') status-light(:color='adminStore.info.isMetricsEnabled ? `positive` : `negative`')
q-item(to='/_admin/rendering', v-ripple, active-class='bg-primary text-white') q-item(to='/_admin/rendering', v-ripple, active-class='bg-primary text-white', v-if='flagsStore.experimental')
q-item-section(avatar) q-item-section(avatar)
q-icon(name='img:/_assets/icons/fluent-rich-text-converter.svg') q-icon(name='img:/_assets/icons/fluent-rich-text-converter.svg')
q-item-section {{ t('admin.rendering.title') }} q-item-section {{ t('admin.rendering.title') }}
@ -416,14 +416,15 @@ onMounted(async () => {
} }
> .q-layout-container { > .q-layout-container {
border-radius: 6px;
box-shadow: 0 0 0 1px rgba(0,0,0,.5);
@at-root .body--light & { @at-root .body--light & {
background-image: linear-gradient(to bottom, $dark-5 10px, $grey-3 11px, $grey-4); background-image: linear-gradient(to bottom, $dark-5 10px, $grey-3 11px, $grey-4);
} }
@at-root .body--dark & { @at-root .body--dark & {
background-image: linear-gradient(to bottom, $dark-4 10px, $dark-4 11px, $dark-3); background-image: linear-gradient(to bottom, $dark-4 10px, $dark-4 11px, $dark-3);
} }
border-radius: 6px;
box-shadow: 0 0 0 1px rgba(0,0,0,.5);
} }
} }
} }

@ -2,7 +2,7 @@
q-layout(view='hHh Lpr lff') q-layout(view='hHh Lpr lff')
header-nav header-nav
q-drawer.bg-sidebar( q-drawer.bg-sidebar(
:modelValue='isSidebarShown' :model-value='isSidebarShown'
:show-if-above='siteStore.theme.sidebarPosition !== `off`' :show-if-above='siteStore.theme.sidebarPosition !== `off`'
:width='isSidebarMini ? 56 : 255' :width='isSidebarMini ? 56 : 255'
:side='siteStore.theme.sidebarPosition === `right` ? `right` : `left`' :side='siteStore.theme.sidebarPosition === `right` ? `right` : `left`'
@ -63,7 +63,7 @@ q-layout(view='hHh Lpr lff')
:aria-label='commonStore.locale' :aria-label='commonStore.locale'
size='sm' size='sm'
) )
locale-selector-menu(:offset="[-5, 5]") locale-selector-menu(:offset='[-5, 5]')
q-separator(vertical) q-separator(vertical)
q-btn.q-px-sm.col( q-btn.q-px-sm.col(
flat flat
@ -232,14 +232,15 @@ body.body--dark {
} }
> .q-layout-container { > .q-layout-container {
border-radius: 6px;
box-shadow: 0 0 30px 0 rgba(0,0,0,.3);
@at-root .body--light & { @at-root .body--light & {
background-image: linear-gradient(to bottom, $dark-5 10px, $grey-3 11px, $grey-4); background-image: linear-gradient(to bottom, $dark-5 10px, $grey-3 11px, $grey-4);
} }
@at-root .body--dark & { @at-root .body--dark & {
background-image: linear-gradient(to bottom, $dark-4 10px, $dark-4 11px, $dark-3); background-image: linear-gradient(to bottom, $dark-4 10px, $dark-4 11px, $dark-3);
} }
border-radius: 6px;
box-shadow: 0 0 30px 0 rgba(0,0,0,.3);
} }
} }
} }

Loading…
Cancel
Save