koprogo_api/application/use_cases/
audit_log_use_cases.rs1use crate::application::dto::PageRequest;
2use crate::application::ports::{AuditLogFilters, AuditLogRepository};
3use crate::infrastructure::audit::AuditLogEntry;
4use std::sync::Arc;
5
6pub struct AuditLogUseCases {
7 repo: Arc<dyn AuditLogRepository>,
8}
9
10impl AuditLogUseCases {
11 pub fn new(repo: Arc<dyn AuditLogRepository>) -> Self {
12 Self { repo }
13 }
14
15 pub async fn find_all_paginated(
16 &self,
17 page_request: &PageRequest,
18 filters: &AuditLogFilters,
19 ) -> Result<(Vec<AuditLogEntry>, i64), String> {
20 self.repo.find_all_paginated(page_request, filters).await
21 }
22}
23
24#[cfg(test)]
25mod tests {
26 use super::*;
27 use crate::infrastructure::audit::{AuditEventType, AuditLogEntry};
28 use async_trait::async_trait;
29 use uuid::Uuid;
30
31 struct MockAuditLogRepository {
32 entries: Vec<AuditLogEntry>,
33 }
34
35 #[async_trait]
36 impl AuditLogRepository for MockAuditLogRepository {
37 async fn create(&self, entry: &AuditLogEntry) -> Result<AuditLogEntry, String> {
38 Ok(entry.clone())
39 }
40 async fn find_by_id(&self, _id: Uuid) -> Result<Option<AuditLogEntry>, String> {
41 Ok(None)
42 }
43 async fn find_all_paginated(
44 &self,
45 _page_request: &PageRequest,
46 _filters: &AuditLogFilters,
47 ) -> Result<(Vec<AuditLogEntry>, i64), String> {
48 let total = self.entries.len() as i64;
49 Ok((self.entries.clone(), total))
50 }
51 async fn find_recent(&self, _limit: i64) -> Result<Vec<AuditLogEntry>, String> {
52 Ok(self.entries.clone())
53 }
54 async fn find_failed_operations(
55 &self,
56 _page_request: &PageRequest,
57 _organization_id: Option<Uuid>,
58 ) -> Result<(Vec<AuditLogEntry>, i64), String> {
59 Ok((vec![], 0))
60 }
61 async fn delete_older_than(
62 &self,
63 _timestamp: chrono::DateTime<chrono::Utc>,
64 ) -> Result<i64, String> {
65 Ok(0)
66 }
67 async fn count_by_filters(&self, _filters: &AuditLogFilters) -> Result<i64, String> {
68 Ok(self.entries.len() as i64)
69 }
70 }
71
72 fn make_entry() -> AuditLogEntry {
73 AuditLogEntry::new(AuditEventType::UserLogin, Some(Uuid::new_v4()), None)
74 }
75
76 #[tokio::test]
77 async fn test_find_all_paginated_returns_entries() {
78 let entry = make_entry();
79 let repo = Arc::new(MockAuditLogRepository {
80 entries: vec![entry],
81 });
82 let use_cases = AuditLogUseCases::new(repo);
83 let page_request = PageRequest {
84 page: 1,
85 per_page: 20,
86 sort_by: None,
87 order: crate::application::dto::SortOrder::Desc,
88 };
89 let filters = AuditLogFilters::default();
90 let (entries, total) = use_cases
91 .find_all_paginated(&page_request, &filters)
92 .await
93 .unwrap();
94 assert_eq!(total, 1);
95 assert_eq!(entries.len(), 1);
96 }
97
98 #[tokio::test]
99 async fn test_find_all_paginated_empty_returns_zero() {
100 let repo = Arc::new(MockAuditLogRepository { entries: vec![] });
101 let use_cases = AuditLogUseCases::new(repo);
102 let page_request = PageRequest {
103 page: 1,
104 per_page: 20,
105 sort_by: None,
106 order: crate::application::dto::SortOrder::Desc,
107 };
108 let filters = AuditLogFilters::default();
109 let (entries, total) = use_cases
110 .find_all_paginated(&page_request, &filters)
111 .await
112 .unwrap();
113 assert_eq!(total, 0);
114 assert!(entries.is_empty());
115 }
116}