ФУНКЦИИ - NODEDC TASK: listen for platform logout

This commit is contained in:
DCCONSTRUCTIONS 2026-05-04 23:24:12 +03:00
parent 424e262a91
commit f02865512f
2 changed files with 74 additions and 0 deletions

View File

@ -24,6 +24,7 @@ import globalStyles from "@/styles/globals.css?url";
import type { Route } from "./+types/root";
import designConfig from "../design.config.json";
// components
import { NodeDCSessionSync } from "@/components/auth-screens/nodedc-session-sync";
// local
import { CustomErrorComponent } from "./error";
import { AppProvider } from "./provider";
@ -181,6 +182,7 @@ export const meta: Route.MetaFunction = () => [
export default function Root() {
return (
<AppProvider>
<NodeDCSessionSync />
<div className={cn("relative flex h-screen w-full flex-col overflow-hidden bg-canvas", "desktop-app-container")}>
<main className="relative h-full w-full overflow-hidden">
<Outlet />

View File

@ -0,0 +1,72 @@
"use client";
import { useEffect } from "react";
import { buildNodeDCLauncherUrl, shouldUseNodeDCOIDC } from "@/helpers/nodedc-auth";
const NODEDC_SESSION_EVENT_TYPE = "nodedc:session:logout";
interface NodeDCSessionEvent {
type: typeof NODEDC_SESSION_EVENT_TYPE;
id: string;
}
export function NodeDCSessionSync() {
useEffect(() => {
if (!shouldUseNodeDCOIDC()) return;
const launcherOrigin = new URL(buildNodeDCLauncherUrl()).origin;
const syncUrl = new URL("/auth/session-sync", launcherOrigin).toString();
const loginUrl = new URL("/auth/login?prompt=login", launcherOrigin).toString();
let isRedirecting = false;
const iframe = document.createElement("iframe");
iframe.src = syncUrl;
iframe.title = "NODE.DC session sync";
iframe.tabIndex = -1;
iframe.setAttribute("aria-hidden", "true");
iframe.style.position = "fixed";
iframe.style.width = "0";
iframe.style.height = "0";
iframe.style.opacity = "0";
iframe.style.pointerEvents = "none";
iframe.style.border = "0";
document.body.appendChild(iframe);
const handleLogout = () => {
if (isRedirecting) return;
isRedirecting = true;
const redirectToLogin = () => window.location.replace(loginUrl);
const fallbackTimer = window.setTimeout(redirectToLogin, 500);
fetch("/logout", { method: "GET", credentials: "include", keepalive: true })
.catch(() => undefined)
.finally(() => {
window.clearTimeout(fallbackTimer);
redirectToLogin();
});
};
const handleMessage = (event: MessageEvent) => {
if (event.origin !== launcherOrigin || !isNodeDCSessionEvent(event.data)) return;
handleLogout();
};
window.addEventListener("message", handleMessage);
return () => {
window.removeEventListener("message", handleMessage);
iframe.remove();
};
}, []);
return null;
}
function isNodeDCSessionEvent(value: unknown): value is NodeDCSessionEvent {
if (!value || typeof value !== "object") return false;
const event = value as Partial<NodeDCSessionEvent>;
return event.type === NODEDC_SESSION_EVENT_TYPE && typeof event.id === "string";
}