fix: address second round of Greptile review feedback

- Add loginCall integration tests verifying setTokenCookie is called with
  token and skipped when absent (backward-compatibility path)
- Use encodeURIComponent/decodeURIComponent in setTokenCookie/getCookie
  for defense-in-depth against non-standard token formats

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hendrik Jaks 2026-03-13 10:09:52 +02:00
parent a8864ea12b
commit 2c5caac531
2 changed files with 34 additions and 2 deletions

View file

@ -80,6 +80,38 @@ describe("networking - expired session handling", () => {
});
});
describe("loginCall - setTokenCookie integration", () => {
const originalFetch = global.fetch;
beforeEach(() => {
vi.clearAllMocks();
});
afterEach(() => {
global.fetch = originalFetch;
});
it("calls setTokenCookie when response includes token", async () => {
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ redirect_url: "/ui/?login=success", token: "my-jwt" }),
}) as any;
const { setTokenCookie } = await import("@/utils/cookieUtils");
await Networking.loginCall("admin", "pass");
expect(setTokenCookie).toHaveBeenCalledWith("my-jwt");
});
it("does not call setTokenCookie when response has no token", async () => {
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ redirect_url: "/ui/?login=success" }),
}) as any;
const { setTokenCookie } = await import("@/utils/cookieUtils");
await Networking.loginCall("admin", "pass");
expect(setTokenCookie).not.toHaveBeenCalled();
});
});
describe("daily activity helpers", () => {
const startTime = new Date("2025-02-12T00:00:00.000Z");
const endTime = new Date("2025-02-19T00:00:00.000Z");

View file

@ -53,7 +53,7 @@ export function clearTokenCookies() {
export function setTokenCookie(token: string) {
if (typeof window === "undefined" || typeof document === "undefined") return;
const isSecure = window.location.protocol === "https:";
document.cookie = `token=${token}; Path=/; SameSite=Lax${isSecure ? "; Secure" : ""}`;
document.cookie = `token=${encodeURIComponent(token)}; Path=/; SameSite=Lax${isSecure ? "; Secure" : ""}`;
}
/**
@ -64,5 +64,5 @@ export function setTokenCookie(token: string) {
export function getCookie(name: string) {
if (typeof document === "undefined") return null;
const cookieValue = document.cookie.split("; ").find((row) => row.startsWith(name + "="));
return cookieValue ? cookieValue.split("=")[1] : null;
return cookieValue ? decodeURIComponent(cookieValue.split("=")[1]) : null;
}