busbar_sf_rest/client/
user_password.rs1use tracing::instrument;
2
3use busbar_sf_client::security::url as url_security;
4
5use crate::error::{Error, ErrorKind, Result};
6use crate::user_password::{SetPasswordRequest, SetPasswordResponse, UserPasswordStatus};
7
8impl super::SalesforceRestClient {
9 #[instrument(skip(self))]
11 pub async fn get_user_password_status(&self, user_id: &str) -> Result<UserPasswordStatus> {
12 if !url_security::is_valid_salesforce_id(user_id) {
13 return Err(Error::new(ErrorKind::Salesforce {
14 error_code: "INVALID_ID".to_string(),
15 message: "Invalid Salesforce ID format".to_string(),
16 }));
17 }
18 let path = format!("sobjects/User/{}/password", user_id);
19 self.client.rest_get(&path).await.map_err(Into::into)
20 }
21
22 #[instrument(skip(self, request))]
24 pub async fn set_user_password(
25 &self,
26 user_id: &str,
27 request: &SetPasswordRequest,
28 ) -> Result<()> {
29 if !url_security::is_valid_salesforce_id(user_id) {
30 return Err(Error::new(ErrorKind::Salesforce {
31 error_code: "INVALID_ID".to_string(),
32 message: "Invalid Salesforce ID format".to_string(),
33 }));
34 }
35 let path = format!("sobjects/User/{}/password", user_id);
36 let _: serde_json::Value = self.client.rest_post(&path, request).await?;
37 Ok(())
38 }
39
40 #[instrument(skip(self))]
45 pub async fn reset_user_password(&self, user_id: &str) -> Result<SetPasswordResponse> {
46 if !url_security::is_valid_salesforce_id(user_id) {
47 return Err(Error::new(ErrorKind::Salesforce {
48 error_code: "INVALID_ID".to_string(),
49 message: "Invalid Salesforce ID format".to_string(),
50 }));
51 }
52 let path = format!("sobjects/User/{}/password", user_id);
53 let url = self.client.rest_url(&path);
54 let request = self.client.delete(&url);
55 let response = self.client.execute(request).await?;
56 response.json().await.map_err(Into::into)
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::super::SalesforceRestClient;
63
64 #[tokio::test]
65 async fn test_get_user_password_status_invalid_id() {
66 let client = SalesforceRestClient::new("https://test.salesforce.com", "token").unwrap();
67 let result = client.get_user_password_status("bad-id").await;
68 assert!(result.is_err());
69 assert!(result.unwrap_err().to_string().contains("INVALID_ID"));
70 }
71
72 #[tokio::test]
73 async fn test_set_user_password_invalid_id() {
74 let client = SalesforceRestClient::new("https://test.salesforce.com", "token").unwrap();
75 let request = crate::user_password::SetPasswordRequest {
76 new_password: "NewPass123!".to_string(),
77 };
78 let result = client.set_user_password("bad-id", &request).await;
79 assert!(result.is_err());
80 assert!(result.unwrap_err().to_string().contains("INVALID_ID"));
81 }
82
83 #[tokio::test]
84 async fn test_reset_user_password_invalid_id() {
85 let client = SalesforceRestClient::new("https://test.salesforce.com", "token").unwrap();
86 let result = client.reset_user_password("bad-id").await;
87 assert!(result.is_err());
88 assert!(result.unwrap_err().to_string().contains("INVALID_ID"));
89 }
90
91 #[tokio::test]
92 async fn test_get_user_password_status_wiremock() {
93 use wiremock::matchers::{method, path_regex};
94 use wiremock::{Mock, MockServer, ResponseTemplate};
95
96 let mock_server = MockServer::start().await;
97
98 let body = serde_json::json!({"isExpired": false});
99
100 Mock::given(method("GET"))
101 .and(path_regex(".*/sobjects/User/005xx000001Svf0AAC/password$"))
102 .respond_with(ResponseTemplate::new(200).set_body_json(&body))
103 .mount(&mock_server)
104 .await;
105
106 let client = SalesforceRestClient::new(mock_server.uri(), "test-token").unwrap();
107 let result = client
108 .get_user_password_status("005xx000001Svf0AAC")
109 .await
110 .expect("get_user_password_status should succeed");
111 assert!(!result.is_expired);
112 }
113
114 #[tokio::test]
115 async fn test_reset_user_password_wiremock() {
116 use wiremock::matchers::{method, path_regex};
117 use wiremock::{Mock, MockServer, ResponseTemplate};
118
119 let mock_server = MockServer::start().await;
120
121 let body = serde_json::json!({"NewPassword": "AutoGenerated123!"});
122
123 Mock::given(method("DELETE"))
124 .and(path_regex(".*/sobjects/User/005xx000001Svf0AAC/password$"))
125 .respond_with(ResponseTemplate::new(200).set_body_json(&body))
126 .mount(&mock_server)
127 .await;
128
129 let client = SalesforceRestClient::new(mock_server.uri(), "test-token").unwrap();
130 let result = client
131 .reset_user_password("005xx000001Svf0AAC")
132 .await
133 .expect("reset_user_password should succeed");
134 assert_eq!(result.new_password, "AutoGenerated123!");
135 }
136}