feat(audit-log-stream): backend rework

This commit is contained in:
x032205
2025-09-04 15:54:46 -04:00
parent d5e99d7fc6
commit fcb931670a
28 changed files with 1120 additions and 538 deletions
@@ -0,0 +1,67 @@
import { RawAxiosRequestHeaders } from "axios";
import { request } from "@app/lib/config/request";
import { BadRequestError } from "@app/lib/errors";
import { blockLocalAndPrivateIpAddresses } from "@app/lib/validator";
import { AUDIT_LOG_STREAM_TIMEOUT } from "../../audit-log/audit-log-queue";
import { TLogStreamFactoryStreamLog, TLogStreamFactoryValidateCredentials } from "../audit-log-stream-types";
import { TCustomProviderCredentials } from "./custom-provider-types";
export const CustomProviderFactory = () => {
const validateCredentials: TLogStreamFactoryValidateCredentials<TCustomProviderCredentials> = async ({
credentials
}) => {
const { url, headers } = credentials;
await blockLocalAndPrivateIpAddresses(url);
const streamHeaders: RawAxiosRequestHeaders = { "Content-Type": "application/json" };
if (headers.length) {
headers.forEach(({ key, value }) => {
streamHeaders[key] = value;
});
}
await request
.post(
url,
{ ping: "ok" },
{
headers: streamHeaders,
timeout: AUDIT_LOG_STREAM_TIMEOUT,
signal: AbortSignal.timeout(AUDIT_LOG_STREAM_TIMEOUT)
}
)
.catch((err) => {
throw new BadRequestError({ message: `Failed to connect with upstream source: ${(err as Error)?.message}` });
});
return credentials;
};
const streamLog: TLogStreamFactoryStreamLog<TCustomProviderCredentials> = async ({ credentials, auditLog }) => {
const { url, headers } = credentials;
await blockLocalAndPrivateIpAddresses(url);
const streamHeaders: RawAxiosRequestHeaders = { "Content-Type": "application/json" };
if (headers.length) {
headers.forEach(({ key, value }) => {
streamHeaders[key] = value;
});
}
await request.post(url, auditLog, {
headers: streamHeaders,
timeout: AUDIT_LOG_STREAM_TIMEOUT,
signal: AbortSignal.timeout(AUDIT_LOG_STREAM_TIMEOUT)
});
};
return {
validateCredentials,
streamLog
};
};
@@ -0,0 +1,8 @@
import { LogProvider } from "../audit-log-stream-enums";
export const getCustomProviderListItem = () => {
return {
name: "Custom" as const,
provider: LogProvider.Custom as const
};
};
@@ -0,0 +1,32 @@
import { z } from "zod";
import { LogProvider } from "../audit-log-stream-enums";
export const CustomProviderCredentialsSchema = z.object({
url: z.string().url().trim().min(1).max(255),
headers: z
.object({
key: z.string().min(1),
value: z.string().min(1)
})
.array()
});
export const CustomProviderSchema = z.object({
provider: z.literal(LogProvider.Custom),
credentials: CustomProviderCredentialsSchema
});
export const SanitizedCustomProviderSchema = z.object({
provider: z.literal(LogProvider.Custom),
credentials: z.object({
url: CustomProviderCredentialsSchema.shape.url,
// Only return header keys
headers: CustomProviderCredentialsSchema.shape.headers.element.pick({ key: true }).array()
})
});
export const CustomProviderListItemSchema = z.object({
name: z.literal("Custom"),
provider: z.literal(LogProvider.Custom)
});
@@ -0,0 +1,7 @@
import { z } from "zod";
import { CustomProviderCredentialsSchema, CustomProviderSchema } from "./custom-provider-schemas";
export type TCustomProvider = z.infer<typeof CustomProviderSchema>;
export type TCustomProviderCredentials = z.infer<typeof CustomProviderCredentialsSchema>;