uptrakit_openapi_client/
auth.rs1use crate::Result;
2use crate::UptrakitClient;
3use crate::types_impl::auth::{
4 AuthResponse, LoginRequest, LogoutRequest, RefreshRequest, RefreshResponse, RegisterRequest,
5 UserResponse,
6};
7use crate::types_impl::device_auth::{DeviceAuthApproveRequest, DeviceAuthApproveResponse};
8use crate::types_impl::oauth::{
9 DeviceAuthDenyRequest, DeviceAuthDenyResponse, DeviceAuthLookupQuery, DeviceAuthLookupResponse,
10 DeviceAuthorizationRequest, DeviceAuthorizationResponse, OAuthAuthorizationServerMetadata,
11 OAuthTokenRequest, OAuthTokenResponse,
12};
13use crate::types_impl::oidc_auth::AuthMethodsResponse;
14
15impl UptrakitClient {
16 pub async fn register(&self, req: &RegisterRequest) -> Result<AuthResponse> {
20 self.post_json_unauth(crate::paths::auth::REGISTER, req)
21 .await
22 }
23
24 pub async fn login(&self, req: &LoginRequest) -> Result<AuthResponse> {
28 self.post_json_unauth(crate::paths::auth::LOGIN, req).await
29 }
30
31 pub async fn refresh(&self, req: &RefreshRequest) -> Result<RefreshResponse> {
35 self.post_json_unauth(crate::paths::auth::REFRESH, req)
36 .await
37 }
38
39 pub async fn logout(&self, req: &LogoutRequest) -> Result<()> {
41 self.post_json_no_content(crate::paths::auth::LOGOUT, req)
42 .await
43 }
44
45 pub async fn auth_methods(&self) -> Result<AuthMethodsResponse> {
49 self.get_unauth(crate::paths::auth::METHODS).await
50 }
51
52 pub async fn device_auth_approve(
54 &self,
55 req: &DeviceAuthApproveRequest,
56 ) -> Result<DeviceAuthApproveResponse> {
57 self.post_json(crate::paths::auth::DEVICE_APPROVE, req)
58 .await
59 }
60
61 pub async fn me(&self) -> Result<UserResponse> {
63 self.get(crate::paths::auth::ME).await
64 }
65
66 pub async fn oauth_device_authorization(
72 &self,
73 req: &DeviceAuthorizationRequest,
74 ) -> Result<DeviceAuthorizationResponse> {
75 self.post_form_unauth(crate::paths::oauth::DEVICE_AUTHORIZATION, req)
76 .await
77 }
78
79 pub async fn oauth_token(&self, req: &OAuthTokenRequest) -> Result<OAuthTokenResponse> {
86 self.post_form_unauth(crate::paths::oauth::TOKEN, req).await
87 }
88
89 pub async fn oauth_authorization_server_metadata(
93 &self,
94 ) -> Result<OAuthAuthorizationServerMetadata> {
95 self.get_unauth(crate::paths::oauth::METADATA).await
96 }
97
98 pub async fn device_auth_deny(
100 &self,
101 req: &DeviceAuthDenyRequest,
102 ) -> Result<DeviceAuthDenyResponse> {
103 self.post_json(crate::paths::auth::DEVICE_DENY, req).await
104 }
105
106 pub async fn device_auth_lookup(
112 &self,
113 query: &DeviceAuthLookupQuery,
114 ) -> Result<DeviceAuthLookupResponse> {
115 self.get_with_query(crate::paths::auth::DEVICE_LOOKUP, query)
116 .await
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use crate::types_impl::SecretString;
123 use crate::types_impl::auth::{LoginRequest, LogoutRequest, RefreshRequest, RegisterRequest};
124 use crate::types_impl::device_auth::DeviceAuthApproveRequest;
125 use crate::types_impl::oauth::{
126 DeviceAuthDenyRequest, DeviceAuthorizationRequest, OAuthTokenRequest,
127 };
128
129 #[test]
130 fn register_request_serialization() {
131 let req = RegisterRequest {
132 email: "admin@example.com".to_string(),
133 first_name: "Admin".to_string(),
134 last_name: "User".to_string(),
135 password: SecretString::new("SecurePass123"),
136 registration_token: None,
137 };
138 let json = serde_json::to_value(&req).expect("serialize");
139 assert_eq!(json["email"], "admin@example.com");
140 assert_eq!(json["first_name"], "Admin");
141 assert_eq!(json["last_name"], "User");
142 assert_eq!(json["password"], "SecurePass123");
143 }
144
145 #[test]
146 fn register_request_with_token_serialization() {
147 let req = RegisterRequest {
148 email: "admin@example.com".to_string(),
149 first_name: "Admin".to_string(),
150 last_name: "User".to_string(),
151 password: SecretString::new("SecurePass123"),
152 registration_token: Some(SecretString::new("invite-tok-abc")),
153 };
154 let json = serde_json::to_value(&req).expect("serialize");
155 assert_eq!(json["registration_token"], "invite-tok-abc");
156 }
157
158 #[test]
159 fn login_request_serialization() {
160 let req = LoginRequest {
161 email: "admin@example.com".to_string(),
162 password: SecretString::new("SecurePass123"),
163 };
164 let json = serde_json::to_value(&req).expect("serialize");
165 assert_eq!(json["email"], "admin@example.com");
166 assert_eq!(json["password"], "SecurePass123");
167 }
168
169 #[test]
170 fn logout_request_serialization() {
171 let req = LogoutRequest {
172 refresh_token: Some(SecretString::new("refresh-tok-xyz")),
173 };
174 let json = serde_json::to_value(&req).expect("serialize");
175 assert_eq!(json["refresh_token"], "refresh-tok-xyz");
176 }
177
178 #[test]
179 fn refresh_request_serialization() {
180 let req = RefreshRequest {
181 refresh_token: Some(SecretString::new("refresh-tok-xyz")),
182 };
183 let json = serde_json::to_value(&req).expect("serialize");
184 assert_eq!(json["refresh_token"], "refresh-tok-xyz");
185 }
186
187 #[test]
188 fn device_auth_approve_request_serialization() {
189 let req = DeviceAuthApproveRequest {
190 user_code: "ABCD-1234".to_string(),
191 };
192 let json = serde_json::to_value(&req).expect("serialize");
193 assert_eq!(json["user_code"], "ABCD-1234");
194 }
195
196 #[test]
197 fn device_authorization_request_form_serialization() {
198 use serde_urlencoded;
199 let req = DeviceAuthorizationRequest::new(
200 "uptrakit-cli".into(),
201 None,
202 Some("cli-host-2026-05-12".into()),
203 );
204 let encoded = serde_urlencoded::to_string(&req).expect("encode");
205 assert!(encoded.contains("client_id=uptrakit-cli"));
206 assert!(encoded.contains("client_name=cli-host-2026-05-12"));
207 assert!(!encoded.contains("scope="), "scope omitted when None");
208 }
209
210 #[test]
211 fn oauth_token_request_form_serialization() {
212 use serde_urlencoded;
213 let req = OAuthTokenRequest::new(
214 "urn:ietf:params:oauth:grant-type:device_code".into(),
215 Some("abc-123".into()),
216 Some("uptrakit-cli".into()),
217 );
218 let encoded = serde_urlencoded::to_string(&req).expect("encode");
219 assert!(
220 encoded.contains("grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code")
221 || encoded.contains("grant_type=urn:ietf:params:oauth:grant-type:device_code"),
222 "grant_type URI preserved verbatim"
223 );
224 assert!(encoded.contains("device_code=abc-123"));
225 assert!(encoded.contains("client_id=uptrakit-cli"));
226 }
227
228 #[test]
229 fn device_auth_deny_request_serialization() {
230 let req = DeviceAuthDenyRequest::new("ABCD-EFGH".into());
231 let json = serde_json::to_value(&req).expect("serialize");
232 assert_eq!(json["user_code"], "ABCD-EFGH");
233 }
234}