Skip to content

Commit

Permalink
feat: add offers_params endpoint handler
Browse files Browse the repository at this point in the history
  • Loading branch information
nanderstabel committed Oct 17, 2024
1 parent 007e986 commit b34a93d
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 4 deletions.
4 changes: 4 additions & 0 deletions agent_api_rest/src/holder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ pub fn router(holder_state: HolderState) -> Router {
.route("/holder/offers/:offer_id/accept", post(accept))
.route("/holder/offers/:offer_id/reject", post(reject)),
)
// TODO: move behind UniCore API
.route("/openid4vci/offers", post(openid4vci::offers))
// TODO: move behind UniCore API
.route("/credential_offer", get(openid4vci::offers_params))
.route("/", get(openid4vci::offers_params))
.route(
"/linked-verifiable-presentations/:presentation_id",
get(presentation_signed),
Expand Down
57 changes: 55 additions & 2 deletions agent_api_rest/src/holder/openid4vci/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use agent_holder::{offer::command::OfferCommand, state::HolderState};
use agent_shared::handlers::command_handler;
use agent_shared::handlers::{command_handler, query_handler};
use axum::{
extract::State,
response::{IntoResponse, Response},
Json,
Form, Json,
};
use hyper::StatusCode;
use oid4vci::credential_offer::CredentialOffer;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use tracing::info;

#[derive(Deserialize, Serialize)]
Expand Down Expand Up @@ -39,3 +40,55 @@ pub(crate) async fn offers(State(state): State<HolderState>, Json(payload): Json
Err(_) => StatusCode::INTERNAL_SERVER_ERROR.into_response(),
}
}

#[axum_macros::debug_handler]
pub(crate) async fn offers_params(
State(state): State<HolderState>,
Form(payload): Form<serde_json::Value>,
) -> Response {
offers_inner(state, payload).await
}

pub(crate) async fn offers_inner(state: HolderState, payload: serde_json::Value) -> Response {
info!("Request Body: {}", payload);

let credential_offer_result: Result<CredentialOffer, _> =
if let Some(credential_offer) = payload.get("credential_offer").and_then(Value::as_str) {
format!("openid-credential-offer://?credential_offer={credential_offer}")
} else if let Some(credential_offer_uri) = payload.get("credential_offer_uri").and_then(Value::as_str) {
format!("openid-credential-offer://?credential_offer_uri={credential_offer_uri}")
} else {
return (StatusCode::BAD_REQUEST, "invalid payload").into_response();
}
.parse();

let credential_offer = match credential_offer_result {
Ok(credential_offer) => credential_offer,
Err(_) => return (StatusCode::BAD_REQUEST, "invalid payload").into_response(),
};

let received_offer_id = uuid::Uuid::new_v4().to_string();

info!("Credential Offer: {:#?}", credential_offer);

let command = OfferCommand::ReceiveCredentialOffer {
received_offer_id: received_offer_id.clone(),
credential_offer,
};

// Add the Credential Offer to the state.
if command_handler(&received_offer_id, &state.command.offer, command)
.await
.is_err()
{
// TODO: add better Error responses. This needs to be done properly in all endpoints once
// https://github.com/impierce/openid4vc/issues/78 is fixed.
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}

match query_handler(&received_offer_id, &state.query.received_offer).await {
// TODO: add Location header
Ok(Some(received_offer)) => (StatusCode::CREATED, Json(received_offer)).into_response(),
_ => StatusCode::INTERNAL_SERVER_ERROR.into_response(),
}
}
14 changes: 12 additions & 2 deletions agent_issuance/src/offer/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,19 @@ impl Aggregate for Offer {
// TODO: add to `service`?
let client = reqwest::Client::new();

let form_url_encoded_credential_offer = self
.credential_offer
.as_ref()
.ok_or(MissingCredentialOfferError)?
.to_string();

let target =
form_url_encoded_credential_offer.replace("openid-credential-offer://", target_url.as_str());

info!("Sending credential offer to: {}", target);

client
.post(target_url.clone())
.json(self.credential_offer.as_ref().ok_or(MissingCredentialOfferError)?)
.get(target)
.send()
.await
.map_err(|e| SendCredentialOfferError(e.to_string()))?;
Expand Down

0 comments on commit b34a93d

Please sign in to comment.