mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(panel): the /tg surface is exempt from the global 401→login redirect (#600)
The app-level agent-roster sync fires /api/agents on every surface; on /tg it races the initData sign-in, takes the cloud-auth 401, and the interceptor bounced the Telegram webview to the password /login page it cannot complete — hijacking the cockpit into the dashboard. The Mini App owns its auth UX (initData sign-in + its own wall), so the redirect now exempts /tg via an exported, tested path predicate. Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
@@ -30,7 +30,7 @@ vi.mock("@/store/rate-limit-store", () => ({
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Import the function under test AFTER mocks are in place
|
// Import the function under test AFTER mocks are in place
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
import { getErrorMessage } from "@/lib/api/client";
|
import { getErrorMessage, isTgSurfacePath } from "@/lib/api/client";
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Helpers
|
// Helpers
|
||||||
@@ -212,3 +212,17 @@ describe("getErrorMessage — non-Axios fallbacks", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("isTgSurfacePath — the /tg login-redirect exemption", () => {
|
||||||
|
it("matches the cockpit root and subpaths", () => {
|
||||||
|
expect(isTgSurfacePath("/tg")).toBe(true);
|
||||||
|
expect(isTgSurfacePath("/tg/")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not match the dashboard or lookalike segments", () => {
|
||||||
|
expect(isTgSurfacePath("/overview")).toBe(false);
|
||||||
|
expect(isTgSurfacePath("/tgsomething")).toBe(false);
|
||||||
|
expect(isTgSurfacePath("/login")).toBe(false);
|
||||||
|
expect(isTgSurfacePath("/")).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -61,6 +61,16 @@ api.interceptors.request.use(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Telegram Mini App owns its auth UX: /tg signs in via initData and
|
||||||
|
* renders its own wall. Global mounts (the agent-roster sync) can 401 there
|
||||||
|
* before that sign-in lands — bouncing the webview to the password /login
|
||||||
|
* page it cannot complete would hijack the cockpit.
|
||||||
|
*/
|
||||||
|
export function isTgSurfacePath(pathname: string): boolean {
|
||||||
|
return /^\/tg(\/|$)/.test(pathname);
|
||||||
|
}
|
||||||
|
|
||||||
// A 401 only means "log in" when cloud auth is actually on. In header-trust /
|
// A 401 only means "log in" when cloud auth is actually on. In header-trust /
|
||||||
// secure mode (cloud auth off) a 401 is a misconfigured agent token, not a
|
// secure mode (cloud auth off) a 401 is a misconfigured agent token, not a
|
||||||
// missing session — bouncing to /login would dead-end on a page whose backend
|
// missing session — bouncing to /login would dead-end on a page whose backend
|
||||||
@@ -70,6 +80,9 @@ async function redirectToLoginIfCloudAuth(): Promise<void> {
|
|||||||
if (typeof window === "undefined" || window.location.pathname === "/login") {
|
if (typeof window === "undefined" || window.location.pathname === "/login") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isTgSurfacePath(window.location.pathname)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API_URL}/auth/status`, {
|
const res = await fetch(`${API_URL}/auth/status`, {
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
|
|||||||
Reference in New Issue
Block a user