From 42265af47bb85e2bb9f4d18ea419f3496f48c574 Mon Sep 17 00:00:00 2001 From: SnapOtter Date: Wed, 13 May 2026 19:06:22 +0800 Subject: [PATCH] feat(oidc): update settings dialog with OIDC user handling and logout flow --- .../components/settings/settings-dialog.tsx | 65 ++++++++++++++----- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/apps/web/src/components/settings/settings-dialog.tsx b/apps/web/src/components/settings/settings-dialog.tsx index 9e9c5ce5..67d3cb30 100644 --- a/apps/web/src/components/settings/settings-dialog.tsx +++ b/apps/web/src/components/settings/settings-dialog.tsx @@ -28,7 +28,7 @@ import { } from "lucide-react"; import { Fragment, useCallback, useEffect, useMemo, useState } from "react"; import { useAuth } from "@/hooks/use-auth"; -import { apiDelete, apiGet, apiPost, apiPut, clearToken } from "@/lib/api"; +import { apiDelete, apiGet, apiPost, apiPut, clearToken, formatHeaders } from "@/lib/api"; import { cn, copyToClipboard } from "@/lib/utils"; import { useAnalyticsStore } from "@/stores/analytics-store"; import { useSettingsStore } from "@/stores/settings-store"; @@ -194,6 +194,10 @@ interface UserEntry { username: string; role: string; team: string; + authProvider?: string; + email?: string; + hasLocalPassword?: boolean; + hasOidcLink?: boolean; createdAt: string; } @@ -235,10 +239,25 @@ function GeneralSection() { ]).finally(() => setLoading(false)); }, []); - const handleLogout = () => { - clearToken(); - localStorage.removeItem("snapotter-username"); - window.location.href = "/login"; + const handleLogout = async () => { + try { + const res = await fetch("/api/auth/logout", { + method: "POST", + headers: formatHeaders(), + }); + const data = await res.json().catch(() => ({})); + clearToken(); + localStorage.removeItem("snapotter-username"); + if (data.logoutUrl) { + window.location.href = data.logoutUrl; + } else { + window.location.href = "/login"; + } + } catch { + clearToken(); + localStorage.removeItem("snapotter-username"); + window.location.href = "/login"; + } }; const handleSave = useCallback(async () => { @@ -1078,6 +1097,16 @@ function PeopleSection() { {u.username.charAt(0).toUpperCase()} {u.username} + {u.hasOidcLink && u.hasLocalPassword !== false && ( + + Local + OIDC + + )} + {u.hasOidcLink && u.hasLocalPassword === false && ( + + OIDC + + )} {/* Role badge */} @@ -1130,18 +1159,20 @@ function PeopleSection() { Edit Role / Team - + {u.hasLocalPassword !== false && ( + + )}