From 8b0361a4456cad8fb9f010c40ecfdfa8dd5683a0 Mon Sep 17 00:00:00 2001 From: dmitrylavrenov Date: Thu, 19 Aug 2021 17:37:45 +0400 Subject: [PATCH 01/11] Tratify logic for robonode transport layer --- Cargo.lock | 2 + crates/robonode-server/Cargo.toml | 2 + crates/robonode-server/src/http/filters.rs | 41 +++++++++---------- crates/robonode-server/src/http/handlers.rs | 32 +++++++-------- crates/robonode-server/src/http/mod.rs | 1 + crates/robonode-server/src/http/traits.rs | 30 ++++++++++++++ .../src/logic/op_authenticate.rs | 7 ++-- crates/robonode-server/src/logic/op_enroll.rs | 5 ++- .../logic/op_get_facetec_device_sdk_params.rs | 5 ++- .../src/logic/op_get_facetec_session_token.rs | 5 ++- crates/robonode-server/src/logic/tests.rs | 6 ++- 11 files changed, 86 insertions(+), 50 deletions(-) create mode 100644 crates/robonode-server/src/http/traits.rs diff --git a/Cargo.lock b/Cargo.lock index 6b6f1a585..a1a0d43f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5450,6 +5450,7 @@ dependencies = [ "async-trait", "facetec-api-client", "hex", + "mockall", "primitives-auth-ticket", "primitives-liveness-data", "rand 0.7.3", @@ -5457,6 +5458,7 @@ dependencies = [ "robonode-crypto", "sc-tracing 3.0.0", "serde", + "serde_json", "sp-application-crypto", "tokio 1.9.0", "tracing", diff --git a/crates/robonode-server/Cargo.toml b/crates/robonode-server/Cargo.toml index 5a7e2997b..d01458303 100644 --- a/crates/robonode-server/Cargo.toml +++ b/crates/robonode-server/Cargo.toml @@ -24,6 +24,8 @@ uuid = { version = "0.8", features = ["v4"] } warp = "0.3" [dev-dependencies] +mockall = "0.10" +serde_json = "1" tracing-test = "0.1" [features] diff --git a/crates/robonode-server/src/http/filters.rs b/crates/robonode-server/src/http/filters.rs index c67eb86d6..799e4216e 100644 --- a/crates/robonode-server/src/http/filters.rs +++ b/crates/robonode-server/src/http/filters.rs @@ -1,14 +1,16 @@ //! Filters, essentially how [`warp`] implements routes and middlewares. -use std::{convert::TryFrom, sync::Arc}; +use std::sync::Arc; use warp::Filter; use crate::{ http::handlers, - logic::{op_authenticate, op_enroll, Logic, Signer, Verifier}, + logic::{op_authenticate, op_enroll}, }; +use super::traits::{Authenticate, Enroll, GetFacetecDeviceSdkParams, GetFacetecSessionToken}; + /// Pass the [`Arc`] to the handler. fn with_arc( val: Arc, @@ -30,12 +32,11 @@ where } /// The root mount point with all the routes. -pub fn root( - logic: Arc>, +pub fn root( + logic: Arc, ) -> impl Filter + Clone where - S: Signer> + Send + Sync + 'static, - PK: Send + Sync + for<'a> TryFrom<&'a [u8]> + AsRef<[u8]> + Verifier> + Into>, + L: Enroll + Authenticate + GetFacetecSessionToken + GetFacetecDeviceSdkParams + Send + Sync, { enroll(Arc::clone(&logic)) .or(authenticate(Arc::clone(&logic))) @@ -44,12 +45,11 @@ where } /// POST /enroll with JSON body. -fn enroll( - logic: Arc>, +fn enroll( + logic: Arc, ) -> impl Filter + Clone where - S: Signer> + Send + 'static, - PK: Send + for<'a> TryFrom<&'a [u8]> + AsRef<[u8]>, + L: Enroll + Authenticate + GetFacetecSessionToken + GetFacetecDeviceSdkParams + Send + Sync, { warp::path!("enroll") .and(warp::post()) @@ -59,12 +59,11 @@ where } /// POST /authenticate with JSON body. -fn authenticate( - logic: Arc>, +fn authenticate( + logic: Arc, ) -> impl Filter + Clone where - S: Signer> + Send + Sync + 'static, - PK: Send + Sync + for<'a> TryFrom<&'a [u8]> + AsRef<[u8]> + Verifier> + Into>, + L: Enroll + Authenticate + GetFacetecSessionToken + GetFacetecDeviceSdkParams + Send + Sync, { warp::path!("authenticate") .and(warp::post()) @@ -74,12 +73,11 @@ where } /// GET /facetec-session-token. -fn get_facetec_session_token( - logic: Arc>, +fn get_facetec_session_token( + logic: Arc, ) -> impl Filter + Clone where - S: Signer> + Send + 'static, - PK: Send + for<'a> TryFrom<&'a [u8]>, + L: Enroll + Authenticate + GetFacetecSessionToken + GetFacetecDeviceSdkParams + Send + Sync, { warp::path!("facetec-session-token") .and(warp::get()) @@ -88,12 +86,11 @@ where } /// GET /facetec-device-sdk-params. -fn get_facetec_device_sdk_params( - logic: Arc>, +fn get_facetec_device_sdk_params( + logic: Arc, ) -> impl Filter + Clone where - S: Signer> + Send + 'static, - PK: Send + for<'a> TryFrom<&'a [u8]>, + L: Enroll + Authenticate + GetFacetecSessionToken + GetFacetecDeviceSdkParams + Send + Sync, { warp::path!("facetec-device-sdk-params") .and(warp::get()) diff --git a/crates/robonode-server/src/http/handlers.rs b/crates/robonode-server/src/http/handlers.rs index 3896e1a43..36decc8aa 100644 --- a/crates/robonode-server/src/http/handlers.rs +++ b/crates/robonode-server/src/http/handlers.rs @@ -1,35 +1,33 @@ //! Handlers, the HTTP transport coupling for the internal logic. -use std::{convert::TryFrom, sync::Arc}; +use std::sync::Arc; use warp::hyper::StatusCode; use warp::Reply; +use super::traits::{Authenticate, Enroll, GetFacetecDeviceSdkParams, GetFacetecSessionToken}; use crate::logic::{ op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, - Logic, Signer, Verifier, }; /// Enroll operation HTTP transport coupling. -pub async fn enroll( - logic: Arc>, +pub async fn enroll( + logic: Arc, input: op_enroll::Request, ) -> Result where - S: Signer> + Send + 'static, - PK: Send + for<'a> TryFrom<&'a [u8]> + AsRef<[u8]>, + L: Enroll, { logic.enroll(input).await.map_err(warp::reject::custom)?; Ok(StatusCode::CREATED) } /// Authenticate operation HTTP transport coupling. -pub async fn authenticate( - logic: Arc>, +pub async fn authenticate( + logic: Arc, input: op_authenticate::Request, ) -> Result where - S: Signer> + Send + 'static, - PK: Send + Sync + for<'a> TryFrom<&'a [u8]> + Verifier> + Into>, + L: Authenticate, { let res = logic .authenticate(input) @@ -42,12 +40,11 @@ where } /// Get FaceTec Session Token operation HTTP transport coupling. -pub async fn get_facetec_session_token( - logic: Arc>, +pub async fn get_facetec_session_token( + logic: Arc, ) -> Result where - S: Signer> + Send + 'static, - PK: Send + for<'a> TryFrom<&'a [u8]>, + L: GetFacetecSessionToken, { let res = logic .get_facetec_session_token() @@ -60,12 +57,11 @@ where } /// Get FaceTec Device SDK Params operation HTTP transport coupling. -pub async fn get_facetec_device_sdk_params( - logic: Arc>, +pub async fn get_facetec_device_sdk_params( + logic: Arc, ) -> Result where - S: Signer> + Send + 'static, - PK: Send + for<'a> TryFrom<&'a [u8]>, + L: GetFacetecDeviceSdkParams, { let res = logic .get_facetec_device_sdk_params() diff --git a/crates/robonode-server/src/http/mod.rs b/crates/robonode-server/src/http/mod.rs index 4b8610cd8..22dccd427 100644 --- a/crates/robonode-server/src/http/mod.rs +++ b/crates/robonode-server/src/http/mod.rs @@ -2,5 +2,6 @@ mod filters; mod handlers; +pub mod traits; pub use filters::root; diff --git a/crates/robonode-server/src/http/traits.rs b/crates/robonode-server/src/http/traits.rs new file mode 100644 index 000000000..db97acd18 --- /dev/null +++ b/crates/robonode-server/src/http/traits.rs @@ -0,0 +1,30 @@ +use crate::logic::{ + op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, +}; + +#[async_trait::async_trait] +pub trait Enroll { + async fn enroll(&self, req: op_enroll::Request) -> Result<(), op_enroll::Error>; +} + +#[async_trait::async_trait] +pub trait Authenticate { + async fn authenticate( + &self, + req: op_authenticate::Request, + ) -> Result; +} + +#[async_trait::async_trait] +pub trait GetFacetecSessionToken { + async fn get_facetec_session_token( + &self, + ) -> Result; +} + +#[async_trait::async_trait] +pub trait GetFacetecDeviceSdkParams { + async fn get_facetec_device_sdk_params( + &self, + ) -> Result; +} diff --git a/crates/robonode-server/src/logic/op_authenticate.rs b/crates/robonode-server/src/logic/op_authenticate.rs index fed55f365..1db090417 100644 --- a/crates/robonode-server/src/logic/op_authenticate.rs +++ b/crates/robonode-server/src/logic/op_authenticate.rs @@ -79,13 +79,14 @@ pub enum Error { InternalErrorAuthTicketSigningFailed, } -impl Logic +#[async_trait::async_trait] +impl crate::http::traits::Authenticate for Logic where - S: Signer> + Send + 'static, + S: Signer> + Send + 'static + Sync, PK: Send + Sync + for<'a> TryFrom<&'a [u8]> + Verifier> + Into>, { /// An authenticate invocation handler. - pub async fn authenticate(&self, req: Request) -> Result { + async fn authenticate(&self, req: Request) -> Result { let liveness_data = LivenessData::try_from(&req.liveness_data).map_err(Error::InvalidLivenessData)?; diff --git a/crates/robonode-server/src/logic/op_enroll.rs b/crates/robonode-server/src/logic/op_enroll.rs index 96893e525..6617192ce 100644 --- a/crates/robonode-server/src/logic/op_enroll.rs +++ b/crates/robonode-server/src/logic/op_enroll.rs @@ -54,13 +54,14 @@ pub enum Error { InternalErrorDbEnrollUnsuccessful, } -impl Logic +#[async_trait::async_trait] +impl crate::http::traits::Enroll for Logic where S: Signer> + Send + 'static, PK: Send + for<'a> TryFrom<&'a [u8]> + AsRef<[u8]>, { /// An enroll invocation handler. - pub async fn enroll(&self, req: Request) -> Result<(), Error> { + async fn enroll(&self, req: Request) -> Result<(), Error> { let public_key = PK::try_from(&req.public_key).map_err(|_| Error::InvalidPublicKey)?; let liveness_data = diff --git a/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs b/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs index 0a780529e..0d4ff5143 100644 --- a/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs +++ b/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs @@ -20,13 +20,14 @@ pub struct Response { #[derive(Debug)] pub enum Error {} -impl Logic +#[async_trait::async_trait] +impl crate::http::traits::GetFacetecDeviceSdkParams for Logic where S: Signer> + Send + 'static, PK: Send + for<'a> TryFrom<&'a [u8]>, { /// Get the FaceTec Device SDK params. - pub async fn get_facetec_device_sdk_params(&self) -> Result { + async fn get_facetec_device_sdk_params(&self) -> Result { Ok(Response { device_key_identifier: self.facetec_device_sdk_params.device_key_identifier.clone(), public_face_map_encryption_key: self diff --git a/crates/robonode-server/src/logic/op_get_facetec_session_token.rs b/crates/robonode-server/src/logic/op_get_facetec_session_token.rs index b452ff499..6b16c16a4 100644 --- a/crates/robonode-server/src/logic/op_get_facetec_session_token.rs +++ b/crates/robonode-server/src/logic/op_get_facetec_session_token.rs @@ -25,13 +25,14 @@ pub enum Error { InternalErrorSessionTokenUnsuccessful, } -impl Logic +#[async_trait::async_trait] +impl crate::http::traits::GetFacetecSessionToken for Logic where S: Signer> + Send + 'static, PK: Send + for<'a> TryFrom<&'a [u8]>, { /// Get a FaceTec Session Token. - pub async fn get_facetec_session_token(&self) -> Result { + async fn get_facetec_session_token(&self) -> Result { let unlocked = self.locked.lock().await; let res = unlocked diff --git a/crates/robonode-server/src/logic/tests.rs b/crates/robonode-server/src/logic/tests.rs index 0d469014f..7b2c31104 100644 --- a/crates/robonode-server/src/logic/tests.rs +++ b/crates/robonode-server/src/logic/tests.rs @@ -7,7 +7,11 @@ use primitives_liveness_data::{LivenessData, OpaqueLivenessData}; use tokio::sync::{Mutex, MutexGuard}; use tracing::{info, trace}; -use crate::{logic::common::DB_GROUP_NAME, sequence::Sequence}; +use crate::{ + http::traits::{Authenticate, Enroll}, + logic::common::DB_GROUP_NAME, + sequence::Sequence, +}; use super::{Locked, Logic}; From a233d1f25c7f0c7a2d97ce0b057fa100049073f3 Mon Sep 17 00:00:00 2001 From: dmitrylavrenov Date: Mon, 23 Aug 2021 15:52:22 +0400 Subject: [PATCH 02/11] Implement unit tests for robonode transport layer with mocked logic --- crates/robonode-server/src/http/mod.rs | 3 + crates/robonode-server/src/http/tests.rs | 247 ++++++++++++++++++ crates/robonode-server/src/http/traits.rs | 10 + .../src/logic/op_authenticate.rs | 2 +- crates/robonode-server/src/logic/op_enroll.rs | 4 +- 5 files changed, 263 insertions(+), 3 deletions(-) create mode 100644 crates/robonode-server/src/http/tests.rs diff --git a/crates/robonode-server/src/http/mod.rs b/crates/robonode-server/src/http/mod.rs index 22dccd427..88a2b81d7 100644 --- a/crates/robonode-server/src/http/mod.rs +++ b/crates/robonode-server/src/http/mod.rs @@ -4,4 +4,7 @@ mod filters; mod handlers; pub mod traits; +#[cfg(test)] +mod tests; + pub use filters::root; diff --git a/crates/robonode-server/src/http/tests.rs b/crates/robonode-server/src/http/tests.rs new file mode 100644 index 000000000..1b8dda419 --- /dev/null +++ b/crates/robonode-server/src/http/tests.rs @@ -0,0 +1,247 @@ +use std::sync::Arc; + +use mockall::predicate::*; +use mockall::*; +use primitives_auth_ticket::OpaqueAuthTicket; +use primitives_liveness_data::OpaqueLivenessData; +use sp_application_crypto::sp_core::hexdisplay::AsBytesRef; +use warp::hyper::StatusCode; + +use crate::{ + http::root, + logic::{ + op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, + }, +}; + +use super::traits::{Authenticate, Enroll, GetFacetecDeviceSdkParams, GetFacetecSessionToken}; + +mock! { + Logic { + fn enroll(&self, req: op_enroll::Request) -> Result<(), op_enroll::Error>; + fn authenticate(&self, req: op_authenticate::Request) -> Result; + fn get_facetec_session_token(&self) -> Result; + fn get_facetec_device_sdk_params(&self) -> Result; + } +} + +#[async_trait::async_trait] +impl Enroll for MockLogic { + async fn enroll(&self, req: op_enroll::Request) -> Result<(), op_enroll::Error> { + self.enroll(req) + } +} + +#[async_trait::async_trait] +impl Authenticate for MockLogic { + async fn authenticate( + &self, + req: op_authenticate::Request, + ) -> Result { + self.authenticate(req) + } +} + +#[async_trait::async_trait] +impl GetFacetecSessionToken for MockLogic { + async fn get_facetec_session_token( + &self, + ) -> Result { + self.get_facetec_session_token() + } +} + +#[async_trait::async_trait] +impl GetFacetecDeviceSdkParams for MockLogic { + async fn get_facetec_device_sdk_params( + &self, + ) -> Result + { + self.get_facetec_device_sdk_params() + } +} + +fn provide_authenticate_response() -> op_authenticate::Response { + op_authenticate::Response { + auth_ticket: OpaqueAuthTicket(b"ticket".to_vec()), + auth_ticket_signature: b"signature".to_vec(), + } +} + +fn provide_facetec_session_token() -> op_get_facetec_session_token::Response { + op_get_facetec_session_token::Response { + session_token: "token".to_owned(), + } +} + +fn provide_facetec_device_sdk_params() -> op_get_facetec_device_sdk_params::Response { + op_get_facetec_device_sdk_params::Response { + public_face_map_encryption_key: "key".to_owned(), + device_key_identifier: "id".to_owned(), + } +} + +#[tokio::test] +async fn it_works_enroll() { + let input = op_enroll::Request { + public_key: b"key".to_vec(), + liveness_data: OpaqueLivenessData(b"data".to_vec()), + }; + + let mut mock_logic = MockLogic::new(); + mock_logic.expect_enroll().returning(|_| Ok(())); + + let logic = Arc::new(mock_logic); + let filter = root(logic); + + let res = warp::test::request() + .method("POST") + .path("/enroll") + .json(&input) + .reply(&filter) + .await; + + assert_eq!(res.status(), StatusCode::CREATED); + assert!(res.body().is_empty()); +} + +#[tokio::test] +async fn it_denies_enroll_with_invalid_public_key() { + let input = op_enroll::Request { + public_key: b"key".to_vec(), + liveness_data: OpaqueLivenessData(b"data".to_vec()), + }; + + let mut mock_logic = MockLogic::new(); + mock_logic + .expect_enroll() + .returning(|_| Err(op_enroll::Error::InvalidPublicKey)); + + let logic = Arc::new(mock_logic); + let filter = root(logic); + + let res = warp::test::request() + .method("POST") + .path("/enroll") + .json(&input) + .reply(&filter) + .await; + + assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR); +} + +#[tokio::test] +async fn it_works_authenticate() { + let input = op_authenticate::Request { + liveness_data: OpaqueLivenessData(b"data".to_vec()), + liveness_data_signature: b"signature".to_vec(), + }; + + let mut mock_logic = MockLogic::new(); + mock_logic + .expect_authenticate() + .returning(|_| Ok(provide_authenticate_response())); + + let logic = Arc::new(mock_logic); + let filter = root(logic); + + let res = warp::test::request() + .method("POST") + .path("/authenticate") + .json(&input) + .reply(&filter) + .await; + + let expected_response = serde_json::to_string(&provide_authenticate_response()).unwrap(); + + assert_eq!(res.status(), StatusCode::OK); + assert_eq!(res.body().as_bytes_ref(), expected_response.as_bytes()); +} + +#[tokio::test] +async fn it_denies_authenticate() { + let input = op_authenticate::Request { + liveness_data: OpaqueLivenessData(b"data".to_vec()), + liveness_data_signature: b"signature".to_vec(), + }; + + let mut mock_logic = MockLogic::new(); + mock_logic + .expect_authenticate() + .returning(|_| Err(op_authenticate::Error::InternalErrorDbSearchUnsuccessful)); + + let logic = Arc::new(mock_logic); + let filter = root(logic); + + let res = warp::test::request() + .method("POST") + .path("/enroll") + .json(&input) + .reply(&filter) + .await; + + assert_eq!(res.status(), StatusCode::BAD_REQUEST); +} + +#[tokio::test] +async fn it_works_get_facetec_session_token() { + let mut mock_logic = MockLogic::new(); + mock_logic + .expect_get_facetec_session_token() + .returning(|| Ok(provide_facetec_session_token())); + + let logic = Arc::new(mock_logic); + let filter = root(logic); + + let res = warp::test::request() + .method("GET") + .path("/facetec-session-token") + .reply(&filter) + .await; + + let expected_response = serde_json::to_string(&provide_facetec_session_token()).unwrap(); + + assert_eq!(res.status(), StatusCode::OK); + assert_eq!(res.body().as_bytes_ref(), expected_response.as_bytes()); +} + +#[tokio::test] +async fn it_denies_get_facetec_session_token() { + let mut mock_logic = MockLogic::new(); + mock_logic.expect_get_facetec_session_token().returning(|| { + Err(op_get_facetec_session_token::Error::InternalErrorSessionTokenUnsuccessful) + }); + + let logic = Arc::new(mock_logic); + let filter = root(logic); + + let res = warp::test::request() + .method("GET") + .path("/facetec-session-token") + .reply(&filter) + .await; + + assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR); +} + +#[tokio::test] +async fn it_works_get_facetec_device_sdk_params() { + let mut mock_logic = MockLogic::new(); + mock_logic + .expect_get_facetec_device_sdk_params() + .returning(|| Ok(provide_facetec_device_sdk_params())); + + let logic = Arc::new(mock_logic); + let filter = root(logic); + + let res = warp::test::request() + .method("GET") + .path("/facetec-device-sdk-params") + .reply(&filter) + .await; + + let expected_response = serde_json::to_string(&provide_facetec_device_sdk_params()).unwrap(); + + assert_eq!(res.status(), StatusCode::OK); + assert_eq!(res.body().as_bytes_ref(), expected_response.as_bytes()); +} diff --git a/crates/robonode-server/src/http/traits.rs b/crates/robonode-server/src/http/traits.rs index db97acd18..d948ba9a6 100644 --- a/crates/robonode-server/src/http/traits.rs +++ b/crates/robonode-server/src/http/traits.rs @@ -1,29 +1,39 @@ +//! The logic-related traits. + use crate::logic::{ op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, }; +/// The trait to make enroll operation. #[async_trait::async_trait] pub trait Enroll { + /// Process Enroll request. async fn enroll(&self, req: op_enroll::Request) -> Result<(), op_enroll::Error>; } +/// The trait to make authenticate operation. #[async_trait::async_trait] pub trait Authenticate { + /// Process Authenticate request. async fn authenticate( &self, req: op_authenticate::Request, ) -> Result; } +/// The trait to make get facetec session token operation. #[async_trait::async_trait] pub trait GetFacetecSessionToken { + /// Process GetFacetecSessionToken request. async fn get_facetec_session_token( &self, ) -> Result; } +/// The trait to make get facetec device sdk params operation. #[async_trait::async_trait] pub trait GetFacetecDeviceSdkParams { + /// Process GetFacetecDeviceSdkParams request. async fn get_facetec_device_sdk_params( &self, ) -> Result; diff --git a/crates/robonode-server/src/logic/op_authenticate.rs b/crates/robonode-server/src/logic/op_authenticate.rs index 1db090417..bb71140c6 100644 --- a/crates/robonode-server/src/logic/op_authenticate.rs +++ b/crates/robonode-server/src/logic/op_authenticate.rs @@ -14,7 +14,7 @@ use crate::logic::facetec_utils::{db_search_result_adapter, DbSearchResult}; use super::{common::*, Logic, Signer, Verifier}; /// The request of the authenticate operation. -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Request { /// The liveness data that the validator owner provided. diff --git a/crates/robonode-server/src/logic/op_enroll.rs b/crates/robonode-server/src/logic/op_enroll.rs index 6617192ce..27f6e085a 100644 --- a/crates/robonode-server/src/logic/op_enroll.rs +++ b/crates/robonode-server/src/logic/op_enroll.rs @@ -4,7 +4,7 @@ use std::convert::TryFrom; use facetec_api_client as ft; use primitives_liveness_data::{LivenessData, OpaqueLivenessData}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use tracing::{error, trace}; use crate::logic::facetec_utils::{db_search_result_adapter, DbSearchResult}; @@ -12,7 +12,7 @@ use crate::logic::facetec_utils::{db_search_result_adapter, DbSearchResult}; use super::{common::*, Logic, Signer}; /// The request for the enroll operation. -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Request { /// The public key of the validator. From 1c44ed1879dfa30da21de90ef95c5b6d84115c41 Mon Sep 17 00:00:00 2001 From: dmitrylavrenov Date: Tue, 24 Aug 2021 15:17:47 +0400 Subject: [PATCH 03/11] Remove redundant traits at filters enroll function --- crates/robonode-server/src/http/filters.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/robonode-server/src/http/filters.rs b/crates/robonode-server/src/http/filters.rs index 799e4216e..1c908ff52 100644 --- a/crates/robonode-server/src/http/filters.rs +++ b/crates/robonode-server/src/http/filters.rs @@ -49,7 +49,7 @@ fn enroll( logic: Arc, ) -> impl Filter + Clone where - L: Enroll + Authenticate + GetFacetecSessionToken + GetFacetecDeviceSdkParams + Send + Sync, + L: Enroll + Send + Sync, { warp::path!("enroll") .and(warp::post()) From bcce929706f9cd883302aef936094b51e6c601e1 Mon Sep 17 00:00:00 2001 From: dmitrylavrenov Date: Tue, 7 Sep 2021 19:33:05 +0300 Subject: [PATCH 04/11] Generalize logic operations with our own generic trait --- Cargo.lock | 21 ++++++ crates/robonode-server/Cargo.toml | 2 + crates/robonode-server/src/http/filters.rs | 43 ++++++++++-- crates/robonode-server/src/http/handlers.rs | 29 ++++---- crates/robonode-server/src/http/tests.rs | 69 ++++++++++++------- crates/robonode-server/src/http/traits.rs | 45 +++--------- .../src/logic/op_authenticate.rs | 8 ++- crates/robonode-server/src/logic/op_enroll.rs | 7 +- .../logic/op_get_facetec_device_sdk_params.rs | 15 ++-- .../src/logic/op_get_facetec_session_token.rs | 15 ++-- crates/robonode-server/src/logic/tests.rs | 18 ++--- 11 files changed, 169 insertions(+), 103 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1a0d43f3..93f0166f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5449,6 +5449,7 @@ version = "0.1.0" dependencies = [ "async-trait", "facetec-api-client", + "futures 0.3.16", "hex", "mockall", "primitives-auth-ticket", @@ -5461,6 +5462,7 @@ dependencies = [ "serde_json", "sp-application-crypto", "tokio 1.9.0", + "tower", "tracing", "tracing-test", "uuid", @@ -8194,6 +8196,25 @@ dependencies = [ "serde", ] +[[package]] +name = "tower" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60422bc7fefa2f3ec70359b8ff1caff59d785877eb70595904605bcc412470f" +dependencies = [ + "futures-core", + "pin-project 1.0.8", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" + [[package]] name = "tower-service" version = "0.3.1" diff --git a/crates/robonode-server/Cargo.toml b/crates/robonode-server/Cargo.toml index d01458303..cafdb09f7 100644 --- a/crates/robonode-server/Cargo.toml +++ b/crates/robonode-server/Cargo.toml @@ -12,6 +12,7 @@ primitives-liveness-data = { version = "0.1", path = "../primitives-liveness-dat robonode-crypto = { version = "0.1", path = "../robonode-crypto" } async-trait = "0.1" +futures = "0.3" hex = "0.4" rand = "0.7" reqwest = "0.11" @@ -19,6 +20,7 @@ sc-tracing = "3" serde = { version = "1", features = ["derive"] } sp-application-crypto = { git = "https://github.com/humanode-network/substrate", branch = "master" } tokio = { version = "1", features = ["full"] } +tower = "0.4" tracing = "0.1" uuid = { version = "0.8", features = ["v4"] } warp = "0.3" diff --git a/crates/robonode-server/src/http/filters.rs b/crates/robonode-server/src/http/filters.rs index 1c908ff52..7835ac620 100644 --- a/crates/robonode-server/src/http/filters.rs +++ b/crates/robonode-server/src/http/filters.rs @@ -2,14 +2,17 @@ use std::sync::Arc; +use serde::Serialize; use warp::Filter; use crate::{ http::handlers, - logic::{op_authenticate, op_enroll}, + logic::{ + op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, + }, }; -use super::traits::{Authenticate, Enroll, GetFacetecDeviceSdkParams, GetFacetecSessionToken}; +use super::traits::LogicOp; /// Pass the [`Arc`] to the handler. fn with_arc( @@ -36,7 +39,26 @@ pub fn root( logic: Arc, ) -> impl Filter + Clone where - L: Enroll + Authenticate + GetFacetecSessionToken + GetFacetecDeviceSdkParams + Send + Sync, + L: LogicOp + + LogicOp + + LogicOp + + LogicOp + + Send + + Sync, + >::Error: + warp::reject::Reject, + >::Error: + warp::reject::Reject, + >::Response: + Serialize, + >::Error: + warp::reject::Reject, + >::Response: + Serialize, + >::Error: + warp::reject::Reject, + >::Response: + Serialize, { enroll(Arc::clone(&logic)) .or(authenticate(Arc::clone(&logic))) @@ -49,7 +71,8 @@ fn enroll( logic: Arc, ) -> impl Filter + Clone where - L: Enroll + Send + Sync, + L: LogicOp + Send + Sync, + L::Error: warp::reject::Reject, { warp::path!("enroll") .and(warp::post()) @@ -63,7 +86,9 @@ fn authenticate( logic: Arc, ) -> impl Filter + Clone where - L: Enroll + Authenticate + GetFacetecSessionToken + GetFacetecDeviceSdkParams + Send + Sync, + L: LogicOp + Send + Sync, + L::Error: warp::reject::Reject, + L::Response: Serialize, { warp::path!("authenticate") .and(warp::post()) @@ -77,7 +102,9 @@ fn get_facetec_session_token( logic: Arc, ) -> impl Filter + Clone where - L: Enroll + Authenticate + GetFacetecSessionToken + GetFacetecDeviceSdkParams + Send + Sync, + L: LogicOp + Send + Sync, + L::Error: warp::reject::Reject, + L::Response: Serialize, { warp::path!("facetec-session-token") .and(warp::get()) @@ -90,7 +117,9 @@ fn get_facetec_device_sdk_params( logic: Arc, ) -> impl Filter + Clone where - L: Enroll + Authenticate + GetFacetecSessionToken + GetFacetecDeviceSdkParams + Send + Sync, + L: LogicOp + Send + Sync, + L::Error: warp::reject::Reject, + L::Response: Serialize, { warp::path!("facetec-device-sdk-params") .and(warp::get()) diff --git a/crates/robonode-server/src/http/handlers.rs b/crates/robonode-server/src/http/handlers.rs index 36decc8aa..211bae58c 100644 --- a/crates/robonode-server/src/http/handlers.rs +++ b/crates/robonode-server/src/http/handlers.rs @@ -1,10 +1,11 @@ //! Handlers, the HTTP transport coupling for the internal logic. +use serde::Serialize; use std::sync::Arc; use warp::hyper::StatusCode; use warp::Reply; -use super::traits::{Authenticate, Enroll, GetFacetecDeviceSdkParams, GetFacetecSessionToken}; +use super::traits::LogicOp; use crate::logic::{ op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, }; @@ -15,9 +16,10 @@ pub async fn enroll( input: op_enroll::Request, ) -> Result where - L: Enroll, + L: LogicOp, + L::Error: warp::reject::Reject, { - logic.enroll(input).await.map_err(warp::reject::custom)?; + logic.call(input).await.map_err(warp::reject::custom)?; Ok(StatusCode::CREATED) } @@ -27,12 +29,11 @@ pub async fn authenticate( input: op_authenticate::Request, ) -> Result where - L: Authenticate, + L: LogicOp, + L::Error: warp::reject::Reject, + L::Response: Serialize, { - let res = logic - .authenticate(input) - .await - .map_err(warp::reject::custom)?; + let res = logic.call(input).await.map_err(warp::reject::custom)?; let reply = warp::reply::json(&res); let reply = warp::reply::with_status(reply, StatusCode::OK); @@ -44,10 +45,12 @@ pub async fn get_facetec_session_token( logic: Arc, ) -> Result where - L: GetFacetecSessionToken, + L: LogicOp, + L::Error: warp::reject::Reject, + L::Response: Serialize, { let res = logic - .get_facetec_session_token() + .call(op_get_facetec_session_token::Request {}) .await .map_err(warp::reject::custom)?; @@ -61,10 +64,12 @@ pub async fn get_facetec_device_sdk_params( logic: Arc, ) -> Result where - L: GetFacetecDeviceSdkParams, + L: LogicOp, + L::Error: warp::reject::Reject, + L::Response: Serialize, { let res = logic - .get_facetec_device_sdk_params() + .call(op_get_facetec_device_sdk_params::Request {}) .await .map_err(warp::reject::custom)?; diff --git a/crates/robonode-server/src/http/tests.rs b/crates/robonode-server/src/http/tests.rs index 1b8dda419..44f334969 100644 --- a/crates/robonode-server/src/http/tests.rs +++ b/crates/robonode-server/src/http/tests.rs @@ -14,50 +14,60 @@ use crate::{ }, }; -use super::traits::{Authenticate, Enroll, GetFacetecDeviceSdkParams, GetFacetecSessionToken}; +use super::traits::LogicOp; mock! { Logic { fn enroll(&self, req: op_enroll::Request) -> Result<(), op_enroll::Error>; fn authenticate(&self, req: op_authenticate::Request) -> Result; - fn get_facetec_session_token(&self) -> Result; - fn get_facetec_device_sdk_params(&self) -> Result; + fn get_facetec_session_token(&self, req: op_get_facetec_session_token::Request) -> Result; + fn get_facetec_device_sdk_params(&self, req: op_get_facetec_device_sdk_params::Request) -> Result; } } #[async_trait::async_trait] -impl Enroll for MockLogic { - async fn enroll(&self, req: op_enroll::Request) -> Result<(), op_enroll::Error> { +impl LogicOp for MockLogic { + type Response = (); + type Error = op_enroll::Error; + + async fn call(&self, req: op_enroll::Request) -> Result { self.enroll(req) } } #[async_trait::async_trait] -impl Authenticate for MockLogic { - async fn authenticate( - &self, - req: op_authenticate::Request, - ) -> Result { +impl LogicOp for MockLogic { + type Response = op_authenticate::Response; + type Error = op_authenticate::Error; + + async fn call(&self, req: op_authenticate::Request) -> Result { self.authenticate(req) } } #[async_trait::async_trait] -impl GetFacetecSessionToken for MockLogic { - async fn get_facetec_session_token( +impl LogicOp for MockLogic { + type Response = op_get_facetec_session_token::Response; + type Error = op_get_facetec_session_token::Error; + + async fn call( &self, - ) -> Result { - self.get_facetec_session_token() + req: op_get_facetec_session_token::Request, + ) -> Result { + self.get_facetec_session_token(req) } } #[async_trait::async_trait] -impl GetFacetecDeviceSdkParams for MockLogic { - async fn get_facetec_device_sdk_params( +impl LogicOp for MockLogic { + type Response = op_get_facetec_device_sdk_params::Response; + type Error = op_get_facetec_device_sdk_params::Error; + + async fn call( &self, - ) -> Result - { - self.get_facetec_device_sdk_params() + req: op_get_facetec_device_sdk_params::Request, + ) -> Result { + self.get_facetec_device_sdk_params(req) } } @@ -185,10 +195,12 @@ async fn it_denies_authenticate() { #[tokio::test] async fn it_works_get_facetec_session_token() { + let input = op_get_facetec_session_token::Request {}; + let mut mock_logic = MockLogic::new(); mock_logic .expect_get_facetec_session_token() - .returning(|| Ok(provide_facetec_session_token())); + .returning(|_| Ok(provide_facetec_session_token())); let logic = Arc::new(mock_logic); let filter = root(logic); @@ -196,6 +208,7 @@ async fn it_works_get_facetec_session_token() { let res = warp::test::request() .method("GET") .path("/facetec-session-token") + .json(&input) .reply(&filter) .await; @@ -207,10 +220,14 @@ async fn it_works_get_facetec_session_token() { #[tokio::test] async fn it_denies_get_facetec_session_token() { + let input = op_get_facetec_session_token::Request {}; + let mut mock_logic = MockLogic::new(); - mock_logic.expect_get_facetec_session_token().returning(|| { - Err(op_get_facetec_session_token::Error::InternalErrorSessionTokenUnsuccessful) - }); + mock_logic + .expect_get_facetec_session_token() + .returning(|_| { + Err(op_get_facetec_session_token::Error::InternalErrorSessionTokenUnsuccessful) + }); let logic = Arc::new(mock_logic); let filter = root(logic); @@ -218,6 +235,7 @@ async fn it_denies_get_facetec_session_token() { let res = warp::test::request() .method("GET") .path("/facetec-session-token") + .json(&input) .reply(&filter) .await; @@ -226,10 +244,12 @@ async fn it_denies_get_facetec_session_token() { #[tokio::test] async fn it_works_get_facetec_device_sdk_params() { + let input = op_get_facetec_device_sdk_params::Request {}; + let mut mock_logic = MockLogic::new(); mock_logic .expect_get_facetec_device_sdk_params() - .returning(|| Ok(provide_facetec_device_sdk_params())); + .returning(|_| Ok(provide_facetec_device_sdk_params())); let logic = Arc::new(mock_logic); let filter = root(logic); @@ -237,6 +257,7 @@ async fn it_works_get_facetec_device_sdk_params() { let res = warp::test::request() .method("GET") .path("/facetec-device-sdk-params") + .json(&input) .reply(&filter) .await; diff --git a/crates/robonode-server/src/http/traits.rs b/crates/robonode-server/src/http/traits.rs index d948ba9a6..5996c82d0 100644 --- a/crates/robonode-server/src/http/traits.rs +++ b/crates/robonode-server/src/http/traits.rs @@ -1,40 +1,13 @@ -//! The logic-related traits. +//! The logic operation related trait. -use crate::logic::{ - op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, -}; - -/// The trait to make enroll operation. +/// The trait to make logiс operations. #[async_trait::async_trait] -pub trait Enroll { - /// Process Enroll request. - async fn enroll(&self, req: op_enroll::Request) -> Result<(), op_enroll::Error>; -} - -/// The trait to make authenticate operation. -#[async_trait::async_trait] -pub trait Authenticate { - /// Process Authenticate request. - async fn authenticate( - &self, - req: op_authenticate::Request, - ) -> Result; -} +pub trait LogicOp { + /// Logic operation Response type. + type Response; + /// Logic operation Error type. + type Error; -/// The trait to make get facetec session token operation. -#[async_trait::async_trait] -pub trait GetFacetecSessionToken { - /// Process GetFacetecSessionToken request. - async fn get_facetec_session_token( - &self, - ) -> Result; -} - -/// The trait to make get facetec device sdk params operation. -#[async_trait::async_trait] -pub trait GetFacetecDeviceSdkParams { - /// Process GetFacetecDeviceSdkParams request. - async fn get_facetec_device_sdk_params( - &self, - ) -> Result; + /// Process logic operation request. + async fn call(&self, req: Request) -> Result; } diff --git a/crates/robonode-server/src/logic/op_authenticate.rs b/crates/robonode-server/src/logic/op_authenticate.rs index bb71140c6..4a4810a64 100644 --- a/crates/robonode-server/src/logic/op_authenticate.rs +++ b/crates/robonode-server/src/logic/op_authenticate.rs @@ -80,13 +80,15 @@ pub enum Error { } #[async_trait::async_trait] -impl crate::http::traits::Authenticate for Logic +impl crate::http::traits::LogicOp for Logic where S: Signer> + Send + 'static + Sync, PK: Send + Sync + for<'a> TryFrom<&'a [u8]> + Verifier> + Into>, { - /// An authenticate invocation handler. - async fn authenticate(&self, req: Request) -> Result { + type Response = Response; + type Error = Error; + + async fn call(&self, req: Request) -> Result { let liveness_data = LivenessData::try_from(&req.liveness_data).map_err(Error::InvalidLivenessData)?; diff --git a/crates/robonode-server/src/logic/op_enroll.rs b/crates/robonode-server/src/logic/op_enroll.rs index 27f6e085a..990ad087f 100644 --- a/crates/robonode-server/src/logic/op_enroll.rs +++ b/crates/robonode-server/src/logic/op_enroll.rs @@ -55,13 +55,16 @@ pub enum Error { } #[async_trait::async_trait] -impl crate::http::traits::Enroll for Logic +impl crate::http::traits::LogicOp for Logic where S: Signer> + Send + 'static, PK: Send + for<'a> TryFrom<&'a [u8]> + AsRef<[u8]>, { + type Response = (); + type Error = Error; + /// An enroll invocation handler. - async fn enroll(&self, req: Request) -> Result<(), Error> { + async fn call(&self, req: Request) -> Result { let public_key = PK::try_from(&req.public_key).map_err(|_| Error::InvalidPublicKey)?; let liveness_data = diff --git a/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs b/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs index 0d4ff5143..3e13cef38 100644 --- a/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs +++ b/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs @@ -2,10 +2,15 @@ use std::convert::TryFrom; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use super::{Logic, Signer}; +/// The request of the get facetec device sdk params operation. +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Request {} + /// The response for the get facetec device sdk params operation. #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] @@ -21,13 +26,15 @@ pub struct Response { pub enum Error {} #[async_trait::async_trait] -impl crate::http::traits::GetFacetecDeviceSdkParams for Logic +impl crate::http::traits::LogicOp for Logic where S: Signer> + Send + 'static, PK: Send + for<'a> TryFrom<&'a [u8]>, { - /// Get the FaceTec Device SDK params. - async fn get_facetec_device_sdk_params(&self) -> Result { + type Response = Response; + type Error = Error; + + async fn call(&self, _req: Request) -> Result { Ok(Response { device_key_identifier: self.facetec_device_sdk_params.device_key_identifier.clone(), public_face_map_encryption_key: self diff --git a/crates/robonode-server/src/logic/op_get_facetec_session_token.rs b/crates/robonode-server/src/logic/op_get_facetec_session_token.rs index 6b16c16a4..07d7a268f 100644 --- a/crates/robonode-server/src/logic/op_get_facetec_session_token.rs +++ b/crates/robonode-server/src/logic/op_get_facetec_session_token.rs @@ -3,10 +3,15 @@ use std::convert::TryFrom; use facetec_api_client as ft; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use super::{Logic, Signer}; +/// The request of the get facetec session token operation. +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Request {} + /// The response for the get facetec session token operation. #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] @@ -26,13 +31,15 @@ pub enum Error { } #[async_trait::async_trait] -impl crate::http::traits::GetFacetecSessionToken for Logic +impl crate::http::traits::LogicOp for Logic where S: Signer> + Send + 'static, PK: Send + for<'a> TryFrom<&'a [u8]>, { - /// Get a FaceTec Session Token. - async fn get_facetec_session_token(&self) -> Result { + type Response = Response; + type Error = Error; + + async fn call(&self, _req: Request) -> Result { let unlocked = self.locked.lock().await; let res = unlocked diff --git a/crates/robonode-server/src/logic/tests.rs b/crates/robonode-server/src/logic/tests.rs index 7b2c31104..c8664eeaa 100644 --- a/crates/robonode-server/src/logic/tests.rs +++ b/crates/robonode-server/src/logic/tests.rs @@ -7,11 +7,7 @@ use primitives_liveness_data::{LivenessData, OpaqueLivenessData}; use tokio::sync::{Mutex, MutexGuard}; use tracing::{info, trace}; -use crate::{ - http::traits::{Authenticate, Enroll}, - logic::common::DB_GROUP_NAME, - sequence::Sequence, -}; +use crate::{http::traits::LogicOp, logic::common::DB_GROUP_NAME, sequence::Sequence}; use super::{Locked, Logic}; @@ -183,7 +179,7 @@ async fn standalone_enroll() { let (_guard, test_params, logic) = setup().await; logic - .enroll(super::op_enroll::Request { + .call(super::op_enroll::Request { liveness_data: test_params.enroll_liveness_data, public_key: TEST_PUBLIC_KEY.to_vec(), }) @@ -197,7 +193,7 @@ async fn first_authenticate() { let (_guard, test_params, logic) = setup().await; let err = logic - .authenticate(super::op_authenticate::Request { + .call(super::op_authenticate::Request { liveness_data: test_params.authenticate_liveness_data, liveness_data_signature: b"qwe".to_vec(), }) @@ -213,7 +209,7 @@ async fn enroll_authenticate() { let (_guard, test_params, logic) = setup().await; logic - .enroll(super::op_enroll::Request { + .call(super::op_enroll::Request { liveness_data: test_params.enroll_liveness_data, public_key: TEST_PUBLIC_KEY.to_vec(), }) @@ -223,7 +219,7 @@ async fn enroll_authenticate() { info!("enroll complete, authenticating now"); logic - .authenticate(super::op_authenticate::Request { + .call(super::op_authenticate::Request { liveness_data: test_params.authenticate_liveness_data, liveness_data_signature: b"qwe".to_vec(), }) @@ -237,7 +233,7 @@ async fn double_enroll() { let (_guard, test_params, logic) = setup().await; logic - .enroll(super::op_enroll::Request { + .call(super::op_enroll::Request { liveness_data: test_params.enroll_liveness_data, public_key: b"a".to_vec(), }) @@ -245,7 +241,7 @@ async fn double_enroll() { .unwrap(); let err = logic - .enroll(super::op_enroll::Request { + .call(super::op_enroll::Request { liveness_data: test_params.authenticate_liveness_data, public_key: b"b".to_vec(), }) From 3c7f846122251e2bbfc235cfe35b811965cfe0c4 Mon Sep 17 00:00:00 2001 From: dmitrylavrenov Date: Wed, 8 Sep 2021 14:59:03 +0300 Subject: [PATCH 05/11] Remove redundant dependencies in Cargo.toml --- Cargo.lock | 21 --------------------- crates/robonode-server/Cargo.toml | 2 -- 2 files changed, 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93f0166f5..a1a0d43f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5449,7 +5449,6 @@ version = "0.1.0" dependencies = [ "async-trait", "facetec-api-client", - "futures 0.3.16", "hex", "mockall", "primitives-auth-ticket", @@ -5462,7 +5461,6 @@ dependencies = [ "serde_json", "sp-application-crypto", "tokio 1.9.0", - "tower", "tracing", "tracing-test", "uuid", @@ -8196,25 +8194,6 @@ dependencies = [ "serde", ] -[[package]] -name = "tower" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60422bc7fefa2f3ec70359b8ff1caff59d785877eb70595904605bcc412470f" -dependencies = [ - "futures-core", - "pin-project 1.0.8", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" - [[package]] name = "tower-service" version = "0.3.1" diff --git a/crates/robonode-server/Cargo.toml b/crates/robonode-server/Cargo.toml index cafdb09f7..d01458303 100644 --- a/crates/robonode-server/Cargo.toml +++ b/crates/robonode-server/Cargo.toml @@ -12,7 +12,6 @@ primitives-liveness-data = { version = "0.1", path = "../primitives-liveness-dat robonode-crypto = { version = "0.1", path = "../robonode-crypto" } async-trait = "0.1" -futures = "0.3" hex = "0.4" rand = "0.7" reqwest = "0.11" @@ -20,7 +19,6 @@ sc-tracing = "3" serde = { version = "1", features = ["derive"] } sp-application-crypto = { git = "https://github.com/humanode-network/substrate", branch = "master" } tokio = { version = "1", features = ["full"] } -tower = "0.4" tracing = "0.1" uuid = { version = "0.8", features = ["v4"] } warp = "0.3" From 6317bad37718416bf0c8b6ef73cb100e7ad91fb5 Mon Sep 17 00:00:00 2001 From: dmitrylavrenov Date: Thu, 9 Sep 2021 09:12:34 +0300 Subject: [PATCH 06/11] Simplify Request structure and add assert on the response body in tests --- crates/robonode-server/src/http/tests.rs | 13 +++++++++++-- .../src/logic/op_get_facetec_device_sdk_params.rs | 2 +- .../src/logic/op_get_facetec_session_token.rs | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/crates/robonode-server/src/http/tests.rs b/crates/robonode-server/src/http/tests.rs index 44f334969..ab300c7a8 100644 --- a/crates/robonode-server/src/http/tests.rs +++ b/crates/robonode-server/src/http/tests.rs @@ -138,6 +138,7 @@ async fn it_denies_enroll_with_invalid_public_key() { .await; assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR); + assert_eq!(res.body(), "Unhandled rejection: InvalidPublicKey"); } #[tokio::test] @@ -185,12 +186,16 @@ async fn it_denies_authenticate() { let res = warp::test::request() .method("POST") - .path("/enroll") + .path("/authenticate") .json(&input) .reply(&filter) .await; - assert_eq!(res.status(), StatusCode::BAD_REQUEST); + assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR); + assert_eq!( + res.body(), + "Unhandled rejection: InternalErrorDbSearchUnsuccessful" + ); } #[tokio::test] @@ -240,6 +245,10 @@ async fn it_denies_get_facetec_session_token() { .await; assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR); + assert_eq!( + res.body(), + "Unhandled rejection: InternalErrorSessionTokenUnsuccessful" + ); } #[tokio::test] diff --git a/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs b/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs index 3e13cef38..98139aea1 100644 --- a/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs +++ b/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs @@ -9,7 +9,7 @@ use super::{Logic, Signer}; /// The request of the get facetec device sdk params operation. #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct Request {} +pub struct Request; /// The response for the get facetec device sdk params operation. #[derive(Debug, Serialize)] diff --git a/crates/robonode-server/src/logic/op_get_facetec_session_token.rs b/crates/robonode-server/src/logic/op_get_facetec_session_token.rs index 07d7a268f..39989d5ae 100644 --- a/crates/robonode-server/src/logic/op_get_facetec_session_token.rs +++ b/crates/robonode-server/src/logic/op_get_facetec_session_token.rs @@ -10,7 +10,7 @@ use super::{Logic, Signer}; /// The request of the get facetec session token operation. #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -pub struct Request {} +pub struct Request; /// The response for the get facetec session token operation. #[derive(Debug, Serialize)] From c3d72230c613f38cc5f27a7cb5b6594ff73636ed Mon Sep 17 00:00:00 2001 From: dmitrylavrenov Date: Thu, 9 Sep 2021 14:22:13 +0300 Subject: [PATCH 07/11] Simplify Request structure in tests --- crates/robonode-server/src/http/tests.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/robonode-server/src/http/tests.rs b/crates/robonode-server/src/http/tests.rs index ab300c7a8..8eb7308f1 100644 --- a/crates/robonode-server/src/http/tests.rs +++ b/crates/robonode-server/src/http/tests.rs @@ -200,7 +200,7 @@ async fn it_denies_authenticate() { #[tokio::test] async fn it_works_get_facetec_session_token() { - let input = op_get_facetec_session_token::Request {}; + let input = op_get_facetec_session_token::Request; let mut mock_logic = MockLogic::new(); mock_logic @@ -225,7 +225,7 @@ async fn it_works_get_facetec_session_token() { #[tokio::test] async fn it_denies_get_facetec_session_token() { - let input = op_get_facetec_session_token::Request {}; + let input = op_get_facetec_session_token::Request; let mut mock_logic = MockLogic::new(); mock_logic @@ -253,7 +253,7 @@ async fn it_denies_get_facetec_session_token() { #[tokio::test] async fn it_works_get_facetec_device_sdk_params() { - let input = op_get_facetec_device_sdk_params::Request {}; + let input = op_get_facetec_device_sdk_params::Request; let mut mock_logic = MockLogic::new(); mock_logic From 4b851d28b0b411873e2d89611fe5733e8331b168 Mon Sep 17 00:00:00 2001 From: dmitrylavrenov Date: Thu, 9 Sep 2021 14:44:24 +0300 Subject: [PATCH 08/11] Move LogicOp trait under logic --- crates/robonode-server/src/http/filters.rs | 24 +++++++------------ crates/robonode-server/src/http/handlers.rs | 2 +- crates/robonode-server/src/http/mod.rs | 1 - crates/robonode-server/src/http/tests.rs | 3 +-- crates/robonode-server/src/http/traits.rs | 13 ---------- crates/robonode-server/src/logic/mod.rs | 2 +- .../src/logic/op_authenticate.rs | 4 ++-- crates/robonode-server/src/logic/op_enroll.rs | 4 ++-- .../logic/op_get_facetec_device_sdk_params.rs | 4 ++-- .../src/logic/op_get_facetec_session_token.rs | 4 ++-- crates/robonode-server/src/logic/tests.rs | 4 ++-- crates/robonode-server/src/logic/traits.rs | 12 ++++++++++ 12 files changed, 33 insertions(+), 44 deletions(-) delete mode 100644 crates/robonode-server/src/http/traits.rs diff --git a/crates/robonode-server/src/http/filters.rs b/crates/robonode-server/src/http/filters.rs index 7835ac620..50da3adc0 100644 --- a/crates/robonode-server/src/http/filters.rs +++ b/crates/robonode-server/src/http/filters.rs @@ -9,11 +9,10 @@ use crate::{ http::handlers, logic::{ op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, + traits::LogicOp, }, }; -use super::traits::LogicOp; - /// Pass the [`Arc`] to the handler. fn with_arc( val: Arc, @@ -45,20 +44,13 @@ where + LogicOp + Send + Sync, - >::Error: - warp::reject::Reject, - >::Error: - warp::reject::Reject, - >::Response: - Serialize, - >::Error: - warp::reject::Reject, - >::Response: - Serialize, - >::Error: - warp::reject::Reject, - >::Response: - Serialize, + >::Error: warp::reject::Reject, + >::Error: warp::reject::Reject, + >::Response: Serialize, + >::Error: warp::reject::Reject, + >::Response: Serialize, + >::Error: warp::reject::Reject, + >::Response: Serialize, { enroll(Arc::clone(&logic)) .or(authenticate(Arc::clone(&logic))) diff --git a/crates/robonode-server/src/http/handlers.rs b/crates/robonode-server/src/http/handlers.rs index 211bae58c..5bc1ebae8 100644 --- a/crates/robonode-server/src/http/handlers.rs +++ b/crates/robonode-server/src/http/handlers.rs @@ -5,9 +5,9 @@ use std::sync::Arc; use warp::hyper::StatusCode; use warp::Reply; -use super::traits::LogicOp; use crate::logic::{ op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, + traits::LogicOp, }; /// Enroll operation HTTP transport coupling. diff --git a/crates/robonode-server/src/http/mod.rs b/crates/robonode-server/src/http/mod.rs index 88a2b81d7..8ecdd7d22 100644 --- a/crates/robonode-server/src/http/mod.rs +++ b/crates/robonode-server/src/http/mod.rs @@ -2,7 +2,6 @@ mod filters; mod handlers; -pub mod traits; #[cfg(test)] mod tests; diff --git a/crates/robonode-server/src/http/tests.rs b/crates/robonode-server/src/http/tests.rs index 8eb7308f1..4e94e5101 100644 --- a/crates/robonode-server/src/http/tests.rs +++ b/crates/robonode-server/src/http/tests.rs @@ -11,11 +11,10 @@ use crate::{ http::root, logic::{ op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, + traits::LogicOp, }, }; -use super::traits::LogicOp; - mock! { Logic { fn enroll(&self, req: op_enroll::Request) -> Result<(), op_enroll::Error>; diff --git a/crates/robonode-server/src/http/traits.rs b/crates/robonode-server/src/http/traits.rs deleted file mode 100644 index 5996c82d0..000000000 --- a/crates/robonode-server/src/http/traits.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! The logic operation related trait. - -/// The trait to make logiс operations. -#[async_trait::async_trait] -pub trait LogicOp { - /// Logic operation Response type. - type Response; - /// Logic operation Error type. - type Error; - - /// Process logic operation request. - async fn call(&self, req: Request) -> Result; -} diff --git a/crates/robonode-server/src/logic/mod.rs b/crates/robonode-server/src/logic/mod.rs index c909c3f41..cc79bf2cc 100644 --- a/crates/robonode-server/src/logic/mod.rs +++ b/crates/robonode-server/src/logic/mod.rs @@ -15,7 +15,7 @@ pub mod op_get_facetec_device_sdk_params; pub mod op_get_facetec_session_token; #[cfg(test)] mod tests; -mod traits; +pub mod traits; pub use traits::*; diff --git a/crates/robonode-server/src/logic/op_authenticate.rs b/crates/robonode-server/src/logic/op_authenticate.rs index 4a4810a64..32a123a3e 100644 --- a/crates/robonode-server/src/logic/op_authenticate.rs +++ b/crates/robonode-server/src/logic/op_authenticate.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; use crate::logic::facetec_utils::{db_search_result_adapter, DbSearchResult}; -use super::{common::*, Logic, Signer, Verifier}; +use super::{common::*, Logic, LogicOp, Signer, Verifier}; /// The request of the authenticate operation. #[derive(Debug, Deserialize, Serialize)] @@ -80,7 +80,7 @@ pub enum Error { } #[async_trait::async_trait] -impl crate::http::traits::LogicOp for Logic +impl LogicOp for Logic where S: Signer> + Send + 'static + Sync, PK: Send + Sync + for<'a> TryFrom<&'a [u8]> + Verifier> + Into>, diff --git a/crates/robonode-server/src/logic/op_enroll.rs b/crates/robonode-server/src/logic/op_enroll.rs index 990ad087f..cef141f8c 100644 --- a/crates/robonode-server/src/logic/op_enroll.rs +++ b/crates/robonode-server/src/logic/op_enroll.rs @@ -9,7 +9,7 @@ use tracing::{error, trace}; use crate::logic::facetec_utils::{db_search_result_adapter, DbSearchResult}; -use super::{common::*, Logic, Signer}; +use super::{common::*, Logic, LogicOp, Signer}; /// The request for the enroll operation. #[derive(Debug, Deserialize, Serialize)] @@ -55,7 +55,7 @@ pub enum Error { } #[async_trait::async_trait] -impl crate::http::traits::LogicOp for Logic +impl LogicOp for Logic where S: Signer> + Send + 'static, PK: Send + for<'a> TryFrom<&'a [u8]> + AsRef<[u8]>, diff --git a/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs b/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs index 98139aea1..c62c34c98 100644 --- a/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs +++ b/crates/robonode-server/src/logic/op_get_facetec_device_sdk_params.rs @@ -4,7 +4,7 @@ use std::convert::TryFrom; use serde::{Deserialize, Serialize}; -use super::{Logic, Signer}; +use super::{Logic, LogicOp, Signer}; /// The request of the get facetec device sdk params operation. #[derive(Debug, Deserialize, Serialize)] @@ -26,7 +26,7 @@ pub struct Response { pub enum Error {} #[async_trait::async_trait] -impl crate::http::traits::LogicOp for Logic +impl LogicOp for Logic where S: Signer> + Send + 'static, PK: Send + for<'a> TryFrom<&'a [u8]>, diff --git a/crates/robonode-server/src/logic/op_get_facetec_session_token.rs b/crates/robonode-server/src/logic/op_get_facetec_session_token.rs index 39989d5ae..73a4bef87 100644 --- a/crates/robonode-server/src/logic/op_get_facetec_session_token.rs +++ b/crates/robonode-server/src/logic/op_get_facetec_session_token.rs @@ -5,7 +5,7 @@ use std::convert::TryFrom; use facetec_api_client as ft; use serde::{Deserialize, Serialize}; -use super::{Logic, Signer}; +use super::{Logic, LogicOp, Signer}; /// The request of the get facetec session token operation. #[derive(Debug, Deserialize, Serialize)] @@ -31,7 +31,7 @@ pub enum Error { } #[async_trait::async_trait] -impl crate::http::traits::LogicOp for Logic +impl LogicOp for Logic where S: Signer> + Send + 'static, PK: Send + for<'a> TryFrom<&'a [u8]>, diff --git a/crates/robonode-server/src/logic/tests.rs b/crates/robonode-server/src/logic/tests.rs index c8664eeaa..73cfa877c 100644 --- a/crates/robonode-server/src/logic/tests.rs +++ b/crates/robonode-server/src/logic/tests.rs @@ -7,9 +7,9 @@ use primitives_liveness_data::{LivenessData, OpaqueLivenessData}; use tokio::sync::{Mutex, MutexGuard}; use tracing::{info, trace}; -use crate::{http::traits::LogicOp, logic::common::DB_GROUP_NAME, sequence::Sequence}; +use crate::{logic::common::DB_GROUP_NAME, sequence::Sequence}; -use super::{Locked, Logic}; +use super::{Locked, Logic, LogicOp}; struct TestSigner; diff --git a/crates/robonode-server/src/logic/traits.rs b/crates/robonode-server/src/logic/traits.rs index 9c594c451..5752b840b 100644 --- a/crates/robonode-server/src/logic/traits.rs +++ b/crates/robonode-server/src/logic/traits.rs @@ -27,3 +27,15 @@ pub trait Verifier { where D: AsRef<[u8]> + Send + 'a; } + +/// The trait to make logiс operations. +#[async_trait::async_trait] +pub trait LogicOp { + /// Logic operation Response type. + type Response; + /// Logic operation Error type. + type Error; + + /// Process logic operation request. + async fn call(&self, req: Request) -> Result; +} From d4b8cc1b3eed78a7a4a2efea3ebab15750756e3a Mon Sep 17 00:00:00 2001 From: dmitrylavrenov Date: Thu, 9 Sep 2021 20:11:45 +0300 Subject: [PATCH 09/11] Use a macro to define impl in tests --- crates/robonode-server/src/http/tests.rs | 92 ++++++++++--------- crates/robonode-server/src/logic/op_enroll.rs | 5 + 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/crates/robonode-server/src/http/tests.rs b/crates/robonode-server/src/http/tests.rs index 4e94e5101..6bf6adc5c 100644 --- a/crates/robonode-server/src/http/tests.rs +++ b/crates/robonode-server/src/http/tests.rs @@ -17,58 +17,58 @@ use crate::{ mock! { Logic { - fn enroll(&self, req: op_enroll::Request) -> Result<(), op_enroll::Error>; + fn enroll(&self, req: op_enroll::Request) -> Result; fn authenticate(&self, req: op_authenticate::Request) -> Result; fn get_facetec_session_token(&self, req: op_get_facetec_session_token::Request) -> Result; fn get_facetec_device_sdk_params(&self, req: op_get_facetec_device_sdk_params::Request) -> Result; } } -#[async_trait::async_trait] -impl LogicOp for MockLogic { - type Response = (); - type Error = op_enroll::Error; - - async fn call(&self, req: op_enroll::Request) -> Result { - self.enroll(req) - } -} - -#[async_trait::async_trait] -impl LogicOp for MockLogic { - type Response = op_authenticate::Response; - type Error = op_authenticate::Error; - - async fn call(&self, req: op_authenticate::Request) -> Result { - self.authenticate(req) - } -} - -#[async_trait::async_trait] -impl LogicOp for MockLogic { - type Response = op_get_facetec_session_token::Response; - type Error = op_get_facetec_session_token::Error; - - async fn call( - &self, - req: op_get_facetec_session_token::Request, - ) -> Result { - self.get_facetec_session_token(req) - } +macro_rules! impl_LogicOp { + ($name:ty, $request:ty, $response:ty, $error:ty, $call: ident) => { + #[async_trait::async_trait] + impl LogicOp<$request> for $name { + type Response = $response; + type Error = $error; + + async fn call(&self, req: $request) -> Result<$response, $error> { + self.$call(req) + } + } + }; } -#[async_trait::async_trait] -impl LogicOp for MockLogic { - type Response = op_get_facetec_device_sdk_params::Response; - type Error = op_get_facetec_device_sdk_params::Error; - - async fn call( - &self, - req: op_get_facetec_device_sdk_params::Request, - ) -> Result { - self.get_facetec_device_sdk_params(req) - } -} +impl_LogicOp!( + MockLogic, + op_enroll::Request, + op_enroll::Response, + op_enroll::Error, + enroll +); + +impl_LogicOp!( + MockLogic, + op_authenticate::Request, + op_authenticate::Response, + op_authenticate::Error, + authenticate +); + +impl_LogicOp!( + MockLogic, + op_get_facetec_session_token::Request, + op_get_facetec_session_token::Response, + op_get_facetec_session_token::Error, + get_facetec_session_token +); + +impl_LogicOp!( + MockLogic, + op_get_facetec_device_sdk_params::Request, + op_get_facetec_device_sdk_params::Response, + op_get_facetec_device_sdk_params::Error, + get_facetec_device_sdk_params +); fn provide_authenticate_response() -> op_authenticate::Response { op_authenticate::Response { @@ -98,7 +98,9 @@ async fn it_works_enroll() { }; let mut mock_logic = MockLogic::new(); - mock_logic.expect_enroll().returning(|_| Ok(())); + mock_logic + .expect_enroll() + .returning(|_| Ok(op_enroll::Response)); let logic = Arc::new(mock_logic); let filter = root(logic); diff --git a/crates/robonode-server/src/logic/op_enroll.rs b/crates/robonode-server/src/logic/op_enroll.rs index cef141f8c..cae64eebd 100644 --- a/crates/robonode-server/src/logic/op_enroll.rs +++ b/crates/robonode-server/src/logic/op_enroll.rs @@ -21,6 +21,11 @@ pub struct Request { pub liveness_data: OpaqueLivenessData, } +/// The response for the enroll operation. +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Response; + /// The errors on the enroll operation. #[derive(Debug)] pub enum Error { From 5285091a28f9e375618eaabe7cae164f56592b99 Mon Sep 17 00:00:00 2001 From: dmitrylavrenov Date: Thu, 9 Sep 2021 20:15:47 +0300 Subject: [PATCH 10/11] Use Self instead of type in tests --- crates/robonode-server/src/http/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/robonode-server/src/http/tests.rs b/crates/robonode-server/src/http/tests.rs index 6bf6adc5c..046a37819 100644 --- a/crates/robonode-server/src/http/tests.rs +++ b/crates/robonode-server/src/http/tests.rs @@ -31,7 +31,7 @@ macro_rules! impl_LogicOp { type Response = $response; type Error = $error; - async fn call(&self, req: $request) -> Result<$response, $error> { + async fn call(&self, req: $request) -> Result { self.$call(req) } } From 66bb332d3e0bd0ef65117ba5e01329573168c1c5 Mon Sep 17 00:00:00 2001 From: dmitrylavrenov Date: Thu, 9 Sep 2021 23:28:15 +0300 Subject: [PATCH 11/11] Remove redundant pub --- crates/robonode-server/src/http/filters.rs | 2 +- crates/robonode-server/src/http/handlers.rs | 2 +- crates/robonode-server/src/http/tests.rs | 2 +- crates/robonode-server/src/logic/mod.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/robonode-server/src/http/filters.rs b/crates/robonode-server/src/http/filters.rs index 50da3adc0..9f45cace5 100644 --- a/crates/robonode-server/src/http/filters.rs +++ b/crates/robonode-server/src/http/filters.rs @@ -9,7 +9,7 @@ use crate::{ http::handlers, logic::{ op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, - traits::LogicOp, + LogicOp, }, }; diff --git a/crates/robonode-server/src/http/handlers.rs b/crates/robonode-server/src/http/handlers.rs index 5bc1ebae8..8715d45e3 100644 --- a/crates/robonode-server/src/http/handlers.rs +++ b/crates/robonode-server/src/http/handlers.rs @@ -7,7 +7,7 @@ use warp::Reply; use crate::logic::{ op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, - traits::LogicOp, + LogicOp, }; /// Enroll operation HTTP transport coupling. diff --git a/crates/robonode-server/src/http/tests.rs b/crates/robonode-server/src/http/tests.rs index 046a37819..6e60d367e 100644 --- a/crates/robonode-server/src/http/tests.rs +++ b/crates/robonode-server/src/http/tests.rs @@ -11,7 +11,7 @@ use crate::{ http::root, logic::{ op_authenticate, op_enroll, op_get_facetec_device_sdk_params, op_get_facetec_session_token, - traits::LogicOp, + LogicOp, }, }; diff --git a/crates/robonode-server/src/logic/mod.rs b/crates/robonode-server/src/logic/mod.rs index cc79bf2cc..c909c3f41 100644 --- a/crates/robonode-server/src/logic/mod.rs +++ b/crates/robonode-server/src/logic/mod.rs @@ -15,7 +15,7 @@ pub mod op_get_facetec_device_sdk_params; pub mod op_get_facetec_session_token; #[cfg(test)] mod tests; -pub mod traits; +mod traits; pub use traits::*;