bug-fix: nym-credential-proxy webhook request is the correct shape and added reporting errors via webhook (#5077)
Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
This commit is contained in:
Generated
+5
-4
@@ -2382,7 +2382,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-credential-proxy"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -2691,7 +2691,6 @@ dependencies = [
|
||||
"flate2",
|
||||
"futures",
|
||||
"itertools 0.13.0",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-coconut-bandwidth-contract-common",
|
||||
"nym-coconut-dkg-common",
|
||||
@@ -2715,6 +2714,7 @@ dependencies = [
|
||||
"thiserror",
|
||||
"time",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
"wasmtimer",
|
||||
"zeroize",
|
||||
@@ -3791,9 +3791,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.128"
|
||||
version = "1.0.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
||||
checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -4917,6 +4917,7 @@ dependencies = [
|
||||
"quote",
|
||||
"regex",
|
||||
"syn 2.0.79",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -10,7 +10,7 @@ use schemars::schema::Schema;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use time::Date;
|
||||
use time::{Date, OffsetDateTime};
|
||||
|
||||
#[cfg(feature = "query-types")]
|
||||
use nym_http_api_common::Output;
|
||||
@@ -236,22 +236,28 @@ pub struct TicketbookWalletSharesAsyncResponse {
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BlindedWalletSharesResponse {
|
||||
pub struct WebhookTicketbookWalletShares {
|
||||
pub id: i64,
|
||||
pub status: String,
|
||||
pub device_id: String,
|
||||
pub credential_id: String,
|
||||
pub data: Option<TicketbookWalletSharesResponse>,
|
||||
pub error_message: Option<String>,
|
||||
pub created: String,
|
||||
pub updated: String,
|
||||
|
||||
#[schemars(with = "String")]
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
pub created: OffsetDateTime,
|
||||
|
||||
#[schemars(with = "String")]
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
pub updated: OffsetDateTime,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema)]
|
||||
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct WebhookBlindedSharesResponse {
|
||||
pub blinded_shares: BlindedWalletSharesResponse,
|
||||
pub struct WebhookTicketbookWalletSharesRequest {
|
||||
pub ticketbook_wallet_shares: WebhookTicketbookWalletShares,
|
||||
pub secret: String,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nym-credential-proxy"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
|
||||
use crate::error::VpnApiError;
|
||||
use crate::http::state::ApiState;
|
||||
use crate::storage::models::BlindedShares;
|
||||
use futures::{stream, StreamExt};
|
||||
use nym_credential_proxy_requests::api::v1::ticketbook::models::{
|
||||
TicketbookAsyncRequest, TicketbookObtainQueryParams, TicketbookRequest,
|
||||
TicketbookWalletSharesResponse, WalletShare,
|
||||
TicketbookWalletSharesResponse, WalletShare, WebhookTicketbookWalletShares,
|
||||
WebhookTicketbookWalletSharesRequest,
|
||||
};
|
||||
use nym_credentials::IssuanceTicketBook;
|
||||
use nym_credentials_interface::Base58;
|
||||
@@ -217,11 +219,13 @@ async fn try_obtain_blinded_ticketbook_async_inner(
|
||||
requested_on: OffsetDateTime,
|
||||
request_data: TicketbookAsyncRequest,
|
||||
params: TicketbookObtainQueryParams,
|
||||
pending: &BlindedShares,
|
||||
) -> Result<(), VpnApiError> {
|
||||
let epoch_id = state.current_epoch_id().await?;
|
||||
|
||||
let device_id = &request_data.device_id;
|
||||
let credential_id = &request_data.credential_id;
|
||||
let secret = request_data.secret.clone();
|
||||
|
||||
// 1. try to obtain global data
|
||||
let (
|
||||
@@ -259,19 +263,70 @@ async fn try_obtain_blinded_ticketbook_async_inner(
|
||||
error!(uuid = %request, "failed to update db with issued information: {err}")
|
||||
}
|
||||
|
||||
// 4. build the response
|
||||
let response = TicketbookWalletSharesResponse {
|
||||
// 4. build the webhook request body
|
||||
let data = Some(TicketbookWalletSharesResponse {
|
||||
epoch_id,
|
||||
shares,
|
||||
master_verification_key,
|
||||
aggregated_coin_index_signatures,
|
||||
aggregated_expiration_date_signatures,
|
||||
});
|
||||
|
||||
let ticketbook_wallet_shares = WebhookTicketbookWalletShares {
|
||||
id: pending.id,
|
||||
status: pending.status.to_string(),
|
||||
device_id: device_id.clone(),
|
||||
credential_id: credential_id.clone(),
|
||||
data,
|
||||
error_message: None,
|
||||
created: pending.created,
|
||||
updated: pending.updated,
|
||||
};
|
||||
|
||||
let webhook_request = WebhookTicketbookWalletSharesRequest {
|
||||
ticketbook_wallet_shares,
|
||||
secret,
|
||||
};
|
||||
|
||||
// 5. call the webhook
|
||||
state
|
||||
.zk_nym_web_hook()
|
||||
.try_trigger(request, &response)
|
||||
.try_trigger(request, &webhook_request)
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn try_trigger_webhook_request_for_error(
|
||||
state: &ApiState,
|
||||
request: Uuid,
|
||||
request_data: TicketbookAsyncRequest,
|
||||
pending: &BlindedShares,
|
||||
error_message: String,
|
||||
) -> Result<(), VpnApiError> {
|
||||
let device_id = &request_data.device_id;
|
||||
let credential_id = &request_data.credential_id;
|
||||
let secret = request_data.secret.clone();
|
||||
|
||||
let ticketbook_wallet_shares = WebhookTicketbookWalletShares {
|
||||
id: pending.id,
|
||||
status: "error".to_string(),
|
||||
device_id: device_id.clone(),
|
||||
credential_id: credential_id.clone(),
|
||||
data: None,
|
||||
error_message: Some(error_message),
|
||||
created: pending.created,
|
||||
updated: pending.updated,
|
||||
};
|
||||
|
||||
let webhook_request = WebhookTicketbookWalletSharesRequest {
|
||||
ticketbook_wallet_shares,
|
||||
secret,
|
||||
};
|
||||
|
||||
state
|
||||
.zk_nym_web_hook()
|
||||
.try_trigger(request, &webhook_request)
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
@@ -285,16 +340,30 @@ pub(crate) async fn try_obtain_blinded_ticketbook_async(
|
||||
requested_on: OffsetDateTime,
|
||||
request_data: TicketbookAsyncRequest,
|
||||
params: TicketbookObtainQueryParams,
|
||||
pending: BlindedShares,
|
||||
) {
|
||||
if let Err(err) = try_obtain_blinded_ticketbook_async_inner(
|
||||
&state,
|
||||
request,
|
||||
requested_on,
|
||||
request_data,
|
||||
request_data.clone(),
|
||||
params,
|
||||
&pending,
|
||||
)
|
||||
.await
|
||||
{
|
||||
// post to the webhook to notify of errors on this side
|
||||
if let Err(webhook_err) = try_trigger_webhook_request_for_error(
|
||||
&state,
|
||||
request,
|
||||
request_data,
|
||||
&pending,
|
||||
format!("Failed to get ticketbook: {err}"),
|
||||
)
|
||||
.await
|
||||
{
|
||||
error!(uuid = %request, "failed to make webhook request to report error: {webhook_err}")
|
||||
}
|
||||
error!(uuid = %request, "failed to resolve the blinded ticketbook issuance: {err}")
|
||||
} else {
|
||||
info!(uuid = %request, "managed to resolve the blinded ticketbook issuance")
|
||||
|
||||
@@ -84,8 +84,8 @@ pub(crate) struct ApiDoc;
|
||||
api_requests::v1::ticketbook::models::WalletShare,
|
||||
api_requests::v1::ticketbook::models::TicketbookWalletSharesResponse,
|
||||
api_requests::v1::ticketbook::models::TicketbookWalletSharesAsyncResponse,
|
||||
api_requests::v1::ticketbook::models::BlindedWalletSharesResponse,
|
||||
api_requests::v1::ticketbook::models::WebhookBlindedSharesResponse,
|
||||
api_requests::v1::ticketbook::models::WebhookTicketbookWalletShares,
|
||||
api_requests::v1::ticketbook::models::WebhookTicketbookWalletSharesRequest,
|
||||
api_requests::v1::ticketbook::models::TicketbookObtainQueryParams,
|
||||
api_requests::v1::ticketbook::models::SharesQueryParams,
|
||||
api_requests::v1::ticketbook::models::PlaceholderJsonSchemaImpl,
|
||||
|
||||
@@ -192,6 +192,7 @@ pub(crate) async fn obtain_ticketbook_shares_async(
|
||||
}
|
||||
Ok(pending) => pending,
|
||||
};
|
||||
let id = pending.id;
|
||||
|
||||
// 3. try to spawn a new task attempting to resolve the request
|
||||
if state
|
||||
@@ -201,6 +202,7 @@ pub(crate) async fn obtain_ticketbook_shares_async(
|
||||
requested_on,
|
||||
payload,
|
||||
params,
|
||||
pending,
|
||||
))
|
||||
.is_none()
|
||||
{
|
||||
@@ -213,10 +215,7 @@ pub(crate) async fn obtain_ticketbook_shares_async(
|
||||
}
|
||||
|
||||
// 4. in the meantime, return the id to the user
|
||||
Ok(output.to_response(TicketbookWalletSharesAsyncResponse {
|
||||
id: pending.id,
|
||||
uuid,
|
||||
}))
|
||||
Ok(output.to_response(TicketbookWalletSharesAsyncResponse { id, uuid }))
|
||||
}
|
||||
|
||||
/// Obtain the current value of the bandwidth voucher deposit
|
||||
|
||||
Generated
+1
-1
@@ -3428,7 +3428,6 @@ dependencies = [
|
||||
"flate2",
|
||||
"futures",
|
||||
"itertools 0.13.0",
|
||||
"log",
|
||||
"nym-api-requests",
|
||||
"nym-coconut-bandwidth-contract-common",
|
||||
"nym-coconut-dkg-common",
|
||||
@@ -3452,6 +3451,7 @@ dependencies = [
|
||||
"thiserror",
|
||||
"time",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
"wasmtimer",
|
||||
"zeroize",
|
||||
|
||||
Reference in New Issue
Block a user