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