Skip to content

Commit

Permalink
Share error serialization code to simplify the mental model
Browse files Browse the repository at this point in the history
  • Loading branch information
MOZGIII authored and dmitrylavrenov committed Sep 12, 2024
1 parent 587c51f commit 0bd240f
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 178 deletions.
26 changes: 26 additions & 0 deletions crates/bioauth-flow-rpc/src/error_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,32 @@ impl Serialize for ScanResultBlob {
}
}

/// The RPC error that would either provide a scan result blob, or specify that a retry is in order.
///
/// The case where no scan result blob is present, but a retry is communicated is possible when
/// the new flow is used with an old robonode that doesn't return scan result blobs yet.
#[derive(serde::Serialize)]
#[serde(untagged)]
pub enum BlobOrRetry {
/// The scan result blob data.
ScanResultBlob(ScanResultBlob),

/// The should retry data.
ShouldRetry(ShouldRetry),
}

impl From<ShouldRetry> for BlobOrRetry {
fn from(value: ShouldRetry) -> Self {
Self::ShouldRetry(value)
}
}

impl From<ScanResultBlob> for BlobOrRetry {
fn from(value: ScanResultBlob) -> Self {
Self::ScanResultBlob(value)
}
}

/// The RPC error context we provide to describe transaction pool errors.
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
Expand Down
57 changes: 23 additions & 34 deletions crates/bioauth-flow-rpc/src/errors/authenticate.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! The `authenticate` method error.

use rpc_validator_key_logic::Error as ValidatorKeyError;
use sp_api::ApiError;
use sp_runtime::transaction_validity::InvalidTransaction;

Expand All @@ -24,36 +23,24 @@ where
{
fn from(err: Error<TxPoolError>) -> Self {
match err {
Error::RobonodeRequest(err) => match err {
shared::FlowBaseError::KeyExtraction(
err @ ValidatorKeyError::MissingValidatorKey,
) => rpc_error_response::data(
api_error_code::MISSING_VALIDATOR_KEY,
err.to_string(),
rpc_validator_key_logic::error_data::ValidatorKeyNotAvailable,
),
shared::FlowBaseError::KeyExtraction(
err @ ValidatorKeyError::ValidatorKeyExtraction,
) => rpc_error_response::simple(
api_error_code::VALIDATOR_KEY_EXTRACTION,
err.to_string(),
),
shared::FlowBaseError::Sign(err) => {
rpc_error_response::simple(api_error_code::SIGN, err.to_string())
}
shared::FlowBaseError::RobonodeClient(
err @ robonode_client::Error::Call(
robonode_client::AuthenticateError::FaceScanRejectedNoBlob,
),
) => rpc_error_response::data(
api_error_code::ROBONODE,
err.to_string(),
error_data::ShouldRetry,
),
shared::FlowBaseError::RobonodeClient(err) => {
rpc_error_response::simple(api_error_code::ROBONODE, err.to_string())
}
},
Error::RobonodeRequest(err) => err.to_jsonrpsee_error::<_, error_data::ShouldRetry>(
|call_error| match call_error {
robonode_client::AuthenticateError::FaceScanRejectedNoBlob
| robonode_client::AuthenticateError::FaceScanRejected(_) => {
Some(error_data::ShouldRetry)
}

robonode_client::AuthenticateError::InvalidLivenessData
| robonode_client::AuthenticateError::PersonNotFoundNoBlob
| robonode_client::AuthenticateError::PersonNotFound(_)
| robonode_client::AuthenticateError::SignatureInvalidNoBlob
| robonode_client::AuthenticateError::SignatureInvalid(_)
| robonode_client::AuthenticateError::LogicInternalNoBlob
| robonode_client::AuthenticateError::LogicInternal(_)
| robonode_client::AuthenticateError::UnknownCode(_)
| robonode_client::AuthenticateError::Unknown(_) => None,
},
),
Error::RuntimeApi(err) => {
rpc_error_response::simple(api_error_code::RUNTIME_API, err.to_string())
}
Expand All @@ -66,9 +53,10 @@ where
}

/// Convert a transaction pool error into a human-readable.
fn map_txpool_error<T: sc_transaction_pool_api::error::IntoPoolError>(
err: T,
) -> (String, Option<error_data::BioauthTxErrorDetails>) {
fn map_txpool_error<T>(err: T) -> (String, Option<error_data::BioauthTxErrorDetails>)
where
T: sc_transaction_pool_api::error::IntoPoolError,
{
let err = match err.into_pool_error() {
Ok(err) => err,
Err(err) => {
Expand Down Expand Up @@ -124,6 +112,7 @@ fn map_txpool_error<T: sc_transaction_pool_api::error::IntoPoolError>(
mod tests {

use jsonrpsee::types::ErrorObject;
use rpc_validator_key_logic::Error as ValidatorKeyError;

use super::*;
use crate::errors::sign::Error as SignError;
Expand Down
77 changes: 22 additions & 55 deletions crates/bioauth-flow-rpc/src/errors/authenticate_v2.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! The `authenticate_v2` method error.

use rpc_validator_key_logic::Error as ValidatorKeyError;

use super::{api_error_code, shared};
use super::shared;
use crate::error_data::{self};

/// The `authenticate_v2` method error kinds.
Expand All @@ -11,65 +9,34 @@ pub struct Error(pub shared::FlowBaseError<robonode_client::AuthenticateError>);

impl From<Error> for jsonrpsee::core::Error {
fn from(err: Error) -> Self {
match err.0 {
shared::FlowBaseError::KeyExtraction(err @ ValidatorKeyError::MissingValidatorKey) => {
rpc_error_response::data(
api_error_code::MISSING_VALIDATOR_KEY,
err.to_string(),
rpc_validator_key_logic::error_data::ValidatorKeyNotAvailable,
)
}
shared::FlowBaseError::KeyExtraction(
err @ ValidatorKeyError::ValidatorKeyExtraction,
) => rpc_error_response::simple(
api_error_code::VALIDATOR_KEY_EXTRACTION,
err.to_string(),
),
shared::FlowBaseError::Sign(err) => {
rpc_error_response::simple(api_error_code::SIGN, err.to_string())
}
shared::FlowBaseError::RobonodeClient(
ref err @ robonode_client::Error::Call(
robonode_client::AuthenticateError::PersonNotFound(ref scan_result_blob)
| robonode_client::AuthenticateError::FaceScanRejected(ref scan_result_blob)
| robonode_client::AuthenticateError::SignatureInvalid(ref scan_result_blob)
| robonode_client::AuthenticateError::LogicInternal(ref scan_result_blob),
),
) => rpc_error_response::data(
api_error_code::ROBONODE,
err.to_string(),
error_data::ScanResultBlob(scan_result_blob.clone()),
),
shared::FlowBaseError::RobonodeClient(
err @ robonode_client::Error::Call(
robonode_client::AuthenticateError::FaceScanRejectedNoBlob,
),
) => rpc_error_response::data(
api_error_code::ROBONODE,
err.to_string(),
error_data::ShouldRetry,
),
shared::FlowBaseError::RobonodeClient(
err @ robonode_client::Error::Call(
robonode_client::AuthenticateError::InvalidLivenessData
| robonode_client::AuthenticateError::PersonNotFoundNoBlob
| robonode_client::AuthenticateError::SignatureInvalidNoBlob
| robonode_client::AuthenticateError::LogicInternalNoBlob
| robonode_client::AuthenticateError::UnknownCode(_)
| robonode_client::AuthenticateError::Unknown(_),
),
) => rpc_error_response::simple(api_error_code::ROBONODE, err.to_string()),
shared::FlowBaseError::RobonodeClient(err @ robonode_client::Error::Reqwest(_)) => {
rpc_error_response::simple(api_error_code::ROBONODE, err.to_string())
}
}
err.0
.to_jsonrpsee_error::<_, error_data::BlobOrRetry>(|call_error| match call_error {
robonode_client::AuthenticateError::PersonNotFound(ref scan_result_blob)
| robonode_client::AuthenticateError::FaceScanRejected(ref scan_result_blob)
| robonode_client::AuthenticateError::SignatureInvalid(ref scan_result_blob)
| robonode_client::AuthenticateError::LogicInternal(ref scan_result_blob) => {
Some(error_data::ScanResultBlob(scan_result_blob.clone()).into())
}

robonode_client::AuthenticateError::FaceScanRejectedNoBlob => {
Some(error_data::ShouldRetry.into())
}

robonode_client::AuthenticateError::InvalidLivenessData
| robonode_client::AuthenticateError::PersonNotFoundNoBlob
| robonode_client::AuthenticateError::SignatureInvalidNoBlob
| robonode_client::AuthenticateError::LogicInternalNoBlob
| robonode_client::AuthenticateError::UnknownCode(_)
| robonode_client::AuthenticateError::Unknown(_) => None,
})
}
}

#[cfg(test)]
mod tests {

use jsonrpsee::types::ErrorObject;
use rpc_validator_key_logic::Error as ValidatorKeyError;

use super::*;
use crate::errors::sign::Error as SignError;
Expand Down
52 changes: 19 additions & 33 deletions crates/bioauth-flow-rpc/src/errors/enroll.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! The `enroll` method error.

use rpc_validator_key_logic::Error as ValidatorKeyError;

use super::{api_error_code, shared};
use super::shared;
use crate::error_data;

/// The `enroll` method error kinds.
Expand All @@ -11,43 +9,31 @@ pub struct Error(pub shared::FlowBaseError<robonode_client::EnrollError>);

impl From<Error> for jsonrpsee::core::Error {
fn from(err: Error) -> Self {
match err.0 {
shared::FlowBaseError::KeyExtraction(err @ ValidatorKeyError::MissingValidatorKey) => {
rpc_error_response::data(
api_error_code::MISSING_VALIDATOR_KEY,
err.to_string(),
rpc_validator_key_logic::error_data::ValidatorKeyNotAvailable,
)
}
shared::FlowBaseError::KeyExtraction(
err @ ValidatorKeyError::ValidatorKeyExtraction,
) => rpc_error_response::simple(
api_error_code::VALIDATOR_KEY_EXTRACTION,
err.to_string(),
),
shared::FlowBaseError::RobonodeClient(
err @ robonode_client::Error::Call(
robonode_client::EnrollError::FaceScanRejectedNoBlob,
),
) => rpc_error_response::data(
api_error_code::ROBONODE,
err.to_string(),
error_data::ShouldRetry,
),
shared::FlowBaseError::RobonodeClient(err) => {
rpc_error_response::simple(api_error_code::ROBONODE, err.to_string())
}
shared::FlowBaseError::Sign(err) => {
rpc_error_response::simple(api_error_code::SIGN, err.to_string())
}
}
err.0
.to_jsonrpsee_error::<_, error_data::ShouldRetry>(|call_error| match call_error {
robonode_client::EnrollError::FaceScanRejectedNoBlob
| robonode_client::EnrollError::FaceScanRejected(_) => {
Some(error_data::ShouldRetry)
}

robonode_client::EnrollError::InvalidPublicKey
| robonode_client::EnrollError::InvalidLivenessData
| robonode_client::EnrollError::PublicKeyAlreadyUsed
| robonode_client::EnrollError::PersonAlreadyEnrolledNoBlob
| robonode_client::EnrollError::PersonAlreadyEnrolled(_)
| robonode_client::EnrollError::LogicInternalNoBlob
| robonode_client::EnrollError::LogicInternal(_)
| robonode_client::EnrollError::UnknownCode(_)
| robonode_client::EnrollError::Unknown(_) => None,
})
}
}

#[cfg(test)]
mod tests {

use jsonrpsee::types::ErrorObject;
use rpc_validator_key_logic::Error as ValidatorKeyError;

use super::*;
use crate::errors::sign::Error as SignError;
Expand Down
77 changes: 22 additions & 55 deletions crates/bioauth-flow-rpc/src/errors/enroll_v2.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//! The `enroll_v2` method error.

use rpc_validator_key_logic::Error as ValidatorKeyError;

use super::{api_error_code, shared};
use super::shared;
use crate::error_data;

/// The `enroll_v2` method error kinds.
Expand All @@ -11,65 +9,34 @@ pub struct Error(pub shared::FlowBaseError<robonode_client::EnrollError>);

impl From<Error> for jsonrpsee::core::Error {
fn from(err: Error) -> Self {
match err.0 {
shared::FlowBaseError::KeyExtraction(err @ ValidatorKeyError::MissingValidatorKey) => {
rpc_error_response::data(
api_error_code::MISSING_VALIDATOR_KEY,
err.to_string(),
rpc_validator_key_logic::error_data::ValidatorKeyNotAvailable,
)
}
shared::FlowBaseError::KeyExtraction(
err @ ValidatorKeyError::ValidatorKeyExtraction,
) => rpc_error_response::simple(
api_error_code::VALIDATOR_KEY_EXTRACTION,
err.to_string(),
),
shared::FlowBaseError::RobonodeClient(
ref err @ robonode_client::Error::Call(
robonode_client::EnrollError::FaceScanRejected(ref scan_result_blob)
| robonode_client::EnrollError::PersonAlreadyEnrolled(ref scan_result_blob)
| robonode_client::EnrollError::LogicInternal(ref scan_result_blob),
),
) => rpc_error_response::data(
api_error_code::ROBONODE,
err.to_string(),
error_data::ScanResultBlob(scan_result_blob.clone()),
),
shared::FlowBaseError::RobonodeClient(
err @ robonode_client::Error::Call(
robonode_client::EnrollError::FaceScanRejectedNoBlob,
),
) => rpc_error_response::data(
api_error_code::ROBONODE,
err.to_string(),
error_data::ShouldRetry,
),
shared::FlowBaseError::RobonodeClient(
err @ robonode_client::Error::Call(
robonode_client::EnrollError::InvalidPublicKey
| robonode_client::EnrollError::InvalidLivenessData
| robonode_client::EnrollError::PublicKeyAlreadyUsed
| robonode_client::EnrollError::PersonAlreadyEnrolledNoBlob
| robonode_client::EnrollError::LogicInternalNoBlob
| robonode_client::EnrollError::UnknownCode(_)
| robonode_client::EnrollError::Unknown(_),
),
) => rpc_error_response::simple(api_error_code::ROBONODE, err.to_string()),
shared::FlowBaseError::RobonodeClient(err @ robonode_client::Error::Reqwest(_)) => {
rpc_error_response::simple(api_error_code::ROBONODE, err.to_string())
}
shared::FlowBaseError::Sign(err) => {
rpc_error_response::simple(api_error_code::SIGN, err.to_string())
}
}
err.0
.to_jsonrpsee_error::<_, error_data::BlobOrRetry>(|call_error| match call_error {
robonode_client::EnrollError::FaceScanRejected(ref scan_result_blob)
| robonode_client::EnrollError::PersonAlreadyEnrolled(ref scan_result_blob)
| robonode_client::EnrollError::LogicInternal(ref scan_result_blob) => {
Some(error_data::ScanResultBlob(scan_result_blob.clone()).into())
}

robonode_client::EnrollError::FaceScanRejectedNoBlob => {
Some(error_data::ShouldRetry.into())
}

robonode_client::EnrollError::InvalidPublicKey
| robonode_client::EnrollError::InvalidLivenessData
| robonode_client::EnrollError::PublicKeyAlreadyUsed
| robonode_client::EnrollError::PersonAlreadyEnrolledNoBlob
| robonode_client::EnrollError::LogicInternalNoBlob
| robonode_client::EnrollError::UnknownCode(_)
| robonode_client::EnrollError::Unknown(_) => None,
})
}
}

#[cfg(test)]
mod tests {

use jsonrpsee::types::ErrorObject;
use rpc_validator_key_logic::Error as ValidatorKeyError;

use super::*;
use crate::errors::sign::Error as SignError;
Expand Down
Loading

0 comments on commit 0bd240f

Please sign in to comment.