1use crate::crypto::hashing::Salt;
4use chrono::{DateTime, Utc};
5use serde::{Deserialize, Serialize};
6use std::fmt;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct ApiKey {
11 pub id: String,
13 pub name: String,
15 pub key: String,
17 pub secret_hash: Option<String>,
19 pub salt: Option<Salt>,
21 pub role: Role,
23 pub created_at: DateTime<Utc>,
25 pub expires_at: Option<DateTime<Utc>>,
27 pub last_used: Option<DateTime<Utc>>,
29 #[serde(default)]
31 pub ip_whitelist: Vec<String>,
32 pub active: bool,
34 #[serde(default)]
36 pub usage_count: u64,
37}
38
39impl ApiKey {
40 pub fn new(
42 name: String,
43 role: Role,
44 expires_at: Option<DateTime<Utc>>,
45 ip_whitelist: Vec<String>,
46 ) -> Self {
47 use crate::crypto::hashing::{generate_salt, hash_api_key};
48 use crate::crypto::keys::{generate_key_id, generate_secure_key};
49
50 let role_str = match &role {
51 Role::Admin => "admin",
52 Role::Operator => "op",
53 Role::Monitor => "mon",
54 Role::Device { .. } => "dev",
55 Role::Custom { .. } => "custom",
56 };
57
58 let id = generate_key_id(role_str);
59 let secret = generate_secure_key();
60
61 let salt = generate_salt();
63 let secret_hash = hash_api_key(&secret, &salt);
64
65 Self {
66 id,
67 name,
68 key: secret,
69 secret_hash: Some(secret_hash),
70 salt: Some(salt),
71 role,
72 created_at: Utc::now(),
73 expires_at,
74 last_used: None,
75 ip_whitelist,
76 active: true,
77 usage_count: 0,
78 }
79 }
80
81 pub fn is_expired(&self) -> bool {
83 if let Some(expires_at) = self.expires_at {
84 Utc::now() > expires_at
85 } else {
86 false
87 }
88 }
89
90 pub fn is_valid(&self) -> bool {
92 self.active && !self.is_expired()
93 }
94
95 pub fn mark_used(&mut self) {
97 self.last_used = Some(Utc::now());
98 self.usage_count += 1;
99 }
100
101 pub fn verify_key(
103 &self,
104 provided_key: &str,
105 ) -> Result<bool, crate::crypto::hashing::HashingError> {
106 use crate::crypto::hashing::verify_api_key;
107
108 if let (Some(hash), Some(salt)) = (&self.secret_hash, &self.salt) {
109 verify_api_key(provided_key, hash, salt)
110 } else {
111 Ok(provided_key == self.key)
113 }
114 }
115
116 pub fn to_secure_storage(&self) -> SecureApiKey {
118 SecureApiKey {
119 id: self.id.clone(),
120 name: self.name.clone(),
121 secret_hash: self.secret_hash.clone(),
122 salt: self.salt.clone(),
123 role: self.role.clone(),
124 created_at: self.created_at,
125 expires_at: self.expires_at,
126 last_used: self.last_used,
127 ip_whitelist: self.ip_whitelist.clone(),
128 active: self.active,
129 usage_count: self.usage_count,
130 }
131 }
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct SecureApiKey {
137 pub id: String,
139 pub name: String,
141 pub secret_hash: Option<String>,
143 pub salt: Option<Salt>,
145 pub role: Role,
147 pub created_at: DateTime<Utc>,
149 pub expires_at: Option<DateTime<Utc>>,
151 pub last_used: Option<DateTime<Utc>>,
153 #[serde(default)]
155 pub ip_whitelist: Vec<String>,
156 pub active: bool,
158 #[serde(default)]
160 pub usage_count: u64,
161}
162
163impl SecureApiKey {
164 pub fn to_api_key(&self) -> ApiKey {
166 ApiKey {
167 id: self.id.clone(),
168 name: self.name.clone(),
169 key: "***redacted***".to_string(), secret_hash: self.secret_hash.clone(),
171 salt: self.salt.clone(),
172 role: self.role.clone(),
173 created_at: self.created_at,
174 expires_at: self.expires_at,
175 last_used: self.last_used,
176 ip_whitelist: self.ip_whitelist.clone(),
177 active: self.active,
178 usage_count: self.usage_count,
179 }
180 }
181
182 pub fn is_expired(&self) -> bool {
184 if let Some(expires_at) = self.expires_at {
185 Utc::now() > expires_at
186 } else {
187 false
188 }
189 }
190
191 pub fn is_valid(&self) -> bool {
193 self.active && !self.is_expired()
194 }
195
196 pub fn verify_key(
198 &self,
199 provided_key: &str,
200 ) -> Result<bool, crate::crypto::hashing::HashingError> {
201 use crate::crypto::hashing::verify_api_key;
202
203 if let (Some(hash), Some(salt)) = (&self.secret_hash, &self.salt) {
204 verify_api_key(provided_key, hash, salt)
205 } else {
206 Ok(false)
208 }
209 }
210}
211
212#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
214#[serde(rename_all = "lowercase")]
215pub enum Role {
216 Admin,
218 Operator,
220 Monitor,
222 Device {
224 allowed_devices: Vec<String>,
226 },
227 Custom {
229 permissions: Vec<String>,
231 },
232}
233
234impl Role {
235 pub fn has_permission(&self, permission: &str) -> bool {
237 match self {
238 Role::Admin => true, Role::Operator => !permission.starts_with("admin."), Role::Monitor => permission.starts_with("read.") || permission == "health.check",
241 Role::Device { allowed_devices } => {
242 if let Some(device_uuid) = permission.strip_prefix("device.") {
244 allowed_devices.contains(&device_uuid.to_string())
245 } else {
246 false
247 }
248 }
249 Role::Custom { permissions } => permissions.contains(&permission.to_string()),
250 }
251 }
252
253 pub fn description(&self) -> String {
255 match self {
256 Role::Admin => "Full administrative access".to_string(),
257 Role::Operator => "Device control and monitoring".to_string(),
258 Role::Monitor => "Read-only system monitoring".to_string(),
259 Role::Device { allowed_devices } => {
260 format!("Device control for {} devices", allowed_devices.len())
261 }
262 Role::Custom { permissions } => {
263 format!("Custom role with {} permissions", permissions.len())
264 }
265 }
266 }
267}
268
269impl fmt::Display for Role {
270 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271 match self {
272 Role::Admin => write!(f, "admin"),
273 Role::Operator => write!(f, "operator"),
274 Role::Monitor => write!(f, "monitor"),
275 Role::Device { .. } => write!(f, "device"),
276 Role::Custom { .. } => write!(f, "custom"),
277 }
278 }
279}
280
281#[derive(Debug)]
283pub struct AuthResult {
284 pub success: bool,
285 pub user_id: Option<String>,
286 pub roles: Vec<Role>,
287 pub message: Option<String>,
288 pub rate_limited: bool,
290 pub client_ip: Option<String>,
292}
293
294impl AuthResult {
295 pub fn success(user_id: String, roles: Vec<Role>) -> Self {
297 Self {
298 success: true,
299 user_id: Some(user_id),
300 roles,
301 message: None,
302 rate_limited: false,
303 client_ip: None,
304 }
305 }
306
307 pub fn failure(message: String) -> Self {
309 Self {
310 success: false,
311 user_id: None,
312 roles: vec![],
313 message: Some(message),
314 rate_limited: false,
315 client_ip: None,
316 }
317 }
318
319 pub fn rate_limited(client_ip: String) -> Self {
321 Self {
322 success: false,
323 user_id: None,
324 roles: vec![],
325 message: Some("Too many failed attempts".to_string()),
326 rate_limited: true,
327 client_ip: Some(client_ip),
328 }
329 }
330}
331
332#[derive(Debug, Clone, Serialize, Deserialize)]
334pub struct AuthContext {
335 pub user_id: Option<String>,
336 pub roles: Vec<Role>,
337 pub api_key_id: Option<String>,
338 pub permissions: Vec<String>,
340}
341
342impl AuthContext {
343 pub fn has_permission(&self, permission: &str) -> bool {
345 self.roles
346 .iter()
347 .any(|role| role.has_permission(permission))
348 }
349
350 pub fn get_all_permissions(&self) -> Vec<String> {
352 self.permissions.clone()
353 }
354}
355
356#[derive(Debug, Clone, Serialize, Deserialize)]
358pub struct KeyCreationRequest {
359 pub name: String,
361 pub role: Role,
363 pub expires_at: Option<DateTime<Utc>>,
365 pub ip_whitelist: Option<Vec<String>>,
367}
368
369#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
371pub struct KeyUsageStats {
372 pub total_keys: u32,
374 pub active_keys: u32,
376 pub disabled_keys: u32,
378 pub expired_keys: u32,
380 pub total_usage_count: u64,
382 pub admin_keys: u32,
384 pub operator_keys: u32,
386 pub monitor_keys: u32,
388 pub device_keys: u32,
390 pub custom_keys: u32,
392}
393
394#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
396pub struct ApiCompletenessCheck {
397 pub has_create_key: bool,
399 pub has_validate_key: bool,
401 pub has_list_keys: bool,
403 pub has_revoke_key: bool,
405 pub has_update_key: bool,
407 pub has_bulk_operations: bool,
409 pub has_role_based_access: bool,
411 pub has_rate_limiting: bool,
413 pub has_ip_whitelisting: bool,
415 pub has_expiration_support: bool,
417 pub has_usage_tracking: bool,
419 pub framework_version: String,
421 pub production_ready: bool,
423}
424
425#[cfg(test)]
426mod tests {
427 use super::*;
428 use chrono::{Duration, Utc};
429
430 #[test]
431 fn test_api_key_creation() {
432 let key = ApiKey::new(
433 "test-key".to_string(),
434 Role::Operator,
435 Some(Utc::now() + Duration::days(30)),
436 vec!["192.168.1.1".to_string()],
437 );
438
439 assert!(!key.id.is_empty());
440 assert_eq!(key.name, "test-key");
441 assert!(!key.key.is_empty());
442 assert!(key.secret_hash.is_some());
443 assert!(key.salt.is_some());
444 assert_eq!(key.role, Role::Operator);
445 assert!(key.expires_at.is_some());
446 assert!(key.last_used.is_none());
447 assert_eq!(key.ip_whitelist, vec!["192.168.1.1"]);
448 assert!(key.active);
449 assert_eq!(key.usage_count, 0);
450 }
451
452 #[test]
453 fn test_api_key_creation_different_roles() {
454 let admin_key = ApiKey::new("admin".to_string(), Role::Admin, None, vec![]);
455 let monitor_key = ApiKey::new("monitor".to_string(), Role::Monitor, None, vec![]);
456 let device_key = ApiKey::new(
457 "device".to_string(),
458 Role::Device {
459 allowed_devices: vec!["device1".to_string()],
460 },
461 None,
462 vec![],
463 );
464
465 assert_eq!(admin_key.role, Role::Admin);
466 assert_eq!(monitor_key.role, Role::Monitor);
467 assert!(matches!(device_key.role, Role::Device { .. }));
468 }
469
470 #[test]
471 fn test_api_key_id_format() {
472 let admin_key = ApiKey::new("admin".to_string(), Role::Admin, None, vec![]);
473 let operator_key = ApiKey::new("operator".to_string(), Role::Operator, None, vec![]);
474 let monitor_key = ApiKey::new("monitor".to_string(), Role::Monitor, None, vec![]);
475 let device_key = ApiKey::new(
476 "device".to_string(),
477 Role::Device {
478 allowed_devices: vec![],
479 },
480 None,
481 vec![],
482 );
483 let custom_key = ApiKey::new(
484 "custom".to_string(),
485 Role::Custom {
486 permissions: vec!["test:read".to_string()],
487 },
488 None,
489 vec![],
490 );
491
492 assert!(admin_key.id.contains("admin"));
493 assert!(operator_key.id.contains("op"));
494 assert!(monitor_key.id.contains("mon"));
495 assert!(device_key.id.contains("dev"));
496 assert!(custom_key.id.contains("custom"));
497 }
498
499 #[test]
500 fn test_api_key_expiration() {
501 let expired_key = ApiKey::new(
502 "expired".to_string(),
503 Role::Monitor,
504 Some(Utc::now() - Duration::days(1)),
505 vec![],
506 );
507 let valid_key = ApiKey::new(
508 "valid".to_string(),
509 Role::Monitor,
510 Some(Utc::now() + Duration::days(1)),
511 vec![],
512 );
513 let no_expiry_key = ApiKey::new("no-expiry".to_string(), Role::Monitor, None, vec![]);
514
515 assert!(expired_key.is_expired());
516 assert!(!valid_key.is_expired());
517 assert!(!no_expiry_key.is_expired());
518 }
519
520 #[test]
521 fn test_api_key_validity() {
522 let valid_key = ApiKey::new(
523 "valid".to_string(),
524 Role::Monitor,
525 Some(Utc::now() + Duration::days(1)),
526 vec![],
527 );
528 let expired_key = ApiKey::new(
529 "expired".to_string(),
530 Role::Monitor,
531 Some(Utc::now() - Duration::days(1)),
532 vec![],
533 );
534 let mut inactive_key = ApiKey::new("inactive".to_string(), Role::Monitor, None, vec![]);
535 inactive_key.active = false;
536
537 assert!(valid_key.is_valid());
538 assert!(!expired_key.is_valid());
539 assert!(!inactive_key.is_valid());
540 }
541
542 #[test]
543 fn test_api_key_mark_used() {
544 let mut key = ApiKey::new("test".to_string(), Role::Monitor, None, vec![]);
545 assert!(key.last_used.is_none());
546 assert_eq!(key.usage_count, 0);
547
548 key.mark_used();
549 assert!(key.last_used.is_some());
550 assert_eq!(key.usage_count, 1);
551
552 key.mark_used();
553 assert_eq!(key.usage_count, 2);
554 }
555
556 #[test]
557 fn test_api_key_verification() {
558 let key = ApiKey::new("test".to_string(), Role::Monitor, None, vec![]);
559 let correct_secret = key.key.clone();
560 let wrong_secret = "wrong-secret";
561
562 let result_correct = key.verify_key(&correct_secret);
563 let result_wrong = key.verify_key(wrong_secret);
564
565 assert!(result_correct.is_ok());
566 assert!(result_correct.unwrap());
567 assert!(result_wrong.is_ok());
568 assert!(!result_wrong.unwrap());
569 }
570
571 #[test]
572 fn test_api_key_to_secure_storage() {
573 let key = ApiKey::new("test".to_string(), Role::Admin, None, vec![]);
574 let secure_key = key.to_secure_storage();
575
576 assert_eq!(secure_key.id, key.id);
577 assert_eq!(secure_key.name, key.name);
578 assert_eq!(secure_key.secret_hash, key.secret_hash);
579 assert_eq!(secure_key.salt, key.salt);
580 assert_eq!(secure_key.role, key.role);
581 assert_eq!(secure_key.created_at, key.created_at);
582 assert_eq!(secure_key.expires_at, key.expires_at);
583 assert_eq!(secure_key.last_used, key.last_used);
584 assert_eq!(secure_key.ip_whitelist, key.ip_whitelist);
585 assert_eq!(secure_key.active, key.active);
586 assert_eq!(secure_key.usage_count, key.usage_count);
587 }
588
589 #[test]
590 fn test_secure_api_key_to_api_key() {
591 let original_key = ApiKey::new("test".to_string(), Role::Admin, None, vec![]);
592 let secure_key = original_key.to_secure_storage();
593 let restored_key = secure_key.to_api_key();
594
595 assert_eq!(restored_key.id, original_key.id);
596 assert_eq!(restored_key.name, original_key.name);
597 assert_eq!(restored_key.key, "***redacted***"); assert_eq!(restored_key.secret_hash, original_key.secret_hash);
599 assert_eq!(restored_key.salt, original_key.salt);
600 assert_eq!(restored_key.role, original_key.role);
601 }
602
603 #[test]
604 fn test_secure_api_key_expiration() {
605 let expired_key = ApiKey::new(
606 "expired".to_string(),
607 Role::Monitor,
608 Some(Utc::now() - Duration::days(1)),
609 vec![],
610 );
611 let secure_expired = expired_key.to_secure_storage();
612
613 assert!(secure_expired.is_expired());
614 assert!(!secure_expired.is_valid());
615 }
616
617 #[test]
618 fn test_secure_api_key_verification() {
619 let key = ApiKey::new("test".to_string(), Role::Monitor, None, vec![]);
620 let secret = key.key.clone();
621 let secure_key = key.to_secure_storage();
622
623 let result = secure_key.verify_key(&secret);
624 assert!(result.is_ok());
625 assert!(result.unwrap());
626
627 let wrong_result = secure_key.verify_key("wrong");
628 assert!(wrong_result.is_ok());
629 assert!(!wrong_result.unwrap());
630 }
631
632 #[test]
633 fn test_role_admin_permissions() {
634 let admin_role = Role::Admin;
635
636 assert!(admin_role.has_permission("admin.create_user"));
637 assert!(admin_role.has_permission("read.status"));
638 assert!(admin_role.has_permission("device.control"));
639 assert!(admin_role.has_permission("anything.really"));
640 }
641
642 #[test]
643 fn test_role_operator_permissions() {
644 let operator_role = Role::Operator;
645
646 assert!(operator_role.has_permission("read.status"));
647 assert!(operator_role.has_permission("device.control"));
648 assert!(!operator_role.has_permission("admin.create_user"));
649 assert!(!operator_role.has_permission("admin.delete_key"));
650 }
651
652 #[test]
653 fn test_role_monitor_permissions() {
654 let monitor_role = Role::Monitor;
655
656 assert!(monitor_role.has_permission("read.status"));
657 assert!(monitor_role.has_permission("read.metrics"));
658 assert!(monitor_role.has_permission("health.check"));
659 assert!(!monitor_role.has_permission("write.config"));
660 assert!(!monitor_role.has_permission("device.control"));
661 assert!(!monitor_role.has_permission("admin.anything"));
662 }
663
664 #[test]
665 fn test_role_device_permissions() {
666 let allowed_devices = vec!["device1".to_string(), "device2".to_string()];
667 let device_role = Role::Device {
668 allowed_devices: allowed_devices.clone(),
669 };
670
671 assert!(device_role.has_permission("device.device1"));
672 assert!(device_role.has_permission("device.device2"));
673 assert!(!device_role.has_permission("device.device3"));
674 assert!(!device_role.has_permission("read.status"));
675 assert!(!device_role.has_permission("admin.anything"));
676 }
677
678 #[test]
679 fn test_role_custom_permissions() {
680 let permissions = vec![
681 "custom.read".to_string(),
682 "custom.write".to_string(),
683 "special.action".to_string(),
684 ];
685 let custom_role = Role::Custom {
686 permissions: permissions.clone(),
687 };
688
689 assert!(custom_role.has_permission("custom.read"));
690 assert!(custom_role.has_permission("custom.write"));
691 assert!(custom_role.has_permission("special.action"));
692 assert!(!custom_role.has_permission("custom.delete"));
693 assert!(!custom_role.has_permission("admin.anything"));
694 }
695
696 #[test]
697 fn test_role_descriptions() {
698 let admin = Role::Admin;
699 let operator = Role::Operator;
700 let monitor = Role::Monitor;
701 let device = Role::Device {
702 allowed_devices: vec!["dev1".to_string(), "dev2".to_string()],
703 };
704 let custom = Role::Custom {
705 permissions: vec![
706 "perm1".to_string(),
707 "perm2".to_string(),
708 "perm3".to_string(),
709 ],
710 };
711
712 assert_eq!(admin.description(), "Full administrative access");
713 assert_eq!(operator.description(), "Device control and monitoring");
714 assert_eq!(monitor.description(), "Read-only system monitoring");
715 assert_eq!(device.description(), "Device control for 2 devices");
716 assert_eq!(custom.description(), "Custom role with 3 permissions");
717 }
718
719 #[test]
720 fn test_role_display() {
721 assert_eq!(Role::Admin.to_string(), "admin");
722 assert_eq!(Role::Operator.to_string(), "operator");
723 assert_eq!(Role::Monitor.to_string(), "monitor");
724 assert_eq!(
725 Role::Device {
726 allowed_devices: vec![]
727 }
728 .to_string(),
729 "device"
730 );
731 assert_eq!(
732 Role::Custom {
733 permissions: vec![]
734 }
735 .to_string(),
736 "custom"
737 );
738 }
739
740 #[test]
741 fn test_auth_result_success() {
742 let result = AuthResult::success("user123".to_string(), vec![Role::Admin]);
743
744 assert!(result.success);
745 assert_eq!(result.user_id, Some("user123".to_string()));
746 assert_eq!(result.roles, vec![Role::Admin]);
747 assert!(result.message.is_none());
748 assert!(!result.rate_limited);
749 assert!(result.client_ip.is_none());
750 }
751
752 #[test]
753 fn test_auth_result_failure() {
754 let result = AuthResult::failure("Invalid credentials".to_string());
755
756 assert!(!result.success);
757 assert!(result.user_id.is_none());
758 assert!(result.roles.is_empty());
759 assert_eq!(result.message, Some("Invalid credentials".to_string()));
760 assert!(!result.rate_limited);
761 assert!(result.client_ip.is_none());
762 }
763
764 #[test]
765 fn test_auth_result_rate_limited() {
766 let result = AuthResult::rate_limited("192.168.1.100".to_string());
767
768 assert!(!result.success);
769 assert!(result.user_id.is_none());
770 assert!(result.roles.is_empty());
771 assert_eq!(result.message, Some("Too many failed attempts".to_string()));
772 assert!(result.rate_limited);
773 assert_eq!(result.client_ip, Some("192.168.1.100".to_string()));
774 }
775
776 #[test]
777 fn test_auth_context_permissions() {
778 let context = AuthContext {
779 user_id: Some("user123".to_string()),
780 roles: vec![Role::Admin, Role::Operator],
781 api_key_id: Some("key456".to_string()),
782 permissions: vec![
783 "admin.create".to_string(),
784 "read.status".to_string(),
785 "device.control".to_string(),
786 ],
787 };
788
789 assert!(context.has_permission("admin.create"));
790 assert!(context.has_permission("read.status"));
791 assert!(context.has_permission("anything")); let permissions = context.get_all_permissions();
794 assert_eq!(permissions.len(), 3);
795 assert!(permissions.contains(&"admin.create".to_string()));
796 }
797
798 #[test]
799 fn test_auth_context_mixed_roles() {
800 let context = AuthContext {
801 user_id: Some("user123".to_string()),
802 roles: vec![
803 Role::Monitor,
804 Role::Device {
805 allowed_devices: vec!["device1".to_string()],
806 },
807 ],
808 api_key_id: Some("key456".to_string()),
809 permissions: vec!["read.status".to_string(), "device.device1".to_string()],
810 };
811
812 assert!(context.has_permission("read.status")); assert!(context.has_permission("device.device1")); assert!(!context.has_permission("device.device2")); assert!(!context.has_permission("admin.create")); }
817
818 #[test]
819 fn test_key_creation_request_serialization() {
820 let request = KeyCreationRequest {
821 name: "test-key".to_string(),
822 role: Role::Operator,
823 expires_at: Some(Utc::now() + Duration::days(30)),
824 ip_whitelist: Some(vec!["192.168.1.1".to_string()]),
825 };
826
827 let json = serde_json::to_string(&request).unwrap();
828 let deserialized: KeyCreationRequest = serde_json::from_str(&json).unwrap();
829
830 assert_eq!(deserialized.name, request.name);
831 assert_eq!(deserialized.role, request.role);
832 assert_eq!(deserialized.expires_at, request.expires_at);
833 assert_eq!(deserialized.ip_whitelist, request.ip_whitelist);
834 }
835
836 #[test]
837 fn test_key_usage_stats_default() {
838 let stats = KeyUsageStats::default();
839
840 assert_eq!(stats.total_keys, 0);
841 assert_eq!(stats.active_keys, 0);
842 assert_eq!(stats.disabled_keys, 0);
843 assert_eq!(stats.expired_keys, 0);
844 assert_eq!(stats.total_usage_count, 0);
845 assert_eq!(stats.admin_keys, 0);
846 assert_eq!(stats.operator_keys, 0);
847 assert_eq!(stats.monitor_keys, 0);
848 assert_eq!(stats.device_keys, 0);
849 assert_eq!(stats.custom_keys, 0);
850 }
851
852 #[test]
853 fn test_api_completeness_check_serialization() {
854 let check = ApiCompletenessCheck {
855 has_create_key: true,
856 has_validate_key: true,
857 has_list_keys: true,
858 has_revoke_key: true,
859 has_update_key: false,
860 has_bulk_operations: false,
861 has_role_based_access: true,
862 has_rate_limiting: true,
863 has_ip_whitelisting: true,
864 has_expiration_support: true,
865 has_usage_tracking: true,
866 framework_version: "1.0.0".to_string(),
867 production_ready: true,
868 };
869
870 let json = serde_json::to_string(&check).unwrap();
871 let deserialized: ApiCompletenessCheck = serde_json::from_str(&json).unwrap();
872
873 assert_eq!(deserialized.has_create_key, check.has_create_key);
874 assert_eq!(deserialized.framework_version, check.framework_version);
875 assert_eq!(deserialized.production_ready, check.production_ready);
876 }
877
878 #[test]
879 fn test_role_equality() {
880 let admin1 = Role::Admin;
881 let admin2 = Role::Admin;
882 let operator = Role::Operator;
883
884 assert_eq!(admin1, admin2);
885 assert_ne!(admin1, operator);
886
887 let device1 = Role::Device {
888 allowed_devices: vec!["dev1".to_string()],
889 };
890 let device2 = Role::Device {
891 allowed_devices: vec!["dev1".to_string()],
892 };
893 let device3 = Role::Device {
894 allowed_devices: vec!["dev2".to_string()],
895 };
896
897 assert_eq!(device1, device2);
898 assert_ne!(device1, device3);
899 }
900
901 #[test]
902 fn test_api_key_serialization() {
903 let key = ApiKey::new("test".to_string(), Role::Admin, None, vec![]);
904
905 let json = serde_json::to_string(&key).unwrap();
906 let deserialized: ApiKey = serde_json::from_str(&json).unwrap();
907
908 assert_eq!(deserialized.id, key.id);
909 assert_eq!(deserialized.name, key.name);
910 assert_eq!(deserialized.role, key.role);
911 assert_eq!(deserialized.active, key.active);
912 assert_eq!(deserialized.usage_count, key.usage_count);
913 }
914}