fiddy/apps/web/lib/server/group-audit.ts
2026-02-11 23:45:15 -08:00

91 lines
2.6 KiB
TypeScript

if (process.env.NODE_ENV !== "test")
require("server-only");
import getPool from "@/lib/server/db";
import type { GroupRole } from "@/lib/server/group-access";
import { requireGroupAdmin } from "@/lib/server/group-access";
export type GroupAuditEvent = {
groupId: number;
actorUserId: number | null;
actorRole: GroupRole | null;
eventType: string;
requestId: string;
ip?: string | null;
userAgent?: string | null;
success?: boolean;
errorCode?: string | null;
metadata?: Record<string, unknown>;
};
export async function recordGroupAudit(event: GroupAuditEvent) {
const pool = getPool();
await pool.query(
`insert into group_audit_log(
group_id,
actor_user_id,
actor_role,
event_type,
request_id,
ip,
user_agent,
success,
error_code,
metadata
) values($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)`,
[
event.groupId,
event.actorUserId,
event.actorRole,
event.eventType,
event.requestId,
event.ip ?? null,
event.userAgent ?? null,
event.success ?? true,
event.errorCode ?? null,
event.metadata ?? {}
]
);
}
type GroupAuditRow = {
id: number;
group_id: number;
actor_user_id: number | null;
actor_role: GroupRole | null;
event_type: string;
request_id: string;
ip: string | null;
user_agent: string | null;
success: boolean;
error_code: string | null;
metadata: Record<string, unknown>;
created_at: string;
};
export async function listGroupAudit(input: { userId: number; groupId: number }) {
await requireGroupAdmin(input.userId, input.groupId);
const pool = getPool();
const { rows } = await pool.query(
`select id, group_id, actor_user_id, actor_role, event_type, request_id, ip, user_agent, success, error_code, metadata, created_at
from group_audit_log
where group_id=$1
order by created_at desc
limit 100`,
[input.groupId]
);
return rows.map((row: GroupAuditRow) => ({
id: Number(row.id),
groupId: Number(row.group_id),
actorUserId: row.actor_user_id === null ? null : Number(row.actor_user_id),
actorRole: row.actor_role,
eventType: row.event_type,
requestId: row.request_id,
ip: row.ip,
userAgent: row.user_agent,
success: Boolean(row.success),
errorCode: row.error_code,
metadata: row.metadata || {},
createdAt: row.created_at
}));
}