From 09ebf30f93614bf5323a11df711d691f3d41e6d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Granh=C3=A3o?= Date: Wed, 14 Aug 2024 12:46:00 +0100 Subject: [PATCH] Use accept terms and conditions v2 --- .github/workflows/code-analysis.yml | 6 ++-- graphql/schemas/operations.graphql | 8 +++--- graphql/src/lib.rs | 4 ++- graphql/src/schema.rs | 2 +- honeybadger/src/asynchronous/mod.rs | 3 +- honeybadger/src/asynchronous/provider.rs | 13 +++++---- honeybadger/src/lib.rs | 3 +- honeybadger/src/provider.rs | 20 ++++++++------ honeybadger/tests/integration_tests.rs | 35 ++++++++++++++---------- 9 files changed, 55 insertions(+), 39 deletions(-) diff --git a/.github/workflows/code-analysis.yml b/.github/workflows/code-analysis.yml index 18962a5..06e941a 100644 --- a/.github/workflows/code-analysis.yml +++ b/.github/workflows/code-analysis.yml @@ -62,7 +62,7 @@ jobs: uses: actions/checkout@v3 - name: Linelint uses: fernandrone/linelint@master - id: linelint + id: linelint unused_dependencies: name: Look for unused dependencies runs-on: ubuntu-latest @@ -70,11 +70,11 @@ jobs: - name: rust-toolchain uses: actions-rs/toolchain@v1.0.6 with: - toolchain: nightly-2023-12-28 + toolchain: nightly-2024-08-14 override: true - name: Install unused dependency checker run: cargo install cargo-udeps --locked - name: Checkout uses: actions/checkout@v3 - name: Run unused dependency checker - run: cargo +nightly-2023-12-28 udeps + run: cargo +nightly-2024-08-14 udeps diff --git a/graphql/schemas/operations.graphql b/graphql/schemas/operations.graphql index 9449697..2ab5df5 100644 --- a/graphql/schemas/operations.graphql +++ b/graphql/schemas/operations.graphql @@ -38,11 +38,11 @@ mutation UnlockWallet($challenge: String!, $challengeSignature: String!, $prepar } } -mutation AcceptTermsAndConditions($serviceProvider: String!, $version: Int!) { - accept_terms_conditions(args: {service_provider: $serviceProvider, version: $version}) { - serviceProvider - acceptedTerms +mutation AcceptTermsAndConditionsV2($fingerprint: String!, $service: Service, $version: Int!) { + accept_terms_conditions_v2(args: {fingerprint: $fingerprint, service: $service, version: $version}) { acceptDate + accepted + service version } } diff --git a/graphql/src/lib.rs b/graphql/src/lib.rs index 6711aea..0a6df81 100644 --- a/graphql/src/lib.rs +++ b/graphql/src/lib.rs @@ -9,7 +9,7 @@ pub use reqwest; use chrono::{DateTime, Utc}; use graphql_client::reqwest::{post_graphql, post_graphql_blocking}; use graphql_client::Response; -use perro::{permanent_failure, runtime_error, MapToError, OptionToError}; +use perro::{invalid_input, permanent_failure, runtime_error, MapToError, OptionToError}; use reqwest::blocking::Client; use reqwest::header::{HeaderValue, AUTHORIZATION}; use reqwest::StatusCode; @@ -160,6 +160,7 @@ fn map_error_code(code: &str) -> Error { const MISSING_HTTP_HEADER_EXCEPTION_CODE: &str = "http-header-missing-exception"; const INVALID_INVITATION_EXCEPTION_CODE: &str = "invalid-invitation-exception"; const REMOTE_SCHEMA_ERROR_CODE: &str = "remote-schema-error"; + const INVALID_FINGERPRINT: &str = "invalid-fingerprint"; match code { AUTH_EXCEPTION_CODE => runtime_error( @@ -179,6 +180,7 @@ fn map_error_code(code: &str) -> Error { REMOTE_SCHEMA_ERROR_CODE => { permanent_failure("A remote schema call has failed on the backend") } + INVALID_FINGERPRINT => invalid_input("The provided fingerprint is invalid"), _ => permanent_failure(format!( "Unexpected backend response: unknown error code: {code}" )), diff --git a/graphql/src/schema.rs b/graphql/src/schema.rs index ab8fedf..014206d 100644 --- a/graphql/src/schema.rs +++ b/graphql/src/schema.rs @@ -55,7 +55,7 @@ pub struct RefreshSession; query_path = "schemas/operations.graphql", response_derives = "Debug" )] -pub struct AcceptTermsAndConditions; +pub struct AcceptTermsAndConditionsV2; #[derive(GraphQLQuery)] #[graphql( diff --git a/honeybadger/src/asynchronous/mod.rs b/honeybadger/src/asynchronous/mod.rs index 32ec399..621592b 100644 --- a/honeybadger/src/asynchronous/mod.rs +++ b/honeybadger/src/asynchronous/mod.rs @@ -69,11 +69,12 @@ impl Auth { &self, terms: TermsAndConditions, version: i64, + fingerprint: String, ) -> Result<()> { let token = self.query_token().await?; let provider = self.provider.lock().await; provider - .accept_terms_and_conditions(token, terms, version) + .accept_terms_and_conditions(token, terms, version, fingerprint) .await } diff --git a/honeybadger/src/asynchronous/provider.rs b/honeybadger/src/asynchronous/provider.rs index 71886ff..bb384a9 100644 --- a/honeybadger/src/asynchronous/provider.rs +++ b/honeybadger/src/asynchronous/provider.rs @@ -67,6 +67,7 @@ impl AuthProvider { access_token: String, terms: TermsAndConditions, version: i64, + fingerprint: String, ) -> Result<()> { info!("Accepting T&C ({:?})...", terms); ensure!( @@ -74,17 +75,19 @@ impl AuthProvider { invalid_input("Accepting T&C not supported for auth levels other than Pseudonymous") ); - let variables = accept_terms_and_conditions::Variables { - service_provider: terms.into(), + let variables = accept_terms_and_conditions_v2::Variables { + fingerprint, + service: Some(terms.into()), version, }; let client = build_async_client(Some(&access_token))?; - let data = post::(&client, &self.backend_url, variables).await?; + let data = + post::(&client, &self.backend_url, variables).await?; ensure!( matches!( - data.accept_terms_conditions, + data.accept_terms_conditions_v2, Some( - accept_terms_and_conditions::AcceptTermsAndConditionsAcceptTermsConditions { .. } + accept_terms_and_conditions_v2::AcceptTermsAndConditionsV2AcceptTermsConditionsV2 { .. } ) ), permanent_failure("Backend rejected accepting Terms and Conditions") diff --git a/honeybadger/src/lib.rs b/honeybadger/src/lib.rs index a1a5541..9f82bb5 100644 --- a/honeybadger/src/lib.rs +++ b/honeybadger/src/lib.rs @@ -99,10 +99,11 @@ impl Auth { &self, terms: TermsAndConditions, version: i64, + fingerprint: String, ) -> Result<()> { let token = self.query_token()?; let provider = self.provider.lock().unwrap(); - provider.accept_terms_and_conditions(token, terms, version) + provider.accept_terms_and_conditions(token, terms, version, fingerprint) } pub fn get_terms_and_conditions_status( diff --git a/honeybadger/src/provider.rs b/honeybadger/src/provider.rs index 27a3c99..2f002cf 100644 --- a/honeybadger/src/provider.rs +++ b/honeybadger/src/provider.rs @@ -4,6 +4,7 @@ use crate::signing::sign; use crate::TermsAndConditionsStatus; use graphql::perro::{ensure, invalid_input, permanent_failure, runtime_error, OptionToError}; use graphql::reqwest::blocking::Client; +use graphql::schema::accept_terms_and_conditions_v2::Service; use graphql::schema::get_terms_and_conditions_status::ServiceProviderEnum; use graphql::schema::*; use graphql::{build_client, perro, post_blocking}; @@ -24,13 +25,12 @@ pub enum TermsAndConditions { Pocket, } -impl From for String { +impl From for Service { fn from(value: TermsAndConditions) -> Self { match value { - TermsAndConditions::Lipa => "LIPA_WALLET", - TermsAndConditions::Pocket => "POCKET_EXCHANGE", + TermsAndConditions::Lipa => Service::LIPA_WALLET, + TermsAndConditions::Pocket => Service::POCKET_EXCHANGE, } - .to_string() } } @@ -114,6 +114,7 @@ impl AuthProvider { access_token: String, terms: TermsAndConditions, version: i64, + fingerprint: String, ) -> Result<()> { info!("Accepting T&C ({:?})...", terms); ensure!( @@ -121,18 +122,19 @@ impl AuthProvider { invalid_input("Accepting T&C not supported for auth levels other than Pseudonymous") ); - let variables = accept_terms_and_conditions::Variables { - service_provider: terms.into(), + let variables = accept_terms_and_conditions_v2::Variables { + fingerprint, + service: Some(terms.into()), version, }; let client = build_client(Some(&access_token))?; let data = - post_blocking::(&client, &self.backend_url, variables)?; + post_blocking::(&client, &self.backend_url, variables)?; ensure!( matches!( - data.accept_terms_conditions, + data.accept_terms_conditions_v2, Some( - accept_terms_and_conditions::AcceptTermsAndConditionsAcceptTermsConditions { .. } + accept_terms_and_conditions_v2::AcceptTermsAndConditionsV2AcceptTermsConditionsV2 { .. } ) ), permanent_failure("Backend rejected accepting Terms and Conditions") diff --git a/honeybadger/tests/integration_tests.rs b/honeybadger/tests/integration_tests.rs index 3606be2..68ff097 100644 --- a/honeybadger/tests/integration_tests.rs +++ b/honeybadger/tests/integration_tests.rs @@ -192,13 +192,17 @@ fn test_accept_terms_and_conditions() { auth_keypair, ) .unwrap(); - auth.accept_terms_and_conditions(TermsAndConditions::Lipa, 1) - .unwrap(); + auth.accept_terms_and_conditions( + TermsAndConditions::Lipa, + 3, + "dcceac0c67d2946e3ea44ccbb439a5b33ee9d36d79df2b0f9070b66938".into(), + ) + .unwrap(); assert_eq!( auth.get_terms_and_conditions_status(TermsAndConditions::Lipa) .unwrap() .version, - 1 + 3 ); let (wallet_keypair, auth_keypair) = generate_keys(); @@ -209,8 +213,11 @@ fn test_accept_terms_and_conditions() { auth_keypair, ) .unwrap(); - let result = auth.accept_terms_and_conditions(TermsAndConditions::Lipa, 2); - assert!(matches!(result, Err(Error::InvalidInput { .. }))); + let result = + auth.accept_terms_and_conditions(TermsAndConditions::Lipa, 3, "fingerprint2".into()); + assert!( + matches!(result, Err(Error::InvalidInput { msg }) if msg.contains("Accepting T&C not supported for auth levels other than Pseudonymous")) + ); let (wallet_keypair, auth_keypair) = generate_keys(); let auth = Auth::new( @@ -220,13 +227,10 @@ fn test_accept_terms_and_conditions() { auth_keypair, ) .unwrap(); - auth.accept_terms_and_conditions(TermsAndConditions::Pocket, 3) - .unwrap(); - assert_eq!( - auth.get_terms_and_conditions_status(TermsAndConditions::Pocket) - .unwrap() - .version, - 3 + let result = + auth.accept_terms_and_conditions(TermsAndConditions::Pocket, 3, "fingerprint3".into()); + assert!( + matches!(result, Err(Error::InvalidInput { msg }) if msg.contains("The provided fingerprint is invalid")) ); let (wallet_keypair, auth_keypair) = generate_keys(); @@ -237,8 +241,11 @@ fn test_accept_terms_and_conditions() { auth_keypair, ) .unwrap(); - let result = auth.accept_terms_and_conditions(TermsAndConditions::Pocket, 4); - assert!(matches!(result, Err(Error::InvalidInput { .. }))); + let result = + auth.accept_terms_and_conditions(TermsAndConditions::Pocket, 4, "fingerprint4".into()); + assert!( + matches!(result, Err(Error::InvalidInput { msg }) if msg.contains("Accepting T&C not supported for auth levels other than Pseudonymous")) + ); } fn generate_keys() -> (KeyPair, KeyPair) {