From 7699aa12a4544f701bbd865fd8e090f1283a1077 Mon Sep 17 00:00:00 2001 From: KyleWiese Date: Thu, 26 Sep 2024 21:27:18 +0000 Subject: [PATCH] For analytics records, upload a singular product that was used for an authorized operation. This replaces the existing functionality that picked a random matching product from the credential --- analytics/record.go | 6 +----- analytics/saas_analytics_test.go | 21 ++++++++++++++++----- auth/context.go | 1 + product/manager.go | 1 + product/product.go | 2 ++ product/product_test.go | 2 ++ 6 files changed, 23 insertions(+), 10 deletions(-) diff --git a/analytics/record.go b/analytics/record.go index 85557c4..98c041e 100644 --- a/analytics/record.go +++ b/analytics/record.go @@ -86,13 +86,9 @@ func (r Record) EnsureFields(authContext *auth.Context) Record { r.ClientID = authContext.ClientID r.Organization = authContext.Organization() r.Environment = authContext.Environment() - r.GatewayFlowID = uuid.New().String() + r.APIProduct = authContext.AnalyticsProduct - // select arbitrary APIProduct - if len(authContext.APIProducts) > 0 { - r.APIProduct = authContext.APIProducts[0] - } return r } diff --git a/analytics/saas_analytics_test.go b/analytics/saas_analytics_test.go index 783e63c..3e2a9a0 100644 --- a/analytics/saas_analytics_test.go +++ b/analytics/saas_analytics_test.go @@ -224,7 +224,6 @@ func TestPushAnalytics(t *testing.T) { { ClientReceivedStartTimestamp: ts * 1000, ClientReceivedEndTimestamp: ts * 1000, - APIProduct: "product", }, }, dir: uploadDir, @@ -257,6 +256,7 @@ func TestPushAnalytics(t *testing.T) { ClientReceivedStartTimestamp: ts * 1000, ClientReceivedEndTimestamp: ts * 1000, APIProxy: "proxy", + APIProduct: "product", }, { RecordType: "APIAnalytics", @@ -280,6 +280,7 @@ func TestPushAnalytics(t *testing.T) { ClientReceivedStartTimestamp: ts * 1000, ClientReceivedEndTimestamp: ts * 1000, RequestURI: "request URI", + APIProduct: "product", }, }, dir: uploadDir, @@ -293,7 +294,10 @@ func TestPushAnalytics(t *testing.T) { tc := authtest.NewContext(fs.URL()) tc.SetOrganization("hi") tc.SetEnvironment("test") - authContext := &auth.Context{Context: tc} + authContext := &auth.Context{ + Context: tc, + AnalyticsProduct: "product", + } if err := m.SendRecords(authContext, sendRecords[t1][0].records); err != nil { t.Errorf("Error on SendRecords(): %s", err) @@ -308,7 +312,10 @@ func TestPushAnalytics(t *testing.T) { tc = authtest.NewContext(fs.URL()) tc.SetOrganization("otherorg") tc.SetEnvironment("test") - authContext = &auth.Context{Context: tc} + authContext = &auth.Context{ + Context: tc, + AnalyticsProduct: "product", + } if err := m.SendRecords(authContext, sendRecords[t2][0].records); err != nil { t.Errorf("Error on SendRecords(): %s", err) } @@ -395,7 +402,6 @@ func TestPushAnalyticsMultipleRecords(t *testing.T) { { ClientReceivedStartTimestamp: ts * 1000, ClientReceivedEndTimestamp: ts * 1000, - APIProduct: "product", }, }, dir: uploadDir, @@ -424,6 +430,7 @@ func TestPushAnalyticsMultipleRecords(t *testing.T) { ClientReceivedStartTimestamp: ts * 1000, ClientReceivedEndTimestamp: ts * 1000, APIProxy: "proxy", + APIProduct: "product", }, { RecordType: "APIAnalytics", @@ -440,6 +447,7 @@ func TestPushAnalyticsMultipleRecords(t *testing.T) { ClientReceivedStartTimestamp: ts * 1000, ClientReceivedEndTimestamp: ts * 1000, RequestURI: "request URI", + APIProduct: "product", }, }, dir: uploadDir, @@ -451,7 +459,10 @@ func TestPushAnalyticsMultipleRecords(t *testing.T) { tc := authtest.NewContext(fs.URL()) tc.SetOrganization("hi") tc.SetEnvironment("test") - authContext := &auth.Context{Context: tc} + authContext := &auth.Context{ + Context: tc, + AnalyticsProduct: "product", + } if err := m.SendRecords(authContext, sendRecords[t1][0].records); err != nil { t.Errorf("Error on SendRecords(): %s", err) diff --git a/auth/context.go b/auth/context.go index f949f3b..57eec7a 100644 --- a/auth/context.go +++ b/auth/context.go @@ -47,6 +47,7 @@ type Context struct { Scopes []string APIKey string CustomAttributes string + AnalyticsProduct string // A single product to attatch to analytics records based on matched operations. } // if claims can't be processed, returns error and sets no fields diff --git a/product/manager.go b/product/manager.go index 9d77b2e..4391ae5 100644 --- a/product/manager.go +++ b/product/manager.go @@ -82,6 +82,7 @@ type AuthorizedOperation struct { QuotaLimit int64 QuotaInterval int64 QuotaTimeUnit string + APIProduct string } // Authorize a request against API Products and its Operations diff --git a/product/product.go b/product/product.go index 5960ad6..ec9f1b1 100644 --- a/product/product.go +++ b/product/product.go @@ -318,6 +318,7 @@ func (p *APIProduct) authorize(authContext *auth.Context, api, path, method stri QuotaLimit: p.QuotaLimitInt, QuotaInterval: p.QuotaIntervalInt, QuotaTimeUnit: p.QuotaTimeUnit, + APIProduct: p.Name, } // OperationConfig quota is an override if oc.Quota != nil && oc.Quota.LimitInt > 0 { @@ -353,6 +354,7 @@ func (p *APIProduct) authorize(authContext *auth.Context, api, path, method stri QuotaLimit: p.QuotaLimitInt, QuotaInterval: p.QuotaIntervalInt, QuotaTimeUnit: p.QuotaTimeUnit, + APIProduct: p.Name, }) hint = " authorized\n" diff --git a/product/product_test.go b/product/product_test.go index 4629f5a..ac2dafe 100644 --- a/product/product_test.go +++ b/product/product_test.go @@ -196,6 +196,7 @@ func TestAuthorize(t *testing.T) { wantAuthOp: &AuthorizedOperation{ ID: "Name 2-prod-foo@google.com-app", QuotaLimit: productsMap["Name 2"].QuotaLimitInt, + APIProduct: "Name 2", }, wantHints: `Authorizing request: environment: prod @@ -255,6 +256,7 @@ func TestAuthorize(t *testing.T) { wantAuthOp: &AuthorizedOperation{ ID: "Name 1-prod-foo@google.com-app", QuotaLimit: productsMap["Name 1"].QuotaLimitInt, + APIProduct: "Name 1", }, wantHints: `Authorizing request: environment: prod