From 50a5caf49df741a1894444aa9953b633600c0fd5 Mon Sep 17 00:00:00 2001 From: Benno Tielen Date: Mon, 27 Jul 2026 10:14:15 +0200 Subject: [PATCH] fix: upload announcements --- src/collections/Announcements.ts | 34 ++++++++++++++++++++++++----- src/collections/access/assigned.ts | 35 ++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/collections/Announcements.ts b/src/collections/Announcements.ts index 1e357d5..5888c86 100644 --- a/src/collections/Announcements.ts +++ b/src/collections/Announcements.ts @@ -1,7 +1,13 @@ import { CollectionConfig } from 'payload' -import { hide } from '@/collections/access/admin' import { nextSunday } from '@/utils/sunday' -import { canCreateAssignedWorship, canMutateAssignedWorship } from '@/collections/access/assigned' +import { + canCreateAssignedAnnouncement, + canMutateAssignedAnnouncement, + defaultToOnlyAssigned, + filterAnnouncementsToAssigned, + hideUnlessAssigned, + unassignedAdditions, +} from '@/collections/access/assigned' export const Announcements: CollectionConfig = { slug: 'announcement', @@ -35,6 +41,21 @@ export const Announcements: CollectionConfig = { admin: { allowCreate: false, allowEdit: false + }, + defaultValue: defaultToOnlyAssigned('parishes'), + // A Gläubiger may only add parishes assigned to them; connections + // already on the doc (set by staff) may always be kept. + validate: (value: unknown, options: any) => { + // A custom validate replaces the built-in one, so re-assert `required`. + if (!Array.isArray(value) || value.length === 0) { + return 'Dieses Feld ist erforderlich.' + } + const user = options.req?.user + if (!user || user.roles !== 'user') return true + if (unassignedAdditions(user, 'parishes', value, options.previousValue).length > 0) { + return 'Sie können nur Gemeinden hinzufügen, die Ihnen zugewiesen sind.' + } + return true } }, { @@ -48,14 +69,15 @@ export const Announcements: CollectionConfig = { } ], admin: { - hidden: hide, + hidden: hideUnlessAssigned('parishes'), + baseFilter: filterAnnouncementsToAssigned(), description: 'Die Vermeldungen werden jeden Samstag automatisch veröffentlicht.', defaultColumns: ['date', 'parish', 'document'] }, access: { read: () => true, - create: canCreateAssignedWorship(), - update: canMutateAssignedWorship(), - delete: canMutateAssignedWorship(), + create: canCreateAssignedAnnouncement(), + update: canMutateAssignedAnnouncement(), + delete: canMutateAssignedAnnouncement(), } } \ No newline at end of file diff --git a/src/collections/access/assigned.ts b/src/collections/access/assigned.ts index 4c6f7fe..46c7a77 100644 --- a/src/collections/access/assigned.ts +++ b/src/collections/access/assigned.ts @@ -231,3 +231,38 @@ export const canMutateOccurrenceOfAssignedEvent = (): Access => if (user.roles !== 'user') return false return eventMatchWhere(user, 'event.') } + +// --------------------------------------------------------------------------- +// Announcements: scoped by the `parish` field (hasMany), not by church. +// --------------------------------------------------------------------------- + +/** + * Announcement create access: staff always; role 'user' with at least one + * parish assignment. Which parishes the new announcement may carry is + * enforced by the validate on the `parish` field. + */ +export const canCreateAssignedAnnouncement = (): Access => + ({ req: { user } }) => { + if (!user) return false + if (isStaff(user)) return true + if (user.roles !== 'user') return false + return getAssignedIds(user, 'parishes').length > 0 + } + +/** Announcement update/delete access: staff always; role 'user' only their parishes. */ +export const canMutateAssignedAnnouncement = (): Access => + ({ req: { user } }) => { + if (!user) return false + if (isStaff(user)) return true + if (user.roles !== 'user') return false + const parishIds = getAssignedIds(user, 'parishes') + if (parishIds.length === 0) return false + return { parish: { in: parishIds } } as Where + } + +/** Announcements admin list filter: staff unfiltered; role 'user' only their parishes. */ +export const filterAnnouncementsToAssigned = (): BaseFilter => + ({ req: { user } }) => { + if (!user || user.roles !== 'user') return null + return { parish: { in: getAssignedIds(user, 'parishes') } } + }