Skip to content

Commit

Permalink
adding check for not allowing delete if number of active credentials …
Browse files Browse the repository at this point in the history
…exceeds threshold

updates to multi-device improvements to get active credentials count

fixing delete tlv2 test cases to include new check call

fixing db field for request_id for tlv2 creds table
  • Loading branch information
husobee committed Jan 29, 2024
1 parent f080e45 commit d3ae44e
Show file tree
Hide file tree
Showing 6 changed files with 502 additions and 0 deletions.
14 changes: 14 additions & 0 deletions services/skus/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ var (
errItemDoesNotExist model.Error = "order item does not exist for order"
errCredsAlreadySubmitted model.Error = "credentials already submitted"

errMaxActiveOrderCredsExceeded model.Error = "maximum active order credentials exceeded"

defaultExpiresAt = time.Now().Add(17532 * time.Hour) // 2 years
retryPolicy = retrypolicy.DefaultRetry
dontRetryCodes = map[int]struct{}{
Expand Down Expand Up @@ -736,10 +738,22 @@ func (s *Service) DeleteOrderCreds(ctx context.Context, orderID uuid.UUID, reqID
return nil
}

// maxTLV2ActiveItemCreds is the max number of credentials an item is allowed to have in the given day
const maxTLV2ActiveOrderCreds = 10

func (s *Service) deleteTLV2(ctx context.Context, dbi sqlx.ExtContext, order *model.Order, reqID uuid.UUID) error {

// Pass the request id as an "item id", which will allow for legacy credentials to be deleted.
// Otherwise, do not delete said credentials for multiple device support.
if !uuid.Equal(reqID, uuid.Nil) {
// check if we already have N active credentials on this item for the current day
activeCreds, err := s.Datastore.GetCountActiveOrderCreds(ctx, dbi, order.ID)
if err != nil {
return fmt.Errorf("failed to get count of active order credentials: %w", err)
}
if activeCreds > maxTLV2ActiveOrderCreds {
return errMaxActiveOrderCredsExceeded
}
return s.Datastore.DeleteTimeLimitedV2OrderCredsByOrderTx(ctx, dbi, order.ID, reqID)
}

Expand Down
5 changes: 5 additions & 0 deletions services/skus/credentials_noint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ func TestService_DeleteTLV2(t *testing.T) {
svc := &Service{Datastore: ds}

ctx := context.Background()
if tc.given.reqID != uuid.Nil {
ds.EXPECT().GetCountActiveOrderCreds(
tc.exp.args[0], tc.exp.args[1], tc.exp.args[2],
).Return(0, nil)
}

ds.EXPECT().DeleteTimeLimitedV2OrderCredsByOrderTx(
tc.exp.args[0], tc.exp.args[1], tc.exp.args[2], tc.exp.args[3],
Expand Down
16 changes: 16 additions & 0 deletions services/skus/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ type Datastore interface {
GetTLV2Creds(ctx context.Context, dbi sqlx.QueryerContext, ordID, itemID, reqID uuid.UUID) (*TimeLimitedV2Creds, error)
DeleteTimeLimitedV2OrderCredsByOrderTx(ctx context.Context, dbi sqlx.ExtContext, orderID uuid.UUID, itemIDs ...uuid.UUID) error
GetTimeLimitedV2OrderCredsByOrderItem(itemID uuid.UUID) (*TimeLimitedV2Creds, error)
GetCountActiveOrderCreds(ctx context.Context, dbi sqlx.ExtContext, orderID uuid.UUID) (int, error)
InsertTimeLimitedV2OrderCredsTx(ctx context.Context, tx *sqlx.Tx, tlv2 TimeAwareSubIssuedCreds) error
InsertSigningOrderRequestOutbox(ctx context.Context, requestID uuid.UUID, orderID uuid.UUID, itemID uuid.UUID, signingOrderRequest SigningOrderRequest) error
GetSigningOrderRequestOutboxByRequestID(ctx context.Context, dbi sqlx.QueryerContext, reqID uuid.UUID) (*SigningOrderRequestOutbox, error)
Expand Down Expand Up @@ -1035,6 +1036,21 @@ func (pg *Postgres) GetTLV2Creds(ctx context.Context, dbi sqlx.QueryerContext, o
return result, nil
}

// GetCountActiveOrderCreds returns the count of order creds currently active on an order
func (pg *Postgres) GetCountActiveOrderCreds(ctx context.Context, dbi sqlx.ExtContext, orderID uuid.UUID) (int, error) {
query := `
select count(1) from time_limited_v2_order_creds
where order_id = $1 and now() > valid_from and valid_to > now() group by request_id
`

var activeCredCount int
if err := sqlx.GetContext(ctx, dbi, &activeCredCount, query, orderID); err != nil {
return 0, fmt.Errorf("error getting active credential count: %w", err)
}

return activeCredCount, nil
}

// GetTimeLimitedV2OrderCredsByOrderItem returns all the order credentials for a single order item.
func (pg *Postgres) GetTimeLimitedV2OrderCredsByOrderItem(itemID uuid.UUID) (*TimeLimitedV2Creds, error) {
query := `
Expand Down
18 changes: 18 additions & 0 deletions services/skus/datastore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,24 @@ func (suite *PostgresTestSuite) TestGetOrderByExternalID() {
}
}

func (suite *PostgresTestSuite) TestCountActiveOrderCreds_Success() {
env := os.Getenv("ENV")
ctx := context.WithValue(context.Background(), appctx.EnvironmentCTXKey, env)

// create paid order with two order items
ctx = context.WithValue(ctx, appctx.WhitelistSKUsCTXKey, []string{devBraveFirewallVPNPremiumTimeLimited,
devBraveSearchPremiumYearTimeLimited})

orderCredentials := suite.createTimeLimitedV2OrderCreds(suite.T(), ctx, devBraveFirewallVPNPremiumTimeLimited,
devBraveSearchPremiumYearTimeLimited)

// both order items have same orderID so can use the first element to retrieve all order creds
count, err := suite.storage.GetCountActiveOrderCreds(ctx, suite.storage.RawDB(), orderCredentials[0].OrderID)
suite.Require().NoError(err)

suite.Assert().Equal(count, 2)
}

func (suite *PostgresTestSuite) TestGetTimeLimitedV2OrderCredsByOrder_Success() {
env := os.Getenv("ENV")
ctx := context.WithValue(context.Background(), appctx.EnvironmentCTXKey, env)
Expand Down
14 changes: 14 additions & 0 deletions services/skus/instrumented_datastore.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d3ae44e

Please sign in to comment.