use serde_json::json;
use super::{
AdminDrafts, AdminResponse, AtomicDraftStore, DraftError, LysPassConsumer, Target, refused,
};
pub struct OutrightAsk {
verified: crate::auth_lys::lys_pass_adapter::LysPass,
client: lys_pass::Client,
}
impl<S: AtomicDraftStore> AdminDrafts<S> {
pub fn outright(
&self,
authorization: Option<&str>,
at_ms: u64,
) -> Result<Result<OutrightAsk, AdminResponse>, DraftError> {
let Some(pass) = authorization.and_then(|header| header.strip_prefix("Bearer ")) else {
return Ok(Err(refused(401, "agent_create_pass_missing")));
};
if pass.is_empty() || pass.len() > self.limits.credential_bytes.get() {
return Ok(Err(refused(401, "agent_create_pass_invalid")));
}
let Ok(verified) = self
.adapter
.verify_offline(pass.as_bytes(), "liminal", at_ms / 1000)
else {
return Ok(Err(refused(401, "agent_create_pass_invalid")));
};
if verified.verified().claims().holder.kind != "person" {
return Ok(Err(refused(403, "agent_create_person_required")));
}
let http = reqwest::Client::builder()
.no_proxy()
.redirect(reqwest::redirect::Policy::none())
.build()
.map_err(|_| DraftError::Lys("transport_failed".to_owned()))?;
let issuer = crate::auth_lys::live::lys_origin(
self.ask.as_deref().unwrap_or_else(|| self.adapter.issuer()),
)
.map_err(|_| DraftError::Contract)?;
let client = lys_pass::Client::new(http, issuer)
.map_err(|error| DraftError::Lys(error.name().to_owned()))?;
Ok(Ok(OutrightAsk { verified, client }))
}
}
impl OutrightAsk {
pub async fn check(
self,
target: &Target,
connector_pass: &str,
) -> Result<
Result<(crate::auth_lys::lys_pass_adapter::LysPass, String), AdminResponse>,
DraftError,
> {
let holder = self.verified.verified().claims().holder.id.clone();
let answer = self
.client
.check_batch(connector_pass, &holder, std::slice::from_ref(target), None)
.await
.map_err(|error| DraftError::Lys(error.name().to_owned()))?;
let Some(result) = answer.results.first() else {
return Err(DraftError::Contract);
};
match (&result.grant, result.allowed, result.mode) {
(Some(grant), true, Some(lys_pass::Mode::Outright)) => {
Ok(Ok((self.verified, grant.clone())))
}
_ => Ok(Err(AdminResponse {
status: 403,
body: json!({"refusal": result.refusal.clone().unwrap_or_else(|| "agent_create_outright_required".to_owned())}),
})),
}
}
}