liminal_server/services/site/
executor_run.rs1use super::{AtomicDraftStore, SiteDraftStore, storage_error};
4use crate::auth_lys::live::drafts::{ApprovalTransition, DraftError};
5use lys_pass::drafts::{ApprovedDraft, Execution, Executor};
6use std::collections::BTreeSet;
7
8impl Executor for SiteDraftStore {
9 type Error = DraftError;
10 fn receipt(&self, draft: &str) -> Result<Option<Execution>, DraftError> {
11 AtomicDraftStore::receipt(self, draft)
12 }
13 fn execute_and_record(&mut self, draft: &ApprovedDraft) -> Result<Execution, DraftError> {
14 let evidence = self.approval(draft)?;
15 let needed = match evidence.mode {
16 crate::auth_lys::GrantMode::ByDraft => 1,
17 crate::auth_lys::GrantMode::ByTwo => 2,
18 crate::auth_lys::GrantMode::Outright => return Err(DraftError::ApprovalUnavailable),
19 };
20 let bound = self
21 .lifecycle
22 .site_bindings()
23 .map_err(storage_error)?
24 .limits
25 .text_bytes
26 .get();
27 let mut people = BTreeSet::new();
28 if evidence.draft != draft.id
29 || evidence.digest != draft.request_digest
30 || evidence.approved_by.len() != needed
31 || evidence.approved_by.iter().any(|person| {
32 person.is_empty()
33 || person.len() > bound
34 || person.chars().any(char::is_control)
35 || !people.insert(person)
36 })
37 {
38 return Err(DraftError::ApprovalUnavailable);
39 }
40 self.commit(
41 draft,
42 &ApprovalTransition {
43 draft: draft.id.clone(),
44 digest: draft.request_digest.clone(),
45 approved_by: evidence.approved_by,
46 executed_at_ms: self.at_ms,
47 },
48 )
49 }
50}