Initial commit
This commit is contained in:
87
packages/core-dsr/src/payload-processing-restriction.ts
Normal file
87
packages/core-dsr/src/payload-processing-restriction.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
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<string, unknown>;
|
||||
|
||||
type PayloadAPI = {
|
||||
find(args: {
|
||||
collection: string;
|
||||
where: Record<string, unknown>;
|
||||
overrideAccess: true;
|
||||
limit: number;
|
||||
}): Promise<{ docs: PayloadDoc[] }>;
|
||||
update(args: {
|
||||
collection: string;
|
||||
id: string;
|
||||
data: Record<string, unknown>;
|
||||
overrideAccess: true;
|
||||
}): Promise<PayloadDoc>;
|
||||
};
|
||||
|
||||
type GetPayload = (args: { config: SanitizedConfig }) => Promise<PayloadAPI>;
|
||||
|
||||
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<void> {
|
||||
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<boolean> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user