Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
9507ba1
Allow response body inspection for JSON parsing errors at facetec-api…
MOZGIII Jul 3, 2021
07a14d2
Implement response body error inspection mechanism at facetec api client
MOZGIII Jul 3, 2021
cb485f5
Implement a logging inspector at the robonode
MOZGIII Jul 3, 2021
3b539cb
Share the test client init code at facetec api client
MOZGIII Jul 3, 2021
3cd7872
Utilize use paths for context at facetec api client
MOZGIII Jul 3, 2021
c458959
Fix a couple of the facetec response handling bugs at the robonode-se…
MOZGIII Jul 3, 2021
4caa989
Correct the facetec api client enrollment 3d call error handling
MOZGIII Jul 3, 2021
2cce03b
Add an Execution ID to the robonode logic
MOZGIII Jul 3, 2021
31e865a
Another correction to the facetec api client and robonode logic
MOZGIII Jul 3, 2021
1d26d57
Another test case and correction at the facetec api client
MOZGIII Jul 3, 2021
baf0c12
Log the unsuccessful facetec server enroll responses
MOZGIII Jul 3, 2021
9116f85
Apparently group parameter can not be empty
MOZGIII Jul 3, 2021
8d8953d
Refactor robonode server structure
MOZGIII Jul 4, 2021
fe334c2
Add an unexpected_error_in_success_response_deserialization
MOZGIII Jul 20, 2021
a46b906
Correct the comment
MOZGIII Jul 20, 2021
b0dbfbf
Fix field visibility at robonode server logic
MOZGIII Jul 20, 2021
a606573
Refactor the builder util at facetec client to be more generic
MOZGIII Jul 20, 2021
f15d11a
Add reset method to facetec client
MOZGIII Jul 20, 2021
f92c98b
Add logic integrtion tests
MOZGIII Jul 20, 2021
43c8273
Enable tracing in tests
MOZGIII Jul 27, 2021
705661b
Pass the reset call body
MOZGIII Jul 21, 2021
ea26288
Add support for injecting fake IP address into the FaceTec API requests
MOZGIII Jul 21, 2021
104b910
Add tracing to robonode logic for facetec responses
MOZGIII Jul 21, 2021
3b97cad
Correct the first_authenticate test logic
MOZGIII Jul 21, 2021
6a3f52f
Add serde_util::Either at facetec api client
MOZGIII Jul 21, 2021
026aad9
Add support for processing errors in success responses at db_search
MOZGIII Jul 21, 2021
9ece384
Trace facetec server reset
MOZGIII Jul 22, 2021
1b62cc9
Add raw response body inspection to FaceTec API client
MOZGIII Jul 23, 2021
bc45452
Add another test case to the logic
MOZGIII Jul 23, 2021
363fdbe
Fix the bug in the logic
MOZGIII Jul 23, 2021
e164b7b
Add an assertion to guarantee that we the enroll and auth liveness da…
MOZGIII Jul 23, 2021
67aaa17
Drop the responses when they're not needed
MOZGIII Jul 23, 2021
6ffebb7
Add a handler for the FaceTec 3D DB search response
MOZGIII Jul 23, 2021
9eaa708
Lower the risk of parsing error by cutting extra details from the 3D …
MOZGIII Jul 23, 2021
190c62c
Add db_search_result_adapter at op_authenticate
MOZGIII Jul 23, 2021
a80deff
Update crates/facetec-api-client/src/db_search.rs
MOZGIII Jul 26, 2021
b38a935
Update crates/facetec-api-client/src/response_body_error.rs
MOZGIII Jul 26, 2021
264730f
Add log event to the enroll_authenticate test
MOZGIII Jul 26, 2021
dbcd996
Add 3D DB deletion endpoint
MOZGIII Jul 26, 2021
f68588c
Clear the known facetec 3D DB entry at robonode tests
MOZGIII Jul 26, 2021
d5c7d94
Use a real response from the facetec server at 3D DB enroll
MOZGIII Jul 26, 2021
9caff3c
Cleanup all of the public keys used in the tests
MOZGIII Jul 27, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
"rust-analyzer.cargo.runBuildScripts": true,
"[toml]": {
"editor.defaultFormatter": "tamasfe.even-better-toml"
}
},
"rust-analyzer.cargo.features": ["logic-integration-tests"]
}
36 changes: 36 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/facetec-api-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ authors = ["Humanode Team <core@humanode.io>"]
publish = false

[dependencies]
async-trait = "0.1"
bytes = "1"
reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
thiserror = "1"

[dev-dependencies]
Expand Down
238 changes: 238 additions & 0 deletions crates/facetec-api-client/src/db_delete.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
//! POST `/3d-db/delete`

use reqwest::StatusCode;
use serde::{Deserialize, Serialize};

use super::Client;

impl<RBEI> Client<RBEI>
where
RBEI: crate::response_body_error::Inspector,
{
/// Perform the `/3d-db/delete` call to the server.
pub async fn db_delete(&self, req: Request<'_>) -> Result<Response, crate::Error<Error>> {
let res = self.build_post("/3d-db/delete", &req).send().await?;
match res.status() {
StatusCode::OK => Ok(self.parse_json(res).await?),
StatusCode::BAD_REQUEST => Err(crate::Error::Call(Error::BadRequest(
self.parse_json(res).await?,
))),
_ => Err(crate::Error::Call(Error::Unknown(res.text().await?))),
}
}
}

/// Input data for the `/3d-db/delete` request.
#[derive(Debug, Serialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Request<'a> {
/// The ID of the enrolled FaceMap to delete.
pub identifier: &'a str,
/// The name of the group to delete the specified FaceMap from.
pub group_name: &'a str,
}

/// The response from `/3d-db/delete`.
#[derive(Debug, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Response {
/// Whether the request was successful.
pub success: bool,
}

/// The `/3d-db/delete`-specific error kind.
#[derive(thiserror::Error, Debug, PartialEq)]
pub enum Error {
/// Bad request error occured.
#[error("bad request: {0}")]
BadRequest(ErrorBadRequest),
/// Some other error occured.
#[error("unknown error: {0}")]
Unknown(String),
}

/// The error kind for the `/3d-db/delete`-specific 400 response.
#[derive(thiserror::Error, Debug, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
#[error("bad request: {error_message}")]
pub struct ErrorBadRequest {
/// Whether the request had any errors during the execution.
/// Expected to always be `true` in this context.
pub error: bool,
/// Whether the request was successful.
/// Expected to always be `false` in this context.
pub success: bool,
/// The error message.
pub error_message: String,
}

#[cfg(test)]
mod tests {
use wiremock::{matchers, Mock, MockServer, ResponseTemplate};

use crate::tests::test_client;

use super::*;

#[test]
fn request_serialization() {
let expected_request = serde_json::json!({
"identifier": "my_test_id",
"groupName": ""
});

let actual_request = serde_json::to_value(&Request {
identifier: "my_test_id",
group_name: "",
})
.unwrap();

assert_eq!(expected_request, actual_request);
}

#[test]
fn response_deserialization() {
let sample_response = serde_json::json!({
"additionalSessionData": {
"isAdditionalDataPartiallyIncomplete": true
},
"callData": {
"tid": "0haAzpKGLfc4fa345-ee26-11eb-86b0-0232fd4aba88",
"path": "/3d-db/delete",
"date": "Jul 26, 2021 15:34:37 PM",
"epochSecond": 1627313677,
"requestMethod": "POST"
},
"error": false,
"serverInfo": {
"version": "9.3.1-dev-2021070201",
"mode": "Development Only",
"notice": "You should only be reading this if you are in server-side code. Please make sure you do not allow the FaceTec Server to be called from the public internet."
},
"success": true
});

let response: Response = serde_json::from_value(sample_response).unwrap();
assert_matches!(response, Response { success: true })
}
#[test]
fn bad_request_error_response_deserialization() {
let sample_response = serde_json::json!({
"error": true,
"errorMessage": "No entry found in the database.",
"success": false
});

let response: ErrorBadRequest = serde_json::from_value(sample_response).unwrap();
assert_eq!(
response,
ErrorBadRequest {
error: true,
success: false,
error_message: "No entry found in the database.".to_owned(),
}
)
}

#[tokio::test]
async fn mock_success() {
let mock_server = MockServer::start().await;

let sample_request = Request {
identifier: "my_test_id",
group_name: "",
};
let sample_response = serde_json::json!({
"additionalSessionData": {
"isAdditionalDataPartiallyIncomplete": true
},
"callData": {
"tid": "0haAzpKGLfc4fa345-ee26-11eb-86b0-0232fd4aba88",
"path": "/3d-db/delete",
"date": "Jul 26, 2021 15:34:37 PM",
"epochSecond": 1627313677,
"requestMethod": "POST"
},
"error": false,
"serverInfo": {
"version": "9.3.1-dev-2021070201",
"mode": "Development Only",
"notice": "You should only be reading this if you are in server-side code. Please make sure you do not allow the FaceTec Server to be called from the public internet."
},
"success": true
});

let expected_response: Response = serde_json::from_value(sample_response.clone()).unwrap();

Mock::given(matchers::method("POST"))
.and(matchers::path("/3d-db/delete"))
.and(matchers::body_json(&sample_request))
.respond_with(ResponseTemplate::new(200).set_body_json(&sample_response))
.mount(&mock_server)
.await;

let client = test_client(mock_server.uri());

let actual_response = client.db_delete(sample_request).await.unwrap();
assert_eq!(actual_response, expected_response);
}

#[tokio::test]
async fn mock_error_unknown() {
let mock_server = MockServer::start().await;

let sample_request = Request {
identifier: "my_test_id",
group_name: "",
};
let sample_response = "Some error text";

Mock::given(matchers::method("POST"))
.and(matchers::path("/3d-db/delete"))
.and(matchers::body_json(&sample_request))
.respond_with(ResponseTemplate::new(500).set_body_string(sample_response))
.mount(&mock_server)
.await;

let client = test_client(mock_server.uri());

let actual_error = client.db_delete(sample_request).await.unwrap_err();
assert_matches!(
actual_error,
crate::Error::Call(Error::Unknown(error_text)) if error_text == sample_response
);
}

#[tokio::test]
async fn mock_error_bad_request() {
let mock_server = MockServer::start().await;

let sample_request = Request {
identifier: "my_test_id",
group_name: "",
};
let sample_response = serde_json::json!({
"error": true,
"errorMessage": "No entry found in the database.",
"success": false
});

let expected_error: ErrorBadRequest =
serde_json::from_value(sample_response.clone()).unwrap();

Mock::given(matchers::method("POST"))
.and(matchers::path("/3d-db/delete"))
.and(matchers::body_json(&sample_request))
.respond_with(ResponseTemplate::new(400).set_body_json(&sample_response))
.mount(&mock_server)
.await;

let client = test_client(mock_server.uri());

let actual_error = client.db_delete(sample_request).await.unwrap_err();
assert_matches!(
actual_error,
crate::Error::Call(Error::BadRequest(err)) if err == expected_error
);
}
}
Loading