Skip to main content

litellm_rs/auth/
user_management.rs

1//! User management operations
2
3use super::system::AuthSystem;
4use crate::core::models::user::types::User;
5use crate::utils::auth::crypto::password::{hash_password, verify_password};
6use crate::utils::error::gateway_error::{GatewayError, Result};
7use tracing::info;
8
9impl AuthSystem {
10    /// Create a new user
11    pub async fn create_user(
12        &self,
13        username: String,
14        email: String,
15        password: String,
16    ) -> Result<User> {
17        info!("Creating new user: {}", username);
18
19        // Hash password
20        let password_hash = hash_password(&password)?;
21
22        // Create user
23        let user = User::new(username, email, password_hash);
24
25        // Store in database
26        self.storage.db().create_user(&user).await
27    }
28
29    /// Login user and create session
30    pub async fn login(&self, username: &str, password: &str) -> Result<(User, String)> {
31        let user = self.verify_login_credentials(username, password).await?;
32        self.finish_login(user, None).await
33    }
34
35    /// Login with an explicit, server-verified active-team selection.
36    pub(crate) async fn login_with_active_team(
37        &self,
38        username: &str,
39        password: &str,
40        team_id: uuid::Uuid,
41    ) -> Result<(User, String)> {
42        let user = self.verify_login_credentials(username, password).await?;
43        let verified_team = self
44            .validate_active_team(user.id(), team_id)
45            .await?
46            .ok_or_else(|| GatewayError::bad_request("Invalid active team selection"))?;
47        self.finish_login(user, Some(verified_team)).await
48    }
49
50    async fn verify_login_credentials(&self, username: &str, password: &str) -> Result<User> {
51        info!("User login attempt: {}", username);
52
53        // Find user
54        let user = self
55            .storage
56            .db()
57            .find_user_by_username(username)
58            .await?
59            .ok_or_else(|| GatewayError::auth("Invalid username or password"))?;
60
61        // Verify password
62        if !verify_password(password, &user.password_hash)? {
63            return Err(GatewayError::auth("Invalid username or password"));
64        }
65
66        // Check if user is active
67        if !user.is_active() {
68            return Err(GatewayError::auth("Account is not active"));
69        }
70
71        Ok(user)
72    }
73
74    async fn finish_login(
75        &self,
76        user: User,
77        verified_team: Option<crate::auth::jwt::types::VerifiedActiveTeam>,
78    ) -> Result<(User, String)> {
79        // Create session
80        let session_id = uuid::Uuid::new_v4();
81        let permissions = self.get_user_permissions(&user).await?;
82        let session_token = match verified_team {
83            Some(ref verified_team) => {
84                self.jwt
85                    .create_access_token_for_verified_team(
86                        user.id(),
87                        user.role.to_string(),
88                        permissions,
89                        verified_team,
90                        Some(session_id),
91                    )
92                    .await?
93            }
94            None => {
95                self.jwt
96                    .create_access_token(
97                        user.id(),
98                        user.role.to_string(),
99                        permissions,
100                        None,
101                        Some(session_id),
102                    )
103                    .await?
104            }
105        };
106
107        // Update last login
108        self.storage.db().update_user_last_login(user.id()).await?;
109
110        info!("User logged in successfully: {}", user.username);
111        Ok((user, session_token))
112    }
113
114    /// Logout user
115    pub async fn logout(&self, session_token: &str) -> Result<()> {
116        info!("User logout");
117
118        // Extract session ID from token
119        if let Ok(claims) = self.jwt.verify_access_token(session_token).await
120            && claims.session_id.is_some()
121        {
122            // Store invalidated session (in practice, you'd use Redis or similar)
123            // For now, just log the session invalidation
124            info!("Session invalidated");
125        }
126
127        Ok(())
128    }
129}