use async_trait::async_trait;
use chrono::{DateTime, Utc};
use crate::audit::{Audit, NewAudit};
use crate::changes::AuditedChanges;
use crate::error::Result;
use crate::id::AuditId;
mod memory;
pub use memory::MemoryBackend;
#[cfg(any(feature = "sqlite", feature = "postgres"))]
mod sqlx_backend;
#[cfg(any(feature = "sqlite", feature = "postgres"))]
pub use sqlx_backend::SqlxBackend;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum Order {
#[default]
VersionAsc,
VersionDesc,
CreatedAtAsc,
CreatedAtDesc,
}
#[derive(Clone, Debug, Default)]
pub struct AuditQuery {
pub action: Option<crate::action::Action>,
pub from_version: Option<i32>,
pub to_version: Option<i32>,
pub up_until: Option<DateTime<Utc>>,
pub order: Order,
pub limit: Option<i64>,
pub offset: Option<i64>,
}
impl AuditQuery {
pub fn matches(&self, audit: &Audit) -> bool {
if let Some(a) = self.action
&& audit.action != a
{
return false;
}
if let Some(v) = self.from_version
&& audit.version < v
{
return false;
}
if let Some(v) = self.to_version
&& audit.version > v
{
return false;
}
if let Some(t) = self.up_until
&& audit.created_at > t
{
return false;
}
true
}
}
#[async_trait]
pub trait Backend: Send + Sync {
async fn insert(&self, audit: NewAudit) -> Result<Audit>;
async fn audits_for_auditable(
&self,
auditable_type: &str,
auditable_id: &AuditId,
query: &AuditQuery,
) -> Result<Vec<Audit>>;
async fn audits_for_associated(
&self,
associated_type: &str,
associated_id: &AuditId,
query: &AuditQuery,
) -> Result<Vec<Audit>>;
async fn own_and_associated_audits(
&self,
auditable_type: &str,
auditable_id: &AuditId,
) -> Result<Vec<Audit>>;
async fn count_for_auditable(
&self,
auditable_type: &str,
auditable_id: &AuditId,
) -> Result<i64>;
async fn find(&self, id: i64) -> Result<Option<Audit>>;
async fn combine(
&self,
target_id: i64,
merged_changes: &AuditedChanges,
comment: Option<&str>,
older_ids: &[i64],
) -> Result<()>;
}