use crate::proto::audit::{Actor, AuditResult, ChainHead, RowStop};
use crate::error::Error;
use crate::state::LocalState;
use crate::vault::{Handle, RawAudit, short};
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct AuditEntry {
pub seq: u64,
pub ts: i64,
pub actor: Actor,
pub action: String,
pub name: Option<String>,
pub refused: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct AuditReport {
pub head: Option<ChainHead>,
pub new_rows: usize,
pub entries: Vec<AuditEntry>,
pub unverifiable: Option<Unverifiable>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct Unverifiable {
pub from_seq: Option<u64>,
pub format: u64,
}
fn report(raw: RawAudit) -> AuditReport {
let RawAudit {
rows,
new_rows,
head,
names,
unverifiable,
} = raw;
let entries = rows
.into_iter()
.map(|r| AuditEntry {
seq: r.seq,
ts: r.ts,
action: r.action.as_str().to_owned(),
name: r.name_hmac.map(|h| {
names
.get(&h)
.cloned()
.unwrap_or_else(|| format!("#{}", short(&h)))
}),
refused: r.result == AuditResult::Refused,
actor: r.actor,
})
.collect();
AuditReport {
head,
new_rows,
entries,
unverifiable: unverifiable.and_then(|stop| match stop {
RowStop::NewerFormat { seq, v } => Some(Unverifiable {
from_seq: seq,
format: v,
}),
_ => None,
}),
}
}
pub(crate) fn verify(
handle: &Handle,
known: Option<ChainHead>,
earlier: usize,
) -> Result<AuditReport, Error> {
Ok(report(handle.verify_audit(known, earlier)?))
}
pub(crate) fn verify_recorded(
handle: &Handle,
state: &mut LocalState,
earlier: usize,
) -> Result<AuditReport, Error> {
let key = handle.vault_id.to_hex();
let known = state.audit.get(&key).copied();
let report = verify(handle, known, earlier)?;
if let Some(head) = report.head {
state.audit.insert(key, head);
}
Ok(report)
}