mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-18 11:32:15 -05:00
fix(logger): respect configured logger in auth request context (#10939)
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@better-auth/core": patch
|
||||
---
|
||||
|
||||
Logs emitted while handling auth requests now respect the configured custom logger, log level, and disabled setting.
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { BetterAuthOptions } from "@better-auth/core";
|
||||
import { logger } from "@better-auth/core/env";
|
||||
import type { AuthEndpointContext } from "@better-auth/core/context";
|
||||
import { runWithEndpointContext } from "@better-auth/core/context";
|
||||
import { createLogger } from "@better-auth/core/env";
|
||||
import type { GoogleProfile } from "@better-auth/core/social-providers";
|
||||
import { safeJSONParse } from "@better-auth/core/utils/json";
|
||||
import { base64Url } from "@better-auth/utils/base64";
|
||||
@@ -15,6 +17,7 @@ import {
|
||||
describe,
|
||||
expect,
|
||||
it,
|
||||
onTestFinished,
|
||||
vi,
|
||||
} from "vitest";
|
||||
import {
|
||||
@@ -1274,7 +1277,7 @@ describe("Cookie Cache Field Filtering", () => {
|
||||
/**
|
||||
* @see https://github.com/better-auth/better-auth/issues/10902
|
||||
*/
|
||||
it("should warn when a signed compact cookie has an invalid payload", async () => {
|
||||
it("should use the configured logger for an invalid signed compact cookie", async () => {
|
||||
const secret = "test-secret";
|
||||
const bakeCookie = async (emailVerified: boolean | null) => {
|
||||
const now = new Date().toISOString();
|
||||
@@ -1313,25 +1316,35 @@ describe("Cookie Cache Field Filtering", () => {
|
||||
isSecure: false,
|
||||
secret,
|
||||
};
|
||||
const warn = vi.spyOn(logger, "warn").mockImplementation(() => {});
|
||||
try {
|
||||
const validCache = await getCookieCache(
|
||||
new Headers({ cookie: `p.session_data=${await bakeCookie(false)}` }),
|
||||
config,
|
||||
);
|
||||
expect(validCache).not.toBeNull();
|
||||
expect(warn).not.toHaveBeenCalled();
|
||||
const log = vi.fn();
|
||||
const defaultWarn = vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
onTestFinished(() => defaultWarn.mockRestore());
|
||||
const endpointContext = {
|
||||
context: { logger: createLogger({ log }) },
|
||||
} as unknown as AuthEndpointContext;
|
||||
const validCookie = await bakeCookie(false);
|
||||
|
||||
const invalidCache = await getCookieCache(
|
||||
new Headers({ cookie: `p.session_data=${await bakeCookie(null)}` }),
|
||||
const validCache = await runWithEndpointContext(endpointContext, () =>
|
||||
getCookieCache(
|
||||
new Headers({ cookie: `p.session_data=${validCookie}` }),
|
||||
config,
|
||||
);
|
||||
),
|
||||
);
|
||||
expect(validCache).not.toBeNull();
|
||||
expect(log).not.toHaveBeenCalled();
|
||||
const invalidCookie = await bakeCookie(null);
|
||||
|
||||
expect(invalidCache).toBeNull();
|
||||
expect(warn).toHaveBeenCalledTimes(1);
|
||||
} finally {
|
||||
warn.mockRestore();
|
||||
}
|
||||
const invalidCache = await runWithEndpointContext(endpointContext, () =>
|
||||
getCookieCache(
|
||||
new Headers({ cookie: `p.session_data=${invalidCookie}` }),
|
||||
config,
|
||||
),
|
||||
);
|
||||
|
||||
expect(invalidCache).toBeNull();
|
||||
expect(log).toHaveBeenCalledTimes(1);
|
||||
expect(log.mock.calls[0]?.[0]).toBe("warn");
|
||||
expect(defaultWarn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should return null for invalid JWT token", async () => {
|
||||
|
||||
Vendored
+80
-3
@@ -1,6 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { LogLevel } from "./logger";
|
||||
import { shouldPublishLog } from "./logger";
|
||||
import { describe, expect, it, onTestFinished, vi } from "vitest";
|
||||
import type { AuthEndpointContext } from "../context";
|
||||
import { runWithEndpointContext } from "../context";
|
||||
import { safeJSONParse } from "../utils/json";
|
||||
import type { InternalLogger, LogLevel } from "./logger";
|
||||
import { createLogger, logger, shouldPublishLog } from "./logger";
|
||||
|
||||
describe("shouldPublishLog", () => {
|
||||
const testCases: {
|
||||
@@ -32,3 +35,77 @@ describe("shouldPublishLog", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("logger", () => {
|
||||
const endpointContext = (logger: InternalLogger) =>
|
||||
({ context: { logger } }) as unknown as AuthEndpointContext;
|
||||
|
||||
it("uses the default logger outside an auth context", () => {
|
||||
const defaultWarn = vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
onTestFinished(() => defaultWarn.mockRestore());
|
||||
|
||||
logger.warn("default warning");
|
||||
|
||||
expect(defaultWarn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("delegates to the logger in the current auth context", async () => {
|
||||
const defaultWarn = vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
onTestFinished(() => defaultWarn.mockRestore());
|
||||
const firstLog = vi.fn();
|
||||
const secondLog = vi.fn();
|
||||
const firstLogger = createLogger({ level: "info", log: firstLog });
|
||||
const secondLogger = createLogger({ level: "error", log: secondLog });
|
||||
|
||||
await Promise.all([
|
||||
runWithEndpointContext(endpointContext(firstLogger), async () => {
|
||||
await Promise.resolve();
|
||||
expect(logger.level).toBe("info");
|
||||
logger.warn("first warning");
|
||||
}),
|
||||
runWithEndpointContext(endpointContext(secondLogger), async () => {
|
||||
await Promise.resolve();
|
||||
expect(logger.level).toBe("error");
|
||||
logger.warn("second warning");
|
||||
}),
|
||||
]);
|
||||
|
||||
expect(firstLog).toHaveBeenCalledWith("warn", "first warning");
|
||||
expect(secondLog).not.toHaveBeenCalled();
|
||||
expect(defaultWarn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("routes utility logs through the current auth context", async () => {
|
||||
const defaultError = vi
|
||||
.spyOn(console, "error")
|
||||
.mockImplementation(() => {});
|
||||
onTestFinished(() => defaultError.mockRestore());
|
||||
const log = vi.fn();
|
||||
const configuredLogger = createLogger({ log });
|
||||
|
||||
await runWithEndpointContext(endpointContext(configuredLogger), () => {
|
||||
expect(safeJSONParse("{")).toBeNull();
|
||||
});
|
||||
|
||||
expect(log).toHaveBeenCalledWith(
|
||||
"error",
|
||||
"Error parsing JSON",
|
||||
expect.objectContaining({ error: expect.any(SyntaxError) }),
|
||||
);
|
||||
expect(defaultError).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("honors disabled logging in the current auth context", async () => {
|
||||
const defaultWarn = vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
onTestFinished(() => defaultWarn.mockRestore());
|
||||
const log = vi.fn();
|
||||
const configuredLogger = createLogger({ disabled: true, log });
|
||||
|
||||
await runWithEndpointContext(endpointContext(configuredLogger), () => {
|
||||
logger.warn("hidden warning");
|
||||
});
|
||||
|
||||
expect(log).not.toHaveBeenCalled();
|
||||
expect(defaultWarn).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Vendored
+22
-1
@@ -1,3 +1,5 @@
|
||||
import type { AuthEndpointContext } from "../context/endpoint-context";
|
||||
import { __getCurrentEndpointContext } from "../context/global";
|
||||
import { getColorDepth } from "./color-depth";
|
||||
|
||||
export const TTY_COLORS = {
|
||||
@@ -142,4 +144,23 @@ export const createLogger = (options?: Logger | undefined): InternalLogger => {
|
||||
};
|
||||
};
|
||||
|
||||
export const logger = createLogger();
|
||||
const defaultLogger = createLogger();
|
||||
|
||||
const getCurrentLogger = (): InternalLogger => {
|
||||
const currentLogger =
|
||||
__getCurrentEndpointContext<AuthEndpointContext>()?.context.logger;
|
||||
return currentLogger && currentLogger !== logger
|
||||
? currentLogger
|
||||
: defaultLogger;
|
||||
};
|
||||
|
||||
export const logger: InternalLogger = {
|
||||
debug: (...params) => getCurrentLogger().debug(...params),
|
||||
info: (...params) => getCurrentLogger().info(...params),
|
||||
success: (...params) => getCurrentLogger().success(...params),
|
||||
warn: (...params) => getCurrentLogger().warn(...params),
|
||||
error: (...params) => getCurrentLogger().error(...params),
|
||||
get level() {
|
||||
return getCurrentLogger().level;
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user