reifydb_sub_server/
auth.rs1use std::{error::Error as StdError, fmt};
5
6use reifydb_auth::service::AuthService;
7use reifydb_type::value::identity::IdentityId;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum AuthError {
12 InvalidHeader,
14 MissingCredentials,
16 InvalidToken,
18 Expired,
20 InsufficientPermissions,
22}
23
24impl fmt::Display for AuthError {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 match self {
27 AuthError::InvalidHeader => write!(f, "Invalid authorization header"),
28 AuthError::MissingCredentials => write!(f, "Authentication required"),
29 AuthError::InvalidToken => write!(f, "Invalid authentication token"),
30 AuthError::Expired => write!(f, "Authentication token expired"),
31 AuthError::InsufficientPermissions => write!(f, "Insufficient permissions"),
32 }
33 }
34}
35
36impl StdError for AuthError {}
37
38pub type AuthResult<T> = Result<T, AuthError>;
40
41pub fn extract_identity_from_auth_header(auth_service: &AuthService, auth_header: &str) -> AuthResult<IdentityId> {
47 if let Some(token) = auth_header.strip_prefix("Bearer ") {
48 validate_bearer_token(auth_service, token.trim())
49 } else if let Some(credentials) = auth_header.strip_prefix("Basic ") {
50 validate_basic_auth(auth_service, credentials.trim())
51 } else {
52 Err(AuthError::InvalidHeader)
53 }
54}
55
56pub fn extract_identity_from_ws_auth(auth_service: &AuthService, token: Option<&str>) -> AuthResult<IdentityId> {
60 match token {
61 Some(t) if !t.is_empty() => validate_bearer_token(auth_service, t),
62 _ => Ok(IdentityId::anonymous()),
63 }
64}
65
66fn validate_bearer_token(auth_service: &AuthService, token: &str) -> AuthResult<IdentityId> {
68 if token.is_empty() {
69 return Err(AuthError::InvalidToken);
70 }
71
72 match auth_service.validate_token(token) {
73 Some(session) => Ok(session.identity),
74 None => Err(AuthError::InvalidToken),
75 }
76}
77
78fn validate_basic_auth(_auth_service: &AuthService, _credentials: &str) -> AuthResult<IdentityId> {
80 Err(AuthError::InvalidToken)
82}
83
84#[cfg(test)]
85pub mod tests {
86 use super::*;
87
88 #[test]
89 fn test_auth_error_display() {
90 assert_eq!(AuthError::InvalidHeader.to_string(), "Invalid authorization header");
91 assert_eq!(AuthError::MissingCredentials.to_string(), "Authentication required");
92 assert_eq!(AuthError::InvalidToken.to_string(), "Invalid authentication token");
93 assert_eq!(AuthError::Expired.to_string(), "Authentication token expired");
94 }
95
96 #[test]
97 fn test_anonymous_identity() {
98 let identity = IdentityId::anonymous();
99 assert!(identity.is_anonymous());
100 }
101
102 #[test]
103 fn test_root_identity() {
104 let identity = IdentityId::root();
105 assert!(identity.is_root());
106 }
107}