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