diff --git a/src/routes/lists/[id]/+page.server.ts b/src/routes/lists/[id]/+page.server.ts index c0cada98..9ce89dfd 100644 --- a/src/routes/lists/[id]/+page.server.ts +++ b/src/routes/lists/[id]/+page.server.ts @@ -1,6 +1,7 @@ import { error, redirect } from "@sveltejs/kit"; import type { PageServerLoad } from "./$types"; import { getConfig } from "$lib/server/config"; +import { Role } from "$lib/schema"; import { getFormatter } from "$lib/server/i18n"; import { getById, getItems, type GetItemsOptions } from "$lib/server/list"; import { getActiveMembership } from "$lib/server/group-membership"; @@ -60,6 +61,8 @@ export const load = (async ({ params, url, locals, depends, cookies }) => { activeGroupId: list.groupId }, isManager: list.managers.find(({ userId }) => userId === locals.user?.id) !== undefined, + // Expose whether the current user is a site admin so the UI can show admin-only controls + isAdmin: locals.user ? locals.user.roleId === Role.ADMIN : false, items }, loggedInUser: locals.user @@ -67,7 +70,8 @@ export const load = (async ({ params, url, locals, depends, cookies }) => { id: locals.user.id, username: locals.user.username, name: locals.user.name, - activeGroupId: activeMembership!.groupId + activeGroupId: activeMembership!.groupId, + roleId: locals.user.roleId } : undefined, listMode: config.listMode, diff --git a/src/routes/lists/[id]/+page.svelte b/src/routes/lists/[id]/+page.svelte index 333f92f0..85490735 100644 --- a/src/routes/lists/[id]/+page.svelte +++ b/src/routes/lists/[id]/+page.svelte @@ -248,7 +248,7 @@ {#if !reordering} {/if} - {#if data.list.owner.isMe || data.list.isManager} + {#if data.list.owner.isMe || data.list.isManager || data.list.isAdmin} goto(`${new URL(page.url).pathname}/manage`)} /> {/if} diff --git a/src/routes/lists/[id]/manage/+page.server.ts b/src/routes/lists/[id]/manage/+page.server.ts index 58a3a39c..a1df097c 100644 --- a/src/routes/lists/[id]/manage/+page.server.ts +++ b/src/routes/lists/[id]/manage/+page.server.ts @@ -3,6 +3,7 @@ import type { Actions, PageServerLoad } from "./$types"; import { getActiveMembership } from "$lib/server/group-membership"; import { client } from "$lib/server/prisma"; import { getFormatter } from "$lib/server/i18n"; +import { Role } from "$lib/schema"; import { getListPropertiesSchema } from "$lib/server/validations"; import { trimToNull } from "$lib/util"; import { deleteList } from "$lib/server/list"; @@ -55,7 +56,10 @@ export const load: PageServerLoad = async ({ params }) => { .then((list) => list ?? error(404, $t("errors.list-not-found"))); // Logged in users must be in the correct group, or viewing a public list - if (list.owner.id !== user.id && !list.managers.find(({ user: manager }) => manager.id === user.id)) { + const isManager = !!list.managers.find(({ user: manager }) => manager.id === user.id); + const isAdmin = user.roleId === Role.ADMIN; + const isGroupManager = activeMembership.roleId === Role.GROUP_MANAGER; + if (list.owner.id !== user.id && !isManager && !isAdmin && !isGroupManager) { error(401, $t("errors.not-authorized")); } if (list.groupId !== activeMembership.groupId) { @@ -169,7 +173,9 @@ export const actions: Actions = { groupId: activeMembership.groupId } }); - if (user.id !== listOwner?.ownerId) { + const isAdmin = user.roleId === Role.ADMIN; + const isGroupManager = activeMembership.roleId === Role.GROUP_MANAGER; + if (user.id !== listOwner?.ownerId && !isAdmin && !isGroupManager) { error(401, $t("errors.not-authorized")); } @@ -204,7 +210,17 @@ async function canManage(id: string, user: LocalUser, groupId: string) { if (!list) { error(404, $t("errors.list-not-found")); } - if (user.id !== list.ownerId && !list.managers.find(({ userId }) => userId === user.id)) { - error(401, $t("errors.not-authorized")); - } + if (user.id === list.ownerId) return; + if (list.managers.find(({ userId }) => userId === user.id)) return; + if (user.roleId === Role.ADMIN) return; + + const membership = await client.userGroupMembership.findFirst({ + where: { + userId: user.id, + groupId + } + }); + if (membership?.roleId === Role.GROUP_MANAGER) return; + + error(401, $t("errors.not-authorized")); }