feat(audit): integrate auditing for network operations

- Added auditing functionality for network creation, recreation, and deletion actions in the network API.
- Updated the audit log schema to include "network" as a resource type.
- Enhanced the network router to log actions with relevant metadata, improving traceability and accountability for network management operations.
This commit is contained in:
Mauricio Siu
2026-07-27 00:42:05 -06:00
parent ec74035c70
commit 29fcc74ca5
3 changed files with 41 additions and 5 deletions
@@ -95,6 +95,7 @@ const RESOURCE_LABELS: Record<string, string> = {
notification: "Notification", notification: "Notification",
settings: "Settings", settings: "Settings",
session: "Session", session: "Session",
network: "Network",
}; };
function MetadataCell({ metadata }: { metadata: string | null }) { function MetadataCell({ metadata }: { metadata: string | null }) {
+38 -4
View File
@@ -18,6 +18,7 @@ import {
apiRemoveNetwork, apiRemoveNetwork,
network as networkTable, network as networkTable,
} from "@/server/db/schema"; } from "@/server/db/schema";
import { audit } from "../utils/audit";
export const networkRouter = createTRPCRouter({ export const networkRouter = createTRPCRouter({
all: protectedProcedure all: protectedProcedure
@@ -50,7 +51,17 @@ export const networkRouter = createTRPCRouter({
create: protectedProcedure create: protectedProcedure
.input(apiCreateNetwork) .input(apiCreateNetwork)
.mutation(async ({ ctx, input }) => { .mutation(async ({ ctx, input }) => {
return createNetwork(input, ctx.session.activeOrganizationId); const created = await createNetwork(
input,
ctx.session.activeOrganizationId,
);
await audit(ctx, {
action: "create",
resourceType: "network",
resourceId: created.networkId,
resourceName: created.name,
});
return created;
}), }),
networksToSync: protectedProcedure networksToSync: protectedProcedure
.input(z.object({ serverId: z.string().optional() })) .input(z.object({ serverId: z.string().optional() }))
@@ -69,11 +80,20 @@ export const networkRouter = createTRPCRouter({
}), }),
) )
.mutation(async ({ ctx, input }) => { .mutation(async ({ ctx, input }) => {
return importDockerNetworks( const result = await importDockerNetworks(
ctx.session.activeOrganizationId, ctx.session.activeOrganizationId,
input.serverId ?? null, input.serverId ?? null,
input.names, input.names,
); );
if (result.imported.length > 0) {
await audit(ctx, {
action: "create",
resourceType: "network",
resourceName: result.imported.join(", "),
metadata: { imported: result.imported },
});
}
return result;
}), }),
inspect: protectedProcedure inspect: protectedProcedure
@@ -99,7 +119,14 @@ export const networkRouter = createTRPCRouter({
message: "Network not found", message: "Network not found",
}); });
} }
return recreateNetwork(input.networkId); const recreated = await recreateNetwork(input.networkId);
await audit(ctx, {
action: "reload",
resourceType: "network",
resourceId: recreated.networkId,
resourceName: recreated.name,
});
return recreated;
}), }),
remove: protectedProcedure remove: protectedProcedure
@@ -112,6 +139,13 @@ export const networkRouter = createTRPCRouter({
message: "Not authorized to delete this network", message: "Not authorized to delete this network",
}); });
} }
return removeNetwork(input.networkId); const removed = await removeNetwork(input.networkId);
await audit(ctx, {
action: "delete",
resourceType: "network",
resourceId: removed.networkId,
resourceName: removed.name,
});
return removed;
}), }),
}); });
+2 -1
View File
@@ -91,4 +91,5 @@ export type AuditResourceType =
| "cluster" | "cluster"
| "mount" | "mount"
| "application" | "application"
| "compose"; | "compose"
| "network";