diff --git a/apps/dashboard/app/(app)/audit/[bucket]/page.tsx b/apps/dashboard/app/(app)/audit/[bucket]/page.tsx index 237c2af876..e865a0c64b 100644 --- a/apps/dashboard/app/(app)/audit/[bucket]/page.tsx +++ b/apps/dashboard/app/(app)/audit/[bucket]/page.tsx @@ -7,6 +7,7 @@ import { getTenantId } from "@/lib/auth"; import { db } from "@/lib/db"; import { clerkClient } from "@clerk/nextjs"; import type { User } from "@clerk/nextjs/server"; +import type { SelectAuditLog, SelectAuditLogTarget } from "@unkey/db/src/schema"; import { unkeyAuditLogEvents } from "@unkey/schema/src/auditlog"; import { Box, X } from "lucide-react"; import Link from "next/link"; @@ -16,6 +17,7 @@ import { Suspense } from "react"; import { BucketSelect } from "./bucket-select"; import { Filter } from "./filter"; import { Row } from "./row"; + export const dynamic = "force-dynamic"; export const runtime = "edge"; @@ -31,11 +33,34 @@ type Props = { }; }; +type AuditLogWithTargets = SelectAuditLog & { targets: Array }; + /** * Parse searchParam string arrays */ const filterParser = parseAsArrayOf(parseAsString).withDefault([]); +/** + * Utility to map log with targets to log entry + */ +const toLogEntry = (l: AuditLogWithTargets) => ({ + id: l.id, + event: l.event, + time: l.time, + actor: { + id: l.actorId, + name: l.actorName, + type: l.actorType, + }, + location: l.remoteIp, + description: l.display, + targets: l.targets.map((t) => ({ + id: t.id, + type: t.type, + name: t.name, + })), +}); + export default async function AuditPage(props: Props) { const tenantId = getTenantId(); const workspace = await db.query.workspaces.findFirst({ @@ -43,6 +68,7 @@ export default async function AuditPage(props: Props) { and(eq(table.tenantId, tenantId), isNull(table.deletedAt)), with: { ratelimitNamespaces: { + where: (table, { isNull }) => isNull(table.deletedAt), columns: { id: true, name: true, @@ -87,19 +113,6 @@ export default async function AuditPage(props: Props) { }, }, }); - if (!bucket) { - return ( - - - - - Bucket Not Found - - The specified audit log bucket does not exist or you do not have access to it. - - - ); - } return (
@@ -159,29 +172,25 @@ export default async function AuditPage(props: Props) { } > - ({ - id: l.id, - event: l.event, - time: l.time, - actor: { - id: l.actorId, - name: l.actorName, - type: l.actorType, - }, - location: l.remoteIp, - description: l.display, - targets: l.targets.map((t) => ({ - id: t.id, - type: t.type, - name: t.name, - })), - }))} - before={props.searchParams.before ? Number(props.searchParams.before) : undefined} - selectedEvents={selectedEvents} - selectedUsers={selectedUsers} - selectedRootKeys={selectedRootKeys} - /> + {!bucket ? ( + + + + + Bucket Not Found + + The specified audit log bucket does not exist or you do not have access to it. + + + ) : ( + + )}
@@ -359,7 +368,12 @@ const UserFilter: React.FC<{ tenantId: string }> = async ({ tenantId }) => { const RootKeyFilter: React.FC<{ workspaceId: string }> = async ({ workspaceId }) => { const rootKeys = await db.query.keys.findMany({ - where: (table, { eq }) => eq(table.forWorkspaceId, workspaceId), + where: (table, { eq, and, or, isNull, gt }) => + and( + eq(table.forWorkspaceId, workspaceId), + isNull(table.deletedAt), + or(isNull(table.expires), gt(table.expires, new Date())), + ), columns: { id: true, name: true, diff --git a/apps/dashboard/app/(app)/audit/[bucket]/row.tsx b/apps/dashboard/app/(app)/audit/[bucket]/row.tsx index 2a1307ae56..a1694526a1 100644 --- a/apps/dashboard/app/(app)/audit/[bucket]/row.tsx +++ b/apps/dashboard/app/(app)/audit/[bucket]/row.tsx @@ -84,11 +84,11 @@ export const Row: React.FC = ({ auditLog, user }) => {
- + {new Date(auditLog.time).toLocaleDateString()} - - {new Date(auditLog.time).toLocaleTimeString()} + + {new Date(auditLog.time).toLocaleDateString()}
diff --git a/internal/db/src/schema/audit_logs.ts b/internal/db/src/schema/audit_logs.ts index 7b93649054..faaa9b4c6a 100644 --- a/internal/db/src/schema/audit_logs.ts +++ b/internal/db/src/schema/audit_logs.ts @@ -137,3 +137,6 @@ export const auditLogTargetRelations = relations(auditLogTarget, ({ one }) => ({ references: [auditLog.id], }), })); + +export type SelectAuditLog = typeof auditLog.$inferSelect; +export type SelectAuditLogTarget = typeof auditLogTarget.$inferSelect;