#![cfg(feature = "webvh")]
use super::helpers::TrustTaskOutcome;
use serde_json::Value;
use trust_tasks_rs::TrustTask;
use vta_sdk::provision_integration::http::{
AssertionMode, ProvisionIntegrationRequest, ProvisionIntegrationResponse,
};
use crate::auth::AuthClaims;
use crate::operations::provision_integration::{
AmbiguousContext, ProvisionIntegrationDeps, ProvisionIntegrationParams,
ensure_target_context_or_create, infer_target_context,
provision_integration as provision_integration_op,
};
use crate::server::AppState;
use super::helpers::{app_error_to_reject, parse_payload, reject_with, success_response};
pub(super) async fn handle_request(
state: &AppState,
auth: &AuthClaims,
doc: TrustTask<Value>,
) -> TrustTaskOutcome {
let req: ProvisionIntegrationRequest = match parse_payload(&doc) {
Ok(r) => r,
Err(resp) => return resp,
};
let verified = match req.request.verify() {
Ok(v) => v,
Err(e) => {
return reject_with(
&doc,
trust_tasks_rs::RejectReason::MalformedRequest {
reason: format!("verify BootstrapRequest: {e}"),
},
);
}
};
let assertion_mode = req.assertion.unwrap_or_default();
let vc_validity = req.vc_validity_seconds.map(chrono::Duration::seconds);
let deps = ProvisionIntegrationDeps::from(state);
let context = match req.context {
Some(c) => c,
None => match infer_target_context(auth, &deps.contexts_ks).await {
Ok(Ok(c)) => c,
Ok(Err(AmbiguousContext {
candidates,
message,
})) => {
return reject_with(
&doc,
trust_tasks_rs::RejectReason::MalformedRequest {
reason: format!("{message} (candidates: {})", candidates.join(", ")),
},
);
}
Err(e) => return app_error_to_reject(&doc, e),
},
};
let context_created = match ensure_target_context_or_create(
&deps.contexts_ks,
auth,
&context,
req.create_context,
)
.await
{
Ok(c) => c,
Err(e) => return app_error_to_reject(&doc, e),
};
let output = match provision_integration_op(
&deps,
auth,
ProvisionIntegrationParams {
request: verified,
context,
assertion_mode: AssertionModeOpAdapter(assertion_mode).into(),
vc_validity,
},
)
.await
{
Ok(o) => o,
Err(e) => return app_error_to_reject(&doc, e),
};
let body = ProvisionIntegrationResponse {
bundle: output.armored,
digest: output.digest,
summary: vta_sdk::provision_integration::http::ProvisionSummary {
client_did: output.summary.client_did,
admin_did: output.summary.admin_did,
admin_rolled_over: output.summary.admin_rolled_over,
integration_did: output.summary.integration_did,
template_name: output.summary.template_name,
template_kind: output.summary.template_kind,
admin_template_name: output.summary.admin_template_name,
bundle_id_hex: output.summary.bundle_id_hex,
secret_count: output.summary.secret_count,
output_count: output.summary.output_count,
webvh_server_id: output.summary.webvh_server_id,
context_created,
},
};
success_response(&doc, body)
}
struct AssertionModeOpAdapter(AssertionMode);
impl From<AssertionModeOpAdapter> for crate::operations::provision_integration::AssertionMode {
fn from(a: AssertionModeOpAdapter) -> Self {
match a.0 {
AssertionMode::DidSigned => {
crate::operations::provision_integration::AssertionMode::DidSigned
}
AssertionMode::PinnedOnly => {
crate::operations::provision_integration::AssertionMode::PinnedOnly
}
}
}
}