Initial public release v0.1.0

This commit is contained in:
thakares committed 2026-06-21 20:05:29 +05:30
commit 6c39e0bfbf
87 files changed
+10867

No files matched your search

+84
View File
@@ -0,0 +1,84 @@
use crate::{
db::{models::AuditSeverity, repository::audit as repo},
error::AppError,
};
/// A structured audit event to be persisted and logged.
#[derive(Debug)]
pub struct AuditEvent<'a> {
/// The user performing the action (None for system/CLI events).
pub actor_id: Option<&'a str>,
/// The user being acted upon, if applicable.
pub target_id: Option<&'a str>,
/// Machine-readable action name (e.g. `"login_success"`, `"user_created"`).
pub action: &'a str,
/// Resource category (e.g. `"user"`, `"session"`, `"token"`).
pub resource_type: &'a str,
/// Specific resource ID, if applicable.
pub resource_id: Option<&'a str>,
/// Event severity.
pub severity: AuditSeverity,
/// Client IP address.
pub ip: Option<&'a str>,
/// Client User-Agent string.
pub ua: Option<&'a str>,
/// Optional structured metadata (serialized JSON string).
pub metadata: Option<&'a str>,
}
impl<'a> AuditEvent<'a> {
/// Convenience constructor for info-level system events with no actor/IP.
pub fn system(action: &'a str, resource_type: &'a str) -> Self {
Self {
actor_id: None,
target_id: None,
action,
resource_type,
resource_id: None,
severity: AuditSeverity::Info,
ip: None,
ua: None,
metadata: None,
}
}
}
/// Persist an audit event to the database and emit a structured log line.
///
/// This function is intentionally fire-and-forget — a failure to write an
/// audit log must never break an otherwise successful operation.
pub async fn log(
tx: &mut sqlx::Transaction<'_, sqlx::Sqlite>,
event: AuditEvent<'_>,
) -> Result<(), AppError> {
let id = uuid::Uuid::new_v4().to_string();
tracing::info!(
event = "audit",
action = event.action,
resource_type = event.resource_type,
resource_id = event.resource_id,
severity = event.severity.as_str(),
actor_id = event.actor_id,
target_id = event.target_id,
ip = event.ip,
);
repo::insert(
tx,
&id,
event.actor_id,
event.target_id,
event.action,
event.resource_type,
event.resource_id,
event.severity.as_str(),
event.ip,
event.ua,
event.metadata,
)
.await
.map_err(AppError::Database)?;
Ok(())
}