vtx_sdk/host/
auth.rs

1//! Host-side auth helpers.
2
3use crate::bindings::vtx::api::auth_types::UserContext;
4use crate::error::{VtxError, VtxResult};
5
6/// 鉴权请求辅助类
7///
8/// 职责:
9/// 封装原始 Header 列表,提供便捷的 Token 提取与校验方法。
10pub struct AuthRequest<'a> {
11    headers: &'a [(String, String)],
12}
13
14impl<'a> AuthRequest<'a> {
15    /// 实例化 AuthRequest
16    pub fn new(headers: &'a [(String, String)]) -> Self {
17        Self { headers }
18    }
19
20    /// 获取 Header 值 (Case-insensitive)
21    pub fn header(&self, key: &str) -> Option<&str> {
22        let search_key = key.to_lowercase();
23        for (k, v) in self.headers {
24            if k.to_lowercase() == search_key {
25                return Some(v.as_str());
26            }
27        }
28        None
29    }
30
31    /// 获取必需的 Header 值
32    ///
33    /// 行为:
34    /// 若 Header 不存在,返回 `AuthDenied(401)` 错误。
35    pub fn require_header(&self, key: &str) -> VtxResult<&str> {
36        self.header(key).ok_or_else(|| {
37            // 提示:具体缺失哪个 Header 的信息在转换为 u16 时会丢失,
38            // 但在调试阶段或后续日志扩展中可能有用。
39            VtxError::AuthDenied(401)
40        })
41    }
42
43    /// 提取 Bearer Token
44    ///
45    /// 格式支持:`Authorization: Bearer <token>` (忽略 Bearer 大小写)。
46    pub fn bearer_token(&self) -> Option<&str> {
47        let val = self.header("Authorization")?;
48        if val.starts_with("Bearer ") || val.starts_with("bearer ") {
49            Some(&val[7..])
50        } else {
51            None
52        }
53    }
54
55    /// 获取必需的 Bearer Token
56    ///
57    /// 行为:
58    /// 若 Authorization 头缺失或格式不正确,返回 `AuthDenied(401)`。
59    pub fn require_bearer_token(&self) -> VtxResult<&str> {
60        self.bearer_token().ok_or_else(|| VtxError::AuthDenied(401))
61    }
62
63    /// 提取 Basic Auth 凭证
64    pub fn basic_auth(&self) -> Option<&str> {
65        let val = self.header("Authorization")?;
66        if val.starts_with("Basic ") || val.starts_with("basic ") {
67            Some(&val[6..])
68        } else {
69            None
70        }
71    }
72}
73
74/// 用户上下文构建器 (Builder Pattern)
75///
76/// 职责:
77/// 构造 `UserContext` 对象,支持链式调用。
78pub struct UserBuilder {
79    user_id: String,
80    username: String,
81    groups: Vec<String>,
82    metadata: serde_json::Map<String, serde_json::Value>,
83}
84
85impl UserBuilder {
86    /// 初始化构建器
87    ///
88    /// 必需参数:用户 ID 和 用户名。
89    pub fn new(id: impl Into<String>, name: impl Into<String>) -> Self {
90        Self {
91            user_id: id.into(),
92            username: name.into(),
93            groups: Vec::new(),
94            metadata: serde_json::Map::new(),
95        }
96    }
97
98    /// 添加用户所属组/角色
99    pub fn group(mut self, group: impl Into<String>) -> Self {
100        self.groups.push(group.into());
101        self
102    }
103
104    /// 添加元数据键值对
105    ///
106    /// 若 `value` 序列化失败,该字段将被静默忽略。
107    pub fn meta<V: serde::Serialize>(mut self, key: &str, value: V) -> Self {
108        if let Ok(val) = serde_json::to_value(value) {
109            self.metadata.insert(key.to_string(), val);
110        }
111        self
112    }
113
114    /// 构建 UserContext
115    ///
116    /// 结果包含序列化后的 metadata JSON 字符串。
117    pub fn build(self) -> UserContext {
118        UserContext {
119            user_id: self.user_id,
120            username: self.username,
121            groups: self.groups,
122            metadata: serde_json::to_string(&self.metadata).unwrap_or_else(|_| "{}".to_string()),
123        }
124    }
125}
126
127/// 鉴权结果转换扩展特征
128///
129/// 职责:
130/// 将 SDK 标准的 `VtxResult<UserContext>` 转换为 WIT 接口要求的 `Result<UserContext, u16>`。
131/// 这允许开发者在 `authenticate` 实现中统一使用 `?` 操作符处理 DB 或逻辑错误。
132pub trait IntoAuthResult {
133    fn into_auth_result(self) -> Result<UserContext, u16>;
134}
135
136impl IntoAuthResult for VtxResult<UserContext> {
137    fn into_auth_result(self) -> Result<UserContext, u16> {
138        match self {
139            Ok(ctx) => Ok(ctx),
140            Err(e) => {
141                // 错误降级策略:将丰富的错误类型映射为 HTTP 状态码
142                let status_code = match e {
143                    VtxError::AuthDenied(code) => code,
144                    VtxError::PermissionDenied(_) => 403,
145                    VtxError::NotFound(_) => 404,
146                    // 数据库错误、序列化错误或内部错误,统一视为 500
147                    VtxError::DatabaseError(_)
148                    | VtxError::SerializationError(_)
149                    | VtxError::Internal(_) => 500,
150                };
151                Err(status_code)
152            }
153        }
154    }
155}