import { getPayload as _getPayload } from "payload"; import type { SanitizedConfig } from "payload"; import type { AuditLogProtocol } from "@repo/core-shared/di"; import type { IProcessingRestriction } from "./processing-restriction.interface"; type PayloadDoc = Record; type PayloadAPI = { find(args: { collection: string; where: Record; overrideAccess: true; limit: number; }): Promise<{ docs: PayloadDoc[] }>; update(args: { collection: string; id: string; data: Record; overrideAccess: true; }): Promise; }; type GetPayload = (args: { config: SanitizedConfig }) => Promise; const USERS_COLLECTION = "users"; const RESTRICTION_FIELD = "processingRestrictedAt"; /** * Payload-backed IProcessingRestriction. Toggles and reads the * `processingRestrictedAt` date field on the subject's user record. * * Emits RESTRICT or UNRESTRICT audit entries on every state change. * The `subjectId` is the document ID in the `users` collection. */ export class PayloadProcessingRestriction implements IProcessingRestriction { constructor( private readonly config: SanitizedConfig, private readonly auditLog: AuditLogProtocol, private readonly getPayloadFn: GetPayload = _getPayload as unknown as GetPayload, ) {} async setRestriction(subjectId: string, granted: boolean): Promise { const payload = await this.getPayloadFn({ config: this.config }); await payload.update({ collection: USERS_COLLECTION, id: subjectId, data: { [RESTRICTION_FIELD]: granted ? new Date().toISOString() : null }, overrideAccess: true, }); await this.auditLog.record({ actorId: subjectId, actorType: "user", actorRoles: [], action: granted ? "RESTRICT" : "UNRESTRICT", resource: { type: USERS_COLLECTION, id: subjectId }, changedFields: [RESTRICTION_FIELD], at: new Date(), scope: { feature: "core-dsr", environment: process.env["NODE_ENV"] ?? "development", tenant: "default", }, from: { ipTruncated: "system", userAgent: "system" }, containsPii: false, outcome: "success", }); } async isRestricted(subjectId: string): Promise { const payload = await this.getPayloadFn({ config: this.config }); const result = await payload.find({ collection: USERS_COLLECTION, where: { id: { equals: subjectId } }, overrideAccess: true, limit: 1, }); const doc = result.docs[0]; if (!doc) return false; const restrictedAt = doc[RESTRICTION_FIELD]; return restrictedAt !== null && restrictedAt !== undefined; } }