Watch
0
0
Fork
You've already forked hyperhive
0

swarm-ui, hive dashboard, agent page: one profile menu with the signed-in user, avatar and authelia links

The swarm UI's user menu moves to @hive/shared and takes the whoami URL and
authelia's URL as props; the swarm UI keeps a thin wrapper, and the hive
dashboard and the per-agent page mount the same component. The dashboard's
nginx vhost proxies /api/whoami to authelia (the agent page is served from
the same vhost), and hive-c0re's state carries authelia_public_url, set from
services.hyperhive.swarm.authelia.url. The agent page shows the menu only
behind the gateway.
This commit is contained in:
iris 2026-10-25 15:05:35 +01:00 • committed by mara
commit cd41e1d510
19 changed files with 417 additions and 154 deletions

View file

@ -0,0 +1,44 @@
// <AgentUserMenu> — the profile menu (`@hive/shared/user-menu.js`) in this
// page's header. Only behind the gateway: the page is then on the dashboard's
// own origin, where the session cookie is valid and nginx proxies
// `/api/whoami` to authelia. Opened directly on the agent's own port there is
// no sign-in to show, so the page has no menu.
//
// Authelia's URL, for the settings and sign-out links, comes from the
// dashboard's `/api/state` (`authelia_public_url`), the one place hive-c0re
// states it.
import { useEffect, useState } from "preact/hooks";
import { UserMenu } from "@hive/shared/user-menu.js";
import "@hive/shared/user-menu.css";
import { isBehindGateway } from "../lib/dashboardBase.js";
export function AgentUserMenu({ dashboardBase }: { dashboardBase: string }) {
const behind = isBehindGateway();
const [autheliaUrl, setAutheliaUrl] = useState<string | null>(null);
useEffect(() => {
if (!behind) return;
let cancelled = false;
fetch(`${dashboardBase}api/state`)
.then((r) =>
r.ok ? r.json() : Promise.reject(new Error(`http ${r.status}`)),
)
.then((state: { authelia_public_url?: string | null }) => {
if (!cancelled) setAutheliaUrl(state.authelia_public_url ?? null);
})
.catch(() => {
/* cosmetic only: the menu then shows the name without the links */
});
return () => {
cancelled = true;
};
}, [behind, dashboardBase]);
if (!behind) return null;
return (
<UserMenu
whoamiUrl={`${dashboardBase}api/whoami`}
autheliaUrl={autheliaUrl}
/>
);
}