import { useEffect, useState } from 'react'; import { Link, useNavigate, useSearchParams } from 'react-router-dom'; import * as authApi from '../../api/auth'; import { ApiError } from '../../api/http'; import { DEFAULT_TENANT } from '../../config'; import { useAuth } from '../../context/AuthContext'; import * as permApi from '../../api/permission'; type OAuthMode = 'login' | 'register'; export function OAuthCallbackPage({ mode }: { mode: OAuthMode }) { const navigate = useNavigate(); const [search] = useSearchParams(); const { syncSession, refreshRoles } = useAuth(); const [error, setError] = useState(''); useEffect(() => { const code = search.get('code'); const state = search.get('state'); const oauthError = search.get('error'); const tenant = localStorage.getItem('tenant_slug') ?? DEFAULT_TENANT; if (oauthError) { setError(search.get('error_description') ?? oauthError); return; } if (!code || !state) { setError('缺少 OAuth 參數(code / state)'); return; } let cancelled = false; (async () => { try { if (mode === 'login') { const result = await authApi.loginSocialCallback(code, state); if (result.mfa_required && result.mfa_challenge_id) { navigate('/login', { replace: true, state: { message: '請完成雙因素驗證以完成登入', mfa_challenge_id: result.mfa_challenge_id, tenant, }, }); return; } } else { await authApi.registerSocialCallback(code, state); } if (cancelled) return; syncSession(); await refreshRoles(); const me = await permApi.getMyPermissions(); const admin = permApi.isAdminRole(me.roles ?? []); navigate(admin ? '/admin' : '/app', { replace: true }); } catch (err) { if (cancelled) return; if (err instanceof ApiError && err.code === 29301000 && mode === 'login') { setError('尚無帳號,請先註冊或聯絡管理員開通 LDAP 帳號。'); } else { setError(err instanceof ApiError ? err.message : '登入失敗'); } } })(); return () => { cancelled = true; }; }, [mode, navigate, refreshRoles, search, syncSession]); return (

{mode === 'login' ? '登入處理中' : '註冊處理中'}

{error ? ( <>

{error}

返回

) : (

正在與身分提供者確認,請稍候…

)}
); }