Commit 2aedd46d by luoqi

fix(登录): 走宿主 SSO 拿到票之后,还在多发一发 /auth/mock-users

产品带 ?code= 走授权登录,控制台已经 code-ok、票也拿到了,
浏览器里却还有一发 `mock-users` —— 那是 dev「快速登录」的探测请求。

真因:AuthGate 里那个探测是**空依赖的 useEffect,每次挂载无条件发**,
结果只在"未登录"那条分流里才用得上。

️ 它不只是多一个请求:`/auth/mock-users` 是 @Public() 的,
   返回**全部客服的真实姓名 + 所属诊所**(测试机 116 人,公网无凭证可拉)。
   挂在每次加载上 = 每开一次页面就把花名册取一遍,嵌在宿主 iframe 里也照发。

⇒ 收紧到"下面那条分流真的会用到它":已登录 / 还在 bootstrap / 嵌入态,
  三种都一次不发。️ hooks 不能条件调用,所以在 effect 里判、条件进依赖。

实测:已登录重新加载 → mock-users 0 次,只剩
session / client-diag / assignments / workload;
未登录(dev)→ 快速登录框照常弹,没被误伤。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
parent db7e0dbf
Pipeline #3554 failed in 0 seconds
...@@ -24,10 +24,31 @@ export function AuthGate({ children }: { children: React.ReactNode }) { ...@@ -24,10 +24,31 @@ export function AuthGate({ children }: { children: React.ReactNode }) {
const [mounted, setMounted] = useState(false); const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []); useEffect(() => setMounted(true), []);
// 探测后端是否开启 mock 快速登录(禁用时 GET /auth/mock-users 返空)。 /**
// 真生产 PAC_ENABLE_MOCK_LOGIN=false → 不弹 dev "快速登录"框(见下方分流)。 * 探测后端是否开启 mock 快速登录(禁用时 GET /auth/mock-users 返空)。
*
* 🔴 **只在真的要弹这个框时才探**(2026-08-10 产品在宿主 SSO 流程里发现的)。
* 原来是个空依赖的 useEffect,**每次挂载无条件发** —— 于是带 `?code=` 走
* 宿主授权登录、`code-ok` 已经拿到票之后,照样多打一发 `/auth/mock-users`。
*
* ⚠️ 它不只是"多一个请求":`mock-users` 是 `@Public()` 的,
* 返回的是**全部客服的真实姓名 + 所属诊所**(测试机实测 116 人)。
* 把它挂在每次加载上,等于每开一次页面就把花名册取一遍 —— 嵌在宿主 iframe 里也照发。
*
* ⇒ 条件收紧到"**下面那条分流真的会用到它**":
* 已登录 / 还在 bootstrap / 嵌入态 —— 三种都不需要,一次都不发。
* ⚠️ hooks 不能条件调用,所以是**在 effect 里判**、把条件放进依赖,⛔ 别把 useEffect 包进 if。
*/
const needMockProbe =
mounted &&
!isAuthenticated &&
status !== 'authenticating' &&
status !== 'idle' &&
!isEmbedded();
const [mockEnabled, setMockEnabled] = useState<boolean | null>(null); const [mockEnabled, setMockEnabled] = useState<boolean | null>(null);
useEffect(() => { useEffect(() => {
if (!needMockProbe) return;
let cancelled = false; let cancelled = false;
fetch(new URL('/pac/v1/auth/mock-users', env.apiBaseUrl).toString(), { credentials: 'omit' }) fetch(new URL('/pac/v1/auth/mock-users', env.apiBaseUrl).toString(), { credentials: 'omit' })
.then((r) => r.json()) .then((r) => r.json())
...@@ -40,7 +61,7 @@ export function AuthGate({ children }: { children: React.ReactNode }) { ...@@ -40,7 +61,7 @@ export function AuthGate({ children }: { children: React.ReactNode }) {
return () => { return () => {
cancelled = true; cancelled = true;
}; };
}, []); }, [needMockProbe]);
if (!mounted) return <Placeholder />; if (!mounted) return <Placeholder />;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment