diff --git a/crates/analytics/src/auth_events/core.rs b/crates/analytics/src/auth_events/core.rs index 41b7b72495..011633dce3 100644 --- a/crates/analytics/src/auth_events/core.rs +++ b/crates/analytics/src/auth_events/core.rs @@ -27,7 +27,7 @@ use crate::{ #[instrument(skip_all)] pub async fn get_metrics( pool: &AnalyticsProvider, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, req: GetAuthEventMetricRequest, ) -> AnalyticsResult> { let mut metrics_accumulator: HashMap< @@ -38,14 +38,14 @@ pub async fn get_metrics( let mut set = tokio::task::JoinSet::new(); for metric_type in req.metrics.iter().cloned() { let req = req.clone(); - let merchant_id_scoped = merchant_id.to_owned(); + let auth_scoped = auth.to_owned(); let pool = pool.clone(); set.spawn(async move { let data = pool .get_auth_event_metrics( &metric_type, &req.group_by_names.clone(), - &merchant_id_scoped, + &auth_scoped, &req.filters, req.time_series.map(|t| t.granularity), &req.time_range, @@ -130,7 +130,7 @@ pub async fn get_metrics( pub async fn get_filters( pool: &AnalyticsProvider, req: GetAuthEventFilterRequest, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, ) -> AnalyticsResult { let mut res = AuthEventFiltersResponse::default(); for dim in req.group_by_names { @@ -139,14 +139,14 @@ pub async fn get_filters( Err(report!(AnalyticsError::UnknownError)) } AnalyticsProvider::Clickhouse(pool) => { - get_auth_events_filter_for_dimension(dim, merchant_id, &req.time_range, pool) + get_auth_events_filter_for_dimension(dim, auth, &req.time_range, pool) .await .map_err(|e| e.change_context(AnalyticsError::UnknownError)) } AnalyticsProvider::CombinedCkh(sqlx_pool, ckh_pool) | AnalyticsProvider::CombinedSqlx(sqlx_pool, ckh_pool) => { let ckh_result = get_auth_events_filter_for_dimension( dim, - merchant_id, + auth, &req.time_range, ckh_pool, ) @@ -154,7 +154,7 @@ pub async fn get_filters( .map_err(|e| e.change_context(AnalyticsError::UnknownError)); let sqlx_result = get_auth_events_filter_for_dimension( dim, - merchant_id, + auth, &req.time_range, sqlx_pool, ) diff --git a/crates/analytics/src/auth_events/filters.rs b/crates/analytics/src/auth_events/filters.rs index 9249613172..7ecf2426df 100644 --- a/crates/analytics/src/auth_events/filters.rs +++ b/crates/analytics/src/auth_events/filters.rs @@ -6,6 +6,7 @@ use error_stack::ResultExt; use time::PrimitiveDateTime; use crate::{ + enums::AuthInfo, query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, ToSql, Window}, types::{ AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, FiltersError, FiltersResult, @@ -17,7 +18,7 @@ pub trait AuthEventFilterAnalytics: LoadRow {} pub async fn get_auth_events_filter_for_dimension( dimension: AuthEventDimensions, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, time_range: &TimeRange, pool: &T, ) -> FiltersResult> @@ -38,12 +39,10 @@ where .attach_printable("Error filtering time range") .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder.set_distinct(); + auth.set_filter_clause(&mut query_builder).switch()?; + query_builder .execute_query::(pool) .await diff --git a/crates/analytics/src/auth_events/metrics.rs b/crates/analytics/src/auth_events/metrics.rs index 46c3805662..ebb1d5d1f0 100644 --- a/crates/analytics/src/auth_events/metrics.rs +++ b/crates/analytics/src/auth_events/metrics.rs @@ -12,6 +12,7 @@ use time::PrimitiveDateTime; use crate::{ query::{Aggregate, GroupByClause, ToSql, Window}, types::{AnalyticsCollection, AnalyticsDataSource, DBEnumWrapper, LoadRow, MetricsResult}, + AuthInfo, }; mod authentication_attempt_count; @@ -86,7 +87,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -107,7 +108,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -117,146 +118,62 @@ where match self { Self::AuthenticationCount => { AuthenticationCount - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::AuthenticationAttemptCount => { AuthenticationAttemptCount - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::AuthenticationSuccessCount => { AuthenticationSuccessCount - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::ChallengeFlowCount => { ChallengeFlowCount - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::ChallengeAttemptCount => { ChallengeAttemptCount - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::ChallengeSuccessCount => { ChallengeSuccessCount - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::FrictionlessFlowCount => { FrictionlessFlowCount - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::FrictionlessSuccessCount => { FrictionlessSuccessCount - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::AuthenticationErrorMessage => { AuthenticationErrorMessage - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::AuthenticationFunnel => { AuthenticationFunnel - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::AuthenticationExemptionApprovedCount => { AuthenticationExemptionApprovedCount - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::AuthenticationExemptionRequestedCount => { AuthenticationExemptionRequestedCount - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } } diff --git a/crates/analytics/src/auth_events/metrics/authentication_attempt_count.rs b/crates/analytics/src/auth_events/metrics/authentication_attempt_count.rs index 967513af32..ce7d11e22a 100644 --- a/crates/analytics/src/auth_events/metrics/authentication_attempt_count.rs +++ b/crates/analytics/src/auth_events/metrics/authentication_attempt_count.rs @@ -13,6 +13,7 @@ use super::AuthEventMetricRow; use crate::{ query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window}, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -30,7 +31,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -65,10 +66,6 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder .add_filter_in_range_clause( "authentication_status", @@ -80,6 +77,7 @@ where .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/auth_events/metrics/authentication_count.rs b/crates/analytics/src/auth_events/metrics/authentication_count.rs index 0334f732f2..8ee5026d28 100644 --- a/crates/analytics/src/auth_events/metrics/authentication_count.rs +++ b/crates/analytics/src/auth_events/metrics/authentication_count.rs @@ -12,6 +12,7 @@ use super::AuthEventMetricRow; use crate::{ query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window}, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -29,7 +30,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -62,14 +63,12 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; filters.set_filter_clause(&mut query_builder).switch()?; time_range .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/auth_events/metrics/authentication_error_message.rs b/crates/analytics/src/auth_events/metrics/authentication_error_message.rs index ac0adc7bbf..180306d9ef 100644 --- a/crates/analytics/src/auth_events/metrics/authentication_error_message.rs +++ b/crates/analytics/src/auth_events/metrics/authentication_error_message.rs @@ -16,6 +16,7 @@ use crate::{ ToSql, Window, }, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -33,7 +34,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -64,10 +65,6 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder .add_filter_clause("authentication_status", AuthenticationStatus::Failed) .switch()?; @@ -84,6 +81,7 @@ where .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/auth_events/metrics/authentication_exemption_approved_count.rs b/crates/analytics/src/auth_events/metrics/authentication_exemption_approved_count.rs index 89ec3affe6..994f66f5f5 100644 --- a/crates/analytics/src/auth_events/metrics/authentication_exemption_approved_count.rs +++ b/crates/analytics/src/auth_events/metrics/authentication_exemption_approved_count.rs @@ -12,6 +12,7 @@ use super::AuthEventMetricRow; use crate::{ query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window}, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -29,7 +30,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -62,10 +63,6 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder .add_filter_clause(AuthEventDimensions::ExemptionAccepted, true) .switch()?; @@ -74,6 +71,7 @@ where .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/auth_events/metrics/authentication_exemption_requested_count.rs b/crates/analytics/src/auth_events/metrics/authentication_exemption_requested_count.rs index aa4af1a47f..f763533082 100644 --- a/crates/analytics/src/auth_events/metrics/authentication_exemption_requested_count.rs +++ b/crates/analytics/src/auth_events/metrics/authentication_exemption_requested_count.rs @@ -12,6 +12,7 @@ use super::AuthEventMetricRow; use crate::{ query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window}, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -29,7 +30,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -62,10 +63,6 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder .add_filter_clause(AuthEventDimensions::ExemptionRequested, true) .switch()?; @@ -75,6 +72,7 @@ where .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/auth_events/metrics/authentication_funnel.rs b/crates/analytics/src/auth_events/metrics/authentication_funnel.rs index 145a70a542..e2eb4ce83b 100644 --- a/crates/analytics/src/auth_events/metrics/authentication_funnel.rs +++ b/crates/analytics/src/auth_events/metrics/authentication_funnel.rs @@ -15,6 +15,7 @@ use crate::{ Window, }, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -32,7 +33,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -65,10 +66,6 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder .add_custom_filter_clause( AuthEventDimensions::TransactionStatus, @@ -81,6 +78,7 @@ where .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/auth_events/metrics/authentication_success_count.rs b/crates/analytics/src/auth_events/metrics/authentication_success_count.rs index 9788b6477c..fbbcdb3208 100644 --- a/crates/analytics/src/auth_events/metrics/authentication_success_count.rs +++ b/crates/analytics/src/auth_events/metrics/authentication_success_count.rs @@ -13,6 +13,7 @@ use super::AuthEventMetricRow; use crate::{ query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window}, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -30,7 +31,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -63,10 +64,6 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder .add_filter_clause("authentication_status", AuthenticationStatus::Success) .switch()?; @@ -75,6 +72,7 @@ where .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/auth_events/metrics/challenge_attempt_count.rs b/crates/analytics/src/auth_events/metrics/challenge_attempt_count.rs index d3d7dcc747..29d1bb2230 100644 --- a/crates/analytics/src/auth_events/metrics/challenge_attempt_count.rs +++ b/crates/analytics/src/auth_events/metrics/challenge_attempt_count.rs @@ -13,6 +13,7 @@ use super::AuthEventMetricRow; use crate::{ query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window}, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -30,7 +31,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -63,10 +64,6 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder .add_filter_clause( "authentication_type", @@ -85,6 +82,7 @@ where .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/auth_events/metrics/challenge_flow_count.rs b/crates/analytics/src/auth_events/metrics/challenge_flow_count.rs index 5b951e1fa8..55a9041ac6 100644 --- a/crates/analytics/src/auth_events/metrics/challenge_flow_count.rs +++ b/crates/analytics/src/auth_events/metrics/challenge_flow_count.rs @@ -13,6 +13,7 @@ use super::AuthEventMetricRow; use crate::{ query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window}, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -30,7 +31,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -63,10 +64,6 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder .add_filter_clause( "authentication_type", @@ -78,6 +75,7 @@ where .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/auth_events/metrics/challenge_success_count.rs b/crates/analytics/src/auth_events/metrics/challenge_success_count.rs index 2bbd4d8198..307b9ada16 100644 --- a/crates/analytics/src/auth_events/metrics/challenge_success_count.rs +++ b/crates/analytics/src/auth_events/metrics/challenge_success_count.rs @@ -13,6 +13,7 @@ use super::AuthEventMetricRow; use crate::{ query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window}, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -30,7 +31,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -63,10 +64,6 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder .add_filter_clause("authentication_status", AuthenticationStatus::Success) .switch()?; @@ -82,6 +79,7 @@ where .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/auth_events/metrics/frictionless_flow_count.rs b/crates/analytics/src/auth_events/metrics/frictionless_flow_count.rs index da8a119d22..fb9ecfa8ef 100644 --- a/crates/analytics/src/auth_events/metrics/frictionless_flow_count.rs +++ b/crates/analytics/src/auth_events/metrics/frictionless_flow_count.rs @@ -13,6 +13,7 @@ use super::AuthEventMetricRow; use crate::{ query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window}, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -30,7 +31,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -63,10 +64,6 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder .add_filter_clause( "authentication_type", @@ -78,6 +75,7 @@ where .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/auth_events/metrics/frictionless_success_count.rs b/crates/analytics/src/auth_events/metrics/frictionless_success_count.rs index b4fb18e48f..a134b9b0e3 100644 --- a/crates/analytics/src/auth_events/metrics/frictionless_success_count.rs +++ b/crates/analytics/src/auth_events/metrics/frictionless_success_count.rs @@ -13,6 +13,7 @@ use super::AuthEventMetricRow; use crate::{ query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window}, types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult}, + AuthInfo, }; #[derive(Default)] @@ -30,7 +31,7 @@ where { async fn load_metrics( &self, - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, dimensions: &[AuthEventDimensions], filters: &AuthEventFilters, granularity: Option, @@ -63,10 +64,6 @@ where }) .switch()?; - query_builder - .add_filter_clause("merchant_id", merchant_id) - .switch()?; - query_builder .add_filter_clause( "authentication_type", @@ -82,6 +79,7 @@ where .set_filter_clause(&mut query_builder) .attach_printable("Error filtering time range") .switch()?; + auth.set_filter_clause(&mut query_builder).switch()?; for dim in dimensions.iter() { query_builder diff --git a/crates/analytics/src/lib.rs b/crates/analytics/src/lib.rs index 1718c5044a..e8a01c27ca 100644 --- a/crates/analytics/src/lib.rs +++ b/crates/analytics/src/lib.rs @@ -912,7 +912,7 @@ impl AnalyticsProvider { &self, metric: &AuthEventMetrics, dimensions: &[AuthEventDimensions], - merchant_id: &common_utils::id_type::MerchantId, + auth: &AuthInfo, filters: &AuthEventFilters, granularity: Option, time_range: &TimeRange, @@ -921,20 +921,13 @@ impl AnalyticsProvider { Self::Sqlx(_pool) => Err(report!(MetricsError::NotImplemented)), Self::Clickhouse(pool) => { metric - .load_metrics( - merchant_id, - dimensions, - filters, - granularity, - time_range, - pool, - ) + .load_metrics(auth, dimensions, filters, granularity, time_range, pool) .await } Self::CombinedCkh(_sqlx_pool, ckh_pool) | Self::CombinedSqlx(_sqlx_pool, ckh_pool) => { metric .load_metrics( - merchant_id, + auth, dimensions, filters, granularity, diff --git a/crates/router/src/analytics.rs b/crates/router/src/analytics.rs index e40bce1233..e41b7e5953 100644 --- a/crates/router/src/analytics.rs +++ b/crates/router/src/analytics.rs @@ -116,11 +116,7 @@ pub mod routes { ) .service( web::resource("metrics/auth_events") - .route(web::post().to(get_auth_event_metrics)), - ) - .service( - web::resource("metrics/auth_events/sankey") - .route(web::post().to(get_auth_event_sankey)), + .route(web::post().to(get_merchant_auth_event_metrics)), ) .service( web::resource("filters/auth_events") @@ -177,6 +173,10 @@ pub mod routes { web::resource("metrics/sankey") .route(web::post().to(get_merchant_sankey)), ) + .service( + web::resource("metrics/auth_events/sankey") + .route(web::post().to(get_merchant_auth_event_sankey)), + ) .service( web::scope("/merchant") .service( @@ -191,6 +191,10 @@ pub mod routes { web::resource("metrics/refunds") .route(web::post().to(get_merchant_refund_metrics)), ) + .service( + web::resource("metrics/auth_events") + .route(web::post().to(get_merchant_auth_event_metrics)), + ) .service( web::resource("filters/payments") .route(web::post().to(get_merchant_payment_filters)), @@ -203,6 +207,10 @@ pub mod routes { web::resource("filters/refunds") .route(web::post().to(get_merchant_refund_filters)), ) + .service( + web::resource("filters/auth_events") + .route(web::post().to(get_merchant_auth_events_filters)), + ) .service( web::resource("{domain}/info").route(web::get().to(get_info)), ) @@ -242,6 +250,10 @@ pub mod routes { .service( web::resource("metrics/sankey") .route(web::post().to(get_merchant_sankey)), + ) + .service( + web::resource("metrics/auth_events/sankey") + .route(web::post().to(get_merchant_auth_event_sankey)), ), ) .service( @@ -277,10 +289,18 @@ pub mod routes { web::resource("metrics/disputes") .route(web::post().to(get_org_dispute_metrics)), ) + .service( + web::resource("metrics/auth_events") + .route(web::post().to(get_org_auth_event_metrics)), + ) .service( web::resource("filters/disputes") .route(web::post().to(get_org_dispute_filters)), ) + .service( + web::resource("filters/auth_events") + .route(web::post().to(get_org_auth_events_filters)), + ) .service( web::resource("report/dispute") .route(web::post().to(generate_org_dispute_report)), @@ -300,6 +320,10 @@ pub mod routes { .service( web::resource("metrics/sankey") .route(web::post().to(get_org_sankey)), + ) + .service( + web::resource("metrics/auth_events/sankey") + .route(web::post().to(get_org_auth_event_sankey)), ), ) .service( @@ -335,10 +359,18 @@ pub mod routes { web::resource("metrics/disputes") .route(web::post().to(get_profile_dispute_metrics)), ) + .service( + web::resource("metrics/auth_events") + .route(web::post().to(get_profile_auth_event_metrics)), + ) .service( web::resource("filters/disputes") .route(web::post().to(get_profile_dispute_filters)), ) + .service( + web::resource("filters/auth_events") + .route(web::post().to(get_profile_auth_events_filters)), + ) .service( web::resource("connector_event_logs") .route(web::get().to(get_profile_connector_events)), @@ -379,6 +411,10 @@ pub mod routes { .service( web::resource("metrics/sankey") .route(web::post().to(get_profile_sankey)), + ) + .service( + web::resource("metrics/auth_events/sankey") + .route(web::post().to(get_profile_auth_event_sankey)), ), ), ) @@ -1043,7 +1079,7 @@ pub mod routes { /// # Panics /// /// Panics if `json_payload` array does not contain one `GetAuthEventMetricRequest` element. - pub async fn get_auth_event_metrics( + pub async fn get_merchant_auth_event_metrics( state: web::Data, req: actix_web::HttpRequest, json_payload: web::Json<[GetAuthEventMetricRequest; 1]>, @@ -1062,13 +1098,16 @@ pub mod routes { &req, payload, |state, auth: AuthenticationData, req, _| async move { - analytics::auth_events::get_metrics( - &state.pool, - auth.merchant_account.get_id(), - req, - ) - .await - .map(ApplicationResponse::Json) + let org_id = auth.merchant_account.get_org_id(); + let merchant_id = auth.merchant_account.get_id(); + let auth: AuthInfo = AuthInfo::MerchantLevel { + org_id: org_id.clone(), + merchant_ids: vec![merchant_id.clone()], + }; + + analytics::auth_events::get_metrics(&state.pool, &auth, req) + .await + .map(ApplicationResponse::Json) }, &auth::JWTAuth { permission: Permission::MerchantAnalyticsRead, @@ -1078,6 +1117,98 @@ pub mod routes { .await } + #[cfg(feature = "v1")] + /// # Panics + /// + /// Panics if `json_payload` array does not contain one `GetAuthEventMetricRequest` element. + pub async fn get_profile_auth_event_metrics( + state: web::Data, + req: actix_web::HttpRequest, + json_payload: web::Json<[GetAuthEventMetricRequest; 1]>, + ) -> impl Responder { + // safety: This shouldn't panic owing to the data type + #[allow(clippy::expect_used)] + let payload = json_payload + .into_inner() + .to_vec() + .pop() + .expect("Couldn't get GetAuthEventMetricRequest"); + let flow = AnalyticsFlow::GetAuthMetrics; + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, auth: AuthenticationData, req, _| async move { + let org_id = auth.merchant_account.get_org_id(); + let merchant_id = auth.merchant_account.get_id(); + let profile_id = auth + .profile_id + .ok_or(report!(UserErrors::JwtProfileIdMissing)) + .change_context(AnalyticsError::AccessForbiddenError)?; + let auth: AuthInfo = AuthInfo::ProfileLevel { + org_id: org_id.clone(), + merchant_id: merchant_id.clone(), + profile_ids: vec![profile_id.clone()], + }; + analytics::auth_events::get_metrics(&state.pool, &auth, req) + .await + .map(ApplicationResponse::Json) + }, + &auth::JWTAuth { + permission: Permission::ProfileAnalyticsRead, + }, + api_locking::LockAction::NotApplicable, + )) + .await + } + + #[cfg(feature = "v1")] + /// # Panics + /// + /// Panics if `json_payload` array does not contain one `GetAuthEventMetricRequest` element. + pub async fn get_org_auth_event_metrics( + state: web::Data, + req: actix_web::HttpRequest, + json_payload: web::Json<[GetAuthEventMetricRequest; 1]>, + ) -> impl Responder { + // safety: This shouldn't panic owing to the data type + #[allow(clippy::expect_used)] + let payload = json_payload + .into_inner() + .to_vec() + .pop() + .expect("Couldn't get GetAuthEventMetricRequest"); + let flow = AnalyticsFlow::GetAuthMetrics; + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, auth: AuthenticationData, req, _| async move { + let org_id = auth.merchant_account.get_org_id(); + let auth: AuthInfo = AuthInfo::OrgLevel { + org_id: org_id.clone(), + }; + analytics::auth_events::get_metrics(&state.pool, &auth, req) + .await + .map(ApplicationResponse::Json) + }, + auth::auth_type( + &auth::PlatformOrgAdminAuth { + is_admin_auth_allowed: false, + organization_id: None, + }, + &auth::JWTAuth { + permission: Permission::OrganizationAnalyticsRead, + }, + req.headers(), + ), + api_locking::LockAction::NotApplicable, + )) + .await + } + pub async fn get_merchant_payment_filters( state: web::Data, req: actix_web::HttpRequest, @@ -1120,13 +1251,16 @@ pub mod routes { &req, json_payload.into_inner(), |state, auth: AuthenticationData, req, _| async move { - analytics::auth_events::get_filters( - &state.pool, - req, - auth.merchant_account.get_id(), - ) - .await - .map(ApplicationResponse::Json) + let org_id = auth.merchant_account.get_org_id(); + let merchant_id = auth.merchant_account.get_id(); + + let auth: AuthInfo = AuthInfo::MerchantLevel { + org_id: org_id.clone(), + merchant_ids: vec![merchant_id.clone()], + }; + analytics::auth_events::get_filters(&state.pool, req, &auth) + .await + .map(ApplicationResponse::Json) }, &auth::JWTAuth { permission: Permission::MerchantAnalyticsRead, @@ -1136,6 +1270,80 @@ pub mod routes { .await } + #[cfg(feature = "v1")] + pub async fn get_org_auth_events_filters( + state: web::Data, + req: actix_web::HttpRequest, + json_payload: web::Json, + ) -> impl Responder { + let flow = AnalyticsFlow::GetAuthEventFilters; + Box::pin(api::server_wrap( + flow, + state, + &req, + json_payload.into_inner(), + |state, auth: AuthenticationData, req, _| async move { + let org_id = auth.merchant_account.get_org_id(); + let auth: AuthInfo = AuthInfo::OrgLevel { + org_id: org_id.clone(), + }; + + analytics::auth_events::get_filters(&state.pool, req, &auth) + .await + .map(ApplicationResponse::Json) + }, + auth::auth_type( + &auth::PlatformOrgAdminAuth { + is_admin_auth_allowed: false, + organization_id: None, + }, + &auth::JWTAuth { + permission: Permission::OrganizationAnalyticsRead, + }, + req.headers(), + ), + api_locking::LockAction::NotApplicable, + )) + .await + } + + #[cfg(feature = "v1")] + pub async fn get_profile_auth_events_filters( + state: web::Data, + req: actix_web::HttpRequest, + json_payload: web::Json, + ) -> impl Responder { + let flow = AnalyticsFlow::GetAuthEventFilters; + Box::pin(api::server_wrap( + flow, + state, + &req, + json_payload.into_inner(), + |state, auth: AuthenticationData, req, _| async move { + let org_id = auth.merchant_account.get_org_id(); + let merchant_id = auth.merchant_account.get_id(); + let profile_id = auth + .profile_id + .ok_or(report!(UserErrors::JwtProfileIdMissing)) + .change_context(AnalyticsError::AccessForbiddenError)?; + + let auth: AuthInfo = AuthInfo::ProfileLevel { + org_id: org_id.clone(), + merchant_id: merchant_id.clone(), + profile_ids: vec![profile_id.clone()], + }; + analytics::auth_events::get_filters(&state.pool, req, &auth) + .await + .map(ApplicationResponse::Json) + }, + &auth::JWTAuth { + permission: Permission::ProfileAnalyticsRead, + }, + api_locking::LockAction::NotApplicable, + )) + .await + } + #[cfg(feature = "v1")] pub async fn get_org_payment_filters( state: web::Data, @@ -2809,7 +3017,7 @@ pub mod routes { .await } - pub async fn get_auth_event_sankey( + pub async fn get_merchant_auth_event_sankey( state: web::Data, req: actix_web::HttpRequest, json_payload: web::Json, @@ -2840,6 +3048,80 @@ pub mod routes { .await } + #[cfg(feature = "v1")] + pub async fn get_org_auth_event_sankey( + state: web::Data, + req: actix_web::HttpRequest, + json_payload: web::Json, + ) -> impl Responder { + let flow = AnalyticsFlow::GetSankey; + let payload = json_payload.into_inner(); + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, auth: AuthenticationData, req, _| async move { + let org_id = auth.merchant_account.get_org_id(); + let auth: AuthInfo = AuthInfo::OrgLevel { + org_id: org_id.clone(), + }; + analytics::auth_events::get_sankey(&state.pool, &auth, req) + .await + .map(ApplicationResponse::Json) + }, + auth::auth_type( + &auth::PlatformOrgAdminAuth { + is_admin_auth_allowed: false, + organization_id: None, + }, + &auth::JWTAuth { + permission: Permission::OrganizationAnalyticsRead, + }, + req.headers(), + ), + api_locking::LockAction::NotApplicable, + )) + .await + } + + #[cfg(feature = "v1")] + pub async fn get_profile_auth_event_sankey( + state: web::Data, + req: actix_web::HttpRequest, + json_payload: web::Json, + ) -> impl Responder { + let flow = AnalyticsFlow::GetSankey; + let payload = json_payload.into_inner(); + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, auth: AuthenticationData, req, _| async move { + let org_id = auth.merchant_account.get_org_id(); + let merchant_id = auth.merchant_account.get_id(); + let profile_id = auth + .profile_id + .ok_or(report!(UserErrors::JwtProfileIdMissing)) + .change_context(AnalyticsError::AccessForbiddenError)?; + let auth: AuthInfo = AuthInfo::ProfileLevel { + org_id: org_id.clone(), + merchant_id: merchant_id.clone(), + profile_ids: vec![profile_id.clone()], + }; + analytics::auth_events::get_sankey(&state.pool, &auth, req) + .await + .map(ApplicationResponse::Json) + }, + &auth::JWTAuth { + permission: Permission::ProfileAnalyticsRead, + }, + api_locking::LockAction::NotApplicable, + )) + .await + } + #[cfg(feature = "v1")] pub async fn get_org_sankey( state: web::Data,