use super::{AtomicDraftStore, SiteDraftStore, storage_error};
use crate::auth_lys::live::drafts::{ApprovalTransition, DraftError};
use lys_pass::drafts::{ApprovedDraft, Execution, Executor};
use std::collections::BTreeSet;
impl Executor for SiteDraftStore {
type Error = DraftError;
fn receipt(&self, draft: &str) -> Result<Option<Execution>, DraftError> {
AtomicDraftStore::receipt(self, draft)
}
fn execute_and_record(&mut self, draft: &ApprovedDraft) -> Result<Execution, DraftError> {
let evidence = self.approval(draft)?;
let needed = match evidence.mode {
crate::auth_lys::GrantMode::ByDraft => 1,
crate::auth_lys::GrantMode::ByTwo => 2,
crate::auth_lys::GrantMode::Outright => return Err(DraftError::ApprovalUnavailable),
};
let bound = self
.lifecycle
.site_bindings()
.map_err(storage_error)?
.limits
.text_bytes
.get();
let mut people = BTreeSet::new();
if evidence.draft != draft.id
|| evidence.digest != draft.request_digest
|| evidence.approved_by.len() != needed
|| evidence.approved_by.iter().any(|person| {
person.is_empty()
|| person.len() > bound
|| person.chars().any(char::is_control)
|| !people.insert(person)
})
{
return Err(DraftError::ApprovalUnavailable);
}
self.commit(
draft,
&ApprovalTransition {
draft: draft.id.clone(),
digest: draft.request_digest.clone(),
approved_by: evidence.approved_by,
executed_at_ms: self.at_ms,
},
)
}
}