use super::super::Lifecycle;
use super::{SiteAct, SiteChange, SiteError};
use crate::auth_lys::live::drafts::DraftLimits;
use crate::auth_lys::live::{HttpLysAsk, PreparedAct};
use crate::auth_lys::lys_pass_adapter::LiveAnswer;
#[derive(Clone, Copy)]
pub struct VerifiedContext<'a> {
pub lifecycle: &'a Lifecycle,
pub pass: &'a lys_pass::VerifiedPass,
pub token: &'a str,
pub live: &'a HttpLysAsk,
pub at_ms: u64,
pub limits: DraftLimits,
}
pub fn hold_verified(
context: VerifiedContext<'_>,
operation: &str,
target: &str,
change: SiteChange,
) -> Result<serde_json::Value, SiteError> {
let VerifiedContext {
lifecycle,
pass,
token,
live,
at_ms,
limits: draft_limits,
} = context;
let bindings = lifecycle.site_bindings()?;
let limits = &bindings.limits;
if pass.claims().exp <= at_ms / 1000 {
return Err(SiteError::Pass("pass_expired".into()));
}
let act = SiteAct::prepare(target.into(), change, pass)?;
let words = serde_json::to_string(&act).map_err(|_| SiteError::Store)?;
if words.len() > limits.request_bytes.get() {
return Err(SiteError::Bound("request_bytes"));
}
let permission = lys_pass::Target::new(
act.change.kind(),
act.permission_id(lifecycle.network_id()),
act.change.action(),
)
.map_err(|_| SiteError::Invalid("construction target"))?;
if act.change.kind() == "liminal.template" {
bindings.effects.place("liminal.template", &act.target)?;
}
let answer = live
.ask_prepared(
token,
&PreparedAct {
holder: &act.holder,
target: &permission,
operation,
words: &words,
at_ms,
},
draft_limits,
)
.map_err(|error| SiteError::Pass(error.name().into()))?;
match answer.decision {
LiveAnswer::Held { draft, .. } => {
Ok(serde_json::json!({"state":"held","draft":draft,"words":words}))
}
LiveAnswer::Outright { grant } => {
lifecycle.apply_outright(&act, &grant, operation, &words, at_ms)
}
LiveAnswer::Refused { refusal } => Err(SiteError::Pass(refusal)),
}
}