sure_client_rs/client/
auth.rs

1use crate::error::ApiResult;
2use crate::models::auth::{
3    AuthLoginResponse, AuthSignupResponse, AuthTokenResponse, DeviceInfo, LoginRequest,
4    RefreshDeviceInfo, RefreshTokenRequest, SignupRequest, SignupUserData,
5};
6use bon::bon;
7use reqwest::Method;
8
9use super::SureClient;
10
11#[bon]
12impl SureClient {
13    /// Sign up a new user
14    ///
15    /// Creates a new user account with the provided credentials.
16    ///
17    /// # Arguments
18    /// * `user` - User data (email, password, first_name, last_name)
19    /// * `device` - Device information
20    /// * `invite_code` - Invite code (required if invite codes are enabled)
21    ///
22    /// # Returns
23    /// Authentication response with access token and user information.
24    ///
25    /// # Errors
26    /// Returns `ApiError::Forbidden` if invite code is required or invalid.
27    /// Returns `ApiError::ValidationError` if validation fails.
28    /// Returns `ApiError::Network` if the request fails due to network issues.
29    ///
30    /// # Example
31    /// ```no_run
32    /// use sure_client_rs::{SureClient, BearerToken};
33    /// use sure_client_rs::models::auth::{SignupUserData, DeviceInfo};
34    ///
35    /// # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
36    /// let response = client.signup()
37    ///     .user(SignupUserData {
38    ///         email: "user@example.com".to_string(),
39    ///         password: "SecureP@ssw0rd".to_string(),
40    ///         first_name: "John".to_string(),
41    ///         last_name: "Doe".to_string(),
42    ///     })
43    ///     .device(DeviceInfo {
44    ///         device_id: "device123".to_string(),
45    ///         device_name: "My Device".to_string(),
46    ///         device_type: "web".to_string(),
47    ///         os_version: "macOS 12.0".to_string(),
48    ///         app_version: "1.0.0".to_string(),
49    ///     })
50    ///     .call()
51    ///     .await?;
52    ///
53    /// println!("User created: {}", response.user.email);
54    /// # Ok(())
55    /// # }
56    /// ```
57    #[builder]
58    pub async fn signup(
59        &self,
60        user: SignupUserData,
61        device: DeviceInfo,
62        invite_code: Option<String>,
63    ) -> ApiResult<AuthSignupResponse> {
64        let request = SignupRequest {
65            user,
66            invite_code,
67            device,
68        };
69
70        self.execute_request(
71            Method::POST,
72            "/api/v1/auth/signup",
73            None,
74            Some(serde_json::to_string(&request)?),
75        )
76        .await
77    }
78
79    /// Log in a user
80    ///
81    /// Authenticates a user with email and password.
82    ///
83    /// # Arguments
84    /// * `email` - Email address
85    /// * `password` - Password
86    /// * `device` - Device information
87    /// * `otp_code` - OTP code (required if user has MFA enabled)
88    ///
89    /// # Returns
90    /// Authentication response with access token and user information.
91    ///
92    /// # Errors
93    /// Returns `ApiError::Unauthorized` if credentials are invalid or MFA is required.
94    /// Returns `ApiError::Network` if the request fails due to network issues.
95    ///
96    /// # Example
97    /// ```no_run
98    /// use sure_client_rs::{SureClient, BearerToken};
99    /// use sure_client_rs::models::auth::DeviceInfo;
100    ///
101    /// # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
102    /// let response = client.login()
103    ///     .email("user@example.com".to_string())
104    ///     .password("SecureP@ssw0rd".to_string())
105    ///     .device(DeviceInfo {
106    ///         device_id: "device123".to_string(),
107    ///         device_name: "My Device".to_string(),
108    ///         device_type: "web".to_string(),
109    ///         os_version: "macOS 12.0".to_string(),
110    ///         app_version: "1.0.0".to_string(),
111    ///     })
112    ///     .call()
113    ///     .await?;
114    ///
115    /// println!("Logged in as: {}", response.user.email);
116    /// # Ok(())
117    /// # }
118    /// ```
119    #[builder]
120    pub async fn login(
121        &self,
122        email: String,
123        password: String,
124        device: DeviceInfo,
125        otp_code: Option<String>,
126    ) -> ApiResult<AuthLoginResponse> {
127        let request = LoginRequest {
128            email,
129            password,
130            otp_code,
131            device,
132        };
133
134        self.execute_request(
135            Method::POST,
136            "/api/v1/auth/login",
137            None,
138            Some(serde_json::to_string(&request)?),
139        )
140        .await
141    }
142
143    /// Refresh an access token
144    ///
145    /// Refreshes an expired access token using a refresh token.
146    ///
147    /// # Arguments
148    /// * `refresh_token` - Refresh token
149    /// * `device` - Device information
150    ///
151    /// # Returns
152    /// New authentication tokens.
153    ///
154    /// # Errors
155    /// Returns `ApiError::BadRequest` if refresh token is missing.
156    /// Returns `ApiError::Unauthorized` if refresh token is invalid.
157    /// Returns `ApiError::Network` if the request fails due to network issues.
158    ///
159    /// # Example
160    /// ```no_run
161    /// use sure_client_rs::{SureClient, BearerToken};
162    /// use sure_client_rs::models::auth::RefreshDeviceInfo;
163    ///
164    /// # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
165    /// let response = client.refresh_token()
166    ///     .refresh_token("refresh_token_here".to_string())
167    ///     .device(RefreshDeviceInfo {
168    ///         device_id: "device123".to_string(),
169    ///     })
170    ///     .call()
171    ///     .await?;
172    ///
173    /// println!("Token refreshed, expires in: {}s", response.expires_in.as_secs());
174    /// # Ok(())
175    /// # }
176    /// ```
177    #[builder]
178    pub async fn refresh_token(
179        &self,
180        refresh_token: String,
181        device: RefreshDeviceInfo,
182    ) -> ApiResult<AuthTokenResponse> {
183        let request = RefreshTokenRequest {
184            refresh_token,
185            device,
186        };
187
188        self.execute_request(
189            Method::POST,
190            "/api/v1/auth/refresh",
191            None,
192            Some(serde_json::to_string(&request)?),
193        )
194        .await
195    }
196}