From 9d12439ce9b479fd0e7528f5ef8df8859fce6f13 Mon Sep 17 00:00:00 2001 From: sighphyre Date: Thu, 7 Sep 2023 11:13:46 +0200 Subject: [PATCH 1/2] chore: some more tests to cover token comparisons --- server/src/tokens.rs | 78 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/server/src/tokens.rs b/server/src/tokens.rs index 41ab9fef..30d00f90 100644 --- a/server/src/tokens.rs +++ b/server/src/tokens.rs @@ -194,7 +194,7 @@ impl EdgeToken { mod tests { use crate::{ tokens::simplify, - types::{EdgeToken, TokenRefresh}, + types::{EdgeToken, TokenRefresh, TokenType}, }; use ulid::Ulid; @@ -311,4 +311,80 @@ mod tests { assert_eq!(actual, expected); } + + #[test] + fn test_single_project_token_is_covered_by_wildcard() { + let self_token = EdgeToken { + projects: vec!["*".into()], + environment: Some("development".into()), + ..Default::default() + }; + + let other_token = EdgeToken { + projects: vec!["A".into()], + environment: Some("development".into()), + ..Default::default() + }; + + let is_covered = + self_token.same_environment_and_broader_or_equal_project_access(&other_token); + assert!(is_covered); + } + + #[test] + fn test_multi_project_token_is_covered_by_wildcard() { + let self_token = EdgeToken { + projects: vec!["*".into()], + environment: Some("development".into()), + ..Default::default() + }; + + let other_token = EdgeToken { + projects: vec!["A".into(), "B".into()], + environment: Some("development".into()), + ..Default::default() + }; + + let is_covered = + self_token.same_environment_and_broader_or_equal_project_access(&other_token); + assert!(is_covered); + } + + #[test] + fn test_multi_project_tokens_cover_each_other() { + let self_token = EdgeToken { + projects: vec!["A".into(), "B".into()], + environment: Some("development".into()), + ..Default::default() + }; + + let fe_token = EdgeToken { + projects: vec!["A".into()], + environment: Some("development".into()), + token_type: Some(TokenType::Frontend), + ..Default::default() + }; + + let is_covered = self_token.same_environment_and_broader_or_equal_project_access(&fe_token); + assert!(is_covered); + } + + #[test] + fn test_multi_project_tokens_do_not_cover_each_other_when_they_do_not_overlap() { + let self_token = EdgeToken { + projects: vec!["A".into(), "B".into()], + environment: Some("development".into()), + ..Default::default() + }; + + let fe_token = EdgeToken { + projects: vec!["A".into(), "C".into()], + environment: Some("development".into()), + token_type: Some(TokenType::Frontend), + ..Default::default() + }; + + let is_covered = self_token.same_environment_and_broader_or_equal_project_access(&fe_token); + assert!(!is_covered); + } } From 6c2db2022556b041d239809ec5cb421bbf519ae8 Mon Sep 17 00:00:00 2001 From: sighphyre Date: Thu, 7 Sep 2023 11:54:05 +0200 Subject: [PATCH 2/2] fix: make fe tokens actually respect the present tokens so that multiple api calls are not made --- server/src/http/feature_refresher.rs | 48 +++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/server/src/http/feature_refresher.rs b/server/src/http/feature_refresher.rs index b35fc1a6..7aaf6d64 100644 --- a/server/src/http/feature_refresher.rs +++ b/server/src/http/feature_refresher.rs @@ -22,6 +22,17 @@ use crate::{ types::{ClientFeaturesRequest, ClientFeaturesResponse, EdgeToken, TokenRefresh}, }; +fn frontend_token_is_covered_by_tokens( + frontend_token: &EdgeToken, + tokens_to_refresh: Arc>, +) -> bool { + tokens_to_refresh.iter().any(|client_token| { + client_token + .token + .same_environment_and_broader_or_equal_project_access(frontend_token) + }) +} + #[derive(Clone)] pub struct FeatureRefresher { pub unleash_client: Arc, @@ -119,9 +130,7 @@ impl FeatureRefresher { &self, frontend_token: &EdgeToken, ) -> bool { - self.tokens_to_refresh.iter().any(|client_token| { - frontend_token.same_environment_and_broader_or_equal_project_access(&client_token.token) - }) + frontend_token_is_covered_by_tokens(frontend_token, self.tokens_to_refresh.clone()) } pub(crate) async fn register_and_hydrate_token( @@ -364,7 +373,7 @@ mod tests { types::{EdgeToken, TokenRefresh}, }; - use super::FeatureRefresher; + use super::{frontend_token_is_covered_by_tokens, FeatureRefresher}; impl PartialEq for TokenRefresh { fn eq(&self, other: &Self) -> bool { @@ -998,4 +1007,35 @@ mod tests { 7 ); } + + #[test] + fn front_end_token_is_properly_covered_by_current_tokens() { + let fe_token = EdgeToken { + projects: vec!["a".into(), "b".into()], + environment: Some("development".into()), + ..Default::default() + }; + + let wildcard_token = EdgeToken { + projects: vec!["*".into()], + environment: Some("development".into()), + ..Default::default() + }; + + let current_tokens = DashMap::new(); + let token_refresh = TokenRefresh { + token: wildcard_token.clone(), + etag: None, + last_refreshed: None, + last_check: None, + }; + + current_tokens.insert(wildcard_token.token, token_refresh); + + let current_tokens_arc = Arc::new(current_tokens); + assert!(frontend_token_is_covered_by_tokens( + &fe_token, + current_tokens_arc + )); + } }