feat(web): 增加统一认证接入与运维页面
系统设置新增统一认证配对、验证、激活、重验证、回滚与禁用流程,安全事件改为统一能力状态。前端登录入口运行时读取公开配置,不再依赖 VITE_OIDC 构建变量。\n\n验证:web 31 项测试;web typecheck;pnpm lint;web production build
This commit is contained in:
+66
-4
@@ -20,6 +20,11 @@ import type {
|
||||
GatewayAuditLog,
|
||||
GatewayRunnerPolicy,
|
||||
GatewayRunnerPolicyUpsertRequest,
|
||||
IdentityConfigurationRevision,
|
||||
IdentityConfigurationView,
|
||||
IdentityPairingExchange,
|
||||
IdentityPairingInput,
|
||||
IdentityRevisionPolicyUpdate,
|
||||
GatewayTenant,
|
||||
GatewayTenantUpsertRequest,
|
||||
GatewayNetworkProxyConfig,
|
||||
@@ -52,7 +57,6 @@ import type {
|
||||
WalletSummaryResponse,
|
||||
} from '@easyai-ai-gateway/contracts';
|
||||
import type { PlatformCreateInput, PlatformModelBindingInput, WorkspaceTaskQuery } from './types';
|
||||
import { oidcBrowserSessionEnabled } from './lib/oidc';
|
||||
|
||||
const API_BASE = import.meta.env.VITE_GATEWAY_API_BASE_URL ?? 'http://localhost:8088';
|
||||
export const OIDC_BROWSER_SESSION_CREDENTIAL = '__easyai_gateway_oidc_browser_session__';
|
||||
@@ -644,7 +648,7 @@ export async function* streamChatCompletionText(
|
||||
...authorizationHeader(token),
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: oidcBrowserSessionEnabled() ? 'include' : 'same-origin',
|
||||
credentials: 'include',
|
||||
method: 'POST',
|
||||
signal,
|
||||
});
|
||||
@@ -845,7 +849,7 @@ export async function uploadFileToStorage(
|
||||
|
||||
const response = await fetch(`${API_BASE}/v1/files/upload`, {
|
||||
body: form,
|
||||
credentials: oidcBrowserSessionEnabled() ? 'include' : 'same-origin',
|
||||
credentials: 'include',
|
||||
headers: authorizationHeader(token),
|
||||
method: 'POST',
|
||||
});
|
||||
@@ -1001,6 +1005,64 @@ export async function updateClientCustomizationSettings(
|
||||
});
|
||||
}
|
||||
|
||||
const identityConfigurationPath = '/api/admin/system/identity';
|
||||
|
||||
export async function getIdentityConfiguration(token: string): Promise<IdentityConfigurationView> {
|
||||
return request<IdentityConfigurationView>(`${identityConfigurationPath}/configuration`, { token });
|
||||
}
|
||||
|
||||
export async function startIdentityPairing(token: string, input: IdentityPairingInput): Promise<IdentityPairingExchange> {
|
||||
return identityConfigurationWrite<IdentityPairingExchange>(token, `${identityConfigurationPath}/pairings`, 'POST', 0, input, 'pair');
|
||||
}
|
||||
|
||||
export async function getIdentityPairing(token: string, pairingId: string): Promise<IdentityPairingExchange> {
|
||||
return request<IdentityPairingExchange>(`${identityConfigurationPath}/pairings/${pairingId}`, { token });
|
||||
}
|
||||
|
||||
export async function updateIdentityRevisionPolicy(
|
||||
token: string,
|
||||
revisionId: string,
|
||||
version: number,
|
||||
input: IdentityRevisionPolicyUpdate,
|
||||
): Promise<IdentityConfigurationRevision> {
|
||||
return identityConfigurationWrite<IdentityConfigurationRevision>(token, `${identityConfigurationPath}/revisions/${revisionId}`, 'PATCH', version, input, 'policy');
|
||||
}
|
||||
|
||||
export async function validateIdentityRevision(token: string, revisionId: string, version: number): Promise<IdentityConfigurationRevision> {
|
||||
return identityConfigurationWrite<IdentityConfigurationRevision>(token, `${identityConfigurationPath}/revisions/${revisionId}/validate`, 'POST', version, undefined, 'validate');
|
||||
}
|
||||
|
||||
export async function activateIdentityRevision(token: string, revisionId: string, version: number): Promise<IdentityConfigurationRevision> {
|
||||
return identityConfigurationWrite<IdentityConfigurationRevision>(token, `${identityConfigurationPath}/revisions/${revisionId}/activate`, 'POST', version, undefined, 'activate');
|
||||
}
|
||||
|
||||
export async function rollbackIdentityRevision(token: string, revisionId: string, version: number): Promise<IdentityConfigurationRevision> {
|
||||
return identityConfigurationWrite<IdentityConfigurationRevision>(token, `${identityConfigurationPath}/revisions/${revisionId}/rollback`, 'POST', version, undefined, 'rollback');
|
||||
}
|
||||
|
||||
export async function disableIdentityConfiguration(token: string, version: number): Promise<IdentityConfigurationRevision> {
|
||||
return identityConfigurationWrite<IdentityConfigurationRevision>(token, `${identityConfigurationPath}/disable`, 'POST', version, undefined, 'disable');
|
||||
}
|
||||
|
||||
function identityConfigurationWrite<T>(
|
||||
token: string,
|
||||
path: string,
|
||||
method: string,
|
||||
version: number,
|
||||
body: unknown,
|
||||
action: string,
|
||||
): Promise<T> {
|
||||
return request<T>(path, {
|
||||
body,
|
||||
method,
|
||||
token,
|
||||
headers: {
|
||||
'Idempotency-Key': `identity-${action}-${crypto.randomUUID()}`,
|
||||
'If-Match': `W/"${version}"`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const securityEventConnectionPath = '/api/admin/system/identity/security-events/connection';
|
||||
|
||||
export async function getSecurityEventConnection(token: string): Promise<SecurityEventConnectionResponse> {
|
||||
@@ -1096,7 +1158,7 @@ async function request<T>(
|
||||
method: options.method ?? 'GET',
|
||||
headers,
|
||||
body: options.body === undefined ? undefined : JSON.stringify(options.body),
|
||||
credentials: oidcBrowserSessionEnabled() ? 'include' : 'same-origin',
|
||||
credentials: 'include',
|
||||
});
|
||||
if (!response.ok) {
|
||||
const body = await response.text();
|
||||
|
||||
Reference in New Issue
Block a user