From 420ff1e715f60b3906a81db0da5aa864227a59eb Mon Sep 17 00:00:00 2001 From: Catherine Renelle <32781029+catrenelle@users.noreply.github.com> Date: Thu, 26 Feb 2026 20:00:51 -0500 Subject: [PATCH] Hide SITE_ADMIN from tenant admin, add Site Admin nav link - Tenant admin user list filters out SITE_ADMIN users (server-side) - API guard prevents tenant admins from modifying SITE_ADMIN users - Tenant admins cannot change their own role (prevents self-demotion) - Nav bar shows separate "Site Admin" link for SITE_ADMIN users - Both desktop and mobile nav updated Co-Authored-By: Claude Opus 4.6 --- src/routes/+layout.svelte | 17 ++++++++++++++ src/routes/admin/+page.server.ts | 3 +-- src/routes/admin/+page.svelte | 23 ++++++++++--------- .../api/admin/users/[userId]/+server.ts | 5 ++++ 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index b321cf8..abc48f2 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -62,6 +62,14 @@ {/if} {#if data.user} + {#if data.user.globalRole === 'SITE_ADMIN'} + + Site Admin + + {/if} {#if data.user.tenantRole === 'ADMIN' || data.user.globalRole === 'SITE_ADMIN'}
(mobileMenuOpen = false)}>{data.user.name} + {#if data.user.globalRole === 'SITE_ADMIN'} + (mobileMenuOpen = false)} + > + Site Admin + + {/if} {#if data.user.tenantRole === 'ADMIN' || data.user.globalRole === 'SITE_ADMIN'} { const { users, boards, tags, categories } = await withTenant(tenant.id, async (tx) => { const [users, boards, tags, categories] = await Promise.all([ tx.user.findMany({ - where: { tenantId: tenant.id }, + where: { tenantId: tenant.id, globalRole: { not: 'SITE_ADMIN' } }, select: { id: true, name: true, email: true, tenantRole: true, - globalRole: true, createdAt: true }, orderBy: { createdAt: 'asc' } diff --git a/src/routes/admin/+page.svelte b/src/routes/admin/+page.svelte index eee4983..5d969a3 100644 --- a/src/routes/admin/+page.svelte +++ b/src/routes/admin/+page.svelte @@ -141,20 +141,21 @@ {user.name} - {#if user.globalRole === 'SITE_ADMIN'} - SITE ADMIN - {/if} {user.email} - + {#if user.id === data.user?.id} + {user.tenantRole === 'ADMIN' ? 'Admin' : 'Member'} + {:else} + + {/if} {formatDate(user.createdAt)} diff --git a/src/routes/api/admin/users/[userId]/+server.ts b/src/routes/api/admin/users/[userId]/+server.ts index 4ec7f56..8bff5de 100644 --- a/src/routes/api/admin/users/[userId]/+server.ts +++ b/src/routes/api/admin/users/[userId]/+server.ts @@ -22,6 +22,11 @@ export const PATCH: RequestHandler = async ({ params, request, locals }) => { }); if (!targetUser) throw error(404, 'User not found'); + // Tenant admins cannot modify SITE_ADMIN users + if (targetUser.globalRole === 'SITE_ADMIN') { + throw error(403, 'Cannot modify a site admin'); + } + // Prevent demoting the last tenant admin if (targetUser.tenantRole === 'ADMIN' && result.data.tenantRole === 'MEMBER') { const adminCount = await tx.user.count({