From ce42414214a114b25a390a808d957d08a6e4aa0f Mon Sep 17 00:00:00 2001 From: NeilClack Date: Tue, 7 Jul 2026 22:10:54 -0500 Subject: [PATCH] Restrict proclamation editing and content to Super admins only - Only roleId <= 1 (SUPER) can create/edit/delete proclamations - Content field is stripped from records for non-Super users - Content field is hidden from the form for non-Super users - Server actions reject upsert/delete from non-Super users --- .../admin/proclamations/+page.server.ts | 22 ++++++++++++ .../admin/proclamations/+page.svelte | 9 +++-- .../proclamations/ProclamationForm.svelte | 36 ++++++++++--------- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/routes/(protected)/admin/proclamations/+page.server.ts b/src/routes/(protected)/admin/proclamations/+page.server.ts index 9a15822..dc2e89c 100644 --- a/src/routes/(protected)/admin/proclamations/+page.server.ts +++ b/src/routes/(protected)/admin/proclamations/+page.server.ts @@ -8,9 +8,24 @@ import * as Schemas from '$lib/svelte-admin/schemas'; const config = getModelConfig('proclamations')!; +function viewerRoleId(locals: App.Locals): number { + return (locals.user as { roleId?: number } | null)?.roleId ?? 4; +} + +function isSuper(locals: App.Locals): boolean { + return viewerRoleId(locals) <= 1; +} + export const load: PageServerLoad = async ({ locals }) => { const base = await loadRecords(locals, config); + // Strip content from non-Super users + if (!isSuper(locals)) { + for (const record of base.records) { + delete record.content; + } + } + const categories = await prisma.proclamationCategory.findMany({ select: { id: true, name: true, parentId: true }, orderBy: { name: 'asc' } @@ -25,6 +40,10 @@ export const actions = { return { success: false, error: 'Unauthorized' }; } + if (!isSuper(locals)) { + return { success: false, error: 'Only Super admins can edit proclamations' }; + } + const formData = await request.formData(); const form = await superValidate(formData, zod4(Schemas.Proclamation)); if (!form.valid) { @@ -70,6 +89,9 @@ export const actions = { return { success: true }; }, delete: async ({ request, locals }) => { + if (!isSuper(locals)) { + return { success: false, error: 'Only Super admins can delete proclamations' }; + } return deleteRecord(request, config, locals); } }; diff --git a/src/routes/(protected)/admin/proclamations/+page.svelte b/src/routes/(protected)/admin/proclamations/+page.svelte index bfa63d5..554f29d 100644 --- a/src/routes/(protected)/admin/proclamations/+page.svelte +++ b/src/routes/(protected)/admin/proclamations/+page.svelte @@ -10,7 +10,9 @@ let { data, form }: PageProps = $props(); const config = getModelConfig('proclamations')!; - const canDelete = $derived((data.adminUser?.roleId ?? 4) <= 2); + const viewerRoleId = $derived(data.adminUser?.roleId ?? 4); + const isSuper = $derived(viewerRoleId <= 1); + const canDelete = $derived(viewerRoleId <= 2); let modalOpen = $state(false); let editingRecord = $state | null>(null); @@ -63,8 +65,8 @@ searchFields={config.searchFields} fieldTypes={config.fieldTypes} singular={config.displayNameSingular} - onRowClick={openEdit} - onNew={openCreate} + onRowClick={isSuper ? openEdit : undefined} + onNew={isSuper ? openCreate : undefined} /> @@ -83,6 +85,7 @@ categories={data.categories} {fieldErrors} {formError} + {isSuper} submitLabel={editingRecord ? 'Update' : 'Create'} /> diff --git a/src/routes/(protected)/admin/proclamations/ProclamationForm.svelte b/src/routes/(protected)/admin/proclamations/ProclamationForm.svelte index 83b24c8..7486f76 100644 --- a/src/routes/(protected)/admin/proclamations/ProclamationForm.svelte +++ b/src/routes/(protected)/admin/proclamations/ProclamationForm.svelte @@ -8,6 +8,7 @@ formError = '', relationOptionsData = {} as Record, categories = [] as { id: number; name: string; parentId: number | null }[], + isSuper = false, action = '?/upsert', submitLabel = 'Save' }: { @@ -16,6 +17,7 @@ formError?: string; relationOptionsData?: Record; categories?: { id: number; name: string; parentId: number | null }[]; + isSuper?: boolean; action?: string; submitLabel?: string; } = $props(); @@ -190,23 +192,25 @@ {/if} -
- -
- + {#if isSuper} +
+ +
+ +
+ {#if fieldErrors.content} +

{fieldErrors.content}

+ {/if}
- {#if fieldErrors.content} -

{fieldErrors.content}

- {/if} -
+ {/if}