fix(auth): generate UUID ids for BetterAuth Prisma writes #427
@@ -524,6 +524,21 @@ describe("auth.config", () => {
|
||||
expect(config.session.updateAge).toBe(7200);
|
||||
});
|
||||
|
||||
it("should configure BetterAuth database ID generation as UUID", () => {
|
||||
const mockPrisma = {} as PrismaClient;
|
||||
createAuth(mockPrisma);
|
||||
|
||||
expect(mockBetterAuth).toHaveBeenCalledOnce();
|
||||
const config = mockBetterAuth.mock.calls[0][0] as {
|
||||
advanced: {
|
||||
database: {
|
||||
generateId: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
expect(config.advanced.database.generateId).toBe("uuid");
|
||||
});
|
||||
|
||||
it("should set httpOnly cookie attribute to true", () => {
|
||||
const mockPrisma = {} as PrismaClient;
|
||||
createAuth(mockPrisma);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { betterAuth } from "better-auth";
|
||||
import { prismaAdapter } from "better-auth/adapters/prisma";
|
||||
import { genericOAuth } from "better-auth/plugins";
|
||||
@@ -260,7 +259,10 @@ export function createAuth(prisma: PrismaClient) {
|
||||
updateAge: 60 * 60 * 2, // 2 hours — minimum session age before BetterAuth refreshes the expiry on next request
|
||||
},
|
||||
advanced: {
|
||||
generateId: () => randomUUID(),
|
||||
database: {
|
||||
// BetterAuth's default ID generator emits opaque strings; our auth tables use UUID PKs.
|
||||
generateId: "uuid",
|
||||
},
|
||||
defaultCookieAttributes: {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
|
||||
@@ -50,6 +50,8 @@ describe("TelemetryInterceptor", () => {
|
||||
getResponse: vi.fn().mockReturnValue({
|
||||
statusCode: 200,
|
||||
setHeader: vi.fn(),
|
||||
headersSent: false,
|
||||
writableEnded: false,
|
||||
}),
|
||||
}),
|
||||
getClass: vi.fn().mockReturnValue({ name: "TestController" }),
|
||||
@@ -101,6 +103,35 @@ describe("TelemetryInterceptor", () => {
|
||||
expect(mockResponse.setHeader).toHaveBeenCalledWith("x-trace-id", "test-trace-id");
|
||||
});
|
||||
|
||||
it("should not set trace header when response is already committed", async () => {
|
||||
const committedResponseContext = {
|
||||
...mockContext,
|
||||
switchToHttp: vi.fn().mockReturnValue({
|
||||
getRequest: vi.fn().mockReturnValue({
|
||||
method: "GET",
|
||||
url: "/api/test",
|
||||
path: "/api/test",
|
||||
}),
|
||||
getResponse: vi.fn().mockReturnValue({
|
||||
statusCode: 200,
|
||||
setHeader: vi.fn(),
|
||||
headersSent: true,
|
||||
writableEnded: true,
|
||||
}),
|
||||
}),
|
||||
} as unknown as ExecutionContext;
|
||||
|
||||
mockHandler = {
|
||||
handle: vi.fn().mockReturnValue(of({ data: "test" })),
|
||||
} as unknown as CallHandler;
|
||||
|
||||
const committedResponse = committedResponseContext.switchToHttp().getResponse();
|
||||
|
||||
await lastValueFrom(interceptor.intercept(committedResponseContext, mockHandler));
|
||||
|
||||
expect(committedResponse.setHeader).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should record exception on error", async () => {
|
||||
const error = new Error("Test error");
|
||||
mockHandler = {
|
||||
|
||||
@@ -88,7 +88,7 @@ export class TelemetryInterceptor implements NestInterceptor {
|
||||
|
||||
// Add trace context to response headers for distributed tracing
|
||||
const spanContext = span.spanContext();
|
||||
if (spanContext.traceId) {
|
||||
if (spanContext.traceId && !response.headersSent && !response.writableEnded) {
|
||||
response.setHeader("x-trace-id", spanContext.traceId);
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user