feat(web): 增加统一认证接入与运维页面

系统设置新增统一认证配对、验证、激活、重验证、回滚与禁用流程,安全事件改为统一能力状态。前端登录入口运行时读取公开配置,不再依赖 VITE_OIDC 构建变量。\n\n验证:web 31 项测试;web typecheck;pnpm lint;web production build
This commit is contained in:
2026-07-17 12:18:26 +08:00
parent b175d545ff
commit e0a356ee0c
11 changed files with 675 additions and 191 deletions
+15 -9
View File
@@ -125,8 +125,7 @@ import {
import { restoreOIDCBrowserSession } from './lib/oidc-browser-session';
import {
consumeOIDCCallbackError,
oidcBrowserSessionEnabled,
oidcLoginEnabled,
loadOIDCRuntimeConfiguration,
startOIDCLogin,
startOIDCLogout,
} from './lib/oidc';
@@ -261,6 +260,7 @@ export function App() {
const [state, setState] = useState<LoadState>('idle');
const [error, setError] = useState('');
const [oidcCallbackError, setOIDCCallbackError] = useState(() => consumeOIDCCallbackError());
const [oidcEnabled, setOIDCEnabled] = useState(false);
const loadedDataKeysRef = useRef(new Set<DataKey>());
const loadingDataKeysRef = useRef(new Set<DataKey>());
const loadedTaskQueryKeyRef = useRef('');
@@ -294,10 +294,11 @@ export function App() {
useEffect(() => {
let cancelled = false;
void (async () => {
if (oidcCallbackError) return;
if (!oidcBrowserSessionEnabled()) return;
if (readStoredAccessToken() || !oidcLoginEnabled()) return;
const loadIdentityRuntime = async (force = false) => {
const configuration = await loadOIDCRuntimeConfiguration(force);
if (cancelled) return;
setOIDCEnabled(configuration.enabled && configuration.oidcLogin);
if (oidcCallbackError || readStoredAccessToken() || !configuration.enabled || !configuration.oidcLogin) return;
const restored = await restoreOIDCBrowserSession();
if (!restored || cancelled) return;
setCurrentUser(restored.user);
@@ -305,13 +306,17 @@ export function App() {
setToken(restored.credential);
setState('idle');
setError('');
})().catch((err) => {
};
const runtimeChanged = () => { void loadIdentityRuntime(true); };
window.addEventListener('identity-runtime-changed', runtimeChanged);
void loadIdentityRuntime().catch((err) => {
if (cancelled) return;
setState('error');
setError(err instanceof Error ? err.message : '统一认证登录失败');
});
return () => {
cancelled = true;
window.removeEventListener('identity-runtime-changed', runtimeChanged);
};
}, [oidcCallbackError]);
useEffect(() => {
@@ -1354,7 +1359,7 @@ export function App() {
onSubmitExternalToken={submitExternalToken}
onSubmitLogin={submitLogin}
onSubmitRegister={submitRegister}
oidcEnabled={oidcLoginEnabled()}
oidcEnabled={oidcEnabled}
onOIDCLogin={loginWithOIDC}
/>
)
@@ -1362,6 +1367,7 @@ export function App() {
{activePage === 'admin' && (
isAuthenticated ? (
<AdminPage
token={token}
data={data}
operationMessage={coreMessage}
section={adminSection}
@@ -1419,7 +1425,7 @@ export function App() {
onSubmitExternalToken={submitExternalToken}
onSubmitLogin={submitLogin}
onSubmitRegister={submitRegister}
oidcEnabled={oidcLoginEnabled()}
oidcEnabled={oidcEnabled}
onOIDCLogin={loginWithOIDC}
/>
)