mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-07 18:07:47 +08:00
refactor: 移除独立 hub/proxy/executor/gateway crate,统一为 gateway tunnel 架构
- 删除 aether-hub、aether-proxy 独立项目及其 Dockerfile/配置 - 删除 crates/aether-executor 和 crates/aether-gateway 全部模块 - 新增 apps/ 目录作为应用入口 - 将 hub 概念重构为 gateway tunnel transport - 将 executor 重构为 execution runtime - 新增 tunnel.rs 合约定义和 testkit tunnel/execution_runtime 模块 - 更新 Python 服务层和测试适配新架构命名
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
use aether_data::repository::wallet::StoredWalletSnapshot;
|
||||
use aether_wallet::{
|
||||
WalletAccessDecision, WalletAccessFailure, WalletLimitMode, WalletSnapshot, WalletStatus,
|
||||
};
|
||||
|
||||
use crate::gateway::gateway_data::StoredGatewayAuthApiKeySnapshot;
|
||||
use crate::gateway::{AppState, GatewayError, GatewayLocalAuthRejection};
|
||||
|
||||
pub(crate) async fn resolve_wallet_auth_gate(
|
||||
state: &AppState,
|
||||
auth_snapshot: &StoredGatewayAuthApiKeySnapshot,
|
||||
) -> Result<Option<WalletAccessDecision>, GatewayError> {
|
||||
if !state.has_wallet_data_reader() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let wallet = state
|
||||
.read_wallet_snapshot_for_auth(
|
||||
&auth_snapshot.user_id,
|
||||
&auth_snapshot.api_key_id,
|
||||
auth_snapshot.api_key_is_standalone,
|
||||
)
|
||||
.await?;
|
||||
let is_admin = auth_snapshot.user_role.eq_ignore_ascii_case("admin");
|
||||
|
||||
Ok(Some(match wallet.as_ref() {
|
||||
Some(wallet) => map_wallet_snapshot(wallet).access_decision(is_admin),
|
||||
None if is_admin => WalletAccessDecision::allowed(None),
|
||||
None => WalletAccessDecision::wallet_unavailable(None),
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn local_rejection_from_wallet_access(
|
||||
decision: &WalletAccessDecision,
|
||||
) -> Option<GatewayLocalAuthRejection> {
|
||||
match decision.failure.as_ref() {
|
||||
Some(WalletAccessFailure::WalletUnavailable) => {
|
||||
Some(GatewayLocalAuthRejection::WalletUnavailable)
|
||||
}
|
||||
Some(WalletAccessFailure::BalanceDenied) => {
|
||||
Some(GatewayLocalAuthRejection::BalanceDenied {
|
||||
remaining: decision.remaining,
|
||||
})
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_wallet_snapshot(snapshot: &StoredWalletSnapshot) -> WalletSnapshot {
|
||||
WalletSnapshot {
|
||||
wallet_id: snapshot.id.clone(),
|
||||
user_id: snapshot.user_id.clone(),
|
||||
api_key_id: snapshot.api_key_id.clone(),
|
||||
recharge_balance: snapshot.balance,
|
||||
gift_balance: snapshot.gift_balance,
|
||||
limit_mode: WalletLimitMode::parse(&snapshot.limit_mode),
|
||||
currency: snapshot.currency.clone(),
|
||||
status: WalletStatus::parse(&snapshot.status),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use aether_data::repository::wallet::StoredWalletSnapshot;
|
||||
use aether_wallet::{WalletAccessFailure, WalletLimitMode, WalletSnapshot, WalletStatus};
|
||||
|
||||
use super::{local_rejection_from_wallet_access, map_wallet_snapshot};
|
||||
use crate::gateway::GatewayLocalAuthRejection;
|
||||
|
||||
#[test]
|
||||
fn maps_wallet_snapshot_and_derives_balance_denied() {
|
||||
let stored = StoredWalletSnapshot::new(
|
||||
"wallet-1".to_string(),
|
||||
Some("user-1".to_string()),
|
||||
None,
|
||||
0.0,
|
||||
0.0,
|
||||
"finite".to_string(),
|
||||
"USD".to_string(),
|
||||
"active".to_string(),
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
100,
|
||||
)
|
||||
.expect("wallet should build");
|
||||
|
||||
let decision = map_wallet_snapshot(&stored).access_decision(false);
|
||||
assert_eq!(decision.failure, Some(WalletAccessFailure::BalanceDenied));
|
||||
assert_eq!(
|
||||
local_rejection_from_wallet_access(&decision),
|
||||
Some(GatewayLocalAuthRejection::BalanceDenied {
|
||||
remaining: Some(0.0),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unlimited_admin_wallet_gate_allows_without_remaining() {
|
||||
let decision = WalletSnapshot {
|
||||
wallet_id: "wallet-1".to_string(),
|
||||
user_id: Some("user-1".to_string()),
|
||||
api_key_id: None,
|
||||
recharge_balance: 0.0,
|
||||
gift_balance: 0.0,
|
||||
limit_mode: WalletLimitMode::Unlimited,
|
||||
currency: "USD".to_string(),
|
||||
status: WalletStatus::Active,
|
||||
}
|
||||
.access_decision(true);
|
||||
|
||||
assert!(decision.allowed);
|
||||
assert_eq!(decision.remaining, None);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user