use std::sync::Arc;
use std::time::SystemTime;
use super::{Store, StoreError, format};
use crate::qso::Date;
#[derive(Debug, PartialEq, Eq)]
pub struct DeletePreview {
pub callsign: String,
pub dxcc: u32,
pub serial: Vec<u8>,
pub qso_dates: (Date, Date),
pub validity: (SystemTime, SystemTime),
pub key_present: bool,
}
pub struct PendingDelete {
owner: Arc<()>,
before: String,
id: String,
preview: DeletePreview,
}
impl PendingDelete {
pub fn preview(&self) -> &DeletePreview {
&self.preview
}
}
impl Store {
pub fn inspect_delete(&self, id: &str) -> Result<PendingDelete, StoreError> {
let _lock = self.lock()?;
let data = self.read()?;
let stored = data
.certificates
.iter()
.find(|c| c.id == id)
.ok_or(StoreError::NotFound)?;
let key_present = match &stored.key_name {
Some(name) => self.keys.exists(name)?,
None => false,
};
let certificate = &stored.certificate;
Ok(PendingDelete {
owner: Arc::clone(&self.import_identity),
before: format::write(&data)?,
id: stored.id.clone(),
preview: DeletePreview {
callsign: certificate.callsign().into(),
dxcc: certificate.dxcc(),
serial: certificate.serial_number().to_vec(),
qso_dates: certificate.qso_dates(),
validity: certificate.validity(),
key_present,
},
})
}
pub fn commit_delete(&self, pending: PendingDelete) -> Result<(), StoreError> {
if !Arc::ptr_eq(&self.import_identity, &pending.owner) {
return Err(StoreError::Conflict);
}
let _lock = self.lock()?;
let mut data = self.read()?;
if format::write(&data)? != pending.before {
return Err(StoreError::Conflict);
}
let i = data
.certificates
.iter()
.position(|c| c.id == pending.id)
.ok_or(StoreError::Conflict)?;
let key_present = match &data.certificates[i].key_name {
Some(name) => self.keys.exists(name)?,
None => false,
};
if key_present != pending.preview.key_present {
return Err(StoreError::Conflict);
}
let certificate = data.certificates.remove(i);
self.replace(&format::write(&data)?)?;
if let Some(name) = certificate.key_name {
self.keys.delete(&name)?;
}
Ok(())
}
}