use super::AuditSink;
use crate::security::{AuditLog, serialize_audit_logs};
use std::future::Future;
use std::pin::Pin;
pub struct InklogAuditSink;
impl InklogAuditSink {
pub fn new() -> Self {
Self
}
}
impl Default for InklogAuditSink {
fn default() -> Self {
Self::new()
}
}
impl AuditSink for InklogAuditSink {
fn write<'a>(
&'a self,
user_id: &'a str,
audit_log: AuditLog,
) -> Pin<Box<dyn Future<Output = Result<(), String>> + Send + 'a>> {
Box::pin(async move {
let serialized = serialize_audit_logs(&[audit_log]);
let json_str = String::from_utf8_lossy(&serialized);
::log::info!(
target: "sdforge::audit",
"audit_log user_id={} event={}",
user_id,
json_str,
);
Ok(())
})
}
fn read(&self, _user_id: &str) -> Vec<AuditLog> {
Vec::new()
}
fn clear(&self, _user_id: &str) {
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::security::{AuditLog, AuditResult, AuthMetadata};
#[test]
fn test_inklog_sink_read_returns_empty() {
let sink = InklogAuditSink::new();
let logs = sink.read("any_user");
assert!(logs.is_empty());
}
#[test]
fn test_inklog_sink_clear_is_noop() {
let sink = InklogAuditSink::new();
sink.clear("any_user");
}
#[tokio::test]
async fn test_inklog_sink_write_succeeds() {
let sink = InklogAuditSink::new();
let log = AuditLog {
id: "test-id".to_string(),
timestamp: 1234567890,
user_id: Some("user1".to_string()),
action: "test_action".to_string(),
resource: "test_resource".to_string(),
result: AuditResult::Success,
metadata: AuthMetadata {
client_ip: None,
user_agent: None,
request_id: "req-1".to_string(),
timestamp: 1234567890,
},
signature: None,
};
let result = sink.write("user1", log).await;
assert!(result.is_ok());
}
}