Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/cargo/once_cell-1.20.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitrylavrenov committed Sep 17, 2024
2 parents c804f8e + e6902a7 commit 4379eb6
Show file tree
Hide file tree
Showing 13 changed files with 863 additions and 205 deletions.
38 changes: 38 additions & 0 deletions crates/bioauth-flow-rpc/src/error_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,44 @@ impl Serialize for ShouldRetry {
}
}

/// The RPC error with scan result blob data.
pub struct ScanResultBlob(pub String);

impl Serialize for ScanResultBlob {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serde_json::json!({ "scanResultBlob": self.0 }).serialize(serializer)
}
}

/// 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
112 changes: 64 additions & 48 deletions crates/bioauth-flow-rpc/src/errors/authenticate.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
//! The `authenticate` method error.

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

use super::{api_error_code, sign::Error as SignError};
use super::{api_error_code, shared};
use crate::error_data::{self, BioauthTxErrorDetails};

/// The `authenticate` method error kinds.
#[derive(Debug)]
pub enum Error<TxPoolError: sc_transaction_pool_api::error::IntoPoolError> {
/// An error that can occur during validator key extraction.
KeyExtraction(ValidatorKeyError),
/// An error that can occur during signing process.
Sign(SignError),
/// An error that can occur during doing a call into robonode.
Robonode(robonode_client::Error<robonode_client::AuthenticateError>),
pub enum Error<TxPoolError> {
/// An error that can occur during doing a request to robonode.
RobonodeRequest(shared::FlowBaseError<robonode_client::AuthenticateError>),
/// An error that can occur during doing a call into runtime api.
RuntimeApi(ApiError),
/// An error that can occur with transaction pool logic.
Expand All @@ -28,32 +23,24 @@ where
{
fn from(err: Error<TxPoolError>) -> Self {
match err {
Error::KeyExtraction(err @ ValidatorKeyError::MissingValidatorKey) => {
rpc_error_response::data(
api_error_code::MISSING_VALIDATOR_KEY,
err.to_string(),
rpc_validator_key_logic::error_data::ValidatorKeyNotAvailable,
)
}
Error::KeyExtraction(err @ ValidatorKeyError::ValidatorKeyExtraction) => {
rpc_error_response::simple(
api_error_code::VALIDATOR_KEY_EXTRACTION,
err.to_string(),
)
}
Error::Sign(err) => rpc_error_response::simple(api_error_code::SIGN, err.to_string()),
Error::Robonode(
err @ robonode_client::Error::Call(
robonode_client::AuthenticateError::FaceScanRejected,
),
) => rpc_error_response::data(
api_error_code::ROBONODE,
err.to_string(),
error_data::ShouldRetry,
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::Robonode(err) => {
rpc_error_response::simple(api_error_code::ROBONODE, err.to_string())
}
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,14 +112,16 @@ 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;

#[test]
fn error_key_extraction_validator_key_extraction() {
let error: jsonrpsee::core::Error =
Error::<sc_transaction_pool_api::error::Error>::KeyExtraction(
ValidatorKeyError::ValidatorKeyExtraction,
Error::<sc_transaction_pool_api::error::Error>::RobonodeRequest(
shared::FlowBaseError::KeyExtraction(ValidatorKeyError::ValidatorKeyExtraction),
)
.into();
let error: ErrorObject = error.into();
Expand All @@ -146,8 +136,8 @@ mod tests {
#[test]
fn error_key_extraction_missing_validator_key() {
let error: jsonrpsee::core::Error =
Error::<sc_transaction_pool_api::error::Error>::KeyExtraction(
ValidatorKeyError::MissingValidatorKey,
Error::<sc_transaction_pool_api::error::Error>::RobonodeRequest(
shared::FlowBaseError::KeyExtraction(ValidatorKeyError::MissingValidatorKey),
)
.into();
let error: ErrorObject = error.into();
Expand All @@ -162,7 +152,10 @@ mod tests {
#[test]
fn error_sign() {
let error: jsonrpsee::core::Error =
Error::<sc_transaction_pool_api::error::Error>::Sign(SignError::SigningFailed).into();
Error::<sc_transaction_pool_api::error::Error>::RobonodeRequest(
shared::FlowBaseError::Sign(SignError::SigningFailed),
)
.into();
let error: ErrorObject = error.into();

let expected_error_message = "{\"code\":100,\"message\":\"signing failed\"}";
Expand All @@ -175,9 +168,11 @@ mod tests {
#[test]
fn error_robonode_face_scan_rejected() {
let error: jsonrpsee::core::Error =
Error::<sc_transaction_pool_api::error::Error>::Robonode(robonode_client::Error::Call(
robonode_client::AuthenticateError::FaceScanRejected,
))
Error::<sc_transaction_pool_api::error::Error>::RobonodeRequest(
shared::FlowBaseError::RobonodeClient(robonode_client::Error::Call(
robonode_client::AuthenticateError::FaceScanRejectedNoBlob,
)),
)
.into();
let error: ErrorObject = error.into();

Expand All @@ -189,12 +184,33 @@ mod tests {
);
}

#[test]
fn error_robonode_logic_internal() {
let error: jsonrpsee::core::Error =
Error::<sc_transaction_pool_api::error::Error>::RobonodeRequest(
shared::FlowBaseError::RobonodeClient(robonode_client::Error::Call(
robonode_client::AuthenticateError::LogicInternalNoBlob,
)),
)
.into();
let error: ErrorObject = error.into();

let expected_error_message =
"{\"code\":200,\"message\":\"server error: logic internal error\"}";
assert_eq!(
expected_error_message,
serde_json::to_string(&error).unwrap()
);
}

#[test]
fn error_robonode_other() {
let error: jsonrpsee::core::Error =
Error::<sc_transaction_pool_api::error::Error>::Robonode(robonode_client::Error::Call(
robonode_client::AuthenticateError::Unknown("test".to_owned()),
))
Error::<sc_transaction_pool_api::error::Error>::RobonodeRequest(
shared::FlowBaseError::RobonodeClient(robonode_client::Error::Call(
robonode_client::AuthenticateError::Unknown("test".to_owned()),
)),
)
.into();
let error: ErrorObject = error.into();

Expand Down
140 changes: 140 additions & 0 deletions crates/bioauth-flow-rpc/src/errors/authenticate_v2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
//! The `authenticate_v2` method error.

use super::shared;
use crate::error_data;

/// The `authenticate_v2` method error kinds.
#[derive(Debug)]
pub struct Error(pub shared::FlowBaseError<robonode_client::AuthenticateError>);

impl From<Error> for jsonrpsee::core::Error {
fn from(err: Error) -> Self {
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;

#[test]
fn error_key_extraction_validator_key_extraction() {
let error: jsonrpsee::core::Error = Error(shared::FlowBaseError::KeyExtraction(
ValidatorKeyError::ValidatorKeyExtraction,
))
.into();
let error: ErrorObject = error.into();

let expected_error_message = "{\"code\":600,\"message\":\"unable to extract own key\"}";
assert_eq!(
expected_error_message,
serde_json::to_string(&error).unwrap()
);
}

#[test]
fn error_key_extraction_missing_validator_key() {
let error: jsonrpsee::core::Error = Error(shared::FlowBaseError::KeyExtraction(
ValidatorKeyError::MissingValidatorKey,
))
.into();
let error: ErrorObject = error.into();

let expected_error_message = "{\"code\":500,\"message\":\"validator key not available\",\"data\":{\"validatorKeyNotAvailable\":true}}";
assert_eq!(
expected_error_message,
serde_json::to_string(&error).unwrap()
);
}

#[test]
fn error_sign() {
let error: jsonrpsee::core::Error =
Error(shared::FlowBaseError::Sign(SignError::SigningFailed)).into();
let error: ErrorObject = error.into();

let expected_error_message = "{\"code\":100,\"message\":\"signing failed\"}";
assert_eq!(
expected_error_message,
serde_json::to_string(&error).unwrap()
);
}

#[test]
fn error_robonode_face_scan_rejected() {
let error: jsonrpsee::core::Error = Error(shared::FlowBaseError::RobonodeClient(
robonode_client::Error::Call(robonode_client::AuthenticateError::FaceScanRejected(
"scan result blob".to_owned(),
)),
))
.into();
let error: ErrorObject = error.into();

let expected_error_message =
"{\"code\":200,\"message\":\"server error: face scan rejected\",\"data\":{\"scanResultBlob\":\"scan result blob\"}}";
assert_eq!(
expected_error_message,
serde_json::to_string(&error).unwrap()
);
}

#[test]
fn error_robonode_logic_internal() {
let error: jsonrpsee::core::Error = Error(shared::FlowBaseError::RobonodeClient(
robonode_client::Error::Call(robonode_client::AuthenticateError::LogicInternal(
"scan result blob".to_owned(),
)),
))
.into();
let error: ErrorObject = error.into();

let expected_error_message =
"{\"code\":200,\"message\":\"server error: logic internal error\",\"data\":{\"scanResultBlob\":\"scan result blob\"}}";
assert_eq!(
expected_error_message,
serde_json::to_string(&error).unwrap()
);
}

#[test]
fn error_robonode_other() {
let error: jsonrpsee::core::Error = Error(shared::FlowBaseError::RobonodeClient(
robonode_client::Error::Call(robonode_client::AuthenticateError::Unknown(
"test".to_owned(),
)),
))
.into();
let error: ErrorObject = error.into();

let expected_error_message =
"{\"code\":200,\"message\":\"server error: unknown error: test\"}";
assert_eq!(
expected_error_message,
serde_json::to_string(&error).unwrap()
);
}
}
Loading

0 comments on commit 4379eb6

Please sign in to comment.