From 046ab3f001947464c52b935097860542e67c4710 Mon Sep 17 00:00:00 2001 From: aman Date: Mon, 3 Aug 2026 12:37:06 +0530 Subject: [PATCH] chore: apply go fix modernizers across the repo Go 1.26's go fix applied at its fixed point: interface{} to any, pointer-helper calls to new(expr), manual loops to maps.Copy, slices.Contains and range-over-int, and WaitGroup.Go where the shape allows. The five pointer helpers orphaned by the rewrite are removed. Co-Authored-By: Claude Fable 5 --- billing/checkout/service.go | 86 +++++++++---------- billing/checkout/service_concurrent_test.go | 8 +- billing/credit/service.go | 2 +- billing/customer/service.go | 8 +- billing/customer/service_concurrent_test.go | 8 +- billing/customer/service_test.go | 54 ++++++------ billing/invoice/service.go | 44 +++++----- billing/invoice/service_concurrent_test.go | 8 +- billing/invoice/service_test.go | 16 ++-- billing/product/service.go | 10 +-- billing/product/service_test.go | 42 ++++----- billing/subscription/service.go | 80 ++++++++--------- .../subscription/service_concurrent_test.go | 8 +- billing/subscription/service_test.go | 8 +- cmd/preferences.go | 2 +- core/aggregates/orgbilling/service.go | 2 +- core/aggregates/orgprojects/service.go | 2 +- core/aggregates/orgtokens/service.go | 2 +- core/aggregates/orgusers/service.go | 2 +- core/audit/context.go | 5 +- core/audit/logger.go | 5 +- core/audit/service.go | 2 +- core/audit/service_test.go | 12 +-- core/auditrecord/models/models.go | 2 +- core/auditrecord/service.go | 11 ++- core/auditrecord/service_test.go | 10 +-- core/authenticate/service_test.go | 4 +- core/authenticate/session/session.go | 4 +- core/authenticate/strategy/oidc.go | 2 +- core/event/service.go | 8 +- core/invitation/service.go | 7 +- core/membership/audit.go | 2 +- core/preference/preference.go | 8 +- core/preference/validator.go | 2 +- core/user/service.go | 2 +- core/webhook/service.go | 5 +- .../v1beta1connect/billing_invoice_test.go | 4 +- .../api/v1beta1connect/billing_usage_test.go | 16 ++-- internal/api/v1beta1connect/policy_test.go | 6 +- internal/api/v1beta1connect/resource_test.go | 2 +- .../reconcile/platformuser_reconciler_test.go | 10 +-- internal/reconcile/role_reconciler.go | 17 ++-- internal/reconcile/role_reconciler_test.go | 4 +- internal/reconcile/role_test.go | 64 +++++++------- internal/store/postgres/audit_record.go | 14 +-- .../store/postgres/audit_record_repository.go | 6 +- .../postgres/audit_record_repository_test.go | 14 ++- .../postgres/billing_checkout_repository.go | 4 +- .../postgres/billing_customer_repository.go | 10 +-- .../billing_customer_repository_test.go | 6 +- .../postgres/billing_invoice_repository.go | 4 +- .../billing_invoice_repository_test.go | 28 +++--- .../postgres/billing_product_repository.go | 2 +- .../billing_subscription_repository.go | 8 +- internal/store/postgres/invitation.go | 4 +- .../store/postgres/invitation_repository.go | 2 +- internal/store/postgres/kyc_repository.go | 4 +- .../store/postgres/org_billing_repository.go | 10 +-- .../postgres/org_billing_repository_test.go | 22 ++--- .../store/postgres/org_invoices_repository.go | 4 +- .../postgres/org_invoices_repository_test.go | 22 ++--- .../store/postgres/org_pats_repository.go | 4 +- .../store/postgres/org_projects_repository.go | 2 +- .../postgres/org_projects_repository_test.go | 12 +-- .../org_serviceuser_credentials_repository.go | 2 +- ...serviceuser_credentials_repository_test.go | 14 +-- .../postgres/org_serviceuser_repository.go | 2 +- .../org_serviceuser_repository_test.go | 30 +++---- .../store/postgres/org_tokens_repository.go | 4 +- .../postgres/org_tokens_repository_test.go | 14 +-- .../store/postgres/org_users_repository.go | 10 +-- .../postgres/org_users_repository_test.go | 36 ++++---- .../store/postgres/organization_repository.go | 11 ++- internal/store/postgres/policy_repository.go | 5 +- internal/store/postgres/postgres_test.go | 2 +- .../postgres/project_users_repository.go | 2 +- .../postgres/project_users_repository_test.go | 6 +- .../store/postgres/user_orgs_repository.go | 4 +- .../postgres/user_orgs_repository_test.go | 6 +- .../postgres/user_projects_repository_test.go | 6 +- internal/store/postgres/user_repository.go | 4 +- .../store/postgres/user_repository_test.go | 12 +-- .../store/postgres/userpat_repository_test.go | 2 +- internal/store/postgres/webhook_endpoint.go | 2 +- internal/store/spicedb/relation_repository.go | 4 +- pkg/file/file.go | 2 +- pkg/metadata/metadata.go | 10 +-- pkg/utils/pointers.go | 4 +- pkg/utils/rql.go | 14 +-- pkg/utils/slice.go | 16 +--- test/e2e/regression/authentication_test.go | 4 +- test/e2e/regression/billing_test.go | 34 ++++---- test/e2e/regression/serviceusers_test.go | 16 ++-- test/e2e/testbench/helper.go | 2 +- test/e2e/testbench/stripe.go | 8 +- 95 files changed, 516 insertions(+), 560 deletions(-) diff --git a/billing/checkout/service.go b/billing/checkout/service.go index 155bbe670..094f1356b 100644 --- a/billing/checkout/service.go +++ b/billing/checkout/service.go @@ -285,8 +285,8 @@ func (s *Service) Create(ctx context.Context, ch Checkout) (Checkout, error) { quantity = userCount } itemParams := &stripe.CheckoutSessionLineItemParams{ - Price: stripe.String(productPrice.ProviderID), - Quantity: stripe.Int64(quantity), + Price: new(productPrice.ProviderID), + Quantity: new(quantity), } subsItems = append(subsItems, itemParams) } @@ -302,7 +302,7 @@ func (s *Service) Create(ctx context.Context, ch Checkout) (Checkout, error) { return Checkout{}, err } if plan.TrialDays > 0 && !ch.SkipTrial && !userHasTrialedBefore { - trialDays = stripe.Int64(plan.TrialDays) + trialDays = new(plan.TrialDays) } // create subscription checkout link @@ -311,10 +311,10 @@ func (s *Service) Create(ctx context.Context, ch Checkout) (Checkout, error) { Context: ctx, }, AutomaticTax: &stripe.CheckoutSessionAutomaticTaxParams{ - Enabled: stripe.Bool(s.stripeAutoTax), + Enabled: new(s.stripeAutoTax), }, - Currency: stripe.String(billingCustomer.Currency), - Customer: stripe.String(billingCustomer.ProviderID), + Currency: new(billingCustomer.Currency), + Customer: new(billingCustomer.ProviderID), LineItems: subsItems, Metadata: map[string]string{ "org_id": billingCustomer.OrgID, @@ -324,11 +324,11 @@ func (s *Service) Create(ctx context.Context, ch Checkout) (Checkout, error) { "managed_by": "frontier", }, CustomerUpdate: &stripe.CheckoutSessionCustomerUpdateParams{ - Address: stripe.String(addressCollectionParam), + Address: new(addressCollectionParam), }, Mode: stripe.String(string(stripe.CheckoutSessionModeSubscription)), SubscriptionData: &stripe.CheckoutSessionSubscriptionDataParams{ - Description: stripe.String(fmt.Sprintf("Checkout for %s", plan.Name)), + Description: new(fmt.Sprintf("Checkout for %s", plan.Name)), Metadata: map[string]string{ "org_id": billingCustomer.OrgID, CheckoutIDMetadataKey: checkoutID, @@ -342,10 +342,10 @@ func (s *Service) Create(ctx context.Context, ch Checkout) (Checkout, error) { }, }, }, - AllowPromotionCodes: stripe.Bool(true), - CancelURL: stripe.String(ch.CancelUrl), - SuccessURL: stripe.String(ch.SuccessUrl), - ExpiresAt: stripe.Int64(time.Now().Add(SessionValidity).Unix()), + AllowPromotionCodes: new(true), + CancelURL: new(ch.CancelUrl), + SuccessURL: new(ch.SuccessUrl), + ExpiresAt: new(time.Now().Add(SessionValidity).Unix()), PaymentMethodCollection: stripe.String(string(stripe.PaymentLinkPaymentMethodCollectionIfRequired)), }) if err != nil { @@ -408,17 +408,17 @@ func (s *Service) Create(ctx context.Context, ch Checkout) (Checkout, error) { continue } itemParams := &stripe.CheckoutSessionLineItemParams{ - Price: stripe.String(productPrice.ProviderID), + Price: new(productPrice.ProviderID), AdjustableQuantity: &stripe.CheckoutSessionLineItemAdjustableQuantityParams{ - Enabled: stripe.Bool(adjustableQuantity), + Enabled: new(adjustableQuantity), }, } if adjustableQuantity { - itemParams.AdjustableQuantity.Minimum = stripe.Int64(minQ) - itemParams.AdjustableQuantity.Maximum = stripe.Int64(maxQ) + itemParams.AdjustableQuantity.Minimum = new(minQ) + itemParams.AdjustableQuantity.Maximum = new(maxQ) } if productPrice.UsageType == product.PriceUsageTypeLicensed { - itemParams.Quantity = stripe.Int64(defaultQ) + itemParams.Quantity = new(defaultQ) } if productPrice.Currency == s.defaultCurrency { @@ -435,7 +435,7 @@ func (s *Service) Create(ctx context.Context, ch Checkout) (Checkout, error) { var paymentMethodTypes []*string for _, paymentMethodConfig := range s.paymentMethodConfig { if paymentMethodConfig.IsAllowedForAmount(amountSubtotal) { - paymentMethodTypes = append(paymentMethodTypes, stripe.String(paymentMethodConfig.Type)) + paymentMethodTypes = append(paymentMethodTypes, new(paymentMethodConfig.Type)) } } @@ -445,12 +445,12 @@ func (s *Service) Create(ctx context.Context, ch Checkout) (Checkout, error) { Context: ctx, }, AutomaticTax: &stripe.CheckoutSessionAutomaticTaxParams{ - Enabled: stripe.Bool(s.stripeAutoTax), + Enabled: new(s.stripeAutoTax), }, - Currency: stripe.String(s.defaultCurrency), - Customer: stripe.String(billingCustomer.ProviderID), + Currency: new(s.defaultCurrency), + Customer: new(billingCustomer.ProviderID), InvoiceCreation: &stripe.CheckoutSessionInvoiceCreationParams{ - Enabled: stripe.Bool(true), + Enabled: new(true), }, LineItems: subsItems, Mode: stripe.String(string(stripe.CheckoutSessionModePayment)), @@ -463,12 +463,12 @@ func (s *Service) Create(ctx context.Context, ch Checkout) (Checkout, error) { "managed_by": "frontier", }, CustomerUpdate: &stripe.CheckoutSessionCustomerUpdateParams{ - Address: stripe.String(addressCollectionParam), + Address: new(addressCollectionParam), }, - AllowPromotionCodes: stripe.Bool(true), - CancelURL: stripe.String(ch.CancelUrl), - SuccessURL: stripe.String(ch.SuccessUrl), - ExpiresAt: stripe.Int64(time.Now().Add(SessionValidity).Unix()), + AllowPromotionCodes: new(true), + CancelURL: new(ch.CancelUrl), + SuccessURL: new(ch.SuccessUrl), + ExpiresAt: new(time.Now().Add(SessionValidity).Unix()), PaymentMethodTypes: paymentMethodTypes, PaymentMethodOptions: &stripe.CheckoutSessionPaymentMethodOptionsParams{ CustomerBalance: &stripe.CheckoutSessionPaymentMethodOptionsCustomerBalanceParams{ @@ -554,7 +554,7 @@ func (s *Service) SyncWithProvider(ctx context.Context, customerID string) error Context: ctx, }, Expand: []*string{ - stripe.String("line_items.data.price.product"), + new("line_items.data.price.product"), }, }) if err != nil { @@ -782,12 +782,12 @@ func (s *Service) CreateSessionForPaymentMethod(ctx context.Context, ch Checkout Params: stripe.Params{ Context: ctx, }, - Customer: stripe.String(billingCustomer.ProviderID), - Currency: stripe.String(billingCustomer.Currency), + Customer: new(billingCustomer.ProviderID), + Currency: new(billingCustomer.Currency), Mode: stripe.String(string(stripe.CheckoutSessionModeSetup)), - CancelURL: stripe.String(ch.CancelUrl), - SuccessURL: stripe.String(ch.SuccessUrl), - ExpiresAt: stripe.Int64(time.Now().Add(SessionValidity).Unix()), + CancelURL: new(ch.CancelUrl), + SuccessURL: new(ch.SuccessUrl), + ExpiresAt: new(time.Now().Add(SessionValidity).Unix()), Metadata: map[string]string{ "org_id": billingCustomer.OrgID, "checkout_id": checkoutID, @@ -827,11 +827,11 @@ func (s *Service) CreateSessionForCustomerPortal(ctx context.Context, ch Checkou Params: stripe.Params{ Context: ctx, }, - Customer: stripe.String(billingCustomer.ProviderID), + Customer: new(billingCustomer.ProviderID), } if ch.CancelUrl != "" { - sessionParams.ReturnURL = stripe.String(ch.CancelUrl) + sessionParams.ReturnURL = new(ch.CancelUrl) } session, err := s.stripeClient.BillingPortalSessions.New(sessionParams) @@ -870,7 +870,7 @@ func (s *Service) Apply(ctx context.Context, ch Checkout) (*subscription.Subscri } autoTaxParams := &stripe.SubscriptionAutomaticTaxParams{ - Enabled: stripe.Bool(s.stripeAutoTax), + Enabled: new(s.stripeAutoTax), } // checkout could be for a plan or a product @@ -929,8 +929,8 @@ func (s *Service) Apply(ctx context.Context, ch Checkout) (*subscription.Subscri } itemParams := &stripe.SubscriptionItemsParams{ - Price: stripe.String(productPrice.ProviderID), - Quantity: stripe.Int64(quantity), + Price: new(productPrice.ProviderID), + Quantity: new(quantity), Metadata: map[string]string{ "org_id": billingCustomer.OrgID, "product_id": planProduct.ID, @@ -946,19 +946,19 @@ func (s *Service) Apply(ctx context.Context, ch Checkout) (*subscription.Subscri var trialDays *int64 = nil if plan.TrialDays > 0 && !ch.SkipTrial { - trialDays = stripe.Int64(plan.TrialDays) + trialDays = new(plan.TrialDays) } if totalExpectedPrice == 0 { // if total price is 0, disable auto tax. This ensures that when the subscription is created without // user billing details while onboarding, creating 0 amount invoice doesn't fail // This will be toggled back on when the user changes it's plan to a paid one - autoTaxParams.Enabled = stripe.Bool(false) + autoTaxParams.Enabled = new(false) } var couponID *string if ch.ProviderCouponID != "" { - couponID = stripe.String(ch.ProviderCouponID) + couponID = new(ch.ProviderCouponID) } // create subscription directly stripeSubscription, err := s.stripeClient.Subscriptions.New(&stripe.SubscriptionParams{ @@ -966,8 +966,8 @@ func (s *Service) Apply(ctx context.Context, ch Checkout) (*subscription.Subscri Context: ctx, }, AutomaticTax: autoTaxParams, - Customer: stripe.String(billingCustomer.ProviderID), - Currency: stripe.String(billingCustomer.Currency), + Customer: new(billingCustomer.ProviderID), + Currency: new(billingCustomer.Currency), Items: subsItems, Metadata: map[string]string{ "org_id": billingCustomer.OrgID, diff --git a/billing/checkout/service_concurrent_test.go b/billing/checkout/service_concurrent_test.go index bc9555a20..fc5c48f9c 100644 --- a/billing/checkout/service_concurrent_test.go +++ b/billing/checkout/service_concurrent_test.go @@ -18,14 +18,12 @@ func TestService_InitClose_Concurrent(t *testing.T) { } var wg sync.WaitGroup - for i := 0; i < 2; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range 2 { + wg.Go(func() { if err := s.Init(context.Background()); err != nil { t.Errorf("Init: %v", err) } - }() + }) } wg.Wait() diff --git a/billing/credit/service.go b/billing/credit/service.go index 00501b27f..5ff4ee123 100644 --- a/billing/credit/service.go +++ b/billing/credit/service.go @@ -192,7 +192,7 @@ func (s Service) createAuditRecord(ctx context.Context, customerID string, event Target: &auditrecord.Target{ ID: txID, Type: pkgAuditRecord.BillingTransactionType, - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "amount": txEntry.Amount, "source": txEntry.Source, "description": txEntry.Description, diff --git a/billing/customer/service.go b/billing/customer/service.go index e6ed72b68..143c26a7a 100644 --- a/billing/customer/service.go +++ b/billing/customer/service.go @@ -106,8 +106,8 @@ func (s *Service) RegisterToProvider(ctx context.Context, customer Customer) (*s var customerTaxes []*stripe.CustomerTaxIDDataParams = nil for _, tax := range customer.TaxData { customerTaxes = append(customerTaxes, &stripe.CustomerTaxIDDataParams{ - Type: stripe.String(tax.Type), - Value: stripe.String(tax.ID), + Type: new(tax.Type), + Value: new(tax.ID), }) } // create a new customer in stripe @@ -318,12 +318,12 @@ func (s *Service) ListPaymentMethods(ctx context.Context, id string) ([]PaymentM } stripePaymentMethodItr := s.stripeClient.PaymentMethods.List(&stripe.PaymentMethodListParams{ - Customer: stripe.String(customer.ProviderID), + Customer: new(customer.ProviderID), ListParams: stripe.ListParams{ Context: ctx, }, Expand: []*string{ - stripe.String("data.customer"), + new("data.customer"), }, }) diff --git a/billing/customer/service_concurrent_test.go b/billing/customer/service_concurrent_test.go index c248b9abf..eca719b07 100644 --- a/billing/customer/service_concurrent_test.go +++ b/billing/customer/service_concurrent_test.go @@ -18,14 +18,12 @@ func TestService_InitClose_Concurrent(t *testing.T) { } var wg sync.WaitGroup - for i := 0; i < 2; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range 2 { + wg.Go(func() { if err := s.Init(context.Background()); err != nil { t.Errorf("Init: %v", err) } - }() + }) } wg.Wait() diff --git a/billing/customer/service_test.go b/billing/customer/service_test.go index d936442dc..348c28215 100644 --- a/billing/customer/service_test.go +++ b/billing/customer/service_test.go @@ -138,16 +138,16 @@ func TestService_Create(t *testing.T) { Context: ctx, }, Address: &stripe.AddressParams{ - City: stripe.String(""), - Country: stripe.String(""), - Line1: stripe.String(""), - Line2: stripe.String(""), - PostalCode: stripe.String(""), - State: stripe.String(""), + City: new(""), + Country: new(""), + Line1: new(""), + Line2: new(""), + PostalCode: new(""), + State: new(""), }, - Email: stripe.String(""), - Name: stripe.String("customer1"), - Phone: stripe.String(""), + Email: new(""), + Name: new("customer1"), + Phone: new(""), TaxIDData: nil, Metadata: map[string]string{ "managed_by": "frontier", @@ -232,16 +232,16 @@ func TestService_Update(t *testing.T) { Context: ctx, }, Address: &stripe.AddressParams{ - City: stripe.String(""), - Country: stripe.String(""), - Line1: stripe.String(""), - Line2: stripe.String(""), - PostalCode: stripe.String(""), - State: stripe.String(""), + City: new(""), + Country: new(""), + Line1: new(""), + Line2: new(""), + PostalCode: new(""), + State: new(""), }, - Email: stripe.String(""), - Name: stripe.String("customer1"), - Phone: stripe.String(""), + Email: new(""), + Name: new("customer1"), + Phone: new(""), TaxIDData: nil, Metadata: map[string]string{ "managed_by": "frontier", @@ -314,16 +314,16 @@ func TestService_Update(t *testing.T) { Context: ctx, }, Address: &stripe.AddressParams{ - City: stripe.String(""), - Country: stripe.String(""), - Line1: stripe.String(""), - Line2: stripe.String(""), - PostalCode: stripe.String(""), - State: stripe.String(""), + City: new(""), + Country: new(""), + Line1: new(""), + Line2: new(""), + PostalCode: new(""), + State: new(""), }, - Email: stripe.String(""), - Name: stripe.String("customer1"), - Phone: stripe.String(""), + Email: new(""), + Name: new("customer1"), + Phone: new(""), TaxIDData: nil, Metadata: map[string]string{ "managed_by": "frontier", diff --git a/billing/invoice/service.go b/billing/invoice/service.go index 0c9d81ee9..341fe9297 100644 --- a/billing/invoice/service.go +++ b/billing/invoice/service.go @@ -197,7 +197,7 @@ func (s *Service) backgroundSync(ctx context.Context) { defer record() } customers, err := s.customerService.List(ctx, customer.Filter{ - Online: utils.Bool(true), + Online: new(true), }) if err != nil { s.log.ErrorContext(ctx, "invoice.backgroundSync", "error", err) @@ -256,12 +256,12 @@ func (s *Service) SyncWithProvider(ctx context.Context, customr customer.Custome var errs []error stripeInvoices := s.stripeClient.Invoices.List(&stripe.InvoiceListParams{ - Customer: stripe.String(customr.ProviderID), + Customer: new(customr.ProviderID), ListParams: stripe.ListParams{ Context: ctx, }, Expand: []*string{ - stripe.String("data.lines"), + new("data.lines"), }, }) for stripeInvoices.Next() { @@ -350,7 +350,7 @@ func (s *Service) GetUpcoming(ctx context.Context, customerID string) (Invoice, } stripeInvoice, err := s.stripeClient.Invoices.Upcoming(&stripe.InvoiceUpcomingParams{ - Customer: stripe.String(custmr.ProviderID), + Customer: new(custmr.ProviderID), Params: stripe.Params{ Context: ctx, }, @@ -477,8 +477,8 @@ func (s *Service) GenerateForCredits(ctx context.Context) error { }() customers, err := s.customerService.List(ctx, customer.Filter{ - Online: utils.Bool(true), - AllowedOverdraft: utils.Bool(true), + Online: new(true), + AllowedOverdraft: new(true), }) if err != nil { return err @@ -651,14 +651,14 @@ func (s *Service) CreateInProvider(ctx context.Context, custmr customer.Customer var daysUntilDue *int64 if custmrDetails.DueInDays > 0 { - daysUntilDue = stripe.Int64(custmrDetails.DueInDays) + daysUntilDue = new(custmrDetails.DueInDays) } // invoice payment methods on the basis of amount subtotal var paymentMethodTypes []*string for _, paymentMethodConfig := range s.paymentMethodConfig { if paymentMethodConfig.IsAllowedForAmount(amountSubtotal) { - paymentMethodTypes = append(paymentMethodTypes, stripe.String(paymentMethodConfig.Type)) + paymentMethodTypes = append(paymentMethodTypes, new(paymentMethodConfig.Type)) } } @@ -666,16 +666,16 @@ func (s *Service) CreateInProvider(ctx context.Context, custmr customer.Customer Params: stripe.Params{ Context: ctx, }, - Customer: stripe.String(custmr.ProviderID), - AutoAdvance: stripe.Bool(true), + Customer: new(custmr.ProviderID), + AutoAdvance: new(true), DaysUntilDue: daysUntilDue, CollectionMethod: stripe.String(string(stripe.InvoiceCollectionMethodSendInvoice)), - Description: stripe.String(description), + Description: new(description), AutomaticTax: &stripe.InvoiceAutomaticTaxParams{ - Enabled: stripe.Bool(s.stripeAutoTax), + Enabled: new(s.stripeAutoTax), }, - Currency: stripe.String(currency), - PendingInvoiceItemsBehavior: stripe.String("include"), + Currency: new(currency), + PendingInvoiceItemsBehavior: new("include"), Metadata: map[string]string{ "org_id": custmr.OrgID, "managed_by": "frontier", @@ -686,7 +686,7 @@ func (s *Service) CreateInProvider(ctx context.Context, custmr customer.Customer CustomerBalance: &stripe.InvoicePaymentSettingsPaymentMethodOptionsCustomerBalanceParams{ FundingType: stripe.String(string(stripe.InvoicePaymentSettingsPaymentMethodOptionsCustomerBalanceFundingTypeBankTransfer)), BankTransfer: &stripe.InvoicePaymentSettingsPaymentMethodOptionsCustomerBalanceBankTransferParams{ - Type: stripe.String("us_bank_transfer"), + Type: new("us_bank_transfer"), }, }, }, @@ -707,8 +707,8 @@ func (s *Service) CreateInProvider(ctx context.Context, custmr customer.Customer var itemPeriod *stripe.InvoiceItemPeriodParams if item.TimeRangeStart != nil && item.TimeRangeEnd != nil { itemPeriod = &stripe.InvoiceItemPeriodParams{ - Start: stripe.Int64(item.TimeRangeStart.Unix()), - End: stripe.Int64(item.TimeRangeEnd.Unix()), + Start: new(item.TimeRangeStart.Unix()), + End: new(item.TimeRangeEnd.Unix()), } } @@ -716,13 +716,13 @@ func (s *Service) CreateInProvider(ctx context.Context, custmr customer.Customer Params: stripe.Params{ Context: ctx, }, - Customer: stripe.String(custmr.ProviderID), - Currency: stripe.String(custmr.Currency), - Invoice: stripe.String(stripeInvoice.ID), + Customer: new(custmr.ProviderID), + Currency: new(custmr.Currency), + Invoice: new(stripeInvoice.ID), UnitAmount: &item.UnitAmount, Quantity: &item.Quantity, Metadata: itemMetadata, - Description: stripe.String(item.Name), + Description: new(item.Name), Period: itemPeriod, }) if err != nil { @@ -736,7 +736,7 @@ func (s *Service) CreateInProvider(ctx context.Context, custmr customer.Customer Context: ctx, }, Expand: []*string{ - stripe.String("lines"), + new("lines"), }, }) } diff --git a/billing/invoice/service_concurrent_test.go b/billing/invoice/service_concurrent_test.go index fe79c8f0e..2320eac1c 100644 --- a/billing/invoice/service_concurrent_test.go +++ b/billing/invoice/service_concurrent_test.go @@ -18,14 +18,12 @@ func TestService_InitClose_Concurrent(t *testing.T) { } var wg sync.WaitGroup - for i := 0; i < 2; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range 2 { + wg.Go(func() { if err := s.Init(context.Background()); err != nil { t.Errorf("Init: %v", err) } - }() + }) } wg.Wait() diff --git a/billing/invoice/service_test.go b/billing/invoice/service_test.go index ac0b81da8..7d49de19f 100644 --- a/billing/invoice/service_test.go +++ b/billing/invoice/service_test.go @@ -44,38 +44,38 @@ func TestService_computeOverdraftWindow(t *testing.T) { { name: "first invoice anchors window at its end", endRange: mar1, - lastInvoice: ptr(creditItem(&createdAtTruncated, &feb1)), + lastInvoice: new(creditItem(&createdAtTruncated, &feb1)), wantStart: feb1, }, { name: "first invoice anchors window when its start equals creation time", endRange: mar1, - lastInvoice: ptr(creditItem(&createdAt, &feb1)), + lastInvoice: new(creditItem(&createdAt, &feb1)), wantStart: feb1, }, { name: "later invoice anchors window at its end instead of customer creation", endRange: jul1, - lastInvoice: ptr(creditItem(&may1, &jun1)), + lastInvoice: new(creditItem(&may1, &jun1)), wantStart: jun1, }, { name: "range ending at window end is already invoiced", endRange: jul1, - lastInvoice: ptr(creditItem(&may1, &jul1)), + lastInvoice: new(creditItem(&may1, &jul1)), wantStart: jul1, wantAlreadyInvoiced: true, }, { name: "item without range start does not panic", endRange: jul1, - lastInvoice: ptr(creditItem(nil, &jun1)), + lastInvoice: new(creditItem(nil, &jun1)), wantStart: jun1, }, { name: "item without range end keeps window at customer creation", endRange: jul1, - lastInvoice: ptr(creditItem(&may1, nil)), + lastInvoice: new(creditItem(&may1, nil)), wantStart: createdAt, }, } @@ -92,10 +92,6 @@ func TestService_computeOverdraftWindow(t *testing.T) { } } -func ptr[T any](v T) *T { - return &v -} - func TestService_getCreditOverdraftRange(t *testing.T) { tests := []struct { name string diff --git a/billing/product/service.go b/billing/product/service.go index fc6065ddf..439fe92d4 100644 --- a/billing/product/service.go +++ b/billing/product/service.go @@ -403,7 +403,7 @@ func (s *Service) setPriceActive(ctx context.Context, price Price, active bool) if price.ProviderID != "" { if _, err := s.stripeClient.Prices.Update(price.ProviderID, &stripe.PriceParams{ Params: stripe.Params{Context: ctx}, - Active: stripe.Bool(active), + Active: new(active), }); err != nil { return err } @@ -460,7 +460,7 @@ func (s *Service) CreatePrice(ctx context.Context, price Price) (Price, error) { }, Product: &price.ProductID, Nickname: &price.Name, - BillingScheme: stripe.String(price.BillingScheme.ToStripe()), + BillingScheme: new(price.BillingScheme.ToStripe()), Currency: &price.Currency, UnitAmount: &price.Amount, Metadata: map[string]string{ @@ -472,11 +472,11 @@ func (s *Service) CreatePrice(ctx context.Context, price Price) (Price, error) { } if price.Interval != "" { providerParams.Recurring = &stripe.PriceRecurringParams{ - Interval: stripe.String(price.Interval), - UsageType: stripe.String(price.UsageType.ToStripe()), + Interval: new(price.Interval), + UsageType: new(price.UsageType.ToStripe()), } if price.UsageType == PriceUsageTypeMetered { - providerParams.Recurring.AggregateUsage = stripe.String(price.MeteredAggregate) + providerParams.Recurring.AggregateUsage = new(price.MeteredAggregate) } } stripePrice, err := s.stripeClient.Prices.New(providerParams) diff --git a/billing/product/service_test.go b/billing/product/service_test.go index 9aea9f1fa..b1ca1eb78 100644 --- a/billing/product/service_test.go +++ b/billing/product/service_test.go @@ -71,9 +71,9 @@ func TestService_Create(t *testing.T) { Params: stripe.Params{ Context: ctx, }, - ID: stripe.String(""), - Name: stripe.String(""), - Description: stripe.String("product 1"), + ID: new(""), + Name: new(""), + Description: new("product 1"), Metadata: map[string]string{ "behavior": "basic", "credit_amount": "0", @@ -174,9 +174,9 @@ func TestService_Create(t *testing.T) { Params: stripe.Params{ Context: ctx, }, - ID: stripe.String(""), - Name: stripe.String(""), - Description: stripe.String("product 1"), + ID: new(""), + Name: new(""), + Description: new("product 1"), Metadata: map[string]string{ "behavior": "basic", "credit_amount": "0", @@ -211,8 +211,8 @@ func TestService_Create(t *testing.T) { Params: stripe.Params{ Context: ctx, }, - Product: stripe.String("1"), - Currency: stripe.String("usd"), + Product: new("1"), + Currency: new("usd"), UnitAmount: stripe.Int64(100), Metadata: map[string]string{ "name": "price1", @@ -220,11 +220,11 @@ func TestService_Create(t *testing.T) { "price_id": "1", "managed_by": "frontier", }, - BillingScheme: stripe.String("per_unit"), - Nickname: stripe.String("price1"), + BillingScheme: new("per_unit"), + Nickname: new("price1"), Recurring: &stripe.PriceRecurringParams{ - Interval: stripe.String("month"), - UsageType: stripe.String("licensed"), + Interval: new("month"), + UsageType: new("licensed"), }, }, &stripe.Price{ ID: "", @@ -403,8 +403,8 @@ func TestService_Update(t *testing.T) { Params: stripe.Params{ Context: ctx, }, - Name: stripe.String(""), - Description: stripe.String("product 1 new description"), + Name: new(""), + Description: new("product 1 new description"), Metadata: map[string]string{ "behavior": "basic", "managed_by": "frontier", @@ -822,8 +822,8 @@ func TestService_CreatePrice(t *testing.T) { Params: stripe.Params{ Context: ctx, }, - Product: stripe.String("1"), - Currency: stripe.String("usd"), + Product: new("1"), + Currency: new("usd"), UnitAmount: stripe.Int64(100), Metadata: map[string]string{ "name": "price1", @@ -831,11 +831,11 @@ func TestService_CreatePrice(t *testing.T) { "price_id": "1", "managed_by": "frontier", }, - BillingScheme: stripe.String("per_unit"), - Nickname: stripe.String("price1"), + BillingScheme: new("per_unit"), + Nickname: new("price1"), Recurring: &stripe.PriceRecurringParams{ - Interval: stripe.String("month"), - UsageType: stripe.String("licensed"), + Interval: new("month"), + UsageType: new("licensed"), }, }, &stripe.Price{ ID: "", @@ -934,7 +934,7 @@ func TestService_UpdatePrice(t *testing.T) { "price_id": "1", "managed_by": "frontier", }, - Nickname: stripe.String("price1.1"), + Nickname: new("price1.1"), }, &stripe.Price{ ID: "", }).Return(nil) diff --git a/billing/subscription/service.go b/billing/subscription/service.go index 058f5dfed..3ae5a7093 100644 --- a/billing/subscription/service.go +++ b/billing/subscription/service.go @@ -285,7 +285,7 @@ func getPendingInvoiceItemInterval(p plan.Plan) *stripe.SubscriptionPendingInvoi // Note: the `pending_invoice_item_interval` must be more frequent than the natural // subscription interval. return &stripe.SubscriptionPendingInvoiceItemIntervalParams{ - Interval: stripe.String("month"), + Interval: new("month"), IntervalCount: stripe.Int64(1), } } @@ -314,8 +314,8 @@ func (s *Service) Cancel(ctx context.Context, id string, immediate bool) (Subscr Params: stripe.Params{ Context: ctx, }, - InvoiceNow: stripe.Bool(true), - Prorate: stripe.Bool(true), + InvoiceNow: new(true), + Prorate: new(true), }) if err != nil { return Subscription{}, fmt.Errorf("failed to cancel subscription at billing provider: %w", err) @@ -365,7 +365,7 @@ func (s *Service) createOrGetSchedule(ctx context.Context, sub Subscription) (*s Context: ctx, }, Expand: []*string{ - stripe.String("schedule"), + new("schedule"), }, }) if err != nil { @@ -382,7 +382,7 @@ func (s *Service) createOrGetSchedule(ctx context.Context, sub Subscription) (*s Context: ctx, }, Expand: []*string{ - stripe.String("phases.items.price.product"), + new("phases.items.price.product"), }, }) if err != nil { @@ -403,9 +403,9 @@ func (s *Service) createOrGetSchedule(ctx context.Context, sub Subscription) (*s Params: stripe.Params{ Context: ctx, }, - FromSubscription: stripe.String(sub.ProviderID), + FromSubscription: new(sub.ProviderID), Expand: []*string{ - stripe.String("phases.items.price.product"), + new("phases.items.price.product"), }, }) if err != nil { @@ -677,8 +677,8 @@ func (s *Service) ChangePlan(ctx context.Context, id string, changeRequest Chang quantity = userCount } nextPhaseItems = append(nextPhaseItems, &stripe.SubscriptionSchedulePhaseItemParams{ - Price: stripe.String(planProductPrice.ProviderID), - Quantity: stripe.Int64(quantity), + Price: new(planProductPrice.ProviderID), + Quantity: new(quantity), Metadata: map[string]string{ "price_id": planProductPrice.ID, "managed_by": "frontier", @@ -701,9 +701,9 @@ func (s *Service) ChangePlan(ctx context.Context, id string, changeRequest Chang var endDate *int64 var endDateNow *bool if immediate { - endDateNow = stripe.Bool(true) + endDateNow = new(true) } else { - endDate = stripe.Int64(stripeSchedule.CurrentPhase.EndDate) + endDate = new(stripeSchedule.CurrentPhase.EndDate) } var prorationBehavior = s.config.PlanChangeConfig.ProrationBehavior if immediate { @@ -718,8 +718,8 @@ func (s *Service) ChangePlan(ctx context.Context, id string, changeRequest Chang if currentPhaseItems != nil { updatePhases = append(updatePhases, &stripe.SubscriptionSchedulePhaseParams{ Items: currentPhaseItems, - Currency: stripe.String(customerObj.Currency), - StartDate: stripe.Int64(stripeSchedule.CurrentPhase.StartDate), + Currency: new(customerObj.Currency), + StartDate: new(stripeSchedule.CurrentPhase.StartDate), EndDate: endDate, EndDateNow: endDateNow, Metadata: map[string]string{ @@ -727,14 +727,14 @@ func (s *Service) ChangePlan(ctx context.Context, id string, changeRequest Chang "managed_by": "frontier", }, AutomaticTax: &stripe.SubscriptionSchedulePhaseAutomaticTaxParams{ - Enabled: stripe.Bool(currentAutoTaxStatus), + Enabled: new(currentAutoTaxStatus), }, }) } if len(nextPhaseItems) > 0 { updatePhases = append(updatePhases, &stripe.SubscriptionSchedulePhaseParams{ Items: nextPhaseItems, - Currency: stripe.String(customerObj.Currency), + Currency: new(customerObj.Currency), Iterations: stripe.Int64(1), Metadata: map[string]string{ "plan_id": planObj.ID, @@ -743,7 +743,7 @@ func (s *Service) ChangePlan(ctx context.Context, id string, changeRequest Chang // when changing plan, we will set up autotax based on config AutomaticTax: &stripe.SubscriptionSchedulePhaseAutomaticTaxParams{ - Enabled: stripe.Bool(s.config.StripeAutoTax), + Enabled: new(s.config.StripeAutoTax), }, }) } @@ -754,10 +754,10 @@ func (s *Service) ChangePlan(ctx context.Context, id string, changeRequest Chang Context: ctx, }, Phases: updatePhases, - EndBehavior: stripe.String("release"), - ProrationBehavior: stripe.String(prorationBehavior), + EndBehavior: new("release"), + ProrationBehavior: new(prorationBehavior), DefaultSettings: &stripe.SubscriptionScheduleDefaultSettingsParams{ - CollectionMethod: stripe.String(s.config.PlanChangeConfig.CollectionMethod), + CollectionMethod: new(s.config.PlanChangeConfig.CollectionMethod), }, }) if err != nil { @@ -803,8 +803,8 @@ func (s *Service) getCurrentPhaseItemsFromSchedule(stripeSchedule *stripe.Subscr currentPhaseItems = make([]*stripe.SubscriptionSchedulePhaseItemParams, 0, len(phase.Items)) for _, item := range phase.Items { currentPhaseItems = append(currentPhaseItems, &stripe.SubscriptionSchedulePhaseItemParams{ - Price: stripe.String(item.Price.ID), - Quantity: stripe.Int64(item.Quantity), + Price: new(item.Price.ID), + Quantity: new(item.Quantity), Metadata: item.Metadata, }) } @@ -837,8 +837,8 @@ func createSchedulePhase(phase *stripe.SubscriptionSchedulePhase) *stripe.Subscr newPhaseItems := make([]*stripe.SubscriptionSchedulePhaseItemParams, 0, len(phase.Items)) for _, item := range phase.Items { newPhaseItems = append(newPhaseItems, &stripe.SubscriptionSchedulePhaseItemParams{ - Price: stripe.String(item.Price.ID), - Quantity: stripe.Int64(item.Quantity), + Price: new(item.Price.ID), + Quantity: new(item.Quantity), Metadata: item.Metadata, }) } @@ -849,23 +849,23 @@ func createSchedulePhase(phase *stripe.SubscriptionSchedulePhase) *stripe.Subscr } newPhase := &stripe.SubscriptionSchedulePhaseParams{ Items: newPhaseItems, - Currency: stripe.String(string(phase.Currency)), - StartDate: stripe.Int64(phase.StartDate), - EndDate: stripe.Int64(phase.EndDate), + Currency: new(string(phase.Currency)), + StartDate: new(phase.StartDate), + EndDate: new(phase.EndDate), Metadata: phase.Metadata, AutomaticTax: &stripe.SubscriptionSchedulePhaseAutomaticTaxParams{ - Enabled: stripe.Bool(phaseAutoTaxStatus), + Enabled: new(phaseAutoTaxStatus), }, - Description: stripe.String(phase.Description), + Description: new(phase.Description), } if phase.TrialEnd > 0 { - newPhase.TrialEnd = stripe.Int64(phase.TrialEnd) + newPhase.TrialEnd = new(phase.TrialEnd) } if phase.ProrationBehavior != "" { - newPhase.ProrationBehavior = stripe.String(string(phase.ProrationBehavior)) + newPhase.ProrationBehavior = new(string(phase.ProrationBehavior)) } if phase.CollectionMethod != nil { - newPhase.CollectionMethod = stripe.String(string(*phase.CollectionMethod)) + newPhase.CollectionMethod = new(string(*phase.CollectionMethod)) } return newPhase } @@ -918,8 +918,8 @@ func (s *Service) CancelUpcomingPhase(ctx context.Context, sub Subscription) err currentPhaseItems := make([]*stripe.SubscriptionSchedulePhaseItemParams, 0, len(stripeSchedule.Phases[0].Items)) for _, item := range stripeSchedule.Phases[0].Items { currentPhaseItems = append(currentPhaseItems, &stripe.SubscriptionSchedulePhaseItemParams{ - Price: stripe.String(item.Price.ID), - Quantity: stripe.Int64(item.Quantity), + Price: new(item.Price.ID), + Quantity: new(item.Quantity), Metadata: item.Metadata, }) } @@ -940,19 +940,19 @@ func (s *Service) CancelUpcomingPhase(ctx context.Context, sub Subscription) err Phases: []*stripe.SubscriptionSchedulePhaseParams{ { Items: currentPhaseItems, - Currency: stripe.String(currency), - StartDate: stripe.Int64(stripeSchedule.CurrentPhase.StartDate), - EndDate: stripe.Int64(stripeSchedule.CurrentPhase.EndDate), + Currency: new(currency), + StartDate: new(stripeSchedule.CurrentPhase.StartDate), + EndDate: new(stripeSchedule.CurrentPhase.EndDate), Metadata: map[string]string{ "plan_id": sub.PlanID, "managed_by": "frontier", }, }, }, - EndBehavior: stripe.String(string(endBehavior)), - ProrationBehavior: stripe.String(prorationBehavior), + EndBehavior: new(string(endBehavior)), + ProrationBehavior: new(prorationBehavior), DefaultSettings: &stripe.SubscriptionScheduleDefaultSettingsParams{ - CollectionMethod: stripe.String(s.config.PlanChangeConfig.CollectionMethod), + CollectionMethod: new(s.config.PlanChangeConfig.CollectionMethod), }, }) if err != nil { @@ -1043,7 +1043,7 @@ func (s *Service) findPlanByStripePhase(ctx context.Context, stripePhase *stripe func (s *Service) ensureCreditsForPlan(ctx context.Context, sub Subscription, subPlan plan.Plan) error { customerID := sub.CustomerID - txID := uuid.NewSHA1(credit.TxNamespaceUUID, []byte(fmt.Sprintf("%s:%s", subPlan.ID, customerID))).String() + txID := uuid.NewSHA1(credit.TxNamespaceUUID, fmt.Appendf(nil, "%s:%s", subPlan.ID, customerID)).String() if subPlan.OnStartCredits == 0 { // no such product return nil diff --git a/billing/subscription/service_concurrent_test.go b/billing/subscription/service_concurrent_test.go index d5a6bd636..dd9520392 100644 --- a/billing/subscription/service_concurrent_test.go +++ b/billing/subscription/service_concurrent_test.go @@ -20,14 +20,12 @@ func TestService_InitClose_Concurrent(t *testing.T) { } var wg sync.WaitGroup - for i := 0; i < 2; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range 2 { + wg.Go(func() { if err := s.Init(context.Background()); err != nil { t.Errorf("Init: %v", err) } - }() + }) } wg.Wait() diff --git a/billing/subscription/service_test.go b/billing/subscription/service_test.go index 5e6e9476b..f2056cbe4 100644 --- a/billing/subscription/service_test.go +++ b/billing/subscription/service_test.go @@ -389,7 +389,7 @@ func TestService_SyncWithProvider(t *testing.T) { }, }, }, - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "price_id": "price_123", }, }, nil).Times(2) // Called for both current and next phase @@ -587,7 +587,7 @@ func TestService_Create(t *testing.T) { CustomerID: "customer-1", PlanID: "plan-1", State: subscription.StateActive.String(), - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "test": "data", }, }, @@ -599,7 +599,7 @@ func TestService_Create(t *testing.T) { CustomerID: "customer-1", PlanID: "plan-1", State: subscription.StateActive.String(), - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "test": "data", }, }, nil) @@ -609,7 +609,7 @@ func TestService_Create(t *testing.T) { CustomerID: "customer-1", PlanID: "plan-1", State: subscription.StateActive.String(), - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "test": "data", }, }, diff --git a/cmd/preferences.go b/cmd/preferences.go index eb5d3f8ad..e89c8ccf8 100644 --- a/cmd/preferences.go +++ b/cmd/preferences.go @@ -182,7 +182,7 @@ func preferencesGetCommand(cliConfig *Config) *cli.Command { return cmd } -func prettyPrint(i interface{}) string { +func prettyPrint(i any) string { s, _ := json.MarshalIndent(i, "", "\t") return string(s) } diff --git a/core/aggregates/orgbilling/service.go b/core/aggregates/orgbilling/service.go index ee77dd586..2aaf995b4 100644 --- a/core/aggregates/orgbilling/service.go +++ b/core/aggregates/orgbilling/service.go @@ -108,7 +108,7 @@ func NewCSVExport(org AggregatedOrganization) CSVExport { // GetHeaders returns the CSV headers based on struct tags func (c CSVExport) GetHeaders() []string { - t := reflect.TypeOf(c) + t := reflect.TypeFor[CSVExport]() headers := make([]string, t.NumField()) for i := 0; i < t.NumField(); i++ { diff --git a/core/aggregates/orgprojects/service.go b/core/aggregates/orgprojects/service.go index 84f5214cd..8083ba3b2 100644 --- a/core/aggregates/orgprojects/service.go +++ b/core/aggregates/orgprojects/service.go @@ -92,7 +92,7 @@ func NewCSVExport(project AggregatedProject) CSVExport { // GetHeaders returns the CSV headers based on struct tags func (c CSVExport) GetHeaders() []string { - t := reflect.TypeOf(c) + t := reflect.TypeFor[CSVExport]() headers := make([]string, t.NumField()) for i := 0; i < t.NumField(); i++ { diff --git a/core/aggregates/orgtokens/service.go b/core/aggregates/orgtokens/service.go index 9c2a72dc6..ad7d698f1 100644 --- a/core/aggregates/orgtokens/service.go +++ b/core/aggregates/orgtokens/service.go @@ -84,7 +84,7 @@ func NewCSVExport(token AggregatedToken) CSVExport { // GetHeaders returns the CSV headers based on struct tags func (c CSVExport) GetHeaders() []string { - t := reflect.TypeOf(c) + t := reflect.TypeFor[CSVExport]() headers := make([]string, t.NumField()) for i := 0; i < t.NumField(); i++ { diff --git a/core/aggregates/orgusers/service.go b/core/aggregates/orgusers/service.go index 512cdb258..3f6c9706f 100644 --- a/core/aggregates/orgusers/service.go +++ b/core/aggregates/orgusers/service.go @@ -100,7 +100,7 @@ func NewCSVExport(user AggregatedUser) CSVExport { // GetHeaders returns the CSV headers based on struct tags func (c CSVExport) GetHeaders() []string { - t := reflect.TypeOf(c) + t := reflect.TypeFor[CSVExport]() headers := make([]string, t.NumField()) for i := 0; i < t.NumField(); i++ { diff --git a/core/audit/context.go b/core/audit/context.go index 434aa5da0..d57499a4a 100644 --- a/core/audit/context.go +++ b/core/audit/context.go @@ -3,6 +3,7 @@ package audit import ( "context" "fmt" + "maps" "github.com/raystack/frontier/pkg/server/consts" ) @@ -37,9 +38,7 @@ func SetContextWithMetadata(ctx context.Context, md map[string]string) context.C } // append new metadata - for k, v := range md { - existingMetadata[k] = v - } + maps.Copy(existingMetadata, md) return context.WithValue(ctx, consts.AuditMetadataContextKey, existingMetadata) } diff --git a/core/audit/logger.go b/core/audit/logger.go index 80403727a..290c5b85e 100644 --- a/core/audit/logger.go +++ b/core/audit/logger.go @@ -2,6 +2,7 @@ package audit import ( "context" + "maps" "time" "github.com/google/uuid" @@ -47,9 +48,7 @@ func (s *Logger) LogWithAttrs(action EventName, target Target, attrs map[string] } } // merge existing metadata with attrs - for k, v := range attrs { - l.Metadata[k] = v - } + maps.Copy(l.Metadata, attrs) // extract actor if s.service.actorExtractor != nil { diff --git a/core/audit/service.go b/core/audit/service.go index ab70f3991..8061472d4 100644 --- a/core/audit/service.go +++ b/core/audit/service.go @@ -107,7 +107,7 @@ func (s *Service) GetByID(ctx context.Context, id string) (Log, error) { return s.repository.GetByID(ctx, id) } -func TransformToEventData(l *Log) map[string]interface{} { +func TransformToEventData(l *Log) map[string]any { anyMap := make(map[string]any) for k, v := range l.Metadata { anyMap[k] = v diff --git a/core/audit/service_test.go b/core/audit/service_test.go index 810b5f56c..4e7c23e51 100644 --- a/core/audit/service_test.go +++ b/core/audit/service_test.go @@ -11,9 +11,9 @@ import ( ) func TestStructPB(t *testing.T) { - input := make(map[string]interface{}) + input := make(map[string]any) input["key"] = "value" - input["data"] = map[string]interface{}{ + input["data"] = map[string]any{ "key2": "value2", } @@ -30,7 +30,7 @@ func TestStructPB(t *testing.T) { delete(input, "data2") now := time.Now() - logDecoded := map[string]interface{}{} + logDecoded := map[string]any{} err = mapstructure.Decode(&Log{ Source: "source", Target: Target{ @@ -59,7 +59,7 @@ func TestTransformToEventData(t *testing.T) { tests := []struct { name string args args - want map[string]interface{} + want map[string]any }{ { name: "should decode everything except metadata", @@ -81,7 +81,7 @@ func TestTransformToEventData(t *testing.T) { CreatedAt: now, }, }, - want: map[string]interface{}{ + want: map[string]any{ "source": "source", "target": map[string]any{"id": "target-id", "type": "target-type"}, "actor": map[string]any{"id": "actor-id", "type": "actor-type", "name": "actor-name"}, @@ -98,7 +98,7 @@ func TestTransformToEventData(t *testing.T) { }, }, }, - want: map[string]interface{}{ + want: map[string]any{ "source": "source", "actor": map[string]any{}, "target": map[string]any{}, diff --git a/core/auditrecord/models/models.go b/core/auditrecord/models/models.go index 618b65537..606b9f45c 100644 --- a/core/auditrecord/models/models.go +++ b/core/auditrecord/models/models.go @@ -18,7 +18,7 @@ type AuditRecord struct { OrgID string `json:"org_id"` OrgName string `json:"org_name"` RequestID *string `json:"request_id"` - CreatedAt time.Time `json:"created_at,omitempty"` + CreatedAt time.Time `json:"created_at"` Metadata metadata.Metadata `json:"metadata"` IdempotencyKey string `json:"idempotency_key"` } diff --git a/core/auditrecord/service.go b/core/auditrecord/service.go index d36662fb1..a2f9ef8ee 100644 --- a/core/auditrecord/service.go +++ b/core/auditrecord/service.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "maps" "strings" "github.com/google/uuid" @@ -236,14 +237,12 @@ func computeHash(auditRecord AuditRecord) string { // SetAuditRecordActorContext sets the audit record actor in context // It accepts an Actor struct but stores it as a map to avoid layer violations in repositories func SetAuditRecordActorContext(ctx context.Context, actor Actor) context.Context { - var metadataMap map[string]interface{} + var metadataMap map[string]any if actor.Metadata != nil { - metadataMap = make(map[string]interface{}, len(actor.Metadata)) - for k, v := range actor.Metadata { - metadataMap[k] = v - } + metadataMap = make(map[string]any, len(actor.Metadata)) + maps.Copy(metadataMap, actor.Metadata) } - actorMap := map[string]interface{}{ + actorMap := map[string]any{ "id": actor.ID, "type": actor.Type, "name": actor.Name, diff --git a/core/auditrecord/service_test.go b/core/auditrecord/service_test.go index 4ccfa64e0..fc014efc2 100644 --- a/core/auditrecord/service_test.go +++ b/core/auditrecord/service_test.go @@ -1340,7 +1340,7 @@ func TestSetAuditRecordActorContext(t *testing.T) { assert.NotNil(t, val) // The value should be assertable as map[string]interface{} (not metadata.Metadata) - actorMap, ok := val.(map[string]interface{}) + actorMap, ok := val.(map[string]any) assert.True(t, ok, "context value should be map[string]interface{}") assert.Equal(t, "actor-123", actorMap["id"]) @@ -1349,7 +1349,7 @@ func TestSetAuditRecordActorContext(t *testing.T) { assert.Equal(t, "Test Token", actorMap["title"]) // Metadata should also be map[string]interface{}, not metadata.Metadata - metadataVal, ok := actorMap["metadata"].(map[string]interface{}) + metadataVal, ok := actorMap["metadata"].(map[string]any) assert.True(t, ok, "metadata should be map[string]interface{}") assert.Equal(t, "value1", metadataVal["key1"]) assert.Equal(t, 42, metadataVal["key2"]) @@ -1364,7 +1364,7 @@ func TestSetAuditRecordActorContext(t *testing.T) { ctx := auditrecord.SetAuditRecordActorContext(context.Background(), actor) val := ctx.Value(consts.AuditRecordActorContextKey) - actorMap, ok := val.(map[string]interface{}) + actorMap, ok := val.(map[string]any) assert.True(t, ok) // Metadata should be nil, not an empty map @@ -1380,10 +1380,10 @@ func TestSetAuditRecordActorContext(t *testing.T) { ctx := auditrecord.SetAuditRecordActorContext(context.Background(), actor) val := ctx.Value(consts.AuditRecordActorContextKey) - actorMap, ok := val.(map[string]interface{}) + actorMap, ok := val.(map[string]any) assert.True(t, ok) - metadataVal, ok := actorMap["metadata"].(map[string]interface{}) + metadataVal, ok := actorMap["metadata"].(map[string]any) assert.True(t, ok, "empty metadata should still be map[string]interface{}") assert.Empty(t, metadataVal) }) diff --git a/core/authenticate/service_test.go b/core/authenticate/service_test.go index 9bd5090c2..881e5399d 100644 --- a/core/authenticate/service_test.go +++ b/core/authenticate/service_test.go @@ -165,7 +165,7 @@ func TestService_GetPrincipal(t *testing.T) { setup: func() *authenticate.Service { mockFlow, mockUserService, mockTokenService, mockSessionService, mockServiceUserService := createMocks(t) - mockTokenService.EXPECT().Parse(mock.Anything, tokenBytes).Return(userID.String(), map[string]interface{}{}, nil) + mockTokenService.EXPECT().Parse(mock.Anything, tokenBytes).Return(userID.String(), map[string]any{}, nil) mockUserService.EXPECT().GetByID(mock.Anything, userID.String()).Return(user.User{ ID: userID.String(), }, nil) @@ -186,7 +186,7 @@ func TestService_GetPrincipal(t *testing.T) { setup: func() *authenticate.Service { mockFlow, mockUserService, mockTokenService, mockSessionService, mockServiceUserService := createMocks(t) - mockTokenService.EXPECT().Parse(mock.Anything, tokenBytes).Return("", map[string]interface{}{}, errors.New("invalid token")) + mockTokenService.EXPECT().Parse(mock.Anything, tokenBytes).Return("", map[string]any{}, errors.New("invalid token")) return authenticate.NewService(slog.New(slog.NewTextHandler(io.Discard, nil)), authenticate.Config{}, mockFlow, nil, mockTokenService, mockSessionService, mockUserService, mockServiceUserService, nil, nil) diff --git a/core/authenticate/session/session.go b/core/authenticate/session/session.go index ba84dfaa3..85194694a 100644 --- a/core/authenticate/session/session.go +++ b/core/authenticate/session/session.go @@ -49,9 +49,9 @@ func (s Session) IsValid(now time.Time) bool { // SetSessionMetadataInContext sets session metadata in context // It accepts a SessionMetadata struct but stores it as a map with the same structure to avoid layer violations in repositories func SetSessionMetadataInContext(ctx context.Context, metadata SessionMetadata) context.Context { - metadataMap := map[string]interface{}{ + metadataMap := map[string]any{ "IpAddress": metadata.IpAddress, - "Location": map[string]interface{}{ + "Location": map[string]any{ "Country": metadata.Location.Country, "City": metadata.Location.City, "Latitude": metadata.Location.Latitude, diff --git a/core/authenticate/strategy/oidc.go b/core/authenticate/strategy/oidc.go index 2233f47e4..ea5408cf9 100644 --- a/core/authenticate/strategy/oidc.go +++ b/core/authenticate/strategy/oidc.go @@ -116,7 +116,7 @@ func EmbedFlowInOIDCState(param string) (string, error) { if _, err := io.ReadFull(rand.Reader, randBytes); err != nil { return "", err } - return base64.RawURLEncoding.EncodeToString([]byte(fmt.Sprintf("%s::%s", param, randBytes))), nil + return base64.RawURLEncoding.EncodeToString(fmt.Appendf(nil, "%s::%s", param, randBytes)), nil } func ExtractFlowFromOIDCState(state string) (string, error) { diff --git a/core/event/service.go b/core/event/service.go index 163974f89..ed6075ec8 100644 --- a/core/event/service.go +++ b/core/event/service.go @@ -264,7 +264,7 @@ func (p *Service) BillingWebhook(ctx context.Context, payload ProviderWebhookEve stripe.EventTypeCheckoutSessionAsyncPaymentSucceeded: // trigger checkout sync deDupKey := fmt.Sprintf("checkout-%s-%d", providerID, currentExecutionUnit) - _, err, _ := p.sf.Do(deDupKey, func() (interface{}, error) { + _, err, _ := p.sf.Do(deDupKey, func() (any, error) { return nil, p.checkoutService.TriggerSyncByProviderID(ctx, providerID) }) if err != nil { @@ -276,7 +276,7 @@ func (p *Service) BillingWebhook(ctx context.Context, payload ProviderWebhookEve stripe.EventTypeCustomerSourceUpdated: // trigger customer sync deDupKey := fmt.Sprintf("customer-%s-%d", providerID, currentExecutionUnit) - _, err, _ := p.sf.Do(deDupKey, func() (interface{}, error) { + _, err, _ := p.sf.Do(deDupKey, func() (any, error) { return nil, p.customerService.TriggerSyncByProviderID(ctx, providerID) }) if err != nil { @@ -287,7 +287,7 @@ func (p *Service) BillingWebhook(ctx context.Context, payload ProviderWebhookEve stripe.EventTypeCustomerSubscriptionDeleted: // trigger subscriptions sync deDupKey := fmt.Sprintf("subscription-%s-%d", providerID, currentExecutionUnit) - _, err, _ := p.sf.Do(deDupKey, func() (interface{}, error) { + _, err, _ := p.sf.Do(deDupKey, func() (any, error) { return nil, p.subsService.TriggerSyncByProviderID(ctx, providerID) }) if err != nil { @@ -296,7 +296,7 @@ func (p *Service) BillingWebhook(ctx context.Context, payload ProviderWebhookEve case stripe.EventTypeInvoicePaid: // trigger invoice sync deDupKey := fmt.Sprintf("invoice-%s-%d", providerID, currentExecutionUnit) - _, err, _ := p.sf.Do(deDupKey, func() (interface{}, error) { + _, err, _ := p.sf.Do(deDupKey, func() (any, error) { return nil, p.invoiceService.TriggerSyncByProviderID(ctx, providerID) }) if err != nil { diff --git a/core/invitation/service.go b/core/invitation/service.go index ff853a788..3fae9e5f8 100644 --- a/core/invitation/service.go +++ b/core/invitation/service.go @@ -7,6 +7,7 @@ import ( "fmt" "html/template" "log/slog" + "slices" "strings" "time" @@ -339,10 +340,8 @@ func (s Service) isUserOrgMember(ctx context.Context, orgID, userID string) (use if err != nil { return userOb, false, err } - for _, id := range orgIDs { - if id == orgID { - return userOb, true, nil - } + if slices.Contains(orgIDs, orgID) { + return userOb, true, nil } return userOb, false, nil } diff --git a/core/membership/audit.go b/core/membership/audit.go index 70c16375e..f1d27951f 100644 --- a/core/membership/audit.go +++ b/core/membership/audit.go @@ -37,7 +37,7 @@ func (s *Service) createAuditRecord(ctx context.Context, record auditrecord.Audi } // The actor is enriched from the context by the repository, so the // failed record carries none; read it from the same place. - if actorMap, ok := ctx.Value(consts.AuditRecordActorContextKey).(map[string]interface{}); ok { + if actorMap, ok := ctx.Value(consts.AuditRecordActorContextKey).(map[string]any); ok { if id, ok := actorMap["id"].(string); ok { args = append(args, "actor_id", id) } diff --git a/core/preference/preference.go b/core/preference/preference.go index 8de34e30e..79d5b674e 100644 --- a/core/preference/preference.go +++ b/core/preference/preference.go @@ -2,6 +2,7 @@ package preference import ( "fmt" + "slices" "time" "github.com/raystack/frontier/internal/bootstrap/schema" @@ -91,12 +92,7 @@ type Trait struct { // IsValidScope checks if the given scope type is allowed for this trait func (t Trait) IsValidScope(scopeType string) bool { - for _, allowed := range t.AllowedScopes { - if allowed == scopeType { - return true - } - } - return false + return slices.Contains(t.AllowedScopes, scopeType) } func (t Trait) GetValidator() PreferenceValidator { diff --git a/core/preference/validator.go b/core/preference/validator.go index 97435f021..a313898ae 100644 --- a/core/preference/validator.go +++ b/core/preference/validator.go @@ -45,7 +45,7 @@ type SelectValidator struct { func NewSelectValidator(inputHints string) *SelectValidator { var allowed []string - for _, v := range strings.Split(inputHints, ",") { + for v := range strings.SplitSeq(inputHints, ",") { trimmed := strings.TrimSpace(v) if trimmed != "" { allowed = append(allowed, trimmed) diff --git a/core/user/service.go b/core/user/service.go index 94297e7e1..740e60d03 100644 --- a/core/user/service.go +++ b/core/user/service.go @@ -405,7 +405,7 @@ func NewCSVExport(user User) CSVExport { // GetHeaders returns the CSV headers based on struct tags func (c CSVExport) GetHeaders() []string { - t := reflect.TypeOf(c) + t := reflect.TypeFor[CSVExport]() headers := make([]string, t.NumField()) for i := 0; i < t.NumField(); i++ { diff --git a/core/webhook/service.go b/core/webhook/service.go index e7637d774..788bf0a9d 100644 --- a/core/webhook/service.go +++ b/core/webhook/service.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log/slog" + "maps" "net/url" "strings" "time" @@ -197,9 +198,7 @@ func (s Service) Publish(ctx context.Context, evt Event) error { } requestHeaders := make(map[string]string) - for k, v := range endpoint.Headers { - requestHeaders[k] = v - } + maps.Copy(requestHeaders, endpoint.Headers) if id, ok := consts.GetRequestIDFromCtx(ctx); ok { requestHeaders[consts.RequestIDHeader] = id } diff --git a/internal/api/v1beta1connect/billing_invoice_test.go b/internal/api/v1beta1connect/billing_invoice_test.go index da107cb50..b89bca97f 100644 --- a/internal/api/v1beta1connect/billing_invoice_test.go +++ b/internal/api/v1beta1connect/billing_invoice_test.go @@ -20,7 +20,7 @@ import ( func TestConnectHandler_ListInvoices(t *testing.T) { fixedTime := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC) - emptyStruct, _ := structpb.NewStruct(map[string]interface{}{}) + emptyStruct, _ := structpb.NewStruct(map[string]any{}) tests := []struct { name string @@ -312,7 +312,7 @@ func TestConnectHandler_ListInvoices(t *testing.T) { func TestConnectHandler_GetUpcomingInvoice(t *testing.T) { fixedTime := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC) - emptyStruct, _ := structpb.NewStruct(map[string]interface{}{}) + emptyStruct, _ := structpb.NewStruct(map[string]any{}) tests := []struct { name string diff --git a/internal/api/v1beta1connect/billing_usage_test.go b/internal/api/v1beta1connect/billing_usage_test.go index ed071ac3e..111c961ba 100644 --- a/internal/api/v1beta1connect/billing_usage_test.go +++ b/internal/api/v1beta1connect/billing_usage_test.go @@ -58,7 +58,7 @@ func TestConnectHandler_CreateBillingUsage(t *testing.T) { Source: "api", Description: "API usage", UserID: "user-123", - Metadata: map[string]interface{}{}, + Metadata: map[string]any{}, }, } us.EXPECT().Report(mock.Anything, expectedUsages).Return(errors.New("service error")) @@ -96,7 +96,7 @@ func TestConnectHandler_CreateBillingUsage(t *testing.T) { Source: "api", Description: "API usage", UserID: "user-123", - Metadata: map[string]interface{}{}, + Metadata: map[string]any{}, }, } us.EXPECT().Report(mock.Anything, expectedUsages).Return(credit.ErrInsufficientCredits) @@ -134,7 +134,7 @@ func TestConnectHandler_CreateBillingUsage(t *testing.T) { Source: "api", Description: "API usage", UserID: "user-123", - Metadata: map[string]interface{}{}, + Metadata: map[string]any{}, }, } us.EXPECT().Report(mock.Anything, expectedUsages).Return(credit.ErrAlreadyApplied) @@ -171,7 +171,7 @@ func TestConnectHandler_CreateBillingUsage(t *testing.T) { Source: "api", Description: "API usage", UserID: "user-123", - Metadata: map[string]interface{}{}, + Metadata: map[string]any{}, }, } us.EXPECT().Report(mock.Anything, expectedUsages).Return(nil) @@ -209,7 +209,7 @@ func TestConnectHandler_CreateBillingUsage(t *testing.T) { Source: "dashboard", Description: "Dashboard usage", UserID: "user-456", - Metadata: map[string]interface{}{}, + Metadata: map[string]any{}, }, } us.EXPECT().Report(mock.Anything, expectedUsages).Return(nil) @@ -256,7 +256,7 @@ func TestConnectHandler_CreateBillingUsage(t *testing.T) { Source: "api", Description: "API usage", UserID: "user-123", - Metadata: map[string]interface{}{}, + Metadata: map[string]any{}, }, { ID: "usage-2", @@ -266,7 +266,7 @@ func TestConnectHandler_CreateBillingUsage(t *testing.T) { Source: "dashboard", Description: "Dashboard usage", UserID: "user-456", - Metadata: map[string]interface{}{}, + Metadata: map[string]any{}, }, } us.EXPECT().Report(mock.Anything, expectedUsages).Return(nil) @@ -303,7 +303,7 @@ func TestConnectHandler_CreateBillingUsage(t *testing.T) { Source: "", Description: "Empty source usage", UserID: "user-123", - Metadata: map[string]interface{}{}, + Metadata: map[string]any{}, }, } us.EXPECT().Report(mock.Anything, expectedUsages).Return(nil) diff --git a/internal/api/v1beta1connect/policy_test.go b/internal/api/v1beta1connect/policy_test.go index ed106ff9c..f72789574 100644 --- a/internal/api/v1beta1connect/policy_test.go +++ b/internal/api/v1beta1connect/policy_test.go @@ -181,7 +181,7 @@ func TestConnectHandler_CreatePolicy(t *testing.T) { { name: "should successfully create policy with metadata", setup: func(ps *mocks.PolicyService) { - metadataMap := map[string]interface{}{ + metadataMap := map[string]any{ "description": "Test policy", "priority": "high", } @@ -209,7 +209,7 @@ func TestConnectHandler_CreatePolicy(t *testing.T) { Resource: "organization:" + testResourceID, Principal: "user:" + testUserID, Metadata: func() *structpb.Struct { - s, _ := structpb.NewStruct(map[string]interface{}{ + s, _ := structpb.NewStruct(map[string]any{ "description": "Test policy", "priority": "high", }) @@ -224,7 +224,7 @@ func TestConnectHandler_CreatePolicy(t *testing.T) { Resource: "app/organization:" + testResourceID, Principal: "app/user:" + testUserID, Metadata: func() *structpb.Struct { - s, _ := structpb.NewStruct(map[string]interface{}{ + s, _ := structpb.NewStruct(map[string]any{ "description": "Test policy", "priority": "high", }) diff --git a/internal/api/v1beta1connect/resource_test.go b/internal/api/v1beta1connect/resource_test.go index 462c869eb..d2906405d 100644 --- a/internal/api/v1beta1connect/resource_test.go +++ b/internal/api/v1beta1connect/resource_test.go @@ -468,7 +468,7 @@ func TestConnectHandler_GetProjectResource(t *testing.T) { name: "should return internal error if transform fails", setup: func(rs *mocks.ResourceService) { invalidResource := testResource - invalidResource.Metadata = map[string]interface{}{ + invalidResource.Metadata = map[string]any{ "invalid": func() {}, // functions can't be marshaled } rs.EXPECT().Get(mock.AnythingOfType("context.backgroundCtx"), testResource.ID).Return(invalidResource, nil) diff --git a/internal/reconcile/platformuser_reconciler_test.go b/internal/reconcile/platformuser_reconciler_test.go index dff6a33c4..12ac613fd 100644 --- a/internal/reconcile/platformuser_reconciler_test.go +++ b/internal/reconcile/platformuser_reconciler_test.go @@ -34,7 +34,7 @@ func (f *fakePlatformUserAPI) RemovePlatformUser(_ context.Context, req *connect func platformUserPB(t *testing.T, id, email, relation string) *frontierv1beta1.User { t.Helper() - md, err := structpb.NewStruct(map[string]interface{}{"relation": relation}) + md, err := structpb.NewStruct(map[string]any{"relation": relation}) if err != nil { t.Fatalf("struct: %v", err) } @@ -44,11 +44,11 @@ func platformUserPB(t *testing.T, id, email, relation string) *frontierv1beta1.U // platformUserPBRelations stamps the full "relations" list the way ListPlatformUsers does. func platformUserPBRelations(t *testing.T, id, email string, relations ...string) *frontierv1beta1.User { t.Helper() - vals := make([]interface{}, len(relations)) + vals := make([]any, len(relations)) for i, r := range relations { vals[i] = r } - md, err := structpb.NewStruct(map[string]interface{}{"relations": vals}) + md, err := structpb.NewStruct(map[string]any{"relations": vals}) if err != nil { t.Fatalf("struct: %v", err) } @@ -58,11 +58,11 @@ func platformUserPBRelations(t *testing.T, id, email string, relations ...string // serviceUserPBRelations builds a platform service-user list entry. func serviceUserPBRelations(t *testing.T, id string, relations ...string) *frontierv1beta1.ServiceUser { t.Helper() - vals := make([]interface{}, len(relations)) + vals := make([]any, len(relations)) for i, r := range relations { vals[i] = r } - md, err := structpb.NewStruct(map[string]interface{}{"relations": vals}) + md, err := structpb.NewStruct(map[string]any{"relations": vals}) if err != nil { t.Fatalf("struct: %v", err) } diff --git a/internal/reconcile/role_reconciler.go b/internal/reconcile/role_reconciler.go index fa2616815..78bdcecc9 100644 --- a/internal/reconcile/role_reconciler.go +++ b/internal/reconcile/role_reconciler.go @@ -3,6 +3,7 @@ package reconcile import ( "context" "fmt" + "maps" "sort" "connectrpc.com/connect" @@ -121,13 +122,13 @@ func (r *RoleReconciler) Export(ctx context.Context) (any, error) { for _, field := range changes { switch field { case "title": - entry.Title = strPtr(have.Title) + entry.Title = new(have.Title) case "description": - entry.Description = strPtr(have.Description) + entry.Description = new(have.Description) case "permissions": - entry.Permissions = slicePtr(have.Permissions) + entry.Permissions = new(have.Permissions) case "scopes": - entry.Scopes = slicePtr(have.Scopes) + entry.Scopes = new(have.Scopes) } } specs = append(specs, entry) @@ -135,10 +136,6 @@ func (r *RoleReconciler) Export(ctx context.Context) (any, error) { return specs, nil } -func strPtr(s string) *string { return &s } - -func slicePtr(s []string) *[]string { return &s } - func (r *RoleReconciler) fetchCurrent(ctx context.Context) ([]currentRole, error) { resp, err := r.client.ListRoles(ctx, authReq(&frontierv1beta1.ListRolesRequest{}, r.header)) if err != nil { @@ -204,9 +201,7 @@ func (r *RoleReconciler) apply(ctx context.Context, op roleOp) error { // dropped. An empty managed description clears the key, matching a reset. func roleBody(name string, want roleFields, base map[string]any) (*frontierv1beta1.RoleRequestBody, error) { fields := map[string]any{} - for k, v := range base { - fields[k] = v - } + maps.Copy(fields, base) fields[managedByKey] = managedByValue if want.Description != "" { fields[descriptionKey] = want.Description diff --git a/internal/reconcile/role_reconciler_test.go b/internal/reconcile/role_reconciler_test.go index 2de6e4356..64e14b4e5 100644 --- a/internal/reconcile/role_reconciler_test.go +++ b/internal/reconcile/role_reconciler_test.go @@ -271,7 +271,7 @@ func TestRoleReconciler(t *testing.T) { assert.NoError(t, err) assert.Equal(t, []RoleSpec{{ Name: schema.RoleOrganizationOwner, - Permissions: ptr([]string{"app_organization_get", "app_organization_policymanage", "app_organization_update"}), + Permissions: new([]string{"app_organization_get", "app_organization_policymanage", "app_organization_update"}), }}, spec) out, err := Export(context.Background(), registry, KindRole) @@ -294,7 +294,7 @@ func TestRoleReconciler(t *testing.T) { assert.NoError(t, err) assert.Equal(t, []RoleSpec{{ Name: schema.RoleOrganizationOwner, - Scopes: ptr([]string{schema.OrganizationNamespace, "compute/order"}), + Scopes: new([]string{schema.OrganizationNamespace, "compute/order"}), }}, spec) out, err := Export(context.Background(), registry, KindRole) diff --git a/internal/reconcile/role_test.go b/internal/reconcile/role_test.go index 85358896c..7ee087144 100644 --- a/internal/reconcile/role_test.go +++ b/internal/reconcile/role_test.go @@ -8,10 +8,6 @@ import ( "github.com/stretchr/testify/assert" ) -// ptr and slicePtr build the presence-tracking pointers a RoleSpec now uses: -// a nil pointer is an omitted field, a non-nil one is a listed value. -func ptr[T any](v T) *T { return &v } - func TestDiffRoles(t *testing.T) { current := []currentRole{ {ID: "r1", Name: "compute_manager", Title: "Compute Manager", @@ -27,9 +23,9 @@ func TestDiffRoles(t *testing.T) { // file is the whole desired state: an omitted field defaults to empty and // would clear the server value. This is what an export writes. keepCustom := []RoleSpec{ - {Name: "compute_manager", Title: ptr("Compute Manager"), - Permissions: ptr([]string{"compute_order_get", "compute_order_update"}), Scopes: ptr([]string{"compute/order"})}, - {Name: "old_role", Title: ptr("Old"), Permissions: ptr([]string{"compute_order_get"})}, + {Name: "compute_manager", Title: new("Compute Manager"), + Permissions: new([]string{"compute_order_get", "compute_order_update"}), Scopes: new([]string{"compute/order"})}, + {Name: "old_role", Title: new("Old"), Permissions: new([]string{"compute_order_get"})}, } t.Run("no changes when converged, unlisted predefined roles at defaults", func(t *testing.T) { @@ -63,7 +59,7 @@ func TestDiffRoles(t *testing.T) { ops, err := diffRoles(append(keepCustom, RoleSpec{ Name: schema.RoleOrganizationOwner, - Permissions: ptr([]string{"app_organization_administer", "app_organization_get"}), + Permissions: new([]string{"app_organization_administer", "app_organization_get"}), }), drifted) assert.NoError(t, err) @@ -98,7 +94,7 @@ func TestDiffRoles(t *testing.T) { Permissions: []string{"app_organization_administer"}}) // empty scopes ops, err := diffRoles(append(keepCustom, RoleSpec{ - Name: schema.RoleOrganizationOwner, Scopes: ptr([]string{schema.OrganizationNamespace}), + Name: schema.RoleOrganizationOwner, Scopes: new([]string{schema.OrganizationNamespace}), }), legacy) assert.NoError(t, err) if assert.Len(t, ops, 1) { @@ -110,7 +106,7 @@ func TestDiffRoles(t *testing.T) { // `scopes: []` in the file is a listed value, not an omission, so it // overrides the definition's scopes with an empty set. ops, err := diffRoles(append(keepCustom, RoleSpec{ - Name: schema.RoleOrganizationOwner, Scopes: ptr([]string{}), + Name: schema.RoleOrganizationOwner, Scopes: new([]string{}), }), current) assert.NoError(t, err) if assert.Len(t, ops, 1) { @@ -121,9 +117,9 @@ func TestDiffRoles(t *testing.T) { t.Run("permission references in any form match slugs", func(t *testing.T) { ops, err := diffRoles([]RoleSpec{ - {Name: "compute_manager", Title: ptr("Compute Manager"), - Permissions: ptr([]string{"compute/order:get", "compute.order.update"}), Scopes: ptr([]string{"compute/order"})}, - {Name: "old_role", Title: ptr("Old"), Permissions: ptr([]string{"compute_order_get"})}, + {Name: "compute_manager", Title: new("Compute Manager"), + Permissions: new([]string{"compute/order:get", "compute.order.update"}), Scopes: new([]string{"compute/order"})}, + {Name: "old_role", Title: new("Old"), Permissions: new([]string{"compute_order_get"})}, }, current) assert.NoError(t, err) assert.Empty(t, ops) @@ -131,10 +127,10 @@ func TestDiffRoles(t *testing.T) { t.Run("adds, updates, and deletes in that order", func(t *testing.T) { ops, err := diffRoles([]RoleSpec{ - {Name: "compute_manager", Title: ptr("Compute Admin"), - Permissions: ptr([]string{"compute_order_get", "compute_order_update"}), Scopes: ptr([]string{"compute/order"})}, + {Name: "compute_manager", Title: new("Compute Admin"), + Permissions: new([]string{"compute_order_get", "compute_order_update"}), Scopes: new([]string{"compute/order"})}, {Name: "old_role", Delete: true}, - {Name: "new_role", Title: ptr("New"), Permissions: ptr([]string{"compute_order_get"})}, + {Name: "new_role", Title: new("New"), Permissions: new([]string{"compute_order_get"})}, }, current) assert.NoError(t, err) @@ -151,8 +147,8 @@ func TestDiffRoles(t *testing.T) { // they are not kept from the server. So listing only permissions here also // clears the title and scopes, because the file is the whole desired state. ops, err := diffRoles([]RoleSpec{ - {Name: "compute_manager", Permissions: ptr([]string{"compute_order_get"})}, // narrow perms, title and scopes omitted - {Name: "old_role", Title: ptr("Old"), Permissions: ptr([]string{"compute_order_get"})}, + {Name: "compute_manager", Permissions: new([]string{"compute_order_get"})}, // narrow perms, title and scopes omitted + {Name: "old_role", Title: new("Old"), Permissions: new([]string{"compute_order_get"})}, }, current) assert.NoError(t, err) @@ -171,9 +167,9 @@ func TestDiffRoles(t *testing.T) { // file is the whole desired state. Export writes them all out for exactly // this reason. ops, err := diffRoles([]RoleSpec{ - {Name: "compute_manager", Title: ptr("Compute Manager"), - Permissions: ptr([]string{"compute_order_get"}), Scopes: ptr([]string{"compute/order"})}, - {Name: "old_role", Title: ptr("Old"), Permissions: ptr([]string{"compute_order_get"})}, + {Name: "compute_manager", Title: new("Compute Manager"), + Permissions: new([]string{"compute_order_get"}), Scopes: new([]string{"compute/order"})}, + {Name: "old_role", Title: new("Old"), Permissions: new([]string{"compute_order_get"})}, }, current) assert.NoError(t, err) @@ -188,9 +184,9 @@ func TestDiffRoles(t *testing.T) { t.Run("a custom role's description is managed like its title", func(t *testing.T) { ops, err := diffRoles([]RoleSpec{ - {Name: "compute_manager", Title: ptr("Compute Manager"), Description: ptr("Runs compute orders"), - Permissions: ptr([]string{"compute_order_get", "compute_order_update"}), Scopes: ptr([]string{"compute/order"})}, - {Name: "old_role", Title: ptr("Old"), Permissions: ptr([]string{"compute_order_get"})}, + {Name: "compute_manager", Title: new("Compute Manager"), Description: new("Runs compute orders"), + Permissions: new([]string{"compute_order_get", "compute_order_update"}), Scopes: new([]string{"compute/order"})}, + {Name: "old_role", Title: new("Old"), Permissions: new([]string{"compute_order_get"})}, }, current) assert.NoError(t, err) @@ -219,8 +215,8 @@ func TestDiffRoles(t *testing.T) { t.Run("predefined role title and permissions can be managed", func(t *testing.T) { specs := append(keepCustom, RoleSpec{ Name: schema.RoleOrganizationOwner, - Title: ptr("Workspace Owner"), - Permissions: ptr([]string{"app_organization_administer", "app_organization_get"}), + Title: new("Workspace Owner"), + Permissions: new([]string{"app_organization_administer", "app_organization_get"}), }) ops, err := diffRoles(specs, current) @@ -237,13 +233,13 @@ func TestDiffRoles(t *testing.T) { }) t.Run("a listed predefined role missing on the server fails the plan", func(t *testing.T) { - _, err := diffRoles(append(keepCustom, RoleSpec{Name: schema.GroupOwnerRole, Title: ptr("X")}), current) + _, err := diffRoles(append(keepCustom, RoleSpec{Name: schema.GroupOwnerRole, Title: new("X")}), current) assert.ErrorContains(t, err, "not found on the server") }) t.Run("a custom server role missing from the file fails the plan", func(t *testing.T) { _, err := diffRoles([]RoleSpec{ - {Name: "compute_manager", Permissions: ptr([]string{"compute_order_get", "compute_order_update"})}, + {Name: "compute_manager", Permissions: new([]string{"compute_order_get", "compute_order_update"})}, }, current) assert.ErrorContains(t, err, "old_role") assert.ErrorContains(t, err, "delete: true") @@ -254,8 +250,8 @@ func TestDiffRoles(t *testing.T) { // desired title is empty. A server role that still has a title drifts and // the title is cleared. ops, err := diffRoles([]RoleSpec{ - {Name: "compute_manager", Permissions: ptr([]string{"compute_order_get", "compute_order_update"}), Scopes: ptr([]string{"compute/order"})}, // title omitted - {Name: "old_role", Title: ptr("Old"), Permissions: ptr([]string{"compute_order_get"})}, + {Name: "compute_manager", Permissions: new([]string{"compute_order_get", "compute_order_update"}), Scopes: new([]string{"compute/order"})}, // title omitted + {Name: "old_role", Title: new("Old"), Permissions: new([]string{"compute_order_get"})}, }, current) assert.NoError(t, err) if assert.Len(t, ops, 1) { @@ -266,8 +262,8 @@ func TestDiffRoles(t *testing.T) { t.Run("duplicate names fail", func(t *testing.T) { _, err := diffRoles([]RoleSpec{ - {Name: "compute_manager", Permissions: ptr([]string{"a"})}, - {Name: "compute_manager", Permissions: ptr([]string{"b"})}, + {Name: "compute_manager", Permissions: new([]string{"a"})}, + {Name: "compute_manager", Permissions: new([]string{"b"})}, }, current) assert.ErrorContains(t, err, "listed more than once") }) @@ -286,13 +282,13 @@ func TestDiffRoles(t *testing.T) { _, omitted := diffRoles([]RoleSpec{{Name: "empty_custom"}}, nil) assert.ErrorContains(t, omitted, "at least one permission") - _, explicit := diffRoles([]RoleSpec{{Name: "empty_custom", Permissions: ptr([]string{})}}, nil) + _, explicit := diffRoles([]RoleSpec{{Name: "empty_custom", Permissions: new([]string{})}}, nil) assert.ErrorContains(t, explicit, "at least one permission") }) t.Run("a predefined role set to empty permissions fails the plan", func(t *testing.T) { cur := []currentRole{{ID: "r1", Name: schema.RoleOrganizationViewer, Permissions: []string{"app_organization_get"}}} - _, err := diffRoles([]RoleSpec{{Name: schema.RoleOrganizationViewer, Permissions: ptr([]string{})}}, cur) + _, err := diffRoles([]RoleSpec{{Name: schema.RoleOrganizationViewer, Permissions: new([]string{})}}, cur) assert.ErrorContains(t, err, "at least one permission") }) } diff --git a/internal/store/postgres/audit_record.go b/internal/store/postgres/audit_record.go index c26a65662..6319c7aae 100644 --- a/internal/store/postgres/audit_record.go +++ b/internal/store/postgres/audit_record.go @@ -149,12 +149,12 @@ func transformFromDomain(record auditrecord.AuditRecord) (AuditRecord, error) { }, nil } -func extractActorFromContext(ctx context.Context) (string, string, string, string, map[string]interface{}) { +func extractActorFromContext(ctx context.Context) (string, string, string, string, map[string]any) { var id, actorType, name, title string - var actorMetadata map[string]interface{} + var actorMetadata map[string]any if val := ctx.Value(consts.AuditRecordActorContextKey); val != nil { - if actorMap, ok := val.(map[string]interface{}); ok { + if actorMap, ok := val.(map[string]any); ok { if v, ok := actorMap["id"].(string); ok { id = v } @@ -167,7 +167,7 @@ func extractActorFromContext(ctx context.Context) (string, string, string, strin if v, ok := actorMap["title"].(string); ok { title = v } - if v, ok := actorMap["metadata"].(map[string]interface{}); ok { + if v, ok := actorMap["metadata"].(map[string]any); ok { actorMetadata = v } } @@ -175,9 +175,9 @@ func extractActorFromContext(ctx context.Context) (string, string, string, strin return id, actorType, name, title, actorMetadata } -func extractSessionMetadataFromContext(ctx context.Context) map[string]interface{} { +func extractSessionMetadataFromContext(ctx context.Context) map[string]any { if val := ctx.Value(consts.SessionContextKey); val != nil { - if sessionMetadataMap, ok := val.(map[string]interface{}); ok { + if sessionMetadataMap, ok := val.(map[string]any); ok { return sessionMetadataMap } } @@ -213,7 +213,7 @@ func enrichActorFromContext(ctx context.Context, actor *auditrecord.Actor) { // Add additional enrichments if actor.Metadata == nil { - actor.Metadata = make(map[string]interface{}) + actor.Metadata = make(map[string]any) } if isSuperUser := extractSuperUserFromContext(ctx); isSuperUser { diff --git a/internal/store/postgres/audit_record_repository.go b/internal/store/postgres/audit_record_repository.go index 1083ad50b..ce0854623 100644 --- a/internal/store/postgres/audit_record_repository.go +++ b/internal/store/postgres/audit_record_repository.go @@ -64,7 +64,7 @@ var ( } ) -func buildOrgNameQuery(orgID interface{}) (string, []interface{}, error) { +func buildOrgNameQuery(orgID any) (string, []any, error) { return dialect.Select("title"). From(TABLE_ORGANIZATIONS). Where(goqu.Ex{"id": orgID}). @@ -124,7 +124,7 @@ func (r AuditRecordRepository) GetByIdempotencyKey(ctx context.Context, key stri return r.getByField(ctx, "idempotency_key", key, "GetByIdempotencyKey") } -func (r AuditRecordRepository) getByField(ctx context.Context, field string, value interface{}, operation string) (auditrecord.AuditRecord, error) { +func (r AuditRecordRepository) getByField(ctx context.Context, field string, value any, operation string) (auditrecord.AuditRecord, error) { if str, ok := value.(string); ok && str == "" { return auditrecord.AuditRecord{}, auditrecord.ErrNotFound } @@ -424,7 +424,7 @@ func (r AuditRecordRepository) streamCursorToCSV(ctx context.Context, tx *sql.Tx for rows.Next() { // Scan all columns into string slice values := make([]string, len(headers)) - valuePtrs := make([]interface{}, len(headers)) + valuePtrs := make([]any, len(headers)) for i := range values { valuePtrs[i] = &values[i] } diff --git a/internal/store/postgres/audit_record_repository_test.go b/internal/store/postgres/audit_record_repository_test.go index 55966d7f0..a54cc9511 100644 --- a/internal/store/postgres/audit_record_repository_test.go +++ b/internal/store/postgres/audit_record_repository_test.go @@ -147,7 +147,7 @@ func (s *AuditRecordRepositoryTestSuite) createValidAuditRecord() auditrecord.Au }, OccurredAt: time.Now().UTC(), OrgID: uuid.New().String(), - RequestID: stringPtr("req-" + uuid.New().String()), + RequestID: new("req-" + uuid.New().String()), Metadata: metadata.Metadata{ "ip_address": "192.168.1.1", }, @@ -155,10 +155,6 @@ func (s *AuditRecordRepositoryTestSuite) createValidAuditRecord() auditrecord.Au } } -func stringPtr(s string) *string { - return &s -} - // TEST 1: Create audit record - Success cases func (s *AuditRecordRepositoryTestSuite) TestCreate_Success() { tests := []struct { @@ -528,7 +524,7 @@ func (s *AuditRecordRepositoryTestSuite) TestConcurrency() { const numGoroutines = 10 errChan := make(chan error, numGoroutines) - for i := 0; i < numGoroutines; i++ { + for i := range numGoroutines { go func(index int) { record := s.createValidAuditRecord() record.IdempotencyKey = uuid.New().String() // Each goroutine gets unique UUID @@ -538,7 +534,7 @@ func (s *AuditRecordRepositoryTestSuite) TestConcurrency() { }(i) } - for i := 0; i < numGoroutines; i++ { + for range numGoroutines { err := <-errChan s.NoError(err, "Concurrent create should succeed") } @@ -551,7 +547,7 @@ func (s *AuditRecordRepositoryTestSuite) TestConcurrency() { successes := 0 conflicts := 0 - for i := 0; i < numGoroutines; i++ { + for range numGoroutines { go func() { record := s.createValidAuditRecord() record.IdempotencyKey = sharedKey // All use the same key @@ -562,7 +558,7 @@ func (s *AuditRecordRepositoryTestSuite) TestConcurrency() { } // Collect results - for i := 0; i < numGoroutines; i++ { + for range numGoroutines { err := <-errChan if err == nil { successes++ diff --git a/internal/store/postgres/billing_checkout_repository.go b/internal/store/postgres/billing_checkout_repository.go index 5c33e4364..b2520cdcd 100644 --- a/internal/store/postgres/billing_checkout_repository.go +++ b/internal/store/postgres/billing_checkout_repository.go @@ -24,7 +24,7 @@ type SubscriptionConfig struct { CancelAfterTrial bool `db:"cancel_after_trial" json:"cancel_after_trial"` } -func (s *SubscriptionConfig) Scan(src interface{}) error { +func (s *SubscriptionConfig) Scan(src any) error { switch src := src.(type) { case []byte: return json.Unmarshal(src, s) @@ -186,7 +186,7 @@ func (r BillingCheckoutRepository) Create(ctx context.Context, toCreate checkout &AuditTarget{ ID: checkoutModel.ID, Type: auditrecord.BillingCheckoutType, - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "plan_id": ptrToString(checkoutModel.PlanID), "feature_id": ptrToString(checkoutModel.FeatureID), "state": checkoutModel.State, diff --git a/internal/store/postgres/billing_customer_repository.go b/internal/store/postgres/billing_customer_repository.go index 51b1fcc5e..a6879dcf7 100644 --- a/internal/store/postgres/billing_customer_repository.go +++ b/internal/store/postgres/billing_customer_repository.go @@ -24,7 +24,7 @@ type Tax struct { TaxIDs []customer.Tax `json:"taxids"` } -func (t *Tax) Scan(src interface{}) error { +func (t *Tax) Scan(src any) error { switch src := src.(type) { case []byte: return json.Unmarshal(src, t) @@ -168,7 +168,7 @@ func (r BillingCustomerRepository) Create(ctx context.Context, toCreate customer ID: customerModel.ID, Type: auditrecord.BillingCustomerType, Name: customerModel.Name, - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "email": customerModel.Email, "currency": customerModel.Currency, "address": customerModel.Address, @@ -327,7 +327,7 @@ func (r BillingCustomerRepository) UpdateByID(ctx context.Context, toUpdate cust return err } - auditMetadata := map[string]interface{}{ + auditMetadata := map[string]any{ "email": customerModel.Email, "currency": customerModel.Currency, "address": customerModel.Address, @@ -466,7 +466,7 @@ func (r BillingCustomerRepository) UpdateDetailsByID(ctx context.Context, custom ID: customerModel.ID, Type: auditrecord.BillingCustomerType, Name: customerModel.Name, - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "credit_min": customerModel.CreditMin, "due_in_days": customerModel.DueInDays, }, @@ -526,7 +526,7 @@ func (r BillingCustomerRepository) Delete(ctx context.Context, id string) error ID: customerModel.ID, Type: auditrecord.BillingCustomerType, Name: customerModel.Name, - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "email": customerModel.Email, "currency": customerModel.Currency, "address": customerModel.Address, diff --git a/internal/store/postgres/billing_customer_repository_test.go b/internal/store/postgres/billing_customer_repository_test.go index 3414a3c95..fd39cab34 100644 --- a/internal/store/postgres/billing_customer_repository_test.go +++ b/internal/store/postgres/billing_customer_repository_test.go @@ -279,7 +279,7 @@ func (s *BillingCustomerRepositoryTestSuite) TestList() { filter: customer.Filter{ OrgID: s.orgIDs[0], State: customer.ActiveState, - Online: utils.Bool(true), + Online: new(true), }, }, { @@ -290,8 +290,8 @@ func (s *BillingCustomerRepositoryTestSuite) TestList() { filter: customer.Filter{ OrgID: s.orgIDs[0], State: customer.ActiveState, - Online: utils.Bool(true), - AllowedOverdraft: utils.Bool(true), + Online: new(true), + AllowedOverdraft: new(true), }, }, } diff --git a/internal/store/postgres/billing_invoice_repository.go b/internal/store/postgres/billing_invoice_repository.go index 7f42cd7ac..c1d36d791 100644 --- a/internal/store/postgres/billing_invoice_repository.go +++ b/internal/store/postgres/billing_invoice_repository.go @@ -45,7 +45,7 @@ type Items struct { Data []invoice.Item `json:"data"` } -func (t *Items) Scan(src interface{}) error { +func (t *Items) Scan(src any) error { switch src := src.(type) { case []byte: return json.Unmarshal(src, t) @@ -361,7 +361,7 @@ func (r BillingInvoiceRepository) Search(ctx context.Context, rqlQuery *rql.Quer return invoices, nil } -func (r BillingInvoiceRepository) prepareDataQuery(rqlQuery *rql.Query) (string, []interface{}, error) { +func (r BillingInvoiceRepository) prepareDataQuery(rqlQuery *rql.Query) (string, []any, error) { query := r.buildBaseQuery() // Apply filters diff --git a/internal/store/postgres/billing_invoice_repository_test.go b/internal/store/postgres/billing_invoice_repository_test.go index 69486233d..904d92ddb 100644 --- a/internal/store/postgres/billing_invoice_repository_test.go +++ b/internal/store/postgres/billing_invoice_repository_test.go @@ -16,7 +16,7 @@ func TestBillingInvoiceRepository_prepareDataQuery(t *testing.T) { name string rql *rql.Query wantSQL string - wantParams []interface{} + wantParams []any wantErr bool }{ { @@ -26,7 +26,7 @@ func TestBillingInvoiceRepository_prepareDataQuery(t *testing.T) { Offset: 20, }, wantSQL: `SELECT "billing_invoices"."id" AS "id", "billing_invoices"."amount" AS "amount", "billing_invoices"."currency" AS "currency", "billing_invoices"."state" AS "state", "billing_invoices"."hosted_url" AS "hosted_url", "billing_invoices"."created_at" AS "created_at", "organizations"."id" AS "org_id", "organizations"."name" AS "org_name", "organizations"."title" AS "org_title" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") LIMIT $1 OFFSET $2`, - wantParams: []interface{}{int64(10), int64(20)}, + wantParams: []any{int64(10), int64(20)}, wantErr: false, }, { @@ -43,7 +43,7 @@ func TestBillingInvoiceRepository_prepareDataQuery(t *testing.T) { Offset: 50, }, wantSQL: `SELECT "billing_invoices"."id" AS "id", "billing_invoices"."amount" AS "amount", "billing_invoices"."currency" AS "currency", "billing_invoices"."state" AS "state", "billing_invoices"."hosted_url" AS "hosted_url", "billing_invoices"."created_at" AS "created_at", "organizations"."id" AS "org_id", "organizations"."name" AS "org_name", "organizations"."title" AS "org_title" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE ("billing_invoices"."amount" >= $1) LIMIT $2 OFFSET $3`, - wantParams: []interface{}{int64(1000), int64(10), int64(50)}, + wantParams: []any{int64(1000), int64(10), int64(50)}, wantErr: false, }, { @@ -61,7 +61,7 @@ func TestBillingInvoiceRepository_prepareDataQuery(t *testing.T) { Offset: 30, }, wantSQL: `SELECT "billing_invoices"."id" AS "id", "billing_invoices"."amount" AS "amount", "billing_invoices"."currency" AS "currency", "billing_invoices"."state" AS "state", "billing_invoices"."hosted_url" AS "hosted_url", "billing_invoices"."created_at" AS "created_at", "organizations"."id" AS "org_id", "organizations"."name" AS "org_name", "organizations"."title" AS "org_title" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."state" = $1) AND ((CAST("billing_invoices"."state" AS TEXT) ILIKE $2) OR (CAST("billing_invoices"."currency" AS TEXT) ILIKE $3) OR (CAST("billing_invoices"."amount" AS TEXT) ILIKE $4) OR (CAST("organizations"."name" AS TEXT) ILIKE $5) OR (CAST("organizations"."title" AS TEXT) ILIKE $6))) LIMIT $7 OFFSET $8`, - wantParams: []interface{}{"paid", "%test%", "%test%", "%test%", "%test%", "%test%", int64(10), int64(30)}, + wantParams: []any{"paid", "%test%", "%test%", "%test%", "%test%", "%test%", int64(10), int64(30)}, wantErr: false, }, { @@ -77,7 +77,7 @@ func TestBillingInvoiceRepository_prepareDataQuery(t *testing.T) { Offset: 40, }, wantSQL: `SELECT "billing_invoices"."id" AS "id", "billing_invoices"."amount" AS "amount", "billing_invoices"."currency" AS "currency", "billing_invoices"."state" AS "state", "billing_invoices"."hosted_url" AS "hosted_url", "billing_invoices"."created_at" AS "created_at", "organizations"."id" AS "org_id", "organizations"."name" AS "org_name", "organizations"."title" AS "org_title" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") ORDER BY "billing_invoices"."state" DESC LIMIT $1 OFFSET $2`, - wantParams: []interface{}{int64(10), int64(40)}, + wantParams: []any{int64(10), int64(40)}, wantErr: false, }, { @@ -93,7 +93,7 @@ func TestBillingInvoiceRepository_prepareDataQuery(t *testing.T) { Offset: 40, }, wantSQL: `SELECT "billing_invoices"."id" AS "id", "billing_invoices"."amount" AS "amount", "billing_invoices"."currency" AS "currency", "billing_invoices"."state" AS "state", "billing_invoices"."hosted_url" AS "hosted_url", "billing_invoices"."created_at" AS "created_at", "organizations"."id" AS "org_id", "organizations"."name" AS "org_name", "organizations"."title" AS "org_title" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") ORDER BY "organizations"."name" ASC LIMIT $1 OFFSET $2`, - wantParams: []interface{}{int64(10), int64(40)}, + wantParams: []any{int64(10), int64(40)}, wantErr: false, }, { @@ -125,7 +125,7 @@ func TestBillingInvoiceRepository_prepareDataQuery(t *testing.T) { Offset: 1, }, wantSQL: `SELECT "billing_invoices"."id" AS "id", "billing_invoices"."amount" AS "amount", "billing_invoices"."currency" AS "currency", "billing_invoices"."state" AS "state", "billing_invoices"."hosted_url" AS "hosted_url", "billing_invoices"."created_at" AS "created_at", "organizations"."id" AS "org_id", "organizations"."name" AS "org_name", "organizations"."title" AS "org_title" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."state" IS NULL) OR ("billing_invoices"."state" = $1)) LIMIT $2 OFFSET $3`, - wantParams: []interface{}{"", int64(10), int64(1)}, + wantParams: []any{"", int64(10), int64(1)}, wantErr: false, }, { @@ -141,7 +141,7 @@ func TestBillingInvoiceRepository_prepareDataQuery(t *testing.T) { Offset: 1, }, wantSQL: `SELECT "billing_invoices"."id" AS "id", "billing_invoices"."amount" AS "amount", "billing_invoices"."currency" AS "currency", "billing_invoices"."state" AS "state", "billing_invoices"."hosted_url" AS "hosted_url", "billing_invoices"."created_at" AS "created_at", "organizations"."id" AS "org_id", "organizations"."name" AS "org_name", "organizations"."title" AS "org_title" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE (("billing_invoices"."state" IS NOT NULL) AND ("billing_invoices"."state" != $1)) LIMIT $2 OFFSET $3`, - wantParams: []interface{}{"", int64(10), int64(1)}, + wantParams: []any{"", int64(10), int64(1)}, wantErr: false, }, { @@ -158,7 +158,7 @@ func TestBillingInvoiceRepository_prepareDataQuery(t *testing.T) { Offset: 1, }, wantSQL: `SELECT "billing_invoices"."id" AS "id", "billing_invoices"."amount" AS "amount", "billing_invoices"."currency" AS "currency", "billing_invoices"."state" AS "state", "billing_invoices"."hosted_url" AS "hosted_url", "billing_invoices"."created_at" AS "created_at", "organizations"."id" AS "org_id", "organizations"."name" AS "org_name", "organizations"."title" AS "org_title" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") INNER JOIN "organizations" ON ("billing_customers"."org_id" = "organizations"."id") WHERE ("billing_invoices"."state" LIKE $1) LIMIT $2 OFFSET $3`, - wantParams: []interface{}{"%paid%", int64(10), int64(1)}, + wantParams: []any{"%paid%", int64(10), int64(1)}, wantErr: false, }, } @@ -211,7 +211,7 @@ func TestRelationRepository_GetByFields_PreparedSQLForwardsParams(t *testing.T) require.NoError(t, err) assert.True(t, strings.Contains(sql, "$1"), "SQL must use $N placeholders, got: %s", sql) - assert.Equal(t, []interface{}{"obj-1", "ns-obj", "sub-1", "ns-sub", "owner"}, params) + assert.Equal(t, []any{"obj-1", "ns-obj", "sub-1", "ns-sub", "owner"}, params) } // Mirror of relation_repository.go::ListByFields query construction. @@ -238,7 +238,7 @@ func TestRelationRepository_ListByFields_PreparedSQLForwardsParams(t *testing.T) require.NoError(t, err) assert.True(t, strings.Contains(sql, "$1"), "SQL must use $N placeholders, got: %s", sql) - assert.Equal(t, []interface{}{"sub-1", "%:member", "obj-1"}, params) + assert.Equal(t, []any{"sub-1", "%:member", "obj-1"}, params) } // Mirror of organization_repository.go::List totalCount path. @@ -251,7 +251,7 @@ func TestOrganizationRepository_ListTotalCount_PreparedSQLForwardsParams(t *test require.NoError(t, err) assert.True(t, strings.Contains(sql, "$1"), "SQL must use $N placeholders, got: %s", sql) - assert.Equal(t, []interface{}{"enabled", "o-1", "o-2"}, params) + assert.Equal(t, []any{"enabled", "o-1", "o-2"}, params) } // Mirror of project_repository.go::List totalCount path. @@ -265,7 +265,7 @@ func TestProjectRepository_ListTotalCount_PreparedSQLForwardsParams(t *testing.T require.NoError(t, err) assert.True(t, strings.Contains(sql, "$1"), "SQL must use $N placeholders, got: %s", sql) - assert.Equal(t, []interface{}{"org-1", "p-1", "p-2", "enabled"}, params) + assert.Equal(t, []any{"org-1", "p-1", "p-2", "enabled"}, params) } // Mirror of billing_invoice_repository.go::List totalCount path. @@ -279,5 +279,5 @@ func TestBillingInvoiceRepository_ListTotalCount_PreparedSQLForwardsParams(t *te require.NoError(t, err) assert.True(t, strings.Contains(sql, "$1"), "SQL must use $N placeholders, got: %s", sql) - assert.Equal(t, []interface{}{"cust-1", int64(0), "paid"}, params) + assert.Equal(t, []any{"cust-1", int64(0), "paid"}, params) } diff --git a/internal/store/postgres/billing_product_repository.go b/internal/store/postgres/billing_product_repository.go index 9392ce0f1..14013c22f 100644 --- a/internal/store/postgres/billing_product_repository.go +++ b/internal/store/postgres/billing_product_repository.go @@ -25,7 +25,7 @@ type BehaviorConfig struct { MaxQuantity int64 `json:"max_quantity"` } -func (b *BehaviorConfig) Scan(src interface{}) error { +func (b *BehaviorConfig) Scan(src any) error { switch src := src.(type) { case []byte: return json.Unmarshal(src, b) diff --git a/internal/store/postgres/billing_subscription_repository.go b/internal/store/postgres/billing_subscription_repository.go index e6f9da79b..e2f32ac0f 100644 --- a/internal/store/postgres/billing_subscription_repository.go +++ b/internal/store/postgres/billing_subscription_repository.go @@ -32,7 +32,7 @@ type Phase struct { Reason string `json:"reason"` } -func (c *SubscriptionChanges) Scan(src interface{}) error { +func (c *SubscriptionChanges) Scan(src any) error { switch src := src.(type) { case []byte: return json.Unmarshal(src, c) @@ -226,7 +226,7 @@ func (r BillingSubscriptionRepository) Create(ctx context.Context, toCreate subs tx, pkgAuditRecord.BillingSubscriptionCreatedEvent, result, - map[string]interface{}{ + map[string]any{ "plan_id": result.PlanID, "state": result.State, }, @@ -397,7 +397,7 @@ func (r BillingSubscriptionRepository) UpdateByID(ctx context.Context, toUpdate tx, pkgAuditRecord.BillingSubscriptionChangedEvent, result, - map[string]interface{}{ + map[string]any{ "old_plan_id": oldSub.PlanID, "new_plan_id": result.PlanID, }, @@ -497,7 +497,7 @@ func (r BillingSubscriptionRepository) createSubscriptionAuditRecord( tx *sqlx.Tx, event pkgAuditRecord.Event, sub subscriptionWithCustomer, - targetMetadata map[string]interface{}, + targetMetadata map[string]any, occurredAt time.Time, ) error { auditRecord := BuildAuditRecord( diff --git a/internal/store/postgres/invitation.go b/internal/store/postgres/invitation.go index 032c77b1f..760e88b6e 100644 --- a/internal/store/postgres/invitation.go +++ b/internal/store/postgres/invitation.go @@ -27,13 +27,13 @@ func (from Invitation) transformToInvitation() (invitation.Invitation, error) { } var groupIDs []string if val, ok := unmarshalledMetadata["group_ids"]; ok && (val != nil) { - for _, groupIDRaw := range val.([]interface{}) { + for _, groupIDRaw := range val.([]any) { groupIDs = append(groupIDs, groupIDRaw.(string)) } } var roleIDs []string if val, ok := unmarshalledMetadata["role_ids"]; ok && (val != nil) { - for _, roleIDRaw := range val.([]interface{}) { + for _, roleIDRaw := range val.([]any) { roleIDs = append(roleIDs, roleIDRaw.(string)) } } diff --git a/internal/store/postgres/invitation_repository.go b/internal/store/postgres/invitation_repository.go index 24a5dd67d..ba0a5f785 100644 --- a/internal/store/postgres/invitation_repository.go +++ b/internal/store/postgres/invitation_repository.go @@ -103,7 +103,7 @@ func (s *InvitationRepository) Set(ctx context.Context, invite invitation.Invita &AuditTarget{ ID: result.ID.String(), Type: auditrecord.InvitationType, - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "email": invite.UserEmailID, "group_ids": invite.GroupIDs, "role_ids": invite.RoleIDs, diff --git a/internal/store/postgres/kyc_repository.go b/internal/store/postgres/kyc_repository.go index 2a3266eb5..b109497d4 100644 --- a/internal/store/postgres/kyc_repository.go +++ b/internal/store/postgres/kyc_repository.go @@ -77,7 +77,7 @@ func (r OrgKycRepository) GetByOrgID(ctx context.Context, orgID string) (kyc.KYC func (r OrgKycRepository) Upsert(ctx context.Context, input kyc.KYC) (kyc.KYC, error) { var query string - var params []interface{} + var params []any // Struct to hold KYC data + org name type kycWithOrgName struct { @@ -160,7 +160,7 @@ func (r OrgKycRepository) Upsert(ctx context.Context, input kyc.KYC) (kyc.KYC, e &AuditTarget{ ID: result.OrgID, Type: auditrecord.KycType, - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "status": result.Status, "link": result.Link, }, diff --git a/internal/store/postgres/org_billing_repository.go b/internal/store/postgres/org_billing_repository.go index 5a75820ac..f2e1fe8e2 100644 --- a/internal/store/postgres/org_billing_repository.go +++ b/internal/store/postgres/org_billing_repository.go @@ -188,8 +188,8 @@ func (r OrgBillingRepository) Search(ctx context.Context, rql *rql.Query) (svc.O } // for each organization, fetch the last created billing_subscription entry -func prepareDataQuery(rql *rql.Query) (string, []interface{}, error) { - dataQuerySelects := []interface{}{ +func prepareDataQuery(rql *rql.Query) (string, []any, error) { + dataQuerySelects := []any{ goqu.I(COLUMN_ID), goqu.I(COLUMN_TITLE), goqu.I(COLUMN_NAME), @@ -234,7 +234,7 @@ func prepareDataQuery(rql *rql.Query) (string, []interface{}, error) { // for each organization, fetch the last created billing_subscription entry grouped by first key in rql.GroupBy list // RQL supports multiple group_by key, but for simplicity of implementation // and view of Frontier Admin Console only one group_by key is being supported -func prepareGroupByQuery(rql *rql.Query) (string, []interface{}, error) { +func prepareGroupByQuery(rql *rql.Query) (string, []any, error) { validGroupByKeys := []string{ COLUMN_STATE, COLUMN_PLAN_NAME, @@ -253,7 +253,7 @@ func prepareGroupByQuery(rql *rql.Query) (string, []interface{}, error) { return "", nil, fmt.Errorf("invalid group_by key %s", groupByKey) } - finalQuerySelects := []interface{}{ + finalQuerySelects := []any{ goqu.COUNT("*").As(COLUMN_COUNT), goqu.I(rql.GroupBy[0]).As(COLUMN_VALUES), } @@ -281,7 +281,7 @@ func prepareGroupByQuery(rql *rql.Query) (string, []interface{}, error) { // prepare a subquery by left joining organizations and billing subscriptions tables // and sort by descending order of billing_subscriptions.created_at column func getSubQuery() *goqu.SelectDataset { - subquerySelects := []interface{}{ + subquerySelects := []any{ goqu.I(TABLE_ORGANIZATIONS + "." + COLUMN_ID).As(COLUMN_ID), goqu.I(TABLE_ORGANIZATIONS + "." + COLUMN_TITLE).As(COLUMN_TITLE), goqu.I(TABLE_ORGANIZATIONS + "." + COLUMN_NAME).As(COLUMN_NAME), diff --git a/internal/store/postgres/org_billing_repository_test.go b/internal/store/postgres/org_billing_repository_test.go index 6e7e3ba09..2da801066 100644 --- a/internal/store/postgres/org_billing_repository_test.go +++ b/internal/store/postgres/org_billing_repository_test.go @@ -13,7 +13,7 @@ func TestPrepareDataQuery(t *testing.T) { name string rqlQuery *rql.Query wantSQL string - wantParameters []interface{} + wantParameters []any wantErr bool }{ { @@ -23,7 +23,7 @@ func TestPrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "id", "title", "name", "state", "avatar", "updated_at", "created_at", "created_by", "country", "plan_id", "plan_name", "subscription_state", "subscription_cycle_end_at", "plan_interval", "payment_mode" FROM (SELECT "organizations"."id" AS "id", "organizations"."title" AS "title", "organizations"."name" AS "name", "organizations"."avatar" AS "avatar", "organizations"."created_at" AS "created_at", "organizations"."updated_at" AS "updated_at", "organizations"."state" AS "state", organizations.metadata->>'country' AS "country", organizations.metadata->>'poc' AS "created_by", "billing_plans"."id" AS "plan_id", "billing_plans"."name" AS "plan_name", "billing_plans"."interval" AS "plan_interval", "billing_subscriptions"."state" AS "subscription_state", "billing_subscriptions"."trial_ends_at", "billing_subscriptions"."current_period_end_at" AS "subscription_cycle_end_at", "billing_customers"."payment_mode" AS "payment_mode", ROW_NUMBER() OVER (PARTITION BY "organizations"."id" ORDER BY "billing_subscriptions"."created_at" DESC) AS "row_num" FROM "organizations" LEFT JOIN "billing_customers" ON ("organizations"."id" = "billing_customers"."org_id") LEFT JOIN "billing_subscriptions" ON (("billing_subscriptions"."customer_id" = "billing_customers"."id") AND ("billing_subscriptions"."state" != $1)) LEFT JOIN "billing_plans" ON ("billing_plans"."id" = "billing_subscriptions"."plan_id")) AS "ranked_subscriptions" WHERE ("row_num" = $2) LIMIT $3`, - wantParameters: []interface{}{"canceled", int64(1), int64(10)}, + wantParameters: []any{"canceled", int64(1), int64(10)}, wantErr: false, }, { @@ -40,7 +40,7 @@ func TestPrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "id", "title", "name", "state", "avatar", "updated_at", "created_at", "created_by", "country", "plan_id", "plan_name", "subscription_state", "subscription_cycle_end_at", "plan_interval", "payment_mode" FROM (SELECT "organizations"."id" AS "id", "organizations"."title" AS "title", "organizations"."name" AS "name", "organizations"."avatar" AS "avatar", "organizations"."created_at" AS "created_at", "organizations"."updated_at" AS "updated_at", "organizations"."state" AS "state", organizations.metadata->>'country' AS "country", organizations.metadata->>'poc' AS "created_by", "billing_plans"."id" AS "plan_id", "billing_plans"."name" AS "plan_name", "billing_plans"."interval" AS "plan_interval", "billing_subscriptions"."state" AS "subscription_state", "billing_subscriptions"."trial_ends_at", "billing_subscriptions"."current_period_end_at" AS "subscription_cycle_end_at", "billing_customers"."payment_mode" AS "payment_mode", ROW_NUMBER() OVER (PARTITION BY "organizations"."id" ORDER BY "billing_subscriptions"."created_at" DESC) AS "row_num" FROM "organizations" LEFT JOIN "billing_customers" ON ("organizations"."id" = "billing_customers"."org_id") LEFT JOIN "billing_subscriptions" ON (("billing_subscriptions"."customer_id" = "billing_customers"."id") AND ("billing_subscriptions"."state" != $1)) LEFT JOIN "billing_plans" ON ("billing_plans"."id" = "billing_subscriptions"."plan_id")) AS "ranked_subscriptions" WHERE (("row_num" = $2) AND ("state" = $3)) LIMIT $4`, - wantParameters: []interface{}{"canceled", int64(1), "active", int64(10)}, + wantParameters: []any{"canceled", int64(1), "active", int64(10)}, wantErr: false, }, { @@ -51,7 +51,7 @@ func TestPrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "id", "title", "name", "state", "avatar", "updated_at", "created_at", "created_by", "country", "plan_id", "plan_name", "subscription_state", "subscription_cycle_end_at", "plan_interval", "payment_mode" FROM (SELECT "organizations"."id" AS "id", "organizations"."title" AS "title", "organizations"."name" AS "name", "organizations"."avatar" AS "avatar", "organizations"."created_at" AS "created_at", "organizations"."updated_at" AS "updated_at", "organizations"."state" AS "state", organizations.metadata->>'country' AS "country", organizations.metadata->>'poc' AS "created_by", "billing_plans"."id" AS "plan_id", "billing_plans"."name" AS "plan_name", "billing_plans"."interval" AS "plan_interval", "billing_subscriptions"."state" AS "subscription_state", "billing_subscriptions"."trial_ends_at", "billing_subscriptions"."current_period_end_at" AS "subscription_cycle_end_at", "billing_customers"."payment_mode" AS "payment_mode", ROW_NUMBER() OVER (PARTITION BY "organizations"."id" ORDER BY "billing_subscriptions"."created_at" DESC) AS "row_num" FROM "organizations" LEFT JOIN "billing_customers" ON ("organizations"."id" = "billing_customers"."org_id") LEFT JOIN "billing_subscriptions" ON (("billing_subscriptions"."customer_id" = "billing_customers"."id") AND ("billing_subscriptions"."state" != $1)) LEFT JOIN "billing_plans" ON ("billing_plans"."id" = "billing_subscriptions"."plan_id")) AS "ranked_subscriptions" WHERE (("row_num" = $2) AND ((CAST("id" AS TEXT) ILIKE $3) OR (CAST("title" AS TEXT) ILIKE $4) OR (CAST("name" AS TEXT) ILIKE $5) OR (CAST("state" AS TEXT) ILIKE $6) OR (CAST("plan_name" AS TEXT) ILIKE $7) OR (CAST("subscription_state" AS TEXT) ILIKE $8) OR (CAST("plan_interval" AS TEXT) ILIKE $9))) LIMIT $10`, - wantParameters: []interface{}{"canceled", int64(1), "%test%", "%test%", "%test%", "%test%", "%test%", "%test%", "%test%", int64(10)}, + wantParameters: []any{"canceled", int64(1), "%test%", "%test%", "%test%", "%test%", "%test%", "%test%", "%test%", int64(10)}, wantErr: false, }, { @@ -67,7 +67,7 @@ func TestPrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "id", "title", "name", "state", "avatar", "updated_at", "created_at", "created_by", "country", "plan_id", "plan_name", "subscription_state", "subscription_cycle_end_at", "plan_interval", "payment_mode" FROM (SELECT "organizations"."id" AS "id", "organizations"."title" AS "title", "organizations"."name" AS "name", "organizations"."avatar" AS "avatar", "organizations"."created_at" AS "created_at", "organizations"."updated_at" AS "updated_at", "organizations"."state" AS "state", organizations.metadata->>'country' AS "country", organizations.metadata->>'poc' AS "created_by", "billing_plans"."id" AS "plan_id", "billing_plans"."name" AS "plan_name", "billing_plans"."interval" AS "plan_interval", "billing_subscriptions"."state" AS "subscription_state", "billing_subscriptions"."trial_ends_at", "billing_subscriptions"."current_period_end_at" AS "subscription_cycle_end_at", "billing_customers"."payment_mode" AS "payment_mode", ROW_NUMBER() OVER (PARTITION BY "organizations"."id" ORDER BY "billing_subscriptions"."created_at" DESC) AS "row_num" FROM "organizations" LEFT JOIN "billing_customers" ON ("organizations"."id" = "billing_customers"."org_id") LEFT JOIN "billing_subscriptions" ON (("billing_subscriptions"."customer_id" = "billing_customers"."id") AND ("billing_subscriptions"."state" != $1)) LEFT JOIN "billing_plans" ON ("billing_plans"."id" = "billing_subscriptions"."plan_id")) AS "ranked_subscriptions" WHERE ("row_num" = $2) ORDER BY "created_at" DESC LIMIT $3`, - wantParameters: []interface{}{"canceled", int64(1), int64(10)}, + wantParameters: []any{"canceled", int64(1), int64(10)}, wantErr: false, }, { @@ -105,7 +105,7 @@ func TestPrepareDataQuery(t *testing.T) { Offset: 40, }, wantSQL: `SELECT "id", "title", "name", "state", "avatar", "updated_at", "created_at", "created_by", "country", "plan_id", "plan_name", "subscription_state", "subscription_cycle_end_at", "plan_interval", "payment_mode" FROM (SELECT "organizations"."id" AS "id", "organizations"."title" AS "title", "organizations"."name" AS "name", "organizations"."avatar" AS "avatar", "organizations"."created_at" AS "created_at", "organizations"."updated_at" AS "updated_at", "organizations"."state" AS "state", organizations.metadata->>'country' AS "country", organizations.metadata->>'poc' AS "created_by", "billing_plans"."id" AS "plan_id", "billing_plans"."name" AS "plan_name", "billing_plans"."interval" AS "plan_interval", "billing_subscriptions"."state" AS "subscription_state", "billing_subscriptions"."trial_ends_at", "billing_subscriptions"."current_period_end_at" AS "subscription_cycle_end_at", "billing_customers"."payment_mode" AS "payment_mode", ROW_NUMBER() OVER (PARTITION BY "organizations"."id" ORDER BY "billing_subscriptions"."created_at" DESC) AS "row_num" FROM "organizations" LEFT JOIN "billing_customers" ON ("organizations"."id" = "billing_customers"."org_id") LEFT JOIN "billing_subscriptions" ON (("billing_subscriptions"."customer_id" = "billing_customers"."id") AND ("billing_subscriptions"."state" != $1)) LEFT JOIN "billing_plans" ON ("billing_plans"."id" = "billing_subscriptions"."plan_id")) AS "ranked_subscriptions" WHERE (("row_num" = $2) AND ("state" = $3) AND (CAST("plan_name" AS TEXT) IN ($4, $5)) AND (("subscription_state" IS NOT NULL) AND ("subscription_state" != $6)) AND ((CAST("id" AS TEXT) ILIKE $7) OR (CAST("title" AS TEXT) ILIKE $8) OR (CAST("name" AS TEXT) ILIKE $9) OR (CAST("state" AS TEXT) ILIKE $10) OR (CAST("plan_name" AS TEXT) ILIKE $11) OR (CAST("subscription_state" AS TEXT) ILIKE $12) OR (CAST("plan_interval" AS TEXT) ILIKE $13))) ORDER BY "created_at" DESC, "title" ASC LIMIT $14 OFFSET $15`, - wantParameters: []interface{}{"canceled", int64(1), "active", "free", "premium", "", "%test%", "%test%", "%test%", "%test%", "%test%", "%test%", "%test%", int64(20), int64(40)}, + wantParameters: []any{"canceled", int64(1), "active", "free", "premium", "", "%test%", "%test%", "%test%", "%test%", "%test%", "%test%", "%test%", int64(20), int64(40)}, wantErr: false, }, { @@ -122,7 +122,7 @@ func TestPrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "id", "title", "name", "state", "avatar", "updated_at", "created_at", "created_by", "country", "plan_id", "plan_name", "subscription_state", "subscription_cycle_end_at", "plan_interval", "payment_mode" FROM (SELECT "organizations"."id" AS "id", "organizations"."title" AS "title", "organizations"."name" AS "name", "organizations"."avatar" AS "avatar", "organizations"."created_at" AS "created_at", "organizations"."updated_at" AS "updated_at", "organizations"."state" AS "state", organizations.metadata->>'country' AS "country", organizations.metadata->>'poc' AS "created_by", "billing_plans"."id" AS "plan_id", "billing_plans"."name" AS "plan_name", "billing_plans"."interval" AS "plan_interval", "billing_subscriptions"."state" AS "subscription_state", "billing_subscriptions"."trial_ends_at", "billing_subscriptions"."current_period_end_at" AS "subscription_cycle_end_at", "billing_customers"."payment_mode" AS "payment_mode", ROW_NUMBER() OVER (PARTITION BY "organizations"."id" ORDER BY "billing_subscriptions"."created_at" DESC) AS "row_num" FROM "organizations" LEFT JOIN "billing_customers" ON ("organizations"."id" = "billing_customers"."org_id") LEFT JOIN "billing_subscriptions" ON (("billing_subscriptions"."customer_id" = "billing_customers"."id") AND ("billing_subscriptions"."state" != $1)) LEFT JOIN "billing_plans" ON ("billing_plans"."id" = "billing_subscriptions"."plan_id")) AS "ranked_subscriptions" WHERE (("row_num" = $2) AND ("payment_mode" = $3)) LIMIT $4`, - wantParameters: []interface{}{"canceled", int64(1), "postpaid", int64(10)}, + wantParameters: []any{"canceled", int64(1), "postpaid", int64(10)}, wantErr: false, }, { @@ -159,7 +159,7 @@ func TestPrepareGroupByQuery(t *testing.T) { name string rqlQuery *rql.Query wantSQL string - wantParameters []interface{} + wantParameters []any wantErr bool }{ { @@ -168,7 +168,7 @@ func TestPrepareGroupByQuery(t *testing.T) { GroupBy: []string{"state"}, }, wantSQL: `SELECT COUNT(*) AS "count", "state" AS "values" FROM (SELECT "organizations"."id" AS "id", "organizations"."title" AS "title", "organizations"."name" AS "name", "organizations"."avatar" AS "avatar", "organizations"."created_at" AS "created_at", "organizations"."updated_at" AS "updated_at", "organizations"."state" AS "state", organizations.metadata->>'country' AS "country", organizations.metadata->>'poc' AS "created_by", "billing_plans"."id" AS "plan_id", "billing_plans"."name" AS "plan_name", "billing_plans"."interval" AS "plan_interval", "billing_subscriptions"."state" AS "subscription_state", "billing_subscriptions"."trial_ends_at", "billing_subscriptions"."current_period_end_at" AS "subscription_cycle_end_at", "billing_customers"."payment_mode" AS "payment_mode", ROW_NUMBER() OVER (PARTITION BY "organizations"."id" ORDER BY "billing_subscriptions"."created_at" DESC) AS "row_num" FROM "organizations" LEFT JOIN "billing_customers" ON ("organizations"."id" = "billing_customers"."org_id") LEFT JOIN "billing_subscriptions" ON (("billing_subscriptions"."customer_id" = "billing_customers"."id") AND ("billing_subscriptions"."state" != $1)) LEFT JOIN "billing_plans" ON ("billing_plans"."id" = "billing_subscriptions"."plan_id")) AS "ranked_subscriptions" WHERE ("row_num" = $2) GROUP BY "state"`, - wantParameters: []interface{}{"canceled", int64(1)}, + wantParameters: []any{"canceled", int64(1)}, wantErr: false, }, { @@ -177,7 +177,7 @@ func TestPrepareGroupByQuery(t *testing.T) { GroupBy: []string{"plan_name"}, }, wantSQL: `SELECT COUNT(*) AS "count", "plan_name" AS "values" FROM (SELECT "organizations"."id" AS "id", "organizations"."title" AS "title", "organizations"."name" AS "name", "organizations"."avatar" AS "avatar", "organizations"."created_at" AS "created_at", "organizations"."updated_at" AS "updated_at", "organizations"."state" AS "state", organizations.metadata->>'country' AS "country", organizations.metadata->>'poc' AS "created_by", "billing_plans"."id" AS "plan_id", "billing_plans"."name" AS "plan_name", "billing_plans"."interval" AS "plan_interval", "billing_subscriptions"."state" AS "subscription_state", "billing_subscriptions"."trial_ends_at", "billing_subscriptions"."current_period_end_at" AS "subscription_cycle_end_at", "billing_customers"."payment_mode" AS "payment_mode", ROW_NUMBER() OVER (PARTITION BY "organizations"."id" ORDER BY "billing_subscriptions"."created_at" DESC) AS "row_num" FROM "organizations" LEFT JOIN "billing_customers" ON ("organizations"."id" = "billing_customers"."org_id") LEFT JOIN "billing_subscriptions" ON (("billing_subscriptions"."customer_id" = "billing_customers"."id") AND ("billing_subscriptions"."state" != $1)) LEFT JOIN "billing_plans" ON ("billing_plans"."id" = "billing_subscriptions"."plan_id")) AS "ranked_subscriptions" WHERE ("row_num" = $2) GROUP BY "plan_name"`, - wantParameters: []interface{}{"canceled", int64(1)}, + wantParameters: []any{"canceled", int64(1)}, wantErr: false, }, { @@ -186,7 +186,7 @@ func TestPrepareGroupByQuery(t *testing.T) { GroupBy: []string{"payment_mode"}, }, wantSQL: `SELECT COUNT(*) AS "count", "payment_mode" AS "values" FROM (SELECT "organizations"."id" AS "id", "organizations"."title" AS "title", "organizations"."name" AS "name", "organizations"."avatar" AS "avatar", "organizations"."created_at" AS "created_at", "organizations"."updated_at" AS "updated_at", "organizations"."state" AS "state", organizations.metadata->>'country' AS "country", organizations.metadata->>'poc' AS "created_by", "billing_plans"."id" AS "plan_id", "billing_plans"."name" AS "plan_name", "billing_plans"."interval" AS "plan_interval", "billing_subscriptions"."state" AS "subscription_state", "billing_subscriptions"."trial_ends_at", "billing_subscriptions"."current_period_end_at" AS "subscription_cycle_end_at", "billing_customers"."payment_mode" AS "payment_mode", ROW_NUMBER() OVER (PARTITION BY "organizations"."id" ORDER BY "billing_subscriptions"."created_at" DESC) AS "row_num" FROM "organizations" LEFT JOIN "billing_customers" ON ("organizations"."id" = "billing_customers"."org_id") LEFT JOIN "billing_subscriptions" ON (("billing_subscriptions"."customer_id" = "billing_customers"."id") AND ("billing_subscriptions"."state" != $1)) LEFT JOIN "billing_plans" ON ("billing_plans"."id" = "billing_subscriptions"."plan_id")) AS "ranked_subscriptions" WHERE ("row_num" = $2) GROUP BY "payment_mode"`, - wantParameters: []interface{}{"canceled", int64(1)}, + wantParameters: []any{"canceled", int64(1)}, wantErr: false, }, { diff --git a/internal/store/postgres/org_invoices_repository.go b/internal/store/postgres/org_invoices_repository.go index 1d3e96680..4754a9d59 100644 --- a/internal/store/postgres/org_invoices_repository.go +++ b/internal/store/postgres/org_invoices_repository.go @@ -141,7 +141,7 @@ func (r OrgInvoicesRepository) Search(ctx context.Context, orgID string, rql *rq }, nil } -func (r OrgInvoicesRepository) prepareDataQuery(orgID string, rql *rql.Query) (string, []interface{}, error) { +func (r OrgInvoicesRepository) prepareDataQuery(orgID string, rql *rql.Query) (string, []any, error) { query := r.buildBaseQuery(orgID) for _, filter := range rql.Filters { @@ -161,7 +161,7 @@ func (r OrgInvoicesRepository) prepareDataQuery(orgID string, rql *rql.Query) (s return query.Offset(uint(rql.Offset)).Limit(uint(rql.Limit)).ToSQL() } -func (r OrgInvoicesRepository) prepareGroupByQuery(orgID string, rql *rql.Query) (string, []interface{}, error) { +func (r OrgInvoicesRepository) prepareGroupByQuery(orgID string, rql *rql.Query) (string, []any, error) { query := dialect.From(TABLE_BILLING_INVOICES).Prepared(true). Select( goqu.COUNT("*").As("count"), diff --git a/internal/store/postgres/org_invoices_repository_test.go b/internal/store/postgres/org_invoices_repository_test.go index 9f5a895a5..bcfa40d20 100644 --- a/internal/store/postgres/org_invoices_repository_test.go +++ b/internal/store/postgres/org_invoices_repository_test.go @@ -13,7 +13,7 @@ func TestOrgInvoicesRepository_prepareDataQuery(t *testing.T) { orgID string rql *rql.Query wantSQL string - wantParams []interface{} + wantParams []any wantErr bool }{ { @@ -24,7 +24,7 @@ func TestOrgInvoicesRepository_prepareDataQuery(t *testing.T) { Offset: 20, }, wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE ("billing_customers"."org_id" = $1) LIMIT $2 OFFSET $3`, - wantParams: []interface{}{"org123", int64(10), int64(20)}, + wantParams: []any{"org123", int64(10), int64(20)}, wantErr: false, }, { @@ -42,7 +42,7 @@ func TestOrgInvoicesRepository_prepareDataQuery(t *testing.T) { Offset: 50, }, wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE (("billing_customers"."org_id" = $1) AND ("billing_invoices"."amount" >= $2)) LIMIT $3 OFFSET $4`, - wantParams: []interface{}{"org123", int64(1000), int64(10), int64(50)}, + wantParams: []any{"org123", int64(1000), int64(10), int64(50)}, wantErr: false, }, { @@ -61,7 +61,7 @@ func TestOrgInvoicesRepository_prepareDataQuery(t *testing.T) { Offset: 30, }, wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE (("billing_customers"."org_id" = $1) AND ("billing_invoices"."state" = $2) AND ((CAST("billing_invoices"."state" AS TEXT) ILIKE $3) OR (CAST("billing_invoices"."hosted_url" AS TEXT) ILIKE $4) OR (CAST("billing_invoices"."amount" AS TEXT) ILIKE $5))) LIMIT $6 OFFSET $7`, - wantParams: []interface{}{"org123", "paid", "%test%", "%test%", "%test%", int64(10), int64(30)}, + wantParams: []any{"org123", "paid", "%test%", "%test%", "%test%", int64(10), int64(30)}, wantErr: false, }, { @@ -78,7 +78,7 @@ func TestOrgInvoicesRepository_prepareDataQuery(t *testing.T) { Offset: 40, }, wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE ("billing_customers"."org_id" = $1) ORDER BY "invoice_state" DESC LIMIT $2 OFFSET $3`, - wantParams: []interface{}{"org123", int64(10), int64(40)}, + wantParams: []any{"org123", int64(10), int64(40)}, wantErr: false, }, { @@ -96,7 +96,7 @@ func TestOrgInvoicesRepository_prepareDataQuery(t *testing.T) { Offset: 25, }, wantSQL: `SELECT "billing_invoices"."id" AS "invoice_id", "billing_invoices"."amount" AS "invoice_amount", "billing_invoices"."currency" AS "invoice_currency", "billing_invoices"."state" AS "invoice_state", "billing_invoices"."hosted_url" AS "invoice_hosted_url", "billing_invoices"."created_at" AS "invoice_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE ("billing_customers"."org_id" = $1) ORDER BY "invoice_state" ASC, "invoice_amount" DESC LIMIT $2 OFFSET $3`, - wantParams: []interface{}{"org123", int64(10), int64(25)}, + wantParams: []any{"org123", int64(10), int64(25)}, wantErr: false, }, { @@ -141,7 +141,7 @@ func TestOrgInvoicesRepository_prepareGroupByQuery(t *testing.T) { orgID string rql *rql.Query wantSQL string - wantParams []interface{} + wantParams []any wantErr bool }{ { @@ -151,7 +151,7 @@ func TestOrgInvoicesRepository_prepareGroupByQuery(t *testing.T) { GroupBy: []string{"state"}, }, wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE ("billing_customers"."org_id" = $1) GROUP BY "billing_invoices"."state"`, - wantParams: []interface{}{"org123"}, + wantParams: []any{"org123"}, wantErr: false, }, { @@ -168,7 +168,7 @@ func TestOrgInvoicesRepository_prepareGroupByQuery(t *testing.T) { }, }, wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE (("billing_customers"."org_id" = $1) AND ("billing_invoices"."amount" >= $2)) GROUP BY "billing_invoices"."state"`, - wantParams: []interface{}{"org123", int64(1000)}, + wantParams: []any{"org123", int64(1000)}, wantErr: false, }, { @@ -179,7 +179,7 @@ func TestOrgInvoicesRepository_prepareGroupByQuery(t *testing.T) { Search: "test", }, wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE (("billing_customers"."org_id" = $1) AND ((CAST("billing_invoices"."state" AS TEXT) ILIKE $2) OR (CAST("billing_invoices"."hosted_url" AS TEXT) ILIKE $3) OR (CAST("billing_invoices"."amount" AS TEXT) ILIKE $4))) GROUP BY "billing_invoices"."state"`, - wantParams: []interface{}{"org123", "%test%", "%test%", "%test%"}, + wantParams: []any{"org123", "%test%", "%test%", "%test%"}, wantErr: false, }, { @@ -197,7 +197,7 @@ func TestOrgInvoicesRepository_prepareGroupByQuery(t *testing.T) { Search: "test", }, wantSQL: `SELECT COUNT(*) AS "count", "billing_invoices"."state" AS "values" FROM "billing_invoices" INNER JOIN "billing_customers" ON ("billing_invoices"."customer_id" = "billing_customers"."id") WHERE (("billing_customers"."org_id" = $1) AND ("billing_invoices"."amount" >= $2) AND ((CAST("billing_invoices"."state" AS TEXT) ILIKE $3) OR (CAST("billing_invoices"."hosted_url" AS TEXT) ILIKE $4) OR (CAST("billing_invoices"."amount" AS TEXT) ILIKE $5))) GROUP BY "billing_invoices"."state"`, - wantParams: []interface{}{"org123", int64(1000), "%test%", "%test%", "%test%"}, + wantParams: []any{"org123", int64(1000), "%test%", "%test%", "%test%"}, wantErr: false, }, } diff --git a/internal/store/postgres/org_pats_repository.go b/internal/store/postgres/org_pats_repository.go index 802b5545c..f945376c2 100644 --- a/internal/store/postgres/org_pats_repository.go +++ b/internal/store/postgres/org_pats_repository.go @@ -158,7 +158,7 @@ func (r OrgPATsRepository) buildInnerSubquery(orgID string, rqlQuery *rql.Query) return inner, nil } -func (r OrgPATsRepository) buildCountQuery(orgID string, rqlQuery *rql.Query) (string, []interface{}, error) { +func (r OrgPATsRepository) buildCountQuery(orgID string, rqlQuery *rql.Query) (string, []any, error) { inner, err := r.buildInnerSubquery(orgID, rqlQuery) if err != nil { return "", nil, err @@ -166,7 +166,7 @@ func (r OrgPATsRepository) buildCountQuery(orgID string, rqlQuery *rql.Query) (s return inner.Select(goqu.L("COUNT(*)")).Prepared(true).ToSQL() } -func (r OrgPATsRepository) buildDataQuery(orgID string, rqlQuery *rql.Query) (string, []interface{}, error) { +func (r OrgPATsRepository) buildDataQuery(orgID string, rqlQuery *rql.Query) (string, []any, error) { inner, err := r.buildInnerSubquery(orgID, rqlQuery) if err != nil { return "", nil, err diff --git a/internal/store/postgres/org_projects_repository.go b/internal/store/postgres/org_projects_repository.go index bd63e922a..d811a2b99 100644 --- a/internal/store/postgres/org_projects_repository.go +++ b/internal/store/postgres/org_projects_repository.go @@ -113,7 +113,7 @@ func (r OrgProjectsRepository) Search(ctx context.Context, orgID string, rql *rq }, nil } -func (r OrgProjectsRepository) prepareDataQuery(orgID string, rqlQuery *rql.Query) (string, []interface{}, error) { +func (r OrgProjectsRepository) prepareDataQuery(orgID string, rqlQuery *rql.Query) (string, []any, error) { baseQ := r.baseQuery(orgID) baseQWithFilters, err := r.applyFilters(rqlQuery, baseQ) diff --git a/internal/store/postgres/org_projects_repository_test.go b/internal/store/postgres/org_projects_repository_test.go index 81ac231d9..1d14bd52d 100644 --- a/internal/store/postgres/org_projects_repository_test.go +++ b/internal/store/postgres/org_projects_repository_test.go @@ -14,7 +14,7 @@ func TestOrgProjectsRepository_prepareDataQuery(t *testing.T) { orgID string rqlQuery *rql.Query wantSQL string - wantArgs []interface{} + wantArgs []any wantErr bool }{ { @@ -25,7 +25,7 @@ func TestOrgProjectsRepository_prepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "projects"."id", "projects"."name", "projects"."title", "projects"."state", "projects"."created_at", "projects"."org_id", COUNT(DISTINCT("policies"."principal_id")) AS "member_count", array_agg(DISTINCT users.id) AS "user_ids" FROM "policies" INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") INNER JOIN "users" ON ("policies"."principal_id" = "users"."id") WHERE (("principal_type" = $1) AND ("projects"."org_id" = $2)) GROUP BY "projects"."id", "projects"."name", "projects"."title", "projects"."state", "projects"."created_at", "projects"."org_id" LIMIT $3`, - wantArgs: []interface{}{"app/user", "org123", int64(10)}, + wantArgs: []any{"app/user", "org123", int64(10)}, wantErr: false, }, { @@ -43,7 +43,7 @@ func TestOrgProjectsRepository_prepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "projects"."id", "projects"."name", "projects"."title", "projects"."state", "projects"."created_at", "projects"."org_id", COUNT(DISTINCT("policies"."principal_id")) AS "member_count", array_agg(DISTINCT users.id) AS "user_ids" FROM "policies" INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") INNER JOIN "users" ON ("policies"."principal_id" = "users"."id") WHERE ((("principal_type" = $1) AND ("projects"."org_id" = $2)) AND ("projects"."name" = $3)) GROUP BY "projects"."id", "projects"."name", "projects"."title", "projects"."state", "projects"."created_at", "projects"."org_id" LIMIT $4`, - wantArgs: []interface{}{"app/user", "org123", "test-project", int64(10)}, + wantArgs: []any{"app/user", "org123", "test-project", int64(10)}, wantErr: false, }, { @@ -61,7 +61,7 @@ func TestOrgProjectsRepository_prepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "projects"."id", "projects"."name", "projects"."title", "projects"."state", "projects"."created_at", "projects"."org_id", COUNT(DISTINCT("policies"."principal_id")) AS "member_count", array_agg(DISTINCT users.id) AS "user_ids" FROM "policies" INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") INNER JOIN "users" ON ("policies"."principal_id" = "users"."id") WHERE ((("principal_type" = $1) AND ("projects"."org_id" = $2)) AND ("projects"."created_at" > CAST($3 AS TIMESTAMP))) GROUP BY "projects"."id", "projects"."name", "projects"."title", "projects"."state", "projects"."created_at", "projects"."org_id" LIMIT $4`, - wantArgs: []interface{}{"app/user", "org123", "2023-11-02T12:10:21.470756Z", int64(10)}, + wantArgs: []any{"app/user", "org123", "2023-11-02T12:10:21.470756Z", int64(10)}, wantErr: false, }, { @@ -72,7 +72,7 @@ func TestOrgProjectsRepository_prepareDataQuery(t *testing.T) { Limit: 10, }, wantSQL: `SELECT "projects"."id", "projects"."name", "projects"."title", "projects"."state", "projects"."created_at", "projects"."org_id", COUNT(DISTINCT("policies"."principal_id")) AS "member_count", array_agg(DISTINCT users.id) AS "user_ids" FROM "policies" INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") INNER JOIN "users" ON ("policies"."principal_id" = "users"."id") WHERE ((("principal_type" = $1) AND ("projects"."org_id" = $2)) AND (("projects"."title" ILIKE $3) OR ("projects"."name" ILIKE $4) OR ("projects"."state" ILIKE $5))) GROUP BY "projects"."id", "projects"."name", "projects"."title", "projects"."state", "projects"."created_at", "projects"."org_id" LIMIT $6`, - wantArgs: []interface{}{"app/user", "org123", "%test%", "%test%", "%test%", int64(10)}, + wantArgs: []any{"app/user", "org123", "%test%", "%test%", "%test%", int64(10)}, wantErr: false, }, { @@ -88,7 +88,7 @@ func TestOrgProjectsRepository_prepareDataQuery(t *testing.T) { Limit: 10, }, wantSQL: `SELECT "projects"."id", "projects"."name", "projects"."title", "projects"."state", "projects"."created_at", "projects"."org_id", COUNT(DISTINCT("policies"."principal_id")) AS "member_count", array_agg(DISTINCT users.id) AS "user_ids" FROM "policies" INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") INNER JOIN "users" ON ("policies"."principal_id" = "users"."id") WHERE (("principal_type" = $1) AND ("projects"."org_id" = $2)) GROUP BY "projects"."id", "projects"."name", "projects"."title", "projects"."state", "projects"."created_at", "projects"."org_id" ORDER BY "created_at" DESC LIMIT $3`, - wantArgs: []interface{}{"app/user", "org123", int64(10)}, + wantArgs: []any{"app/user", "org123", int64(10)}, wantErr: false, }, { diff --git a/internal/store/postgres/org_serviceuser_credentials_repository.go b/internal/store/postgres/org_serviceuser_credentials_repository.go index 998fef140..ebb537150 100644 --- a/internal/store/postgres/org_serviceuser_credentials_repository.go +++ b/internal/store/postgres/org_serviceuser_credentials_repository.go @@ -99,7 +99,7 @@ func (r OrgServiceUserCredentialsRepository) buildBaseQuery(orgID string) *goqu. }) } -func (r OrgServiceUserCredentialsRepository) prepareDataQuery(orgID string, rql *rql.Query) (string, []interface{}, error) { +func (r OrgServiceUserCredentialsRepository) prepareDataQuery(orgID string, rql *rql.Query) (string, []any, error) { query := r.buildBaseQuery(orgID) // Apply filters diff --git a/internal/store/postgres/org_serviceuser_credentials_repository_test.go b/internal/store/postgres/org_serviceuser_credentials_repository_test.go index 4a91f8ec0..b1d30cff6 100644 --- a/internal/store/postgres/org_serviceuser_credentials_repository_test.go +++ b/internal/store/postgres/org_serviceuser_credentials_repository_test.go @@ -13,7 +13,7 @@ func TestOrgServiceUserCredentialsRepository_prepareDataQuery(t *testing.T) { orgID string rql *rql.Query wantSQL string - wantParams []interface{} + wantParams []any wantErr bool }{ { @@ -24,7 +24,7 @@ func TestOrgServiceUserCredentialsRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceuser_credentials"."title" AS "credential_title", "serviceusers"."title" AS "serviceuser_title", "serviceuser_credentials"."created_at" AS "credential_created_at", "serviceusers"."org_id" AS "org_id" FROM "serviceuser_credentials" INNER JOIN "serviceusers" ON ("serviceuser_credentials"."serviceuser_id" = "serviceusers"."id") WHERE ("serviceusers"."org_id" = $1) LIMIT $2 OFFSET $3`, - wantParams: []interface{}{ + wantParams: []any{ "org1", // org_id int64(10), // limit int64(5), // offset @@ -40,7 +40,7 @@ func TestOrgServiceUserCredentialsRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceuser_credentials"."title" AS "credential_title", "serviceusers"."title" AS "serviceuser_title", "serviceuser_credentials"."created_at" AS "credential_created_at", "serviceusers"."org_id" AS "org_id" FROM "serviceuser_credentials" INNER JOIN "serviceusers" ON ("serviceuser_credentials"."serviceuser_id" = "serviceusers"."id") WHERE (("serviceusers"."org_id" = $1) AND ((CAST("serviceuser_credentials"."title" AS TEXT) ILIKE $2) OR (CAST("serviceusers"."title" AS TEXT) ILIKE $3))) LIMIT $4 OFFSET $5`, - wantParams: []interface{}{ + wantParams: []any{ "org1", // org_id "%test%", // search pattern for title "%test%", // search pattern for serviceuser_title @@ -64,7 +64,7 @@ func TestOrgServiceUserCredentialsRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceuser_credentials"."title" AS "credential_title", "serviceusers"."title" AS "serviceuser_title", "serviceuser_credentials"."created_at" AS "credential_created_at", "serviceusers"."org_id" AS "org_id" FROM "serviceuser_credentials" INNER JOIN "serviceusers" ON ("serviceuser_credentials"."serviceuser_id" = "serviceusers"."id") WHERE (("serviceusers"."org_id" = $1) AND ("serviceuser_credentials"."title" = $2)) LIMIT $3 OFFSET $4`, - wantParams: []interface{}{ + wantParams: []any{ "org1", // org_id "test-title", // filter value int64(10), // limit @@ -86,7 +86,7 @@ func TestOrgServiceUserCredentialsRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceuser_credentials"."title" AS "credential_title", "serviceusers"."title" AS "serviceuser_title", "serviceuser_credentials"."created_at" AS "credential_created_at", "serviceusers"."org_id" AS "org_id" FROM "serviceuser_credentials" INNER JOIN "serviceusers" ON ("serviceuser_credentials"."serviceuser_id" = "serviceusers"."id") WHERE ("serviceusers"."org_id" = $1) ORDER BY "serviceuser_credentials"."title" DESC LIMIT $2 OFFSET $3`, - wantParams: []interface{}{ + wantParams: []any{ "org1", // org_id int64(10), // limit int64(5), // offset @@ -124,7 +124,7 @@ func TestOrgServiceUserCredentialsRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceuser_credentials"."title" AS "credential_title", "serviceusers"."title" AS "serviceuser_title", "serviceuser_credentials"."created_at" AS "credential_created_at", "serviceusers"."org_id" AS "org_id" FROM "serviceuser_credentials" INNER JOIN "serviceusers" ON ("serviceuser_credentials"."serviceuser_id" = "serviceusers"."id") WHERE (("serviceusers"."org_id" = $1) AND (("serviceuser_credentials"."title" IS NULL) OR ("serviceuser_credentials"."title" = $2))) LIMIT $3 OFFSET $4`, - wantParams: []interface{}{ + wantParams: []any{ "org1", // org_id "", // empty string for comparison int64(10), // limit @@ -159,7 +159,7 @@ func TestOrgServiceUserCredentialsRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceuser_credentials"."title" AS "credential_title", "serviceusers"."title" AS "serviceuser_title", "serviceuser_credentials"."created_at" AS "credential_created_at", "serviceusers"."org_id" AS "org_id" FROM "serviceuser_credentials" INNER JOIN "serviceusers" ON ("serviceuser_credentials"."serviceuser_id" = "serviceusers"."id") WHERE (("serviceusers"."org_id" = $1) AND ("serviceuser_credentials"."title" LIKE $2) AND ("serviceuser_credentials"."created_at" > $3) AND ((CAST("serviceuser_credentials"."title" AS TEXT) ILIKE $4) OR (CAST("serviceusers"."title" AS TEXT) ILIKE $5))) ORDER BY "serviceuser_credentials"."created_at" DESC LIMIT $6 OFFSET $7`, - wantParams: []interface{}{ + wantParams: []any{ "org1", // org_id "%api%", // like pattern for title "2023-01-01T00:00:00Z", // created_at value diff --git a/internal/store/postgres/org_serviceuser_repository.go b/internal/store/postgres/org_serviceuser_repository.go index a2a865a61..9f7865382 100644 --- a/internal/store/postgres/org_serviceuser_repository.go +++ b/internal/store/postgres/org_serviceuser_repository.go @@ -90,7 +90,7 @@ func (r OrgServiceUserRepository) Search(ctx context.Context, orgID string, rql }, nil } -func (r OrgServiceUserRepository) prepareDataQuery(orgID string, rql *rql.Query) (string, []interface{}, error) { +func (r OrgServiceUserRepository) prepareDataQuery(orgID string, rql *rql.Query) (string, []any, error) { query := r.buildBaseQuery(orgID) if rql != nil { diff --git a/internal/store/postgres/org_serviceuser_repository_test.go b/internal/store/postgres/org_serviceuser_repository_test.go index 2fb131da3..65b7c19d4 100644 --- a/internal/store/postgres/org_serviceuser_repository_test.go +++ b/internal/store/postgres/org_serviceuser_repository_test.go @@ -13,7 +13,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { orgID string rql *rql.Query wantSQL string - wantParams []interface{} + wantParams []any wantErr bool }{ { @@ -24,7 +24,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE ("serviceusers"."org_id" = $3) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC LIMIT $4 OFFSET $5`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -42,7 +42,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE (("serviceusers"."org_id" = $3) AND (CAST("serviceusers"."title" AS TEXT) ILIKE $4)) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC LIMIT $5 OFFSET $6`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -67,7 +67,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE (("serviceusers"."org_id" = $3) AND ("serviceusers"."title" = $4)) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC LIMIT $5 OFFSET $6`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -92,7 +92,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE (("serviceusers"."org_id" = $3) AND ("serviceusers"."title" LIKE $4)) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC LIMIT $5 OFFSET $6`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -117,7 +117,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE (("serviceusers"."org_id" = $3) AND ("serviceusers"."created_at" > $4)) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC LIMIT $5 OFFSET $6`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -141,7 +141,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE ("serviceusers"."org_id" = $3) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC, "serviceusers"."title" DESC LIMIT $4 OFFSET $5`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -164,7 +164,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE ("serviceusers"."org_id" = $3) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC, "serviceusers"."created_at" ASC LIMIT $4 OFFSET $5`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -204,7 +204,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE (("serviceusers"."org_id" = $3) AND (("serviceusers"."title" IS NULL) OR ("serviceusers"."title" = $4))) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC LIMIT $5 OFFSET $6`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -228,7 +228,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE (("serviceusers"."org_id" = $3) AND (("serviceusers"."title" IS NOT NULL) AND ("serviceusers"."title" != $4))) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC LIMIT $5 OFFSET $6`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -253,7 +253,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE (("serviceusers"."org_id" = $3) AND ("serviceusers"."title" NOT LIKE $4)) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC LIMIT $5 OFFSET $6`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -278,7 +278,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE ("serviceusers"."org_id" = $3) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC LIMIT $4 OFFSET $5`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -314,7 +314,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Offset: 5, }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE (("serviceusers"."org_id" = $3) AND ("serviceusers"."title" LIKE $4) AND ("serviceusers"."created_at" > $5) AND (CAST("serviceusers"."title" AS TEXT) ILIKE $6)) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC, "serviceusers"."created_at" DESC LIMIT $7 OFFSET $8`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -333,7 +333,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { Search: "test", }, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE (("serviceusers"."org_id" = $3) AND (CAST("serviceusers"."title" AS TEXT) ILIKE $4)) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id @@ -346,7 +346,7 @@ func TestOrgServiceUserRepository_prepareDataQuery(t *testing.T) { orgID: "org1", rql: nil, wantSQL: `SELECT "serviceusers"."id" AS "id", "serviceusers"."title" AS "title", "serviceusers"."org_id" AS "org_id", "serviceusers"."created_at" AS "created_at", JSON_AGG(JSON_BUILD_OBJECT('id', projects.id, 'title', projects.title, 'name', projects.name)) AS "project_data" FROM "serviceusers" INNER JOIN "policies" ON (("serviceusers"."id" = "policies"."principal_id") AND ("policies"."principal_type" = $1) AND ("policies"."resource_type" = $2)) INNER JOIN "projects" ON ("policies"."resource_id" = "projects"."id") WHERE ("serviceusers"."org_id" = $3) GROUP BY "serviceusers"."id" ORDER BY "serviceusers"."title" ASC`, - wantParams: []interface{}{ + wantParams: []any{ "app/serviceuser", // principal_type "app/project", // resource_type "org1", // org_id diff --git a/internal/store/postgres/org_tokens_repository.go b/internal/store/postgres/org_tokens_repository.go index ed5a499a8..ad750177f 100644 --- a/internal/store/postgres/org_tokens_repository.go +++ b/internal/store/postgres/org_tokens_repository.go @@ -94,7 +94,7 @@ func (r OrgTokensRepository) Search(ctx context.Context, orgID string, rql *rql. }, nil } -func (r OrgTokensRepository) prepareDataQuery(orgID string, rql *rql.Query) (string, []interface{}, error) { +func (r OrgTokensRepository) prepareDataQuery(orgID string, rql *rql.Query) (string, []any, error) { query := r.buildBaseQuery(orgID) var err error @@ -171,7 +171,7 @@ func (r OrgTokensRepository) addFilter(query *goqu.SelectDataset, filter rql.Fil // in/notin only applies to string-type RQL fields (source, type, etc.) // numeric fields like amount are rejected by rql.ValidateQuery before reaching here values := make([]string, 0) - for _, v := range strings.Split(filter.Value.(string), ",") { + for v := range strings.SplitSeq(filter.Value.(string), ",") { if trimmed := strings.TrimSpace(v); trimmed != "" { values = append(values, trimmed) } diff --git a/internal/store/postgres/org_tokens_repository_test.go b/internal/store/postgres/org_tokens_repository_test.go index a5f50e889..65475e481 100644 --- a/internal/store/postgres/org_tokens_repository_test.go +++ b/internal/store/postgres/org_tokens_repository_test.go @@ -13,7 +13,7 @@ func TestOrgTokensRepository_prepareDataQuery(t *testing.T) { orgID string rql *rql.Query wantSQL string - wantParams []interface{} + wantParams []any wantErr bool }{ { @@ -24,7 +24,7 @@ func TestOrgTokensRepository_prepareDataQuery(t *testing.T) { Offset: 20, }, wantSQL: `SELECT "billing_transactions"."amount" AS "token_amount", "billing_transactions"."type" AS "token_type", "billing_transactions"."source" AS "token_source", "billing_transactions"."description" AS "token_description", "billing_transactions"."user_id" AS "token_user_id", "users"."title" AS "user_title", "users"."avatar" AS "user_avatar", "billing_transactions"."created_at" AS "token_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_transactions" INNER JOIN "billing_customers" ON ("billing_transactions"."account_id" = "billing_customers"."id") LEFT JOIN "users" ON CASE WHEN "billing_transactions"."user_id" IS NOT NULL AND "billing_transactions"."user_id" != '' THEN CAST("billing_transactions"."user_id" AS uuid) = "users"."id" ELSE false END WHERE ("billing_customers"."org_id" = $1) LIMIT $2 OFFSET $3`, - wantParams: []interface{}{"org123", int64(10), int64(20)}, + wantParams: []any{"org123", int64(10), int64(20)}, wantErr: false, }, { @@ -42,7 +42,7 @@ func TestOrgTokensRepository_prepareDataQuery(t *testing.T) { Offset: 30, }, wantSQL: `SELECT "billing_transactions"."amount" AS "token_amount", "billing_transactions"."type" AS "token_type", "billing_transactions"."source" AS "token_source", "billing_transactions"."description" AS "token_description", "billing_transactions"."user_id" AS "token_user_id", "users"."title" AS "user_title", "users"."avatar" AS "user_avatar", "billing_transactions"."created_at" AS "token_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_transactions" INNER JOIN "billing_customers" ON ("billing_transactions"."account_id" = "billing_customers"."id") LEFT JOIN "users" ON CASE WHEN "billing_transactions"."user_id" IS NOT NULL AND "billing_transactions"."user_id" != '' THEN CAST("billing_transactions"."user_id" AS uuid) = "users"."id" ELSE false END WHERE (("billing_customers"."org_id" = $1) AND ("billing_transactions"."amount" >= $2)) LIMIT $3 OFFSET $4`, - wantParams: []interface{}{"org123", int64(1000), int64(10), int64(30)}, + wantParams: []any{"org123", int64(1000), int64(10), int64(30)}, wantErr: false, }, { @@ -61,7 +61,7 @@ func TestOrgTokensRepository_prepareDataQuery(t *testing.T) { Offset: 40, }, wantSQL: `SELECT "billing_transactions"."amount" AS "token_amount", "billing_transactions"."type" AS "token_type", "billing_transactions"."source" AS "token_source", "billing_transactions"."description" AS "token_description", "billing_transactions"."user_id" AS "token_user_id", "users"."title" AS "user_title", "users"."avatar" AS "user_avatar", "billing_transactions"."created_at" AS "token_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_transactions" INNER JOIN "billing_customers" ON ("billing_transactions"."account_id" = "billing_customers"."id") LEFT JOIN "users" ON CASE WHEN "billing_transactions"."user_id" IS NOT NULL AND "billing_transactions"."user_id" != '' THEN CAST("billing_transactions"."user_id" AS uuid) = "users"."id" ELSE false END WHERE (("billing_customers"."org_id" = $1) AND ("billing_transactions"."type" = $2) AND ((CAST("billing_transactions"."type" AS TEXT) ILIKE $3) OR (CAST("billing_transactions"."description" AS TEXT) ILIKE $4) OR (CAST("users"."title" AS TEXT) ILIKE $5) OR (CAST("billing_transactions"."amount" AS TEXT) ILIKE $6))) LIMIT $7 OFFSET $8`, - wantParams: []interface{}{"org123", "credit", "%test%", "%test%", "%test%", "%test%", int64(10), int64(40)}, + wantParams: []any{"org123", "credit", "%test%", "%test%", "%test%", "%test%", int64(10), int64(40)}, wantErr: false, }, { @@ -85,7 +85,7 @@ func TestOrgTokensRepository_prepareDataQuery(t *testing.T) { Offset: 50, }, wantSQL: `SELECT "billing_transactions"."amount" AS "token_amount", "billing_transactions"."type" AS "token_type", "billing_transactions"."source" AS "token_source", "billing_transactions"."description" AS "token_description", "billing_transactions"."user_id" AS "token_user_id", "users"."title" AS "user_title", "users"."avatar" AS "user_avatar", "billing_transactions"."created_at" AS "token_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_transactions" INNER JOIN "billing_customers" ON ("billing_transactions"."account_id" = "billing_customers"."id") LEFT JOIN "users" ON CASE WHEN "billing_transactions"."user_id" IS NOT NULL AND "billing_transactions"."user_id" != '' THEN CAST("billing_transactions"."user_id" AS uuid) = "users"."id" ELSE false END WHERE (("billing_customers"."org_id" = $1) AND ("billing_transactions"."created_at" >= $2)) ORDER BY "billing_transactions"."created_at" DESC LIMIT $3 OFFSET $4`, - wantParams: []interface{}{"org123", "2024-01-01T00:00:00Z", int64(10), int64(50)}, + wantParams: []any{"org123", "2024-01-01T00:00:00Z", int64(10), int64(50)}, wantErr: false, }, { @@ -106,7 +106,7 @@ func TestOrgTokensRepository_prepareDataQuery(t *testing.T) { Offset: 25, }, wantSQL: `SELECT "billing_transactions"."amount" AS "token_amount", "billing_transactions"."type" AS "token_type", "billing_transactions"."source" AS "token_source", "billing_transactions"."description" AS "token_description", "billing_transactions"."user_id" AS "token_user_id", "users"."title" AS "user_title", "users"."avatar" AS "user_avatar", "billing_transactions"."created_at" AS "token_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_transactions" INNER JOIN "billing_customers" ON ("billing_transactions"."account_id" = "billing_customers"."id") LEFT JOIN "users" ON CASE WHEN "billing_transactions"."user_id" IS NOT NULL AND "billing_transactions"."user_id" != '' THEN CAST("billing_transactions"."user_id" AS uuid) = "users"."id" ELSE false END WHERE ("billing_customers"."org_id" = $1) ORDER BY "billing_transactions"."type" DESC, "users"."title" ASC LIMIT $2 OFFSET $3`, - wantParams: []interface{}{"org123", int64(10), int64(25)}, + wantParams: []any{"org123", int64(10), int64(25)}, wantErr: false, }, { @@ -123,7 +123,7 @@ func TestOrgTokensRepository_prepareDataQuery(t *testing.T) { Offset: 45, }, wantSQL: `SELECT "billing_transactions"."amount" AS "token_amount", "billing_transactions"."type" AS "token_type", "billing_transactions"."source" AS "token_source", "billing_transactions"."description" AS "token_description", "billing_transactions"."user_id" AS "token_user_id", "users"."title" AS "user_title", "users"."avatar" AS "user_avatar", "billing_transactions"."created_at" AS "token_created_at", "billing_customers"."org_id" AS "org_id" FROM "billing_transactions" INNER JOIN "billing_customers" ON ("billing_transactions"."account_id" = "billing_customers"."id") LEFT JOIN "users" ON CASE WHEN "billing_transactions"."user_id" IS NOT NULL AND "billing_transactions"."user_id" != '' THEN CAST("billing_transactions"."user_id" AS uuid) = "users"."id" ELSE false END WHERE (("billing_customers"."org_id" = $1) AND (("billing_transactions"."description" IS NULL) OR ("billing_transactions"."description" = $2))) LIMIT $3 OFFSET $4`, - wantParams: []interface{}{"org123", "", int64(10), int64(45)}, + wantParams: []any{"org123", "", int64(10), int64(45)}, wantErr: false, }, { diff --git a/internal/store/postgres/org_users_repository.go b/internal/store/postgres/org_users_repository.go index 8e8838922..d90899cd5 100644 --- a/internal/store/postgres/org_users_repository.go +++ b/internal/store/postgres/org_users_repository.go @@ -143,7 +143,7 @@ func (r OrgUsersRepository) Search(ctx context.Context, orgID string, rql *rql.Q // prepare a query by joining policy, users and roles tables // combines all roles of a user as a comma separated string -func (r OrgUsersRepository) prepareDataQuery(orgID string, input *rql.Query) (string, []interface{}, error) { +func (r OrgUsersRepository) prepareDataQuery(orgID string, input *rql.Query) (string, []any, error) { baseQuery := r.buildBaseQuery(orgID) if err := r.validateFilters(input.Filters); err != nil { @@ -169,7 +169,7 @@ func (r OrgUsersRepository) prepareDataQuery(orgID string, input *rql.Query) (st } func (r OrgUsersRepository) buildBaseQuery(orgID string) *goqu.SelectDataset { - querySelects := []interface{}{ + querySelects := []any{ goqu.I(TABLE_POLICIES + "." + COLUMN_RESOURCE_ID).As(COLUMN_ORG_ID), goqu.I(TABLE_USERS + "." + COLUMN_ID).As(COLUMN_ID), goqu.I(TABLE_USERS + "." + COLUMN_NAME).As(COLUMN_NAME), @@ -205,8 +205,8 @@ func (r OrgUsersRepository) buildBaseQuery(orgID string) *goqu.SelectDataset { GroupBy(r.getGroupByColumns()...) } -func (r OrgUsersRepository) getGroupByColumns() []interface{} { - return []interface{}{ +func (r OrgUsersRepository) getGroupByColumns() []any { + return []any{ goqu.I(TABLE_POLICIES + "." + COLUMN_RESOURCE_ID), goqu.I(TABLE_USERS + "." + COLUMN_ID), goqu.I(TABLE_USERS + "." + COLUMN_NAME), @@ -293,7 +293,7 @@ func (r OrgUsersRepository) getRoleColumnName(filterName string) string { } } -func (r OrgUsersRepository) buildRoleExistsSubquery(orgID string, columnName string, value interface{}) *goqu.SelectDataset { +func (r OrgUsersRepository) buildRoleExistsSubquery(orgID string, columnName string, value any) *goqu.SelectDataset { return dialect.From(TABLE_POLICIES).Prepared(true). Join( goqu.T(TABLE_ROLES), diff --git a/internal/store/postgres/org_users_repository_test.go b/internal/store/postgres/org_users_repository_test.go index acb7c6d08..e1b64be14 100644 --- a/internal/store/postgres/org_users_repository_test.go +++ b/internal/store/postgres/org_users_repository_test.go @@ -17,7 +17,7 @@ func TestOrgUsersRepository_PrepareDataQuery(t *testing.T) { orgID string rqlQuery *rql.Query wantSQL string - wantParams []interface{} + wantParams []any wantErr bool }{ { @@ -28,7 +28,7 @@ func TestOrgUsersRepository_PrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "policies"."resource_id" AS "org_id", "users"."id" AS "id", "users"."name" AS "name", "users"."title" AS "title", "users"."email" AS "email", "users"."state" AS "state", "users"."avatar" AS "avatar", MIN("policies"."created_at") AS "org_joined_at", ARRAY_AGG("roles"."name") AS "role_names", ARRAY_AGG(COALESCE("roles"."title", '')) AS "role_titles", ARRAY_AGG(CAST("roles"."id" AS TEXT)) AS "role_ids" FROM "policies" INNER JOIN "users" ON ("users"."id" = "policies"."principal_id") LEFT JOIN "roles" ON ("roles"."id" = "policies"."role_id") WHERE (("policies"."resource_id" = $1) AND ("policies"."resource_type" = $2) AND ("policies"."principal_type" = $3) AND ("users"."deleted_at" IS NULL) AND ("roles"."deleted_at" IS NULL)) GROUP BY "policies"."resource_id", "users"."id", "users"."name", "users"."title", "users"."email", "users"."state", "users"."created_at", "users"."updated_at" LIMIT $4`, - wantParams: []interface{}{"org123", "app/organization", "app/user", int64(10)}, + wantParams: []any{"org123", "app/organization", "app/user", int64(10)}, }, { name: "query with email filter", @@ -45,7 +45,7 @@ func TestOrgUsersRepository_PrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "policies"."resource_id" AS "org_id", "users"."id" AS "id", "users"."name" AS "name", "users"."title" AS "title", "users"."email" AS "email", "users"."state" AS "state", "users"."avatar" AS "avatar", MIN("policies"."created_at") AS "org_joined_at", ARRAY_AGG("roles"."name") AS "role_names", ARRAY_AGG(COALESCE("roles"."title", '')) AS "role_titles", ARRAY_AGG(CAST("roles"."id" AS TEXT)) AS "role_ids" FROM "policies" INNER JOIN "users" ON ("users"."id" = "policies"."principal_id") LEFT JOIN "roles" ON ("roles"."id" = "policies"."role_id") WHERE (("policies"."resource_id" = $1) AND ("policies"."resource_type" = $2) AND ("policies"."principal_type" = $3) AND ("users"."deleted_at" IS NULL) AND ("roles"."deleted_at" IS NULL) AND ("users"."email" = $4)) GROUP BY "policies"."resource_id", "users"."id", "users"."name", "users"."title", "users"."email", "users"."state", "users"."created_at", "users"."updated_at" LIMIT $5`, - wantParams: []interface{}{"org123", "app/organization", "app/user", "test@example.com", int64(10)}, + wantParams: []any{"org123", "app/organization", "app/user", "test@example.com", int64(10)}, }, { name: "query with role filter", @@ -62,7 +62,7 @@ func TestOrgUsersRepository_PrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "policies"."resource_id" AS "org_id", "users"."id" AS "id", "users"."name" AS "name", "users"."title" AS "title", "users"."email" AS "email", "users"."state" AS "state", "users"."avatar" AS "avatar", MIN("policies"."created_at") AS "org_joined_at", ARRAY_AGG("roles"."name") AS "role_names", ARRAY_AGG(COALESCE("roles"."title", '')) AS "role_titles", ARRAY_AGG(CAST("roles"."id" AS TEXT)) AS "role_ids" FROM "policies" INNER JOIN "users" ON ("users"."id" = "policies"."principal_id") LEFT JOIN "roles" ON ("roles"."id" = "policies"."role_id") WHERE (("policies"."resource_id" = $1) AND ("policies"."resource_type" = $2) AND ("policies"."principal_type" = $3) AND ("users"."deleted_at" IS NULL) AND ("roles"."deleted_at" IS NULL) AND EXISTS (SELECT 1 FROM "policies" INNER JOIN "roles" ON ("roles"."id" = "policies"."role_id") WHERE (("policies"."principal_id" = "users"."id") AND ("policies"."resource_id" = $4) AND ("policies"."resource_type" = $5) AND ("roles"."name" = $6)) LIMIT $7)) GROUP BY "policies"."resource_id", "users"."id", "users"."name", "users"."title", "users"."email", "users"."state", "users"."created_at", "users"."updated_at" LIMIT $8`, - wantParams: []interface{}{"org123", "app/organization", "app/user", "org123", "app/organization", "admin", int64(1), int64(10)}, + wantParams: []any{"org123", "app/organization", "app/user", "org123", "app/organization", "admin", int64(1), int64(10)}, }, { name: "query with search", @@ -73,7 +73,7 @@ func TestOrgUsersRepository_PrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "policies"."resource_id" AS "org_id", "users"."id" AS "id", "users"."name" AS "name", "users"."title" AS "title", "users"."email" AS "email", "users"."state" AS "state", "users"."avatar" AS "avatar", MIN("policies"."created_at") AS "org_joined_at", ARRAY_AGG("roles"."name") AS "role_names", ARRAY_AGG(COALESCE("roles"."title", '')) AS "role_titles", ARRAY_AGG(CAST("roles"."id" AS TEXT)) AS "role_ids" FROM "policies" INNER JOIN "users" ON ("users"."id" = "policies"."principal_id") LEFT JOIN "roles" ON ("roles"."id" = "policies"."role_id") WHERE (("policies"."resource_id" = $1) AND ("policies"."resource_type" = $2) AND ("policies"."principal_type" = $3) AND ("users"."deleted_at" IS NULL) AND ("roles"."deleted_at" IS NULL) AND ((CAST("users"."name" AS TEXT) ILIKE $4) OR (CAST("users"."title" AS TEXT) ILIKE $5) OR (CAST("users"."email" AS TEXT) ILIKE $6) OR (CAST("users"."state" AS TEXT) ILIKE $7))) GROUP BY "policies"."resource_id", "users"."id", "users"."name", "users"."title", "users"."email", "users"."state", "users"."created_at", "users"."updated_at" LIMIT $8`, - wantParams: []interface{}{"org123", "app/organization", "app/user", "%john%", "%john%", "%john%", "%john%", int64(10)}, + wantParams: []any{"org123", "app/organization", "app/user", "%john%", "%john%", "%john%", "%john%", int64(10)}, }, { name: "query with sort", @@ -87,7 +87,7 @@ func TestOrgUsersRepository_PrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "policies"."resource_id" AS "org_id", "users"."id" AS "id", "users"."name" AS "name", "users"."title" AS "title", "users"."email" AS "email", "users"."state" AS "state", "users"."avatar" AS "avatar", MIN("policies"."created_at") AS "org_joined_at", ARRAY_AGG("roles"."name") AS "role_names", ARRAY_AGG(COALESCE("roles"."title", '')) AS "role_titles", ARRAY_AGG(CAST("roles"."id" AS TEXT)) AS "role_ids" FROM "policies" INNER JOIN "users" ON ("users"."id" = "policies"."principal_id") LEFT JOIN "roles" ON ("roles"."id" = "policies"."role_id") WHERE (("policies"."resource_id" = $1) AND ("policies"."resource_type" = $2) AND ("policies"."principal_type" = $3) AND ("users"."deleted_at" IS NULL) AND ("roles"."deleted_at" IS NULL)) GROUP BY "policies"."resource_id", "users"."id", "users"."name", "users"."title", "users"."email", "users"."state", "users"."created_at", "users"."updated_at" ORDER BY "name" ASC, "email" DESC LIMIT $4`, - wantParams: []interface{}{"org123", "app/organization", "app/user", int64(10)}, + wantParams: []any{"org123", "app/organization", "app/user", int64(10)}, }, } @@ -113,7 +113,7 @@ func TestOrgUsersRepository_BuildNonRoleFilterCondition(t *testing.T) { name string filter rql.Filter wantSQL string - wantArgs []interface{} + wantArgs []any wantErr bool }{ { @@ -124,7 +124,7 @@ func TestOrgUsersRepository_BuildNonRoleFilterCondition(t *testing.T) { Value: "test@example.com", }, wantSQL: `("users"."email" = $1)`, - wantArgs: []interface{}{"test@example.com"}, + wantArgs: []any{"test@example.com"}, }, { name: "like operator", @@ -134,7 +134,7 @@ func TestOrgUsersRepository_BuildNonRoleFilterCondition(t *testing.T) { Value: "%john%", }, wantSQL: `(CAST("users"."name" AS TEXT) LIKE $1)`, - wantArgs: []interface{}{"%john%"}, + wantArgs: []any{"%john%"}, }, { name: "notlike operator", @@ -144,7 +144,7 @@ func TestOrgUsersRepository_BuildNonRoleFilterCondition(t *testing.T) { Value: "%john%", }, wantSQL: `(CAST("users"."name" AS TEXT) NOT LIKE $1)`, - wantArgs: []interface{}{"%john%"}, + wantArgs: []any{"%john%"}, }, { name: "ilike operator", @@ -154,7 +154,7 @@ func TestOrgUsersRepository_BuildNonRoleFilterCondition(t *testing.T) { Value: "%john%", }, wantSQL: `(CAST("users"."title" AS TEXT) ILIKE $1)`, - wantArgs: []interface{}{"%john%"}, + wantArgs: []any{"%john%"}, }, { name: "notilike operator", @@ -164,7 +164,7 @@ func TestOrgUsersRepository_BuildNonRoleFilterCondition(t *testing.T) { Value: "%john%", }, wantSQL: `(CAST("users"."title" AS TEXT) NOT ILIKE $1)`, - wantArgs: []interface{}{"%john%"}, + wantArgs: []any{"%john%"}, }, { name: "in operator", @@ -174,7 +174,7 @@ func TestOrgUsersRepository_BuildNonRoleFilterCondition(t *testing.T) { Value: "active,inactive", }, wantSQL: `("users"."state" IN ($1, $2))`, - wantArgs: []interface{}{"active", "inactive"}, + wantArgs: []any{"active", "inactive"}, }, { name: "empty operator", @@ -183,7 +183,7 @@ func TestOrgUsersRepository_BuildNonRoleFilterCondition(t *testing.T) { Operator: "empty", }, wantSQL: `(("users"."title" IS NULL) OR ("users"."title" = $1))`, - wantArgs: []interface{}{""}, + wantArgs: []any{""}, }, { name: "datetime gte operator", @@ -193,7 +193,7 @@ func TestOrgUsersRepository_BuildNonRoleFilterCondition(t *testing.T) { Value: "2024-01-01T00:00:00Z", }, wantSQL: `("policies"."created_at" >= $1)`, - wantArgs: []interface{}{"2024-01-01T00:00:00Z"}, + wantArgs: []any{"2024-01-01T00:00:00Z"}, }, { name: "ilike operator not allowed on datetime column", @@ -250,7 +250,7 @@ func TestOrgUsersRepository_BuildRoleFilterCondition(t *testing.T) { orgID string filter rql.Filter wantSQL string - wantArgs []interface{} + wantArgs []any wantErr bool }{ { @@ -262,7 +262,7 @@ func TestOrgUsersRepository_BuildRoleFilterCondition(t *testing.T) { Value: "admin", }, wantSQL: `EXISTS (SELECT 1 FROM "policies" INNER JOIN "roles" ON ("roles"."id" = "policies"."role_id") WHERE (("policies"."principal_id" = "users"."id") AND ("policies"."resource_id" = $1) AND ("policies"."resource_type" = $2) AND ("roles"."name" = $3)) LIMIT $4)`, - wantArgs: []interface{}{"org123", "app/organization", "admin", int64(1)}, + wantArgs: []any{"org123", "app/organization", "admin", int64(1)}, }, { name: "neq operator", @@ -273,7 +273,7 @@ func TestOrgUsersRepository_BuildRoleFilterCondition(t *testing.T) { Value: "admin", }, wantSQL: `(NOT EXISTS (SELECT 1 FROM "policies" INNER JOIN "roles" ON ("roles"."id" = "policies"."role_id") WHERE (("policies"."principal_id" = "users"."id") AND ("policies"."resource_id" = $1) AND ("policies"."resource_type" = $2) AND ("roles"."name" = $3)) LIMIT $4) AND EXISTS (SELECT 1 FROM "policies" INNER JOIN "roles" ON ("roles"."id" = "policies"."role_id") WHERE (("policies"."principal_id" = "users"."id") AND ("policies"."resource_id" = $5) AND ("policies"."resource_type" = $6)) LIMIT $7))`, - wantArgs: []interface{}{"org123", "app/organization", "admin", int64(1), "org123", "app/organization", int64(1)}, + wantArgs: []any{"org123", "app/organization", "admin", int64(1), "org123", "app/organization", int64(1)}, }, { name: "invalid operator", diff --git a/internal/store/postgres/organization_repository.go b/internal/store/postgres/organization_repository.go index 48fa691bb..71287dc95 100644 --- a/internal/store/postgres/organization_repository.go +++ b/internal/store/postgres/organization_repository.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "maps" "strings" "github.com/raystack/frontier/pkg/auditrecord" @@ -280,17 +281,15 @@ func (r OrganizationRepository) List(ctx context.Context, flt organization.Filte } // buildOrgUpdateAuditRecord creates an audit record for organization updates -func buildOrgUpdateAuditRecord(ctx context.Context, orgBeforeUpdate, orgAfterUpdate Organization, metadata map[string]interface{}) AuditRecord { +func buildOrgUpdateAuditRecord(ctx context.Context, orgBeforeUpdate, orgAfterUpdate Organization, metadata map[string]any) AuditRecord { title := nullStringToString(orgBeforeUpdate.Title) updatedTitle := nullStringToString(orgAfterUpdate.Title) auditMetadata := metadata if title != updatedTitle { // Create a new one to avoid mutating the original - auditMetadata = make(map[string]interface{}) - for k, v := range metadata { - auditMetadata[k] = v - } + auditMetadata = make(map[string]any) + maps.Copy(auditMetadata, metadata) auditMetadata["title"] = title auditMetadata["updated_title"] = updatedTitle } @@ -486,7 +485,7 @@ func (r OrganizationRepository) SetState(ctx context.Context, id string, state o ID: orgModel.ID, Type: auditrecord.OrganizationType, Name: nullStringToString(orgModel.Title), - Metadata: map[string]interface{}{ + Metadata: map[string]any{ "state": state.String(), }, }, diff --git a/internal/store/postgres/policy_repository.go b/internal/store/postgres/policy_repository.go index 59728a375..0003146e1 100644 --- a/internal/store/postgres/policy_repository.go +++ b/internal/store/postgres/policy_repository.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "maps" "strings" "time" @@ -575,9 +576,7 @@ func (r PolicyRepository) buildPolicyAuditRecord(ctx context.Context, tx *sqlx.T "principal_type": pol.PrincipalType, "grant_relation": pol.GrantRelation, } - for k, v := range additionalMetadata { - targetMetadata[k] = v - } + maps.Copy(targetMetadata, additionalMetadata) return BuildAuditRecord( ctx, diff --git a/internal/store/postgres/postgres_test.go b/internal/store/postgres/postgres_test.go index c081dc9dc..a69b4c7d5 100644 --- a/internal/store/postgres/postgres_test.go +++ b/internal/store/postgres/postgres_test.go @@ -326,7 +326,7 @@ func bootstrapRelation(client *db.Client) ([]relation.Relation, error) { // setTestAuditActorContext sets up audit context for tests without importing service layer func setTestAuditActorContext(ctx context.Context) context.Context { testActorID := uuid.New().String() - actorMap := map[string]interface{}{ + actorMap := map[string]any{ "id": testActorID, "type": schema.UserPrincipal, "name": "unit-test", diff --git a/internal/store/postgres/project_users_repository.go b/internal/store/postgres/project_users_repository.go index a34171b0b..a10090ca7 100644 --- a/internal/store/postgres/project_users_repository.go +++ b/internal/store/postgres/project_users_repository.go @@ -97,7 +97,7 @@ func (r ProjectUsersRepository) Search(ctx context.Context, projectID string, rq }, nil } -func (r ProjectUsersRepository) prepareDataQuery(projectID string, rql *rql.Query) (string, []interface{}, error) { +func (r ProjectUsersRepository) prepareDataQuery(projectID string, rql *rql.Query) (string, []any, error) { query := r.buildBaseQuery(projectID) if rql.Search != "" { diff --git a/internal/store/postgres/project_users_repository_test.go b/internal/store/postgres/project_users_repository_test.go index 928f404e5..b1f2466cc 100644 --- a/internal/store/postgres/project_users_repository_test.go +++ b/internal/store/postgres/project_users_repository_test.go @@ -14,7 +14,7 @@ func TestProjectUsersRepository_PrepareDataQuery(t *testing.T) { projectID string rql *rql.Query wantSQL string - wantArgs []interface{} + wantArgs []any wantErr bool }{ { @@ -25,7 +25,7 @@ func TestProjectUsersRepository_PrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT "users"."id", "users"."name", "users"."email", "users"."title", "users"."avatar", "users"."state", "policies"."resource_id" AS "project_id", MIN("policies"."created_at") AS "project_joined_at", string_agg(DISTINCT roles.name, ',') AS "role_names", string_agg(DISTINCT roles.title, ',') AS "role_titles", string_agg(DISTINCT roles.id::text, ',') AS "role_ids" FROM "policies" INNER JOIN "users" ON ("policies"."principal_id" = "users"."id") INNER JOIN "roles" ON ("policies"."role_id" = "roles"."id") WHERE (("policies"."principal_type" = $1) AND ("policies"."resource_id" = $2) AND ("policies"."resource_type" = $3)) GROUP BY "users"."id", "users"."name", "users"."email", "users"."title", "users"."state", "policies"."resource_id" LIMIT $4`, - wantArgs: []interface{}{"app/user", "project-123", "app/project", int64(10)}, + wantArgs: []any{"app/user", "project-123", "app/project", int64(10)}, wantErr: false, }, { @@ -37,7 +37,7 @@ func TestProjectUsersRepository_PrepareDataQuery(t *testing.T) { Offset: 0, }, wantSQL: `SELECT * FROM (SELECT "users"."id", "users"."name", "users"."email", "users"."title", "users"."avatar", "users"."state", "policies"."resource_id" AS "project_id", MIN("policies"."created_at") AS "project_joined_at", string_agg(DISTINCT roles.name, ',') AS "role_names", string_agg(DISTINCT roles.title, ',') AS "role_titles", string_agg(DISTINCT roles.id::text, ',') AS "role_ids" FROM "policies" INNER JOIN "users" ON ("policies"."principal_id" = "users"."id") INNER JOIN "roles" ON ("policies"."role_id" = "roles"."id") WHERE (("policies"."principal_type" = $1) AND ("policies"."resource_id" = $2) AND ("policies"."resource_type" = $3)) GROUP BY "users"."id", "users"."name", "users"."email", "users"."title", "users"."state", "policies"."resource_id") AS "base" WHERE (("base"."name" ILIKE $4) OR ("base"."email" ILIKE $5) OR ("base"."title" ILIKE $6) OR ("base"."state" ILIKE $7) OR ("base"."role_names" ILIKE $8) OR ("base"."role_titles" ILIKE $9) OR ("base"."role_ids" ILIKE $10)) LIMIT $11`, - wantArgs: []interface{}{"app/user", "project-123", "app/project", "%john%", "%john%", "%john%", "%john%", "%john%", "%john%", "%john%", int64(10)}, + wantArgs: []any{"app/user", "project-123", "app/project", "%john%", "%john%", "%john%", "%john%", "%john%", "%john%", "%john%", int64(10)}, wantErr: false, }, } diff --git a/internal/store/postgres/user_orgs_repository.go b/internal/store/postgres/user_orgs_repository.go index 26133be66..3f4b78312 100644 --- a/internal/store/postgres/user_orgs_repository.go +++ b/internal/store/postgres/user_orgs_repository.go @@ -147,7 +147,7 @@ func (r UserOrgsRepository) Search(ctx context.Context, principalID string, rql // this principal explicitly granted", while the membership path answers "what // can this principal access". Do not "fix" one to match the other without a // product decision. -func (r UserOrgsRepository) buildBaseQuery(principalID string) (string, []interface{}, error) { +func (r UserOrgsRepository) buildBaseQuery(principalID string) (string, []any, error) { projectCountSubquery := dialect.From(TABLE_PROJECTS). Select( goqu.I(COLUMN_ORG_ID), @@ -160,7 +160,7 @@ func (r UserOrgsRepository) buildBaseQuery(principalID string) (string, []interf GroupBy(COLUMN_ORG_ID). As(ALIAS_PROJECT_COUNTS) - querySelects := []interface{}{ + querySelects := []any{ goqu.I(TABLE_POLICIES + "." + COLUMN_PRINCIPAL_ID), goqu.I(TABLE_POLICIES + "." + COLUMN_RESOURCE_ID).As(COLUMN_ORG_ID), goqu.I(TABLE_ORGANIZATIONS + "." + COLUMN_NAME).As(COLUMN_ORG_NAME), diff --git a/internal/store/postgres/user_orgs_repository_test.go b/internal/store/postgres/user_orgs_repository_test.go index b47e1db80..09486d516 100644 --- a/internal/store/postgres/user_orgs_repository_test.go +++ b/internal/store/postgres/user_orgs_repository_test.go @@ -12,21 +12,21 @@ func TestUserOrgsRepository_buildBaseQuery(t *testing.T) { name string principalID string wantSQL string - wantParams []interface{} + wantParams []any wantErr bool }{ { name: "should build query for valid principal id", principalID: "test-user-id", wantSQL: `SELECT "policies"."principal_id", "policies"."resource_id" AS "org_id", "organizations"."name" AS "org_name", "organizations"."title" AS "org_title", "organizations"."avatar" AS "org_avatar", MIN("policies"."created_at") AS "org_joined_on", ARRAY_AGG("roles"."name") AS "role_names", ARRAY_AGG("roles"."title") AS "role_titles", ARRAY_AGG("roles"."id") AS "role_ids", COALESCE("project_counts"."project_count", $1) AS "project_count" FROM "policies" INNER JOIN "roles" ON ("policies"."role_id" = "roles"."id") INNER JOIN "organizations" ON ("policies"."resource_id" = "organizations"."id") INNER JOIN "users" ON ("policies"."principal_id" = "users"."id") LEFT JOIN (SELECT "org_id", COUNT("id") AS "project_count" FROM "projects" WHERE (("deleted_at" IS NULL) AND ("state" = $2)) GROUP BY "org_id") AS "project_counts" ON ("project_counts"."org_id" = "organizations"."id") WHERE (("policies"."resource_type" = $3) AND ("policies"."principal_id" = $4)) GROUP BY "policies"."principal_id", "users"."email", "policies"."resource_id", "organizations"."name", "organizations"."title", "organizations"."avatar", "project_counts"."project_count" ORDER BY "organizations"."name" ASC`, - wantParams: []interface{}{int64(0), "enabled", "app/organization", "test-user-id"}, + wantParams: []any{int64(0), "enabled", "app/organization", "test-user-id"}, wantErr: false, }, { name: "should build query for empty principal id", principalID: "", wantSQL: `SELECT "policies"."principal_id", "policies"."resource_id" AS "org_id", "organizations"."name" AS "org_name", "organizations"."title" AS "org_title", "organizations"."avatar" AS "org_avatar", MIN("policies"."created_at") AS "org_joined_on", ARRAY_AGG("roles"."name") AS "role_names", ARRAY_AGG("roles"."title") AS "role_titles", ARRAY_AGG("roles"."id") AS "role_ids", COALESCE("project_counts"."project_count", $1) AS "project_count" FROM "policies" INNER JOIN "roles" ON ("policies"."role_id" = "roles"."id") INNER JOIN "organizations" ON ("policies"."resource_id" = "organizations"."id") INNER JOIN "users" ON ("policies"."principal_id" = "users"."id") LEFT JOIN (SELECT "org_id", COUNT("id") AS "project_count" FROM "projects" WHERE (("deleted_at" IS NULL) AND ("state" = $2)) GROUP BY "org_id") AS "project_counts" ON ("project_counts"."org_id" = "organizations"."id") WHERE (("policies"."resource_type" = $3) AND ("policies"."principal_id" = $4)) GROUP BY "policies"."principal_id", "users"."email", "policies"."resource_id", "organizations"."name", "organizations"."title", "organizations"."avatar", "project_counts"."project_count" ORDER BY "organizations"."name" ASC`, - wantParams: []interface{}{int64(0), "enabled", "app/organization", ""}, + wantParams: []any{int64(0), "enabled", "app/organization", ""}, wantErr: false, }, } diff --git a/internal/store/postgres/user_projects_repository_test.go b/internal/store/postgres/user_projects_repository_test.go index fec73e1ec..47d716c15 100644 --- a/internal/store/postgres/user_projects_repository_test.go +++ b/internal/store/postgres/user_projects_repository_test.go @@ -14,7 +14,7 @@ func TestUserProjectsRepository_prepareDataQuery(t *testing.T) { orgID string rql *rql.Query wantSQL string - wantArgs []interface{} + wantArgs []any wantError bool }{ { @@ -26,7 +26,7 @@ func TestUserProjectsRepository_prepareDataQuery(t *testing.T) { Limit: 10, }, wantSQL: `SELECT "p"."id" AS "project_id", "p"."title" AS "project_title", "p"."name" AS "project_name", "p"."created_at" AS "project_created_on", array_agg(DISTINCT u.id ORDER BY u.id) AS "user_ids", array_agg(DISTINCT u.avatar ORDER BY u.avatar) AS "user_avatars", array_agg(DISTINCT u.name ORDER BY u.name) AS "user_names", array_agg(DISTINCT u.title ORDER BY u.title) AS "user_titles" FROM "projects" AS "p" INNER JOIN "policies" AS "pol" ON (("p"."id" = "pol"."resource_id") AND ("pol"."resource_type" = $1) AND ("pol"."deleted_at" IS NULL)) INNER JOIN "users" AS "u" ON (("pol"."principal_id" = "u"."id") AND ("pol"."principal_type" = $2)) WHERE ("p"."id" IN ((SELECT "p2"."id" FROM "projects" AS "p2" INNER JOIN "policies" AS "pol2" ON ("p2"."id" = "pol2"."resource_id") WHERE (("p2"."org_id" = $3) AND ("pol2"."principal_id" = $4) AND ("pol2"."resource_type" = $5) AND ("pol2"."principal_type" = $6) AND ("pol2"."deleted_at" IS NULL))))) GROUP BY "p"."id", "p"."name", "p"."created_at" ORDER BY "p"."name" ASC LIMIT $7 OFFSET $8`, - wantArgs: []interface{}{"app/project", "app/user", "org456", "user123", "app/project", "app/user", int64(10), int64(1)}, + wantArgs: []any{"app/project", "app/user", "org456", "user123", "app/project", "app/user", int64(10), int64(1)}, wantError: false, }, { @@ -39,7 +39,7 @@ func TestUserProjectsRepository_prepareDataQuery(t *testing.T) { Search: "test", }, wantSQL: `SELECT * FROM (SELECT "p"."id" AS "project_id", "p"."title" AS "project_title", "p"."name" AS "project_name", "p"."created_at" AS "project_created_on", array_agg(DISTINCT u.id ORDER BY u.id) AS "user_ids", array_agg(DISTINCT u.avatar ORDER BY u.avatar) AS "user_avatars", array_agg(DISTINCT u.name ORDER BY u.name) AS "user_names", array_agg(DISTINCT u.title ORDER BY u.title) AS "user_titles" FROM "projects" AS "p" INNER JOIN "policies" AS "pol" ON (("p"."id" = "pol"."resource_id") AND ("pol"."resource_type" = $1) AND ("pol"."deleted_at" IS NULL)) INNER JOIN "users" AS "u" ON (("pol"."principal_id" = "u"."id") AND ("pol"."principal_type" = $2)) WHERE ("p"."id" IN ((SELECT "p2"."id" FROM "projects" AS "p2" INNER JOIN "policies" AS "pol2" ON ("p2"."id" = "pol2"."resource_id") WHERE (("p2"."org_id" = $3) AND ("pol2"."principal_id" = $4) AND ("pol2"."resource_type" = $5) AND ("pol2"."principal_type" = $6) AND ("pol2"."deleted_at" IS NULL))))) GROUP BY "p"."id", "p"."name", "p"."created_at" ORDER BY "p"."name" ASC) AS "base" WHERE (("base"."project_title" ILIKE $7) OR ("base"."project_name" ILIKE $8)) LIMIT $9 OFFSET $10`, - wantArgs: []interface{}{"app/project", "app/user", "org456", "user123", "app/project", "app/user", "%test%", "%test%", int64(10), int64(1)}, + wantArgs: []any{"app/project", "app/user", "org456", "user123", "app/project", "app/user", "%test%", "%test%", int64(10), int64(1)}, wantError: false, }, } diff --git a/internal/store/postgres/user_repository.go b/internal/store/postgres/user_repository.go index 4d2b24549..cc1660d08 100644 --- a/internal/store/postgres/user_repository.go +++ b/internal/store/postgres/user_repository.go @@ -613,7 +613,7 @@ func (r UserRepository) Search(ctx context.Context, input *rql.Query) (user.Sear }, nil } -func (r UserRepository) PrepareDataQuery(input *rql.Query) (string, []interface{}, error) { +func (r UserRepository) PrepareDataQuery(input *rql.Query) (string, []any, error) { query := r.buildBaseQuery() for _, filter := range input.Filters { @@ -705,7 +705,7 @@ func (r UserRepository) addSort(query *goqu.SelectDataset, input *rql.Query) (*g return query, nil } -func (r UserRepository) PrepareGroupByQuery(input *rql.Query) (string, []interface{}, error) { +func (r UserRepository) PrepareGroupByQuery(input *rql.Query) (string, []any, error) { // Start with base query that includes COUNT and group by field query := dialect.From(TABLE_USERS).Prepared(true). Select( diff --git a/internal/store/postgres/user_repository_test.go b/internal/store/postgres/user_repository_test.go index b226e54f9..f00aa0940 100644 --- a/internal/store/postgres/user_repository_test.go +++ b/internal/store/postgres/user_repository_test.go @@ -634,7 +634,7 @@ func TestUserRepository_PrepareDataQuery(t *testing.T) { name string rqlQuery *rql.Query wantSQL string - wantParams []interface{} + wantParams []any wantErr bool }{ { @@ -654,7 +654,7 @@ func TestUserRepository_PrepareDataQuery(t *testing.T) { Limit: 20, }, wantSQL: `SELECT "id", "name", "email", "state", "avatar", "title", "created_at", "updated_at" FROM "users" WHERE (("CAST(users"."id AS TEXT)" = $1) AND ("users"."state" ILIKE $2) AND (("users"."email" IS NULL) OR ("users"."email" = $3)) AND ((CAST("id" AS TEXT) ILIKE $4) OR ("title" ILIKE $5) OR ("name" ILIKE $6) OR ("state" ILIKE $7))) ORDER BY "name" ASC, "created_at" DESC LIMIT $8 OFFSET $9`, - wantParams: []interface{}{int64(123), "%active%", "", "%john%", "%john%", "%john%", "%john%", int64(20), int64(10)}, + wantParams: []any{int64(123), "%active%", "", "%john%", "%john%", "%john%", "%john%", int64(20), int64(10)}, }, { name: "query with group by", @@ -670,7 +670,7 @@ func TestUserRepository_PrepareDataQuery(t *testing.T) { Limit: 15, }, wantSQL: `SELECT "id", "name", "email", "state", "avatar", "title", "created_at", "updated_at" FROM "users" WHERE ("users"."state" = $1) ORDER BY "state" ASC, "name" ASC LIMIT $2 OFFSET $3`, - wantParams: []interface{}{ + wantParams: []any{ "active", int64(15), int64(5), @@ -700,7 +700,7 @@ func TestUserRepository_PrepareGroupByQuery(t *testing.T) { name string rqlQuery *rql.Query wantSQL string - wantParams []interface{} + wantParams []any wantErr bool }{ { @@ -714,7 +714,7 @@ func TestUserRepository_PrepareGroupByQuery(t *testing.T) { Search: "test", }, wantSQL: `SELECT COUNT(*) AS "count", "users"."state" AS "values" FROM "users" WHERE (("users"."state" = $1) AND ("CAST(users"."id AS TEXT)" = $2) AND ((CAST("id" AS TEXT) ILIKE $3) OR ("title" ILIKE $4) OR ("name" ILIKE $5) OR ("state" ILIKE $6))) GROUP BY "users"."state"`, - wantParams: []interface{}{"active", int64(123), "%test%", "%test%", "%test%", "%test%"}, + wantParams: []any{"active", int64(123), "%test%", "%test%", "%test%", "%test%"}, }, { name: "group by state with search only", @@ -723,7 +723,7 @@ func TestUserRepository_PrepareGroupByQuery(t *testing.T) { Search: "pending", }, wantSQL: `SELECT COUNT(*) AS "count", "users"."state" AS "values" FROM "users" WHERE ((CAST("id" AS TEXT) ILIKE $1) OR ("title" ILIKE $2) OR ("name" ILIKE $3) OR ("state" ILIKE $4)) GROUP BY "users"."state"`, - wantParams: []interface{}{"%pending%", "%pending%", "%pending%", "%pending%"}, + wantParams: []any{"%pending%", "%pending%", "%pending%", "%pending%"}, }, } diff --git a/internal/store/postgres/userpat_repository_test.go b/internal/store/postgres/userpat_repository_test.go index a37759d8e..1915ee421 100644 --- a/internal/store/postgres/userpat_repository_test.go +++ b/internal/store/postgres/userpat_repository_test.go @@ -297,7 +297,7 @@ func (s *UserPATRepositoryTestSuite) TestCountActive_FiltersByUserAndOrg() { func (s *UserPATRepositoryTestSuite) TestCountActive_MultipleTokens() { s.truncateTokens() - for i := 0; i < 3; i++ { + for i := range 3 { _, err := s.repository.Create(s.ctx, models.PAT{ UserID: s.users[0].ID, OrgID: s.orgs[0].ID, diff --git a/internal/store/postgres/webhook_endpoint.go b/internal/store/postgres/webhook_endpoint.go index 45f7cad6f..de07a90e5 100644 --- a/internal/store/postgres/webhook_endpoint.go +++ b/internal/store/postgres/webhook_endpoint.go @@ -18,7 +18,7 @@ type WebhookHeaders struct { KVs map[string]string `json:"kvs"` } -func (s *WebhookHeaders) Scan(src interface{}) error { +func (s *WebhookHeaders) Scan(src any) error { switch src := src.(type) { case []byte: return json.Unmarshal(src, s) diff --git a/internal/store/spicedb/relation_repository.go b/internal/store/spicedb/relation_repository.go index abc3feff4..723febb8f 100644 --- a/internal/store/spicedb/relation_repository.go +++ b/internal/store/spicedb/relation_repository.go @@ -86,7 +86,7 @@ func (r *RelationRepository) Add(ctx context.Context, rel relation.Relation) err if nrCtx != nil { nr := newrelic.DatastoreSegment{ Product: nrProductName, - QueryParameters: map[string]interface{}{ + QueryParameters: map[string]any{ "relation": rel.Subject.SubRelationName, "subject_namespace": rel.Subject.Namespace, "object_namespace": rel.Object.Namespace, @@ -171,7 +171,7 @@ func (r *RelationRepository) Delete(ctx context.Context, rel relation.Relation) if nrCtx != nil { nr := newrelic.DatastoreSegment{ Product: nrProductName, - QueryParameters: map[string]interface{}{ + QueryParameters: map[string]any{ "relation": rel.Subject.SubRelationName, "subject_namespace": rel.Subject.Namespace, "object_namespace": rel.Object.Namespace, diff --git a/pkg/file/file.go b/pkg/file/file.go index 1bc1339a4..145cfdf8c 100644 --- a/pkg/file/file.go +++ b/pkg/file/file.go @@ -29,7 +29,7 @@ func DirExists(path string) bool { // in the 2nd argument // File extension matters, only file with extension // json, yaml, or yml that is parsable -func Parse(filePath string, v interface{}) error { +func Parse(filePath string, v any) error { b, err := os.ReadFile(filePath) if err != nil { return err diff --git a/pkg/metadata/metadata.go b/pkg/metadata/metadata.go index b425ad22d..bfee09689 100644 --- a/pkg/metadata/metadata.go +++ b/pkg/metadata/metadata.go @@ -1,6 +1,8 @@ package metadata import ( + "maps" + "google.golang.org/protobuf/types/known/structpb" ) @@ -13,9 +15,7 @@ type Metadata map[string]any func (m Metadata) ToStructPB() (*structpb.Struct, error) { newMap := make(map[string]any) - for key, value := range m { - newMap[key] = value - } + maps.Copy(newMap, m) return structpb.NewStruct(newMap) } @@ -23,9 +23,7 @@ func (m Metadata) ToStructPB() (*structpb.Struct, error) { // Build transforms a Metadata from map[string]any func Build(m map[string]any) Metadata { newMap := make(Metadata) - for key, value := range m { - newMap[key] = value - } + maps.Copy(newMap, m) return newMap } diff --git a/pkg/utils/pointers.go b/pkg/utils/pointers.go index f2da199fc..cea6516e6 100644 --- a/pkg/utils/pointers.go +++ b/pkg/utils/pointers.go @@ -1,8 +1,10 @@ package utils // Bool returns a pointer to the bool value passed in. +// +//go:fix inline func Bool(v bool) *bool { - return &v + return new(v) } // BoolValue returns the value of the bool pointer passed in or diff --git a/pkg/utils/rql.go b/pkg/utils/rql.go index c094a220b..da0ce862a 100644 --- a/pkg/utils/rql.go +++ b/pkg/utils/rql.go @@ -63,7 +63,7 @@ func NewRQLQuery(search string, offset int, limit int, filters []rql.Filter, sor } } -func TransformProtoToRQL(q *frontierv1beta1.RQLRequest, checkStruct interface{}) (*rql.Query, error) { +func TransformProtoToRQL(q *frontierv1beta1.RQLRequest, checkStruct any) (*rql.Query, error) { filters := make([]rql.Filter, 0) for _, filter := range q.GetFilters() { datatype, err := rql.GetDataTypeOfField(filter.GetName(), checkStruct) @@ -91,7 +91,7 @@ func TransformProtoToRQL(q *frontierv1beta1.RQLRequest, checkStruct interface{}) q.GetGroupBy()), nil } -func TransformExportProtoToRQL(q *frontierv1beta1.RQLExportRequest, checkStruct interface{}) (*rql.Query, error) { +func TransformExportProtoToRQL(q *frontierv1beta1.RQLExportRequest, checkStruct any) (*rql.Query, error) { // use TransformProtoToRQL by constructing an RQLRequest rqlReq := &frontierv1beta1.RQLRequest{ Filters: q.GetFilters(), @@ -137,7 +137,7 @@ func AddRQLSearchInQuery(query *goqu.SelectDataset, rql *rql.Query, rqlSearchSup return query.Where(goqu.Or(searchExpressions...)), nil } -func AddRQLFiltersInQuery(query *goqu.SelectDataset, rqlInput *rql.Query, rqlFilerSupportedColumns []string, checkStruct interface{}) (*goqu.SelectDataset, error) { +func AddRQLFiltersInQuery(query *goqu.SelectDataset, rqlInput *rql.Query, rqlFilerSupportedColumns []string, checkStruct any) (*goqu.SelectDataset, error) { for _, filter := range rqlInput.Filters { if !slices.Contains(rqlFilerSupportedColumns, filter.Name) { return nil, fmt.Errorf("%s is not supported in filters", filter.Name) @@ -237,15 +237,15 @@ func AddGroupInQuery(query *goqu.SelectDataset, rql *rql.Query, allowedGroupByCo return query, nil } -func buildGroupByColumns(columns []string) []interface{} { - exprs := make([]interface{}, 0, len(columns)) +func buildGroupByColumns(columns []string) []any { + exprs := make([]any, 0, len(columns)) for _, col := range columns { exprs = append(exprs, goqu.C(col)) } return exprs } -func buildSelectColumns(columns []string) []interface{} { +func buildSelectColumns(columns []string) []any { var valueExpr goqu.Expression switch len(columns) { case 1: @@ -256,7 +256,7 @@ func buildSelectColumns(columns []string) []interface{} { valueExpr = goqu.C(columns[0]).As("values") } - return []interface{}{ + return []any{ valueExpr, goqu.L("COUNT(*) as count"), } diff --git a/pkg/utils/slice.go b/pkg/utils/slice.go index 0de431356..1dff81d2b 100644 --- a/pkg/utils/slice.go +++ b/pkg/utils/slice.go @@ -1,5 +1,7 @@ package utils +import "slices" + func AppendIfUnique[T comparable](slice1 []T, slice2 []T) []T { for _, i := range slice2 { if !Contains(slice1, i) { @@ -11,21 +13,11 @@ func AppendIfUnique[T comparable](slice1 []T, slice2 []T) []T { } func Contains[T comparable](s []T, e T) bool { - for _, v := range s { - if v == e { - return true - } - } - return false + return slices.Contains(s, e) } func ContainsFunc[T any](s []T, f func(T) bool) bool { - for _, v := range s { - if f(v) { - return true - } - } - return false + return slices.ContainsFunc(s, f) } func ContainsAny[T comparable](s []T, e []T) bool { diff --git a/test/e2e/regression/authentication_test.go b/test/e2e/regression/authentication_test.go index 444c7e591..81c2af80f 100644 --- a/test/e2e/regression/authentication_test.go +++ b/test/e2e/regression/authentication_test.go @@ -219,8 +219,8 @@ func (s *AuthenticationRegressionTestSuite) TestUserSession() { mailParts := strings.Split(mailMsg, "\r\n") emailOTP := "" for _, part := range mailParts { - if strings.HasPrefix(part, "Subject: ") { - emailOTP = strings.TrimPrefix(part, "Subject: ") + if after, ok := strings.CutPrefix(part, "Subject: "); ok { + emailOTP = after } } s.Assert().NotEmpty(emailOTP) diff --git a/test/e2e/regression/billing_test.go b/test/e2e/regression/billing_test.go index 2c0390986..f967bc5ff 100644 --- a/test/e2e/regression/billing_test.go +++ b/test/e2e/regression/billing_test.go @@ -476,7 +476,7 @@ func (s *BillingRegressionTestSuite) TestProductsAPI() { Name: "test-feature-3", Title: "Test Feature-3", ProductIds: []string{createProductResp.Msg.GetProduct().GetId()}, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -683,7 +683,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: 20, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -701,7 +701,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: -20, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -735,7 +735,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: 20, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -768,7 +768,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: 20, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -809,7 +809,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: 20, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -843,7 +843,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: 20, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -877,7 +877,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: 20, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -926,7 +926,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: 20, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -975,7 +975,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: 20, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -1030,7 +1030,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: 5, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -1081,7 +1081,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: beforeBalance + 10, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -1106,7 +1106,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { Description: "billing test", Amount: 50, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -1143,7 +1143,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { // Create multiple concurrent usage requests numRequests := 20 errChan := make(chan error, numRequests) - for i := 0; i < numRequests; i++ { + for range numRequests { go func() { _, err := s.testBench.Client.CreateBillingUsage(ctxOrgAdminAuth, connect.NewRequest(&frontierv1beta1.CreateBillingUsageRequest{ OrgId: createOrgResp.Msg.GetOrganization().GetId(), @@ -1162,7 +1162,7 @@ func (s *BillingRegressionTestSuite) TestUsageAPI() { // Wait for all requests to complete var successCount int - for i := 0; i < numRequests; i++ { + for range numRequests { err := <-errChan if err == nil { successCount++ @@ -1241,7 +1241,7 @@ func (s *BillingRegressionTestSuite) TestInvoiceAPI() { Description: "billing test", Amount: 30, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, @@ -1251,7 +1251,7 @@ func (s *BillingRegressionTestSuite) TestInvoiceAPI() { Description: "billing test", Amount: 50, UserId: testUserID, - Metadata: Must(structpb.NewStruct(map[string]interface{}{ + Metadata: Must(structpb.NewStruct(map[string]any{ "key": "value", })), }, diff --git a/test/e2e/regression/serviceusers_test.go b/test/e2e/regression/serviceusers_test.go index 3bb0daa27..e47dca9d0 100644 --- a/test/e2e/regression/serviceusers_test.go +++ b/test/e2e/regression/serviceusers_test.go @@ -363,8 +363,8 @@ func (s *ServiceUsersRegressionTestSuite) TestServiceUserWithSecret() { s.Assert().NoError(err) s.Assert().NotNil(createServiceUserCredentialResp) ctxWithSecret := testbench.ContextWithHeaders(context.Background(), map[string]string{ - "Authorization": "Basic " + base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", createServiceUserCredentialResp.Msg.GetSecret().GetId(), - createServiceUserCredentialResp.Msg.GetSecret().GetSecret()))), + "Authorization": "Basic " + base64.StdEncoding.EncodeToString(fmt.Appendf(nil, "%s:%s", createServiceUserCredentialResp.Msg.GetSecret().GetId(), + createServiceUserCredentialResp.Msg.GetSecret().GetSecret())), }) // create dummy permissions @@ -508,8 +508,8 @@ func (s *ServiceUsersRegressionTestSuite) TestServiceUserWithSecret() { s.Assert().NoError(err) s.Assert().NotNil(createServiceUserCredentialResp) - createdSVKey := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", createServiceUserCredentialResp.Msg.GetSecret().GetId(), - createServiceUserCredentialResp.Msg.GetSecret().GetSecret()))) + createdSVKey := base64.StdEncoding.EncodeToString(fmt.Appendf(nil, "%s:%s", createServiceUserCredentialResp.Msg.GetSecret().GetId(), + createServiceUserCredentialResp.Msg.GetSecret().GetSecret())) ctxWithKey := testbench.ContextWithHeaders(context.Background(), map[string]string{ "Authorization": "Basic " + createdSVKey, }) @@ -607,8 +607,8 @@ func (s *ServiceUsersRegressionTestSuite) TestServiceUserWithSecret() { s.Assert().Len(listServiceUserCredentialResp.Msg.GetSecrets(), 2) // first org su key - createdOrg1SVKey := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", createServiceUserCredentialResp.Msg.GetSecret().GetId(), - createServiceUserCredentialResp.Msg.GetSecret().GetSecret()))) + createdOrg1SVKey := base64.StdEncoding.EncodeToString(fmt.Appendf(nil, "%s:%s", createServiceUserCredentialResp.Msg.GetSecret().GetId(), + createServiceUserCredentialResp.Msg.GetSecret().GetSecret())) ctxOrg1SVUWithKey := testbench.ContextWithHeaders(context.Background(), map[string]string{ "Authorization": "Basic " + createdOrg1SVKey, }) @@ -1050,8 +1050,8 @@ func TestEndToEndServiceUsersRegressionTestSuite(t *testing.T) { func getSVUCtx(cred *frontierv1beta1.SecretCredential) context.Context { ctxWithKey := testbench.ContextWithHeaders(context.Background(), map[string]string{ - "Authorization": "Basic " + base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", cred.GetId(), - cred.GetSecret()))), + "Authorization": "Basic " + base64.StdEncoding.EncodeToString(fmt.Appendf(nil, "%s:%s", cred.GetId(), + cred.GetSecret())), }) return ctxWithKey } diff --git a/test/e2e/testbench/helper.go b/test/e2e/testbench/helper.go index 1d6e279c7..94e47ba88 100644 --- a/test/e2e/testbench/helper.go +++ b/test/e2e/testbench/helper.go @@ -52,7 +52,7 @@ func PromoteBootstrapAdmin(ctx context.Context, ad frontierv1beta1connect.AdminS // suites run in one process, a prior suite's Close() SIGINTs the process, so the // next testbench's server can take a moment to accept connections. var lastErr error - for i := 0; i < 60; i++ { + for range 60 { _, err := ad.AddPlatformUser(authCtx, connect.NewRequest(&frontierv1beta1.AddPlatformUserRequest{ UserId: email, Relation: schema.AdminRelationName, diff --git a/test/e2e/testbench/stripe.go b/test/e2e/testbench/stripe.go index 006831844..36c3fe618 100644 --- a/test/e2e/testbench/stripe.go +++ b/test/e2e/testbench/stripe.go @@ -63,10 +63,10 @@ func StartStripeMock(logger *slog.Logger, network *docker.Network, pool *dockert if err = pool.Retry(func() error { customer, err := stripeClient.Customers.New(&stripe.CustomerParams{ Params: stripe.Params{ - IdempotencyKey: stripe.String(idemKey.String()), + IdempotencyKey: new(idemKey.String()), }, - Email: stripe.String("test@testtest.com"), - Name: stripe.String("Test Customer"), + Email: new("test@testtest.com"), + Name: new("Test Customer"), }) if customer.Email == "" { return fmt.Errorf("not ready") @@ -95,7 +95,7 @@ func BuildStripeClient(port, name string, mode recorder.Mode) (StripeClientBuild var closer = func() error { return nil } var stripeURL *string if port != "" { - stripeURL = stripe.String("http://localhost:" + port) + stripeURL = new("http://localhost:" + port) } if name == "" { name = uuid.NewString()