mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
feat(admin): 完善代理节点与 OAuth 授权管理
This commit is contained in:
@@ -508,7 +508,7 @@ impl AuthApiKeyWriteRepository for InMemoryAuthApiKeySnapshotRepository {
|
||||
api_key_is_active: record.is_active,
|
||||
api_key_is_locked: false,
|
||||
api_key_is_standalone: true,
|
||||
api_key_rate_limit: Some(record.rate_limit),
|
||||
api_key_rate_limit: record.rate_limit,
|
||||
api_key_concurrent_limit: Some(record.concurrent_limit),
|
||||
api_key_expires_at_unix_secs: record.expires_at_unix_secs,
|
||||
api_key_allowed_providers: record.allowed_providers.clone(),
|
||||
@@ -536,7 +536,7 @@ impl AuthApiKeyWriteRepository for InMemoryAuthApiKeySnapshotRepository {
|
||||
record.is_active,
|
||||
false,
|
||||
true,
|
||||
Some(record.rate_limit),
|
||||
record.rate_limit,
|
||||
Some(record.concurrent_limit),
|
||||
record.expires_at_unix_secs.map(|value| value as i64),
|
||||
record
|
||||
@@ -572,7 +572,7 @@ impl AuthApiKeyWriteRepository for InMemoryAuthApiKeySnapshotRepository {
|
||||
.allowed_models
|
||||
.as_ref()
|
||||
.map(|value| serde_json::json!(value)),
|
||||
Some(record.rate_limit),
|
||||
record.rate_limit,
|
||||
Some(record.concurrent_limit),
|
||||
record.force_capabilities,
|
||||
record.is_active,
|
||||
@@ -650,12 +650,12 @@ impl AuthApiKeyWriteRepository for InMemoryAuthApiKeySnapshotRepository {
|
||||
export.name = Some(name);
|
||||
}
|
||||
}
|
||||
if let Some(rate_limit) = record.rate_limit {
|
||||
if record.rate_limit_present {
|
||||
if let Some(snapshot) = index.by_api_key_id.get_mut(&record.api_key_id) {
|
||||
snapshot.api_key_rate_limit = Some(rate_limit);
|
||||
snapshot.api_key_rate_limit = record.rate_limit;
|
||||
}
|
||||
if let Some(export) = index.export_by_api_key_id.get_mut(&record.api_key_id) {
|
||||
export.rate_limit = Some(rate_limit);
|
||||
export.rate_limit = record.rate_limit;
|
||||
}
|
||||
}
|
||||
if let Some(allowed_providers) = record.allowed_providers {
|
||||
@@ -682,6 +682,19 @@ impl AuthApiKeyWriteRepository for InMemoryAuthApiKeySnapshotRepository {
|
||||
export.allowed_models = allowed_models;
|
||||
}
|
||||
}
|
||||
if record.expires_at_present {
|
||||
if let Some(snapshot) = index.by_api_key_id.get_mut(&record.api_key_id) {
|
||||
snapshot.api_key_expires_at_unix_secs = record.expires_at_unix_secs;
|
||||
}
|
||||
if let Some(export) = index.export_by_api_key_id.get_mut(&record.api_key_id) {
|
||||
export.expires_at_unix_secs = record.expires_at_unix_secs;
|
||||
}
|
||||
}
|
||||
if record.auto_delete_on_expiry_present {
|
||||
if let Some(export) = index.export_by_api_key_id.get_mut(&record.api_key_id) {
|
||||
export.auto_delete_on_expiry = record.auto_delete_on_expiry;
|
||||
}
|
||||
}
|
||||
Ok(index.export_by_api_key_id.get(&record.api_key_id).cloned())
|
||||
}
|
||||
|
||||
|
||||
@@ -468,10 +468,12 @@ const UPDATE_STANDALONE_API_KEY_BASIC_SQL: &str = r#"
|
||||
UPDATE api_keys
|
||||
SET
|
||||
name = COALESCE($2, name),
|
||||
rate_limit = COALESCE($3, rate_limit),
|
||||
allowed_providers = CASE WHEN $4 THEN $5::json ELSE allowed_providers END,
|
||||
allowed_api_formats = CASE WHEN $6 THEN $7::json ELSE allowed_api_formats END,
|
||||
allowed_models = CASE WHEN $8 THEN $9::json ELSE allowed_models END,
|
||||
rate_limit = CASE WHEN $3 THEN $4 ELSE rate_limit END,
|
||||
allowed_providers = CASE WHEN $5 THEN $6::json ELSE allowed_providers END,
|
||||
allowed_api_formats = CASE WHEN $7 THEN $8::json ELSE allowed_api_formats END,
|
||||
allowed_models = CASE WHEN $9 THEN $10::json ELSE allowed_models END,
|
||||
expires_at = CASE WHEN $11 THEN $12 ELSE expires_at END,
|
||||
auto_delete_on_expiry = CASE WHEN $13 THEN $14 ELSE auto_delete_on_expiry END,
|
||||
updated_at = NOW()
|
||||
WHERE id = $1
|
||||
AND is_standalone = TRUE
|
||||
@@ -1085,9 +1087,18 @@ impl AuthApiKeyWriteRepository for SqlxAuthApiKeySnapshotReadRepository {
|
||||
.map(serde_json::to_value)
|
||||
.transpose()
|
||||
.map_err(|err| DataLayerError::UnexpectedValue(err.to_string()))?;
|
||||
let expires_at = record
|
||||
.expires_at_unix_secs
|
||||
.map(|value| {
|
||||
chrono::DateTime::<chrono::Utc>::from_timestamp(value as i64, 0).ok_or_else(|| {
|
||||
DataLayerError::UnexpectedValue(format!("invalid api_keys.expires_at: {value}"))
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
let row = sqlx::query(UPDATE_STANDALONE_API_KEY_BASIC_SQL)
|
||||
.bind(record.api_key_id)
|
||||
.bind(record.name)
|
||||
.bind(record.rate_limit_present)
|
||||
.bind(record.rate_limit)
|
||||
.bind(record.allowed_providers.is_some())
|
||||
.bind(allowed_providers)
|
||||
@@ -1095,6 +1106,10 @@ impl AuthApiKeyWriteRepository for SqlxAuthApiKeySnapshotReadRepository {
|
||||
.bind(allowed_api_formats)
|
||||
.bind(record.allowed_models.is_some())
|
||||
.bind(allowed_models)
|
||||
.bind(record.expires_at_present)
|
||||
.bind(expires_at)
|
||||
.bind(record.auto_delete_on_expiry_present)
|
||||
.bind(record.auto_delete_on_expiry)
|
||||
.fetch_optional(&self.pool)
|
||||
.await
|
||||
.map_postgres_err()?;
|
||||
@@ -1299,12 +1314,19 @@ mod tests {
|
||||
#[test]
|
||||
fn update_standalone_api_key_basic_sql_casts_json_case_values() {
|
||||
assert!(UPDATE_STANDALONE_API_KEY_BASIC_SQL
|
||||
.contains("allowed_providers = CASE WHEN $4 THEN $5::json ELSE allowed_providers END"));
|
||||
.contains("allowed_providers = CASE WHEN $5 THEN $6::json ELSE allowed_providers END"));
|
||||
assert!(UPDATE_STANDALONE_API_KEY_BASIC_SQL.contains(
|
||||
"allowed_api_formats = CASE WHEN $6 THEN $7::json ELSE allowed_api_formats END"
|
||||
"allowed_api_formats = CASE WHEN $7 THEN $8::json ELSE allowed_api_formats END"
|
||||
));
|
||||
assert!(UPDATE_STANDALONE_API_KEY_BASIC_SQL
|
||||
.contains("allowed_models = CASE WHEN $8 THEN $9::json ELSE allowed_models END"));
|
||||
.contains("allowed_models = CASE WHEN $9 THEN $10::json ELSE allowed_models END"));
|
||||
assert!(UPDATE_STANDALONE_API_KEY_BASIC_SQL
|
||||
.contains("rate_limit = CASE WHEN $3 THEN $4 ELSE rate_limit END"));
|
||||
assert!(UPDATE_STANDALONE_API_KEY_BASIC_SQL
|
||||
.contains("expires_at = CASE WHEN $11 THEN $12 ELSE expires_at END"));
|
||||
assert!(UPDATE_STANDALONE_API_KEY_BASIC_SQL.contains(
|
||||
"auto_delete_on_expiry = CASE WHEN $13 THEN $14 ELSE auto_delete_on_expiry END"
|
||||
));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -390,7 +390,7 @@ pub struct CreateStandaloneApiKeyRecord {
|
||||
pub allowed_providers: Option<Vec<String>>,
|
||||
pub allowed_api_formats: Option<Vec<String>>,
|
||||
pub allowed_models: Option<Vec<String>>,
|
||||
pub rate_limit: i32,
|
||||
pub rate_limit: Option<i32>,
|
||||
pub concurrent_limit: i32,
|
||||
pub force_capabilities: Option<serde_json::Value>,
|
||||
pub is_active: bool,
|
||||
@@ -404,10 +404,15 @@ pub struct CreateStandaloneApiKeyRecord {
|
||||
pub struct UpdateStandaloneApiKeyBasicRecord {
|
||||
pub api_key_id: String,
|
||||
pub name: Option<String>,
|
||||
pub rate_limit_present: bool,
|
||||
pub rate_limit: Option<i32>,
|
||||
pub allowed_providers: Option<Option<Vec<String>>>,
|
||||
pub allowed_api_formats: Option<Option<Vec<String>>>,
|
||||
pub allowed_models: Option<Option<Vec<String>>>,
|
||||
pub expires_at_present: bool,
|
||||
pub expires_at_unix_secs: Option<u64>,
|
||||
pub auto_delete_on_expiry_present: bool,
|
||||
pub auto_delete_on_expiry: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
||||
Reference in New Issue
Block a user