From 46351fb17daf1e21a5ae44bca78b9851c8700414 Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Sun, 9 Jun 2024 11:42:01 +0300 Subject: [PATCH] Invert privilege check logic --- src/lib/components/admin/AdminSidebar.svelte | 2 +- src/lib/server/admin-utils.ts | 6 ++++++ src/lib/utils.ts | 10 ++++++++-- src/routes/account/+page.svelte | 2 +- src/routes/ssoadmin/+layout.server.ts | 3 ++- src/routes/ssoadmin/oauth2/+page.server.ts | 4 ++-- src/routes/ssoadmin/oauth2/[uuid]/+page.server.ts | 2 +- .../ssoadmin/oauth2/[uuid]/user/[user]/+page.server.ts | 2 +- src/routes/ssoadmin/oauth2/new/+page.server.ts | 2 +- 9 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/lib/components/admin/AdminSidebar.svelte b/src/lib/components/admin/AdminSidebar.svelte index 1d794ee..12c8f7c 100644 --- a/src/lib/components/admin/AdminSidebar.svelte +++ b/src/lib/components/admin/AdminSidebar.svelte @@ -15,7 +15,7 @@ { href: '/ssoadmin/oauth2', title: $t('admin.menu.oauth2'), - privileges: [['admin:oauth2', 'self:oauth2']] + privileges: ['admin:oauth2', 'self:oauth2'] }, { href: '/ssoadmin/audit', diff --git a/src/lib/server/admin-utils.ts b/src/lib/server/admin-utils.ts index 94bbc16..c8deb24 100644 --- a/src/lib/server/admin-utils.ts +++ b/src/lib/server/admin-utils.ts @@ -3,6 +3,12 @@ import { Users, type UserSession } from './users'; import { hasPrivileges, type RequiredPrivileges } from '$lib/utils'; export class AdminUtils { + /** + * Check a session privileges against a list of required privileges. + * @param session User session with privileges loaded + * @param privileges OR logic, AND's arrays + * @throws 403 error if privileges are not met + */ static checkPrivileges(session: UserSession, privileges: RequiredPrivileges): void { if (!session.privileges?.length || !hasPrivileges(session.privileges, privileges)) { error(403, 'Forbidden resource'); diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 9376327..9db166a 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,9 +1,15 @@ export type RequiredPrivileges = (string | string[])[]; +/** + * Check a list of privileges against a list of required privileges. + * @param list List of privileges + * @param privileges OR logic, AND's arrays + * @returns Satisfies privileges + */ export const hasPrivileges = (list: string[], privileges: RequiredPrivileges) => - privileges.every((item) => { + privileges.some((item) => { if (Array.isArray(item)) { - return item.some((sub) => list.includes(sub)); + return item.every((sub) => list.includes(sub)); } return list.includes(item); }); diff --git a/src/routes/account/+page.svelte b/src/routes/account/+page.svelte index 6cbe98f..961ab54 100644 --- a/src/routes/account/+page.svelte +++ b/src/routes/account/+page.svelte @@ -28,7 +28,7 @@ let internalErrors: string[] = []; $: errors = [...internalErrors, ...(form?.errors?.length ? form.errors : [])]; - $: adminButton = hasPrivileges(data.privileges, [['admin', 'self:oauth2']]); + $: adminButton = hasPrivileges(data.privileges, ['admin', 'self:oauth2']); let usernameRef: HTMLInputElement; let displayRef: HTMLInputElement; diff --git a/src/routes/ssoadmin/+layout.server.ts b/src/routes/ssoadmin/+layout.server.ts index 7b8a8fd..ec4d1d3 100644 --- a/src/routes/ssoadmin/+layout.server.ts +++ b/src/routes/ssoadmin/+layout.server.ts @@ -1,4 +1,5 @@ import { Users } from '$lib/server/users/index.js'; +import { hasPrivileges } from '$lib/utils.js'; import { error, redirect } from '@sveltejs/kit'; export const load = async ({ url, locals }) => { @@ -11,7 +12,7 @@ export const load = async ({ url, locals }) => { // Only users with 'admin' privilege can access const privileges = await Users.getUserPrivileges(currentUser); - if (!privileges.includes('admin')) { + if (!hasPrivileges(privileges, ['admin', 'self:oauth2'])) { return error(404, 'Not Found'); } diff --git a/src/routes/ssoadmin/oauth2/+page.server.ts b/src/routes/ssoadmin/oauth2/+page.server.ts index addb593..d6e5f3e 100644 --- a/src/routes/ssoadmin/oauth2/+page.server.ts +++ b/src/routes/ssoadmin/oauth2/+page.server.ts @@ -9,7 +9,7 @@ const PAGE_SIZE = 20; export const load = async ({ parent, url }) => { const { user } = await parent(); const currentUser = await Users.getBySession(user); - AdminUtils.checkPrivileges(user, [['admin:oauth2', 'self:oauth2']]); + AdminUtils.checkPrivileges(user, ['admin:oauth2', 'self:oauth2']); let limit = PAGE_SIZE; let page = 1; @@ -28,7 +28,7 @@ export const load = async ({ parent, url }) => { const offset = (page - 1) * limit; const fullPrivileges = hasPrivileges(user.privileges, ['admin:oauth2']); - const createPrivileges = hasPrivileges(user.privileges, [['admin:oauth2', 'self:oauth2:create']]); + const createPrivileges = hasPrivileges(user.privileges, ['admin:oauth2', 'self:oauth2:create']); const data = await OAuth2Clients.getClientByAdminUser(currentUser as User, { filter, diff --git a/src/routes/ssoadmin/oauth2/[uuid]/+page.server.ts b/src/routes/ssoadmin/oauth2/[uuid]/+page.server.ts index f378341..01a4167 100644 --- a/src/routes/ssoadmin/oauth2/[uuid]/+page.server.ts +++ b/src/routes/ssoadmin/oauth2/[uuid]/+page.server.ts @@ -375,7 +375,7 @@ export const actions = { export const load = async ({ params: { uuid }, parent }) => { const { user } = await parent(); const currentUser = await Users.getBySession(user); - AdminUtils.checkPrivileges(user, [['admin:oauth2', 'self:oauth2']]); + AdminUtils.checkPrivileges(user, ['admin:oauth2', 'self:oauth2']); const fullPrivileges = hasPrivileges(user.privileges, ['admin:oauth2']); diff --git a/src/routes/ssoadmin/oauth2/[uuid]/user/[user]/+page.server.ts b/src/routes/ssoadmin/oauth2/[uuid]/user/[user]/+page.server.ts index 80897bb..c1303d3 100644 --- a/src/routes/ssoadmin/oauth2/[uuid]/user/[user]/+page.server.ts +++ b/src/routes/ssoadmin/oauth2/[uuid]/user/[user]/+page.server.ts @@ -67,7 +67,7 @@ export const actions = { export const load = async ({ params: { uuid, user: userId }, parent }) => { const { user } = await parent(); const currentUser = await Users.getBySession(user); - AdminUtils.checkPrivileges(user, [['admin:oauth2', 'self:oauth2']]); + AdminUtils.checkPrivileges(user, ['admin:oauth2', 'self:oauth2']); const fullPrivileges = hasPrivileges(user.privileges || [], ['admin:oauth2']); diff --git a/src/routes/ssoadmin/oauth2/new/+page.server.ts b/src/routes/ssoadmin/oauth2/new/+page.server.ts index f96af15..5e8338e 100644 --- a/src/routes/ssoadmin/oauth2/new/+page.server.ts +++ b/src/routes/ssoadmin/oauth2/new/+page.server.ts @@ -48,7 +48,7 @@ export const actions = { export const load = async ({ parent }) => { const { user } = await parent(); - AdminUtils.checkPrivileges(user, [['admin:oauth2', 'self:oauth2:create']]); + AdminUtils.checkPrivileges(user, ['admin:oauth2', 'self:oauth2:create']); return {}; };