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}