Skip to content

Commit

Permalink
feat: add permission check to resolvers (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
NGPixel committed Sep 1, 2024
1 parent 1aa5854 commit 1c65d23
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 31 deletions.
2 changes: 0 additions & 2 deletions server/controllers/auth.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* global WIKI */

import express from 'express'
import ExpressBrute from 'express-brute'
import BruteKnex from '../helpers/brute-knex.mjs'
Expand Down
1 change: 1 addition & 0 deletions server/db/migrations/3.0.0.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ export async function up (knex) {
private: certs.privateKey
},
secret,
rootAdminGroupId: groupAdminId,
rootAdminUserId: userAdminId,
guestUserId: userGuestId
}
Expand Down
8 changes: 8 additions & 0 deletions server/graph/resolvers/analytics.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { generateError, generateSuccess } from '../../helpers/graph.mjs'
export default {
Query: {
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)
providers = providers.map(stg => {
const providerInfo = find(WIKI.data.analytics, ['key', stg.key]) || {}
Expand All @@ -28,6 +32,10 @@ export default {
Mutation: {
async updateAnalyticsProviders(obj, args, context) {
try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}

for (let str of args.providers) {
await WIKI.db.analytics.query().patch({
isEnabled: str.isEnabled,
Expand Down
6 changes: 6 additions & 0 deletions server/graph/resolvers/asset.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { pipeline } from 'node:stream/promises'
export default {
Query: {
async assetById(obj, args, context) {
// FIXME: Perm
const asset = await WIKI.db.assets.query().findById(args.id)
if (asset) {
return asset
Expand Down Expand Up @@ -145,6 +146,7 @@ export default {
*/
async uploadAssets(obj, args, context) {
try {
// FIXME: Perm
// -> Get Folder
let folder = {}
if (args.folderId || args.folderPath) {
Expand Down Expand Up @@ -380,6 +382,10 @@ export default {
*/
async flushTempUploads(obj, args, context) {
try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}

await WIKI.db.assets.flushTempUploads()
return {
operation: generateSuccess('Temporary Uploads have been flushed successfully.')
Expand Down
10 changes: 9 additions & 1 deletion server/graph/resolvers/authentication.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ export default {
/**
* 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 => ({
...stg,
isAvailable: stg.isAvailable === true
Expand All @@ -56,6 +60,10 @@ export default {
* Fetch active authentication strategies
*/
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 })
return strategies.map(a => {
const str = _.find(WIKI.data.authentication, ['key', a.module]) || {}
Expand Down
8 changes: 8 additions & 0 deletions server/graph/resolvers/comment.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export default {
* Fetch list of Comments Providers
*/
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()
return providers.map(provider => {
const providerInfo = _.find(WIKI.data.commentProviders, ['key', provider.key]) || {}
Expand Down Expand Up @@ -137,6 +141,10 @@ export default {
*/
async updateCommentsProviders(obj, args, context) {
try {
if (!WIKI.auth.checkAccess(context.req.user, ['manage:system'])) {
throw new Error('ERR_FORBIDDEN')
}

for (let provider of args.providers) {
await WIKI.db.commentProviders.query().patch({
isEnabled: provider.isEnabled,
Expand Down
42 changes: 34 additions & 8 deletions server/graph/resolvers/group.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { generateError, generateSuccess } from '../../helpers/graph.mjs'
import { generateSuccess } from '../../helpers/graph.mjs'
import safeRegex from 'safe-regex'
import _ from 'lodash-es'
import { v4 as uuid } from 'uuid'
Expand All @@ -8,7 +8,10 @@ export default {
/**
* 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(
'groups.*',
WIKI.db.groups.relatedQuery('users').count().as('userCount')
Expand All @@ -17,7 +20,10 @@ export default {
/**
* 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)
}
},
Expand All @@ -26,8 +32,12 @@ export default {
* ASSIGN USER TO GROUP
*/
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
if (args.userId === 2) {
if (args.userId === WIKI.config.auth.guestUserId) {
throw new Error('Cannot assign the Guest user to a group.')
}

Expand Down Expand Up @@ -78,6 +88,10 @@ export default {
* CREATE NEW GROUP
*/
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({
name: args.name,
permissions: JSON.stringify(WIKI.data.groups.defaultPermissions),
Expand All @@ -97,8 +111,12 @@ export default {
/**
* DELETE GROUP
*/
async deleteGroup (obj, args) {
if (args.id === 1 || args.id === 2) {
async deleteGroup (obj, args, { req }) {
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.')
}

Expand All @@ -117,11 +135,15 @@ export default {
/**
* 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) {
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.')
}
const grp = await WIKI.db.groups.query().findById(args.groupId)
Expand All @@ -145,6 +167,10 @@ export default {
* UPDATE GROUP
*/
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
if (_.some(args.pageRules, pr => {
return pr.match === 'REGEX' && !safeRegex(pr.path)
Expand Down
26 changes: 13 additions & 13 deletions server/graph/resolvers/user.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default {
* FETCH ALL USERS
*/
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')
}

Expand Down Expand Up @@ -51,7 +51,7 @@ export default {
*/
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'])) {
if (!WIKI.auth.checkAccess(context.req.user, ['read:users', 'write:users', 'manage:users', 'manage:groups'])) {
throw new Error('ERR_FORBIDDEN')
}
}
Expand Down Expand Up @@ -88,7 +88,7 @@ export default {
},

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')
}

Expand Down Expand Up @@ -134,7 +134,7 @@ export default {
Mutation: {
async createUser (obj, args, context) {
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')
}

Expand All @@ -149,7 +149,7 @@ export default {
},
async deleteUser (obj, args, context) {
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')
}

Expand All @@ -174,7 +174,7 @@ export default {
},
async updateUser (obj, args, context) {
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')
}

Expand All @@ -189,7 +189,7 @@ export default {
},
async verifyUser (obj, args, context) {
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')
}

Expand All @@ -204,7 +204,7 @@ export default {
},
async activateUser (obj, args, context) {
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')
}

Expand All @@ -219,7 +219,7 @@ export default {
},
async deactivateUser (obj, args, context) {
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')
}

Expand All @@ -240,7 +240,7 @@ export default {
},
async enableUserTFA (obj, args, context) {
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')
}

Expand All @@ -255,7 +255,7 @@ export default {
},
async disableUserTFA (obj, args, context) {
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')
}

Expand All @@ -270,7 +270,7 @@ export default {
},
async changeUserPassword (obj, args, context) {
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')
}

Expand Down Expand Up @@ -430,7 +430,7 @@ export default {
*/
async updateUserDefaults (obj, args, context) {
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')
}

Expand Down
7 changes: 4 additions & 3 deletions ux/src/layouts/AdminLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ q-layout.admin(view='hHh Lpr lff')
q-item-section {{ t('admin.metrics.title') }}
q-item-section(side)
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-icon(name='img:/_assets/icons/fluent-rich-text-converter.svg')
q-item-section {{ t('admin.rendering.title') }}
Expand Down Expand Up @@ -416,14 +416,15 @@ onMounted(async () => {
}
> .q-layout-container {
border-radius: 6px;
box-shadow: 0 0 0 1px rgba(0,0,0,.5);
@at-root .body--light & {
background-image: linear-gradient(to bottom, $dark-5 10px, $grey-3 11px, $grey-4);
}
@at-root .body--dark & {
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);
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions ux/src/layouts/MainLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
q-layout(view='hHh Lpr lff')
header-nav
q-drawer.bg-sidebar(
:modelValue='isSidebarShown'
:model-value='isSidebarShown'
:show-if-above='siteStore.theme.sidebarPosition !== `off`'
:width='isSidebarMini ? 56 : 255'
:side='siteStore.theme.sidebarPosition === `right` ? `right` : `left`'
Expand Down Expand Up @@ -63,7 +63,7 @@ q-layout(view='hHh Lpr lff')
:aria-label='commonStore.locale'
size='sm'
)
locale-selector-menu(:offset="[-5, 5]")
locale-selector-menu(:offset='[-5, 5]')
q-separator(vertical)
q-btn.q-px-sm.col(
flat
Expand Down Expand Up @@ -232,14 +232,15 @@ body.body--dark {
}
> .q-layout-container {
border-radius: 6px;
box-shadow: 0 0 30px 0 rgba(0,0,0,.3);
@at-root .body--light & {
background-image: linear-gradient(to bottom, $dark-5 10px, $grey-3 11px, $grey-4);
}
@at-root .body--dark & {
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);
}
}
}
Expand Down

0 comments on commit 1c65d23

Please sign in to comment.