rocketmq_client_rust/common/
session_credentials.rs1use std::collections::HashMap;
16use std::fmt;
17use std::fs;
18use std::path::PathBuf;
19
20use cheetah_string::CheetahString;
21
22pub const ACCESS_KEY: &str = "AccessKey";
23pub const SECRET_KEY: &str = "SecretKey";
24pub const SIGNATURE: &str = "Signature";
25pub const SECURITY_TOKEN: &str = "SecurityToken";
26
27fn get_key_file_path() -> PathBuf {
28 if let Ok(key_file) = std::env::var("rocketmq.client.keyFile") {
29 PathBuf::from(key_file)
30 } else if let Ok(home) = std::env::var("HOME").or_else(|_| std::env::var("USERPROFILE")) {
31 PathBuf::from(home).join("key")
32 } else {
33 PathBuf::from("key")
34 }
35}
36
37#[derive(Debug, Clone, Default)]
38pub struct SessionCredentials {
39 access_key: Option<CheetahString>,
40 secret_key: Option<CheetahString>,
41 security_token: Option<CheetahString>,
42 signature: Option<CheetahString>,
43}
44
45impl SessionCredentials {
46 pub fn new() -> Self {
47 let mut credentials = Self::default();
48 credentials.load_from_file();
49 credentials
50 }
51
52 pub fn with_keys(access_key: impl Into<CheetahString>, secret_key: impl Into<CheetahString>) -> Self {
53 Self {
54 access_key: Some(access_key.into()),
55 secret_key: Some(secret_key.into()),
56 security_token: None,
57 signature: None,
58 }
59 }
60
61 pub fn with_token(
62 access_key: impl Into<CheetahString>,
63 secret_key: impl Into<CheetahString>,
64 security_token: impl Into<CheetahString>,
65 ) -> Self {
66 Self {
67 access_key: Some(access_key.into()),
68 secret_key: Some(secret_key.into()),
69 security_token: Some(security_token.into()),
70 signature: None,
71 }
72 }
73
74 fn load_from_file(&mut self) {
75 let key_file = get_key_file_path();
76 if let Ok(content) = fs::read_to_string(key_file) {
77 if let Ok(properties) = self.parse_properties(&content) {
78 self.update_content(&properties);
79 }
80 }
81 }
82
83 fn parse_properties(&self, content: &str) -> Result<HashMap<String, String>, ()> {
84 let mut properties = HashMap::new();
85 for line in content.lines() {
86 let line = line.trim();
87 if line.is_empty() || line.starts_with('#') {
88 continue;
89 }
90 if let Some(pos) = line.find('=') {
91 let key = line[..pos].trim().to_string();
92 let value = line[pos + 1..].trim().to_string();
93 properties.insert(key, value);
94 }
95 }
96 Ok(properties)
97 }
98
99 pub fn update_content(&mut self, properties: &HashMap<String, String>) {
100 if let Some(value) = properties.get(ACCESS_KEY) {
101 self.access_key = Some(CheetahString::from_string(value.trim().to_string()));
102 }
103 if let Some(value) = properties.get(SECRET_KEY) {
104 self.secret_key = Some(CheetahString::from_string(value.trim().to_string()));
105 }
106 if let Some(value) = properties.get(SECURITY_TOKEN) {
107 self.security_token = Some(CheetahString::from_string(value.trim().to_string()));
108 }
109 }
110
111 pub fn access_key(&self) -> Option<&CheetahString> {
112 self.access_key.as_ref()
113 }
114
115 pub fn set_access_key(&mut self, access_key: impl Into<CheetahString>) {
116 self.access_key = Some(access_key.into());
117 }
118
119 pub fn secret_key(&self) -> Option<&CheetahString> {
120 self.secret_key.as_ref()
121 }
122
123 pub fn set_secret_key(&mut self, secret_key: impl Into<CheetahString>) {
124 self.secret_key = Some(secret_key.into());
125 }
126
127 pub fn signature(&self) -> Option<&CheetahString> {
128 self.signature.as_ref()
129 }
130
131 pub fn set_signature(&mut self, signature: impl Into<CheetahString>) {
132 self.signature = Some(signature.into());
133 }
134
135 pub fn security_token(&self) -> Option<&CheetahString> {
136 self.security_token.as_ref()
137 }
138
139 pub fn set_security_token(&mut self, security_token: impl Into<CheetahString>) {
140 self.security_token = Some(security_token.into());
141 }
142}
143
144impl PartialEq for SessionCredentials {
145 fn eq(&self, other: &Self) -> bool {
146 self.access_key == other.access_key && self.secret_key == other.secret_key && self.signature == other.signature
147 }
148}
149
150impl Eq for SessionCredentials {}
151
152impl std::hash::Hash for SessionCredentials {
153 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
154 self.access_key.hash(state);
155 self.secret_key.hash(state);
156 self.signature.hash(state);
157 }
158}
159
160impl fmt::Display for SessionCredentials {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 write!(
163 f,
164 "SessionCredentials [accessKey={:?}, secretKey={:?}, signature={:?}, SecurityToken={:?}]",
165 self.access_key, self.secret_key, self.signature, self.security_token
166 )
167 }
168}
169
170#[cfg(test)]
171mod tests {
172 use super::*;
173
174 #[test]
175 fn session_credentials_new_and_default() {
176 let credentials = SessionCredentials::new();
177 assert!(credentials.access_key().is_none());
178 let credentials = SessionCredentials::default();
179 assert!(credentials.secret_key().is_none());
180 }
181
182 #[test]
183 fn session_credentials_with_keys() {
184 let access_key = "ak";
185 let secret_key = "sk";
186 let credentials = SessionCredentials::with_keys(access_key, secret_key);
187 assert_eq!(credentials.access_key().unwrap(), access_key);
188 assert_eq!(credentials.secret_key().unwrap(), secret_key);
189 assert!(credentials.security_token().is_none());
190 assert!(credentials.signature().is_none());
191 }
192
193 #[test]
194 fn session_credentials_with_token() {
195 let access_key = "ak";
196 let secret_key = "sk";
197 let token = "token";
198 let credentials = SessionCredentials::with_token(access_key, secret_key, token);
199 assert_eq!(credentials.access_key().unwrap(), access_key);
200 assert_eq!(credentials.secret_key().unwrap(), secret_key);
201 assert_eq!(credentials.security_token().unwrap(), token);
202 assert!(credentials.signature().is_none());
203 }
204
205 #[test]
206 fn session_credentials_parse_properties() {
207 let content = "AccessKey=ak123\nSecretKey=sk456\n#comment\n \nSecurityToken=tk789\nSignature=sig123";
208 let credentials = SessionCredentials::default();
209 let properties = credentials.parse_properties(content).unwrap();
210 assert_eq!(properties.get("AccessKey").unwrap(), "ak123");
211 assert_eq!(properties.get("SecretKey").unwrap(), "sk456");
212 assert_eq!(properties.get("SecurityToken").unwrap(), "tk789");
213 assert_eq!(properties.get("Signature").unwrap(), "sig123");
214 }
215
216 #[test]
217 fn session_credentials_update_content() {
218 let mut properties = HashMap::new();
219 properties.insert(ACCESS_KEY.to_string(), "ak".to_string());
220 properties.insert(SECRET_KEY.to_string(), "sk".to_string());
221 properties.insert(SECURITY_TOKEN.to_string(), "token".to_string());
222
223 let mut credentials = SessionCredentials::default();
224 credentials.update_content(&properties);
225
226 assert_eq!(credentials.access_key().unwrap(), "ak");
227 assert_eq!(credentials.secret_key().unwrap(), "sk");
228 assert_eq!(credentials.security_token().unwrap(), "token");
229 }
230
231 #[test]
232 fn session_credentials_getters_and_setters() {
233 let mut credentials = SessionCredentials::default();
234 credentials.set_access_key("ak");
235 credentials.set_secret_key("sk");
236 credentials.set_security_token("token");
237 credentials.set_signature("sig");
238
239 assert_eq!(credentials.access_key().unwrap(), "ak");
240 assert_eq!(credentials.secret_key().unwrap(), "sk");
241 assert_eq!(credentials.security_token().unwrap(), "token");
242 assert_eq!(credentials.signature().unwrap(), "sig");
243 }
244
245 #[test]
246 fn session_credentials_eq_and_hash() {
247 let c1 = SessionCredentials::with_keys("ak", "sk");
248 let c2 = SessionCredentials::with_keys("ak", "sk");
249 let c3 = SessionCredentials::with_keys("ak2", "sk");
250
251 assert_eq!(c1, c2);
252 assert_ne!(c1, c3);
253
254 use std::collections::hash_map::DefaultHasher;
255 use std::hash::Hash;
256 use std::hash::Hasher;
257 let mut h1 = DefaultHasher::new();
258 c1.hash(&mut h1);
259 let mut h2 = DefaultHasher::new();
260 c2.hash(&mut h2);
261 assert_eq!(h1.finish(), h2.finish());
262 }
263
264 #[test]
265 fn session_credentials_display() {
266 let credentials = SessionCredentials::with_token("ak", "sk", "tk");
267 let display = format!("{}", credentials);
268 let expected = "SessionCredentials [accessKey=Some(\"ak\"), secretKey=Some(\"sk\"), signature=None, \
269 SecurityToken=Some(\"tk\")]";
270 assert_eq!(display, expected);
271 }
272}