cloudreve_api/api/v3/
session.rs

1//! Session and authentication management for Cloudreve API v3
2
3use crate::api::v3::models::*;
4use crate::api::v3::ApiV3Client;
5use crate::Error;
6use log::debug;
7
8impl ApiV3Client {
9    /// Login with email and password
10    pub async fn login(&mut self, request: &LoginRequest<'_>) -> Result<User, Error> {
11        let url = self.get_url("/user/session");
12        let mut http_request = self.http_client.post(&url).json(request);
13
14        if let Some(cookie) = &self.session_cookie {
15            http_request = http_request.header("Cookie", format!("cloudreve-session={}", cookie));
16        }
17
18        let response = http_request.send().await?;
19
20        // Extract session cookie from Set-Cookie headers
21        // V3 uses Set-Cookie headers to set the session cookie
22        let cookie_headers = response.headers().get_all("Set-Cookie");
23        for cookie_header in cookie_headers {
24            if let Ok(cookie_str) = cookie_header.to_str() {
25                // Check if this Set-Cookie header contains cloudreve-session
26                if cookie_str.contains("cloudreve-session=") {
27                    // Parse the cookie value
28                    // Format: "cloudreve-session=VALUE; Path=/; HttpOnly" etc.
29                    for part in cookie_str.split(';') {
30                        let part = part.trim();
31                        if part.starts_with("cloudreve-session=") {
32                            let session_value = part.trim_start_matches("cloudreve-session=");
33                            self.session_cookie = Some(session_value.to_string());
34                            debug!("Extracted V3 session cookie: {}...", &session_value[..session_value.len().min(20)]);
35                            break;
36                        }
37                    }
38                }
39            }
40        }
41
42        debug!("V3 session_cookie after login: {:?}", self.session_cookie);
43
44        let _status = response.status();
45        let api_response: ApiResponse<User> = response.json().await?;
46
47        match api_response.data {
48            Some(user) => Ok(user),
49            None => Err(Error::Api {
50                code: api_response.code,
51                message: api_response.msg,
52            }),
53        }
54    }
55
56    /// Login with OTP (Two-Factor Authentication)
57    pub async fn login_2fa(&mut self, request: &OtpLoginRequest) -> Result<User, Error> {
58        let url = self.get_url("/user/2fa");
59        let mut http_request = self.http_client.post(&url).json(request);
60
61        if let Some(cookie) = &self.session_cookie {
62            http_request = http_request.header("Cookie", format!("cloudreve-session={}", cookie));
63        }
64
65        let response = http_request.send().await?;
66
67        // Extract session cookie from Set-Cookie headers
68        let cookie_headers = response.headers().get_all("Set-Cookie");
69        for cookie_header in cookie_headers {
70            if let Ok(cookie_str) = cookie_header.to_str() {
71                if cookie_str.contains("cloudreve-session=") {
72                    for part in cookie_str.split(';') {
73                        let part = part.trim();
74                        if part.starts_with("cloudreve-session=") {
75                            let session_value = part.trim_start_matches("cloudreve-session=");
76                            self.session_cookie = Some(session_value.to_string());
77                            debug!("Extracted V3 session cookie (2FA): {}...", &session_value[..session_value.len().min(20)]);
78                            break;
79                        }
80                    }
81                }
82            }
83        }
84
85        let _status = response.status();
86        let api_response: ApiResponse<User> = response.json().await?;
87
88        match api_response.data {
89            Some(user) => Ok(user),
90            None => Err(Error::Api {
91                code: api_response.code,
92                message: api_response.msg,
93            }),
94        }
95    }
96
97    /// Logout from current session
98    pub async fn logout(&self) -> Result<(), Error> {
99        let response: ApiResponse<()> = self.delete("/user/session").await?;
100        if response.code == 0 {
101            Ok(())
102        } else {
103            Err(Error::Api {
104                code: response.code,
105                message: response.msg,
106            })
107        }
108    }
109}