feat: add user groups and inherited access policies

This commit is contained in:
Entropy.Xu
2026-05-09 21:47:33 +08:00
parent 4a64d078f3
commit 3a814f3d1f
49 changed files with 6381 additions and 250 deletions

View File

@@ -2927,8 +2927,11 @@ async fn gateway_handles_admin_usage_cache_affinity_interval_timeline_with_legac
role: "user".to_string(),
auth_source: "local".to_string(),
allowed_providers: None,
allowed_providers_mode: "unrestricted".to_string(),
allowed_api_formats: None,
allowed_api_formats_mode: "unrestricted".to_string(),
allowed_models: None,
allowed_models_mode: "unrestricted".to_string(),
is_active: true,
is_deleted: false,
created_at: None,

View File

@@ -377,7 +377,10 @@ async fn embeddings_route_rejects_chat_only_model() {
Some(EXECUTION_PATH_LOCAL_AUTH_DENIED)
);
let payload: serde_json::Value = response.json().await.expect("body should parse");
assert_eq!(payload["error"]["message"], "当前密钥不允许访问模型 gpt-5");
assert_eq!(
payload["error"]["message"],
"当前用户、用户组或密钥的访问控制策略不允许访问模型 gpt-5"
);
gateway_handle.abort();
}
@@ -416,7 +419,7 @@ async fn embeddings_route_rejects_chat_only_api_format() {
let payload: serde_json::Value = response.json().await.expect("body should parse");
assert_eq!(
payload["error"]["message"],
"当前密钥不允许访问 openai:embedding 格式"
"当前用户、用户组或密钥的访问控制策略不允许访问 openai:embedding 格式"
);
gateway_handle.abort();

View File

@@ -501,7 +501,7 @@ async fn gateway_locally_denies_disallowed_claude_api_format_without_hitting_con
assert_eq!(payload["error"]["type"], "http_error");
assert_eq!(
payload["error"]["message"],
"当前密钥不允许访问 claude:messages 格式"
"当前用户、用户组或密钥的访问控制策略不允许访问 claude:messages 格式"
);
assert_eq!(*auth_context_hits.lock().expect("mutex should lock"), 0);
assert_eq!(*public_hits.lock().expect("mutex should lock"), 0);
@@ -584,7 +584,7 @@ async fn gateway_locally_denies_disallowed_provider_without_hitting_control_or_u
assert_eq!(payload["error"]["type"], "http_error");
assert_eq!(
payload["error"]["message"],
"当前密钥不允许访问 claude 提供商"
"当前用户、用户组或密钥的访问控制策略不允许访问 claude 提供商"
);
assert_eq!(*auth_context_hits.lock().expect("mutex should lock"), 0);
assert_eq!(*public_hits.lock().expect("mutex should lock"), 0);
@@ -656,7 +656,7 @@ async fn gateway_locally_denies_disallowed_gemini_model_without_hitting_control_
assert_eq!(payload["error"]["type"], "http_error");
assert_eq!(
payload["error"]["message"],
"当前密钥不允许访问模型 gemini-2.5-pro"
"当前用户、用户组或密钥的访问控制策略不允许访问模型 gemini-2.5-pro"
);
assert_eq!(*auth_context_hits.lock().expect("mutex should lock"), 0);
assert_eq!(*public_hits.lock().expect("mutex should lock"), 0);
@@ -806,7 +806,10 @@ async fn gateway_locally_denies_disallowed_openai_model_without_hitting_control_
);
let payload: serde_json::Value = response.json().await.expect("response json should parse");
assert_eq!(payload["error"]["type"], "http_error");
assert_eq!(payload["error"]["message"], "当前密钥不允许访问模型 gpt-5");
assert_eq!(
payload["error"]["message"],
"当前用户、用户组或密钥的访问控制策略不允许访问模型 gpt-5"
);
assert_eq!(*auth_context_hits.lock().expect("mutex should lock"), 0);
assert_eq!(*public_hits.lock().expect("mutex should lock"), 0);

View File

@@ -319,7 +319,7 @@ async fn rerank_route_rejects_chat_only_api_format() {
let payload: serde_json::Value = response.json().await.expect("body should parse");
assert_eq!(
payload["error"]["message"],
"当前密钥不允许访问 openai:rerank 格式"
"当前用户、用户组或密钥的访问控制策略不允许访问 openai:rerank 格式"
);
gateway_handle.abort();