vtx_sdk/
auth.rs

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