mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
fix(admin-api-keys): 独立余额 Key 统计与时间字段改为直读 api_keys 表 (#319)
- 列表/详情/更新响应中的 `total_requests`、`total_tokens`、`created_at`、`last_used_at` 统一直接读取 `api_keys` 导出记录字段 - 保持“已消费”继续走钱包字段(不改消费口径) - 在 auth 导出记录中补充 `last_used_at_unix_secs`、`created_at_unix_secs`、`updated_at_unix_secs` - 扩展 auth SQL 查询与 RETURNING 字段映射,确保时间字段完整回传 - 移除 admin api-keys 路由中对 usage summary token 聚合的依赖 - 更新 admin api-keys 控制层测试,校验 token/时间字段来源与格式
This commit is contained in:
@@ -152,6 +152,9 @@ SELECT
|
||||
api_keys.total_requests,
|
||||
COALESCE(api_keys.total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(api_keys.total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
api_keys.is_standalone
|
||||
FROM api_keys
|
||||
WHERE api_keys.user_id = ANY($1::TEXT[])
|
||||
@@ -178,6 +181,9 @@ SELECT
|
||||
api_keys.total_requests,
|
||||
COALESCE(api_keys.total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(api_keys.total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
api_keys.is_standalone
|
||||
FROM api_keys
|
||||
WHERE api_keys.id = ANY($1::TEXT[])
|
||||
@@ -203,6 +209,9 @@ SELECT
|
||||
api_keys.total_requests,
|
||||
COALESCE(api_keys.total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(api_keys.total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
api_keys.is_standalone
|
||||
FROM api_keys
|
||||
WHERE LOWER(COALESCE(api_keys.name, '')) LIKE $1
|
||||
@@ -228,6 +237,9 @@ SELECT
|
||||
api_keys.total_requests,
|
||||
COALESCE(api_keys.total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(api_keys.total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
api_keys.is_standalone
|
||||
FROM api_keys
|
||||
WHERE api_keys.is_standalone = TRUE
|
||||
@@ -253,6 +265,9 @@ SELECT
|
||||
api_keys.total_requests,
|
||||
COALESCE(api_keys.total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(api_keys.total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
api_keys.is_standalone
|
||||
FROM api_keys
|
||||
WHERE api_keys.is_standalone = TRUE
|
||||
@@ -322,6 +337,9 @@ SELECT
|
||||
api_keys.total_requests,
|
||||
COALESCE(api_keys.total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(api_keys.total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM api_keys.updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
api_keys.is_standalone
|
||||
FROM api_keys
|
||||
WHERE api_keys.is_standalone = TRUE
|
||||
@@ -400,6 +418,9 @@ RETURNING
|
||||
total_requests,
|
||||
COALESCE(total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
is_standalone
|
||||
"#;
|
||||
|
||||
@@ -468,6 +489,9 @@ RETURNING
|
||||
total_requests,
|
||||
COALESCE(total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
is_standalone
|
||||
"#;
|
||||
|
||||
@@ -499,6 +523,9 @@ RETURNING
|
||||
total_requests,
|
||||
COALESCE(total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
is_standalone
|
||||
"#;
|
||||
|
||||
@@ -534,6 +561,9 @@ RETURNING
|
||||
total_requests,
|
||||
COALESCE(total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
is_standalone
|
||||
"#;
|
||||
|
||||
@@ -563,6 +593,9 @@ RETURNING
|
||||
total_requests,
|
||||
COALESCE(total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
is_standalone
|
||||
"#;
|
||||
|
||||
@@ -591,6 +624,9 @@ RETURNING
|
||||
total_requests,
|
||||
COALESCE(total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
is_standalone
|
||||
"#;
|
||||
|
||||
@@ -630,6 +666,9 @@ RETURNING
|
||||
total_requests,
|
||||
COALESCE(total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
is_standalone
|
||||
"#;
|
||||
|
||||
@@ -659,6 +698,9 @@ RETURNING
|
||||
total_requests,
|
||||
COALESCE(total_tokens, 0)::BIGINT AS total_tokens,
|
||||
COALESCE(CAST(total_cost_usd AS DOUBLE PRECISION), 0) AS total_cost_usd,
|
||||
CAST(EXTRACT(EPOCH FROM last_used_at) AS BIGINT) AS last_used_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM created_at) AS BIGINT) AS created_at_unix_secs,
|
||||
CAST(EXTRACT(EPOCH FROM updated_at) AS BIGINT) AS updated_at_unix_secs,
|
||||
is_standalone
|
||||
"#;
|
||||
|
||||
@@ -1397,6 +1439,13 @@ fn map_auth_api_key_export_row(
|
||||
row_get(row, "total_cost_usd")?,
|
||||
row_get(row, "is_standalone")?,
|
||||
)
|
||||
.and_then(|record| {
|
||||
record.with_activity_timestamps(
|
||||
row_get(row, "last_used_at_unix_secs")?,
|
||||
row_get(row, "created_at_unix_secs")?,
|
||||
row_get(row, "updated_at_unix_secs")?,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -268,6 +268,9 @@ pub struct StoredAuthApiKeyExportRecord {
|
||||
pub total_requests: u64,
|
||||
pub total_tokens: u64,
|
||||
pub total_cost_usd: f64,
|
||||
pub last_used_at_unix_secs: Option<u64>,
|
||||
pub created_at_unix_secs: Option<u64>,
|
||||
pub updated_at_unix_secs: Option<u64>,
|
||||
pub is_standalone: bool,
|
||||
}
|
||||
|
||||
@@ -337,9 +340,30 @@ impl StoredAuthApiKeyExportRecord {
|
||||
total_requests: parse_u64_i64(total_requests, "api_keys.total_requests")?,
|
||||
total_tokens: parse_u64_i64(total_tokens, "api_keys.total_tokens")?,
|
||||
total_cost_usd,
|
||||
last_used_at_unix_secs: None,
|
||||
created_at_unix_secs: None,
|
||||
updated_at_unix_secs: None,
|
||||
is_standalone,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn with_activity_timestamps(
|
||||
mut self,
|
||||
last_used_at_unix_secs: Option<i64>,
|
||||
created_at_unix_secs: Option<i64>,
|
||||
updated_at_unix_secs: Option<i64>,
|
||||
) -> Result<Self, crate::DataLayerError> {
|
||||
self.last_used_at_unix_secs = last_used_at_unix_secs
|
||||
.map(|value| parse_u64_i64(value, "api_keys.last_used_at_unix_secs"))
|
||||
.transpose()?;
|
||||
self.created_at_unix_secs = created_at_unix_secs
|
||||
.map(|value| parse_u64_i64(value, "api_keys.created_at_unix_secs"))
|
||||
.transpose()?;
|
||||
self.updated_at_unix_secs = updated_at_unix_secs
|
||||
.map(|value| parse_u64_i64(value, "api_keys.updated_at_unix_secs"))
|
||||
.transpose()?;
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
|
||||
|
||||
Reference in New Issue
Block a user