actix_security_core/http/security/
user.rs1use std::fmt;
7
8#[derive(Clone, Debug)]
25pub struct User {
26 username: String,
27 password: String,
28 roles: Vec<String>,
29 authorities: Vec<String>,
30}
31
32impl User {
33 pub fn new(username: String, password: String) -> Self {
39 User {
40 username,
41 password,
42 roles: Vec::new(),
43 authorities: Vec::new(),
44 }
45 }
46
47 pub fn with_encoded_password(username: &str, encoded_password: String) -> Self {
63 User {
64 username: username.to_string(),
65 password: encoded_password,
66 roles: Vec::new(),
67 authorities: Vec::new(),
68 }
69 }
70
71 pub fn get_username(&self) -> &str {
73 &self.username
74 }
75
76 pub fn get_password(&self) -> &str {
78 &self.password
79 }
80
81 pub fn get_roles(&self) -> &[String] {
83 &self.roles
84 }
85
86 pub fn get_authorities(&self) -> &[String] {
88 &self.authorities
89 }
90
91 pub fn roles(mut self, roles: &[String]) -> Self {
93 for role in roles {
94 if !self.roles.contains(role) {
95 self.roles.push(role.clone());
96 }
97 }
98 self
99 }
100
101 pub fn authorities(mut self, authorities: &[String]) -> Self {
103 for authority in authorities {
104 if !self.authorities.contains(authority) {
105 self.authorities.push(authority.clone());
106 }
107 }
108 self
109 }
110
111 pub fn has_role(&self, role: &str) -> bool {
113 self.roles.iter().any(|r| r == role)
114 }
115
116 pub fn has_any_role(&self, roles: &[&str]) -> bool {
118 roles.iter().any(|role| self.has_role(role))
119 }
120
121 pub fn has_all_roles(&self, roles: &[&str]) -> bool {
123 roles.iter().all(|role| self.has_role(role))
124 }
125
126 pub fn has_authority(&self, authority: &str) -> bool {
128 self.authorities.iter().any(|a| a == authority)
129 }
130
131 pub fn has_any_authority(&self, authorities: &[&str]) -> bool {
133 authorities.iter().any(|auth| self.has_authority(auth))
134 }
135
136 pub fn has_all_authorities(&self, authorities: &[&str]) -> bool {
138 authorities.iter().all(|auth| self.has_authority(auth))
139 }
140
141 pub fn has_roles(&self, roles: &[String]) -> bool {
145 roles.iter().any(|role| self.roles.contains(role))
146 }
147
148 #[doc(hidden)]
150 pub fn has_authorities(&self, authorities: &[String]) -> bool {
151 authorities
152 .iter()
153 .any(|auth| self.authorities.contains(auth))
154 }
155}
156
157impl fmt::Display for User {
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 write!(
160 f,
161 "User {{ username: {}, roles: {:?}, authorities: {:?} }}",
162 self.username, self.roles, self.authorities
163 )
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
176 fn test_user_new() {
177 let user = User::new("alice".to_string(), "secret".to_string());
178 assert_eq!(user.get_username(), "alice");
179 assert_eq!(user.get_password(), "secret");
180 assert!(user.get_roles().is_empty());
181 assert!(user.get_authorities().is_empty());
182 }
183
184 #[test]
185 fn test_user_with_encoded_password() {
186 let user = User::with_encoded_password("bob", "encoded_hash".to_string());
187 assert_eq!(user.get_username(), "bob");
188 assert_eq!(user.get_password(), "encoded_hash");
189 }
190
191 #[test]
196 fn test_user_roles_builder() {
197 let user = User::new("admin".to_string(), "pass".to_string())
198 .roles(&["ADMIN".into(), "USER".into()]);
199
200 assert_eq!(user.get_roles().len(), 2);
201 assert!(user.get_roles().contains(&"ADMIN".to_string()));
202 assert!(user.get_roles().contains(&"USER".to_string()));
203 }
204
205 #[test]
206 fn test_user_authorities_builder() {
207 let user = User::new("admin".to_string(), "pass".to_string())
208 .authorities(&["users:read".into(), "users:write".into()]);
209
210 assert_eq!(user.get_authorities().len(), 2);
211 assert!(user.get_authorities().contains(&"users:read".to_string()));
212 assert!(user.get_authorities().contains(&"users:write".to_string()));
213 }
214
215 #[test]
216 fn test_user_chained_builder() {
217 let user = User::new("admin".to_string(), "pass".to_string())
218 .roles(&["ADMIN".into()])
219 .authorities(&["api:read".into()]);
220
221 assert_eq!(user.get_roles().len(), 1);
222 assert_eq!(user.get_authorities().len(), 1);
223 }
224
225 #[test]
226 fn test_user_roles_no_duplicates() {
227 let user = User::new("admin".to_string(), "pass".to_string())
228 .roles(&["ADMIN".into(), "USER".into()])
229 .roles(&["ADMIN".into(), "MANAGER".into()]);
230
231 assert_eq!(user.get_roles().len(), 3);
233 }
234
235 #[test]
236 fn test_user_authorities_no_duplicates() {
237 let user = User::new("admin".to_string(), "pass".to_string())
238 .authorities(&["read".into(), "write".into()])
239 .authorities(&["read".into(), "delete".into()]);
240
241 assert_eq!(user.get_authorities().len(), 3);
243 }
244
245 #[test]
250 fn test_has_role() {
251 let user = User::new("admin".to_string(), "pass".to_string())
252 .roles(&["ADMIN".into(), "USER".into()]);
253
254 assert!(user.has_role("ADMIN"));
255 assert!(user.has_role("USER"));
256 assert!(!user.has_role("MANAGER"));
257 }
258
259 #[test]
260 fn test_has_any_role() {
261 let user = User::new("user".to_string(), "pass".to_string()).roles(&["USER".into()]);
262
263 assert!(user.has_any_role(&["ADMIN", "USER"]));
264 assert!(user.has_any_role(&["USER", "GUEST"]));
265 assert!(!user.has_any_role(&["ADMIN", "MANAGER"]));
266 }
267
268 #[test]
269 fn test_has_all_roles() {
270 let user = User::new("admin".to_string(), "pass".to_string()).roles(&[
271 "ADMIN".into(),
272 "USER".into(),
273 "MANAGER".into(),
274 ]);
275
276 assert!(user.has_all_roles(&["ADMIN", "USER"]));
277 assert!(user.has_all_roles(&["ADMIN", "USER", "MANAGER"]));
278 assert!(!user.has_all_roles(&["ADMIN", "SUPERADMIN"]));
279 }
280
281 #[test]
282 fn test_has_any_role_empty() {
283 let user = User::new("guest".to_string(), "pass".to_string());
284
285 assert!(!user.has_any_role(&["ADMIN", "USER"]));
286 }
287
288 #[test]
289 fn test_has_all_roles_empty_requirement() {
290 let user = User::new("user".to_string(), "pass".to_string()).roles(&["USER".into()]);
291
292 assert!(user.has_all_roles(&[]));
294 }
295
296 #[test]
301 fn test_has_authority() {
302 let user = User::new("admin".to_string(), "pass".to_string())
303 .authorities(&["users:read".into(), "users:write".into()]);
304
305 assert!(user.has_authority("users:read"));
306 assert!(user.has_authority("users:write"));
307 assert!(!user.has_authority("users:delete"));
308 }
309
310 #[test]
311 fn test_has_any_authority() {
312 let user =
313 User::new("reader".to_string(), "pass".to_string()).authorities(&["read".into()]);
314
315 assert!(user.has_any_authority(&["read", "write"]));
316 assert!(!user.has_any_authority(&["write", "delete"]));
317 }
318
319 #[test]
320 fn test_has_all_authorities() {
321 let user = User::new("admin".to_string(), "pass".to_string()).authorities(&[
322 "read".into(),
323 "write".into(),
324 "delete".into(),
325 ]);
326
327 assert!(user.has_all_authorities(&["read", "write"]));
328 assert!(user.has_all_authorities(&["read", "write", "delete"]));
329 assert!(!user.has_all_authorities(&["read", "admin"]));
330 }
331
332 #[test]
337 fn test_has_roles_legacy() {
338 let user = User::new("user".to_string(), "pass".to_string())
339 .roles(&["USER".into(), "READER".into()]);
340
341 assert!(user.has_roles(&["USER".to_string()]));
342 assert!(user.has_roles(&["ADMIN".to_string(), "USER".to_string()]));
343 assert!(!user.has_roles(&["ADMIN".to_string()]));
344 }
345
346 #[test]
347 fn test_has_authorities_legacy() {
348 let user =
349 User::new("user".to_string(), "pass".to_string()).authorities(&["api:read".into()]);
350
351 assert!(user.has_authorities(&["api:read".to_string()]));
352 assert!(user.has_authorities(&["api:write".to_string(), "api:read".to_string()]));
353 assert!(!user.has_authorities(&["api:write".to_string()]));
354 }
355
356 #[test]
361 fn test_display() {
362 let user = User::new("admin".to_string(), "secret".to_string())
363 .roles(&["ADMIN".into()])
364 .authorities(&["read".into()]);
365
366 let display = format!("{}", user);
367 assert!(display.contains("admin"));
368 assert!(display.contains("ADMIN"));
369 assert!(display.contains("read"));
370 assert!(!display.contains("secret"));
372 }
373
374 #[test]
379 fn test_user_clone() {
380 let original = User::new("admin".to_string(), "pass".to_string())
381 .roles(&["ADMIN".into()])
382 .authorities(&["read".into()]);
383
384 let cloned = original.clone();
385
386 assert_eq!(cloned.get_username(), original.get_username());
387 assert_eq!(cloned.get_password(), original.get_password());
388 assert_eq!(cloned.get_roles(), original.get_roles());
389 assert_eq!(cloned.get_authorities(), original.get_authorities());
390 }
391
392 #[test]
397 fn test_empty_username() {
398 let user = User::new("".to_string(), "pass".to_string());
399 assert_eq!(user.get_username(), "");
400 }
401
402 #[test]
403 fn test_special_characters_in_role() {
404 let user = User::new("user".to_string(), "pass".to_string())
405 .roles(&["ROLE:ADMIN".into(), "users:write".into()]);
406
407 assert!(user.has_role("ROLE:ADMIN"));
408 assert!(user.has_role("users:write"));
409 }
410
411 #[test]
412 fn test_case_sensitive_roles() {
413 let user = User::new("user".to_string(), "pass".to_string()).roles(&["ADMIN".into()]);
414
415 assert!(user.has_role("ADMIN"));
416 assert!(!user.has_role("admin")); assert!(!user.has_role("Admin")); }
419
420 #[test]
421 fn test_case_sensitive_authorities() {
422 let user =
423 User::new("user".to_string(), "pass".to_string()).authorities(&["users:read".into()]);
424
425 assert!(user.has_authority("users:read"));
426 assert!(!user.has_authority("USERS:READ")); }
428}