feat(auth-portal): 添加部署控制服务调用支持
- 导入callDeployControl和normalizeTokenResponse函数用于处理部署配置 - 新增hasTargetFrontendUrl函数检查响应中是否存在目标前端URL - 在注册流程中添加部署路由解析逻辑,当缺少前端URL时调用部署控制服务获取配置 - 更新normalizeTokenResponse函数以支持从实例对象中提取URL配置 refactor(runtime-control): 增强令牌响应标准化功能 - 扩展normalizeTokenResponse函数支持从instance对象中获取URL配置 - 添加对instance字段的支持,优先级为routing > instance配置 - 支持从instance中提取frontend_base_url、api_base_url和public_url build(tsconfig): 排除测试文件构建 - 在tsconfig.json中添加排除规则,排除**/*.test.ts和**/*.test.tsx文件 - 避免测试文件参与生产构建 refactor(authz-service): 优化Python后端令牌响应处理 - 更新_normalize_portal_token_response函数支持从实例对象中提取URL配置 - 重构URL优先级逻辑,支持routing和instance双重数据源 - 改进代码可读性,将复杂的URL赋值逻辑拆分为多行
This commit is contained in:
@ -2,7 +2,13 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
import type { TokenResponse } from '@/types/auth';
|
||||
import { normalizePortalLocale, pickPortalText } from '@/lib/i18n/core';
|
||||
import { HttpError, REGISTER_REQUEST_TIMEOUT_MS, callAuthzService } from '@/lib/runtime-control';
|
||||
import {
|
||||
HttpError,
|
||||
REGISTER_REQUEST_TIMEOUT_MS,
|
||||
callAuthzService,
|
||||
callDeployControl,
|
||||
normalizeTokenResponse,
|
||||
} from '@/lib/runtime-control';
|
||||
|
||||
function errorStatus(error: unknown): number {
|
||||
if (error instanceof HttpError) {
|
||||
@ -18,6 +24,15 @@ function errorDetail(error: unknown): string {
|
||||
return error instanceof Error ? error.message : 'registration failed';
|
||||
}
|
||||
|
||||
function hasTargetFrontendUrl(response: TokenResponse): boolean {
|
||||
return Boolean(
|
||||
response.backend_connection?.frontend_base_url ||
|
||||
response.backend_connection?.public_base_url ||
|
||||
response.backend_connection?.api_base_url ||
|
||||
response.local_backend?.public_base_url
|
||||
);
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const locale = normalizePortalLocale(
|
||||
request.cookies.get('beaver_locale')?.value ||
|
||||
@ -46,7 +61,18 @@ export async function POST(request: NextRequest) {
|
||||
password,
|
||||
}, REGISTER_REQUEST_TIMEOUT_MS);
|
||||
|
||||
return NextResponse.json(response);
|
||||
if (hasTargetFrontendUrl(response)) {
|
||||
return NextResponse.json(response);
|
||||
}
|
||||
|
||||
const routing = await callDeployControl<{
|
||||
api_base_url?: string;
|
||||
frontend_base_url?: string;
|
||||
public_url?: string;
|
||||
instance?: unknown;
|
||||
}>('/api/instances/resolve', { username });
|
||||
|
||||
return NextResponse.json(normalizeTokenResponse(response, routing));
|
||||
} catch (error) {
|
||||
return NextResponse.json({ detail: errorDetail(error) }, { status: errorStatus(error) });
|
||||
}
|
||||
|
||||
25
auth-portal/src/lib/runtime-control.test.ts
Normal file
25
auth-portal/src/lib/runtime-control.test.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { normalizeTokenResponse } from './runtime-control';
|
||||
|
||||
describe('normalizeTokenResponse', () => {
|
||||
it('uses nested instance routing when top-level route URLs are missing', () => {
|
||||
const response = normalizeTokenResponse({
|
||||
access_token: 'token',
|
||||
refresh_token: '',
|
||||
token_type: 'bearer',
|
||||
user_id: 'alice',
|
||||
username: 'alice',
|
||||
role: 'owner',
|
||||
handoff_code: 'handoff-1',
|
||||
}, {
|
||||
instance: {
|
||||
public_url: 'workspace.example.com:8088',
|
||||
frontend_base_url: 'workspace.example.com:8088',
|
||||
},
|
||||
});
|
||||
|
||||
expect(response.backend_connection?.frontend_base_url).toBe('workspace.example.com:8088');
|
||||
expect(response.backend_connection?.public_base_url).toBe('workspace.example.com:8088');
|
||||
});
|
||||
});
|
||||
@ -107,11 +107,20 @@ export function normalizeTokenResponse(
|
||||
frontend_base_url?: unknown;
|
||||
api_base_url?: unknown;
|
||||
public_url?: unknown;
|
||||
instance?: unknown;
|
||||
}
|
||||
): TokenResponse {
|
||||
const frontendBaseUrl = asString(routing.frontend_base_url);
|
||||
const apiBaseUrl = asString(routing.api_base_url) || asString(routing.public_url);
|
||||
const publicUrl = asString(routing.public_url) || apiBaseUrl;
|
||||
const instance = asObject(routing.instance);
|
||||
const frontendBaseUrl =
|
||||
asString(routing.frontend_base_url) ||
|
||||
asString(instance.frontend_base_url) ||
|
||||
asString(instance.public_url);
|
||||
const apiBaseUrl =
|
||||
asString(routing.api_base_url) ||
|
||||
asString(instance.api_base_url) ||
|
||||
asString(routing.public_url) ||
|
||||
asString(instance.public_url);
|
||||
const publicUrl = asString(routing.public_url) || asString(instance.public_url) || apiBaseUrl;
|
||||
const backendConnection = asObject(response.backend_connection);
|
||||
|
||||
const mergedBackendConnection = {
|
||||
|
||||
@ -36,7 +36,8 @@
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
"node_modules",
|
||||
"**/*.test.ts",
|
||||
"**/*.test.tsx"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -187,14 +187,33 @@ def _normalize_portal_token_response(
|
||||
response: dict[str, Any],
|
||||
routing: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
frontend_base_url = _as_string(routing.get("frontend_base_url"))
|
||||
api_base_url = _as_string(routing.get("api_base_url")) or _as_string(routing.get("public_url"))
|
||||
public_url = _as_string(routing.get("public_url")) or api_base_url
|
||||
instance = _as_object(routing.get("instance"))
|
||||
frontend_base_url = (
|
||||
_as_string(routing.get("frontend_base_url"))
|
||||
or _as_string(instance.get("frontend_base_url"))
|
||||
or _as_string(instance.get("public_url"))
|
||||
)
|
||||
api_base_url = (
|
||||
_as_string(routing.get("api_base_url"))
|
||||
or _as_string(instance.get("api_base_url"))
|
||||
or _as_string(routing.get("public_url"))
|
||||
or _as_string(instance.get("public_url"))
|
||||
)
|
||||
public_url = (
|
||||
_as_string(routing.get("public_url"))
|
||||
or _as_string(instance.get("public_url"))
|
||||
or api_base_url
|
||||
)
|
||||
backend_connection = _as_object(response.get("backend_connection"))
|
||||
|
||||
merged_backend_connection = {
|
||||
**backend_connection,
|
||||
"frontend_base_url": _as_string(backend_connection.get("frontend_base_url")) or frontend_base_url or public_url or None,
|
||||
"frontend_base_url": (
|
||||
_as_string(backend_connection.get("frontend_base_url"))
|
||||
or frontend_base_url
|
||||
or public_url
|
||||
or None
|
||||
),
|
||||
"api_base_url": _as_string(backend_connection.get("api_base_url")) or api_base_url or public_url or None,
|
||||
"public_base_url": _as_string(backend_connection.get("public_base_url")) or public_url or api_base_url or None,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user