Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Production 2024-02-05_01 #2330

Merged
merged 2 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 1 addition & 43 deletions services/skus/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ func Router(
cr.Method(http.MethodGet, "/items/{itemID}/batches/{requestID}", metricsMwr("GetOrderCredsByID", getOrderCredsByID(svc, false)))

cr.Method(http.MethodPut, "/items/{itemID}/batches/{requestID}", metricsMwr("CreateOrderItemCreds", createItemCreds(svc)))
cr.Method(http.MethodDelete, "/items/{itemID}/batches/{requestID}", metricsMwr("DeleteOrderItemCreds", authMwr(deleteItemCreds(svc))))
})

return r
Expand Down Expand Up @@ -604,47 +603,6 @@ func CreateOrderCreds(svc *Service) handlers.AppHandler {
}
}

// deleteItemCreds handles requests for deleting credentials for an item.
func deleteItemCreds(svc *Service) handlers.AppHandler {
return func(w http.ResponseWriter, r *http.Request) *handlers.AppError {
ctx := r.Context()
lg := logging.Logger(ctx, "skus").With().Str("func", "deleteItemCreds").Logger()

orderID, err := uuid.FromString(chi.URLParamFromCtx(ctx, "orderID"))
if err != nil {
lg.Error().Err(err).Msg("failed to validate order id")
return handlers.ValidationError("request url parameter", map[string]interface{}{
"orderID": err.Error(),
})
}

reqID, err := uuid.FromString(chi.URLParamFromCtx(ctx, "reqID"))
if err != nil {
lg.Error().Err(err).Msg("failed to validate request id")
return handlers.ValidationError("request url parameter", map[string]interface{}{
"itemID": err.Error(),
})
}

isSigned := r.URL.Query().Get("isSigned") == "true"

if err := svc.DeleteOrderCreds(ctx, orderID, reqID, isSigned); err != nil {
lg.Error().Err(err).Msg("failed to delete the order credentials")

switch {
case errors.Is(err, model.ErrOrderNotFound), errors.Is(err, ErrOrderHasNoItems):
return handlers.WrapError(err, "order or item not found", http.StatusNotFound)
case errors.Is(err, errExceededMaxActiveOrderCreds):
return handlers.WrapError(err, errExceededMaxActiveOrderCreds.Error(), http.StatusUnprocessableEntity)
default:
return handlers.WrapError(err, "error deleting credentials", http.StatusInternalServerError)
}
}

return handlers.RenderContent(ctx, nil, w, http.StatusOK)
}
}

// createItemCredsRequest includes the blinded credentials to be signed.
type createItemCredsRequest struct {
BlindedCreds []string `json:"blindedCreds" valid:"base64"`
Expand Down Expand Up @@ -750,7 +708,7 @@ func DeleteOrderCreds(service *Service) handlers.AppHandler {
}

isSigned := r.URL.Query().Get("isSigned") == "true"
if err := service.DeleteOrderCreds(ctx, id, uuid.Nil, isSigned); err != nil {
if err := service.DeleteOrderCreds(ctx, id, isSigned); err != nil {
return handlers.WrapError(err, "Error deleting credentials", http.StatusBadRequest)
}

Expand Down
34 changes: 2 additions & 32 deletions services/skus/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ var (
errItemDoesNotExist model.Error = "order item does not exist for order"
errCredsAlreadySubmitted model.Error = "credentials already submitted"

errExceededMaxActiveOrderCreds 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 @@ -690,7 +688,7 @@ func (s *SigningOrderResultErrorHandler) Handle(ctx context.Context, message kaf
// - create repos for credentials;
// - move the corresponding methods there;
// - make those methods work on per-item basis.
func (s *Service) DeleteOrderCreds(ctx context.Context, orderID uuid.UUID, reqID uuid.UUID, isSigned bool) error {
func (s *Service) DeleteOrderCreds(ctx context.Context, orderID uuid.UUID, isSigned bool) error {
order, err := s.Datastore.GetOrder(orderID)
if err != nil {
return err
Expand Down Expand Up @@ -722,7 +720,7 @@ func (s *Service) DeleteOrderCreds(ctx context.Context, orderID uuid.UUID, reqID
}

if doTlv2 {
if err := s.deleteTLV2(ctx, tx, order, reqID, time.Now()); err != nil {
if err := s.Datastore.DeleteTimeLimitedV2OrderCredsByOrderTx(ctx, tx, orderID); err != nil {
return fmt.Errorf("error deleting time limited v2 order creds: %w", err)
}
}
Expand All @@ -738,34 +736,6 @@ 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, now time.Time) 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, now)
if err != nil {
return fmt.Errorf("failed to get count of active order credentials: %w", err)
}
if activeCreds > maxTLV2ActiveOrderCreds {
return errExceededMaxActiveOrderCreds
}
return s.Datastore.DeleteTimeLimitedV2OrderCredsByOrderTx(ctx, dbi, order.ID, reqID)
}

itemIDs := make([]uuid.UUID, 0, len(order.Items))
// Legacy, delete all items.
for i := range order.Items {
itemIDs = append(itemIDs, order.Items[i].ID)
}

return s.Datastore.DeleteTimeLimitedV2OrderCredsByOrderTx(ctx, dbi, order.ID, itemIDs...)
}

// checkNumBlindedCreds checks the number of submitted blinded credentials.
//
// The number of submitted credentials must not exceed:
Expand Down
110 changes: 0 additions & 110 deletions services/skus/credentials_noint_test.go

This file was deleted.

29 changes: 3 additions & 26 deletions services/skus/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,8 @@ type Datastore interface {
AreTimeLimitedV2CredsSubmitted(ctx context.Context, blindedCreds ...string) (bool, error)
GetTimeLimitedV2OrderCredsByOrder(orderID uuid.UUID) (*TimeLimitedV2Creds, error)
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
DeleteTimeLimitedV2OrderCredsByOrderTx(ctx context.Context, tx *sqlx.Tx, orderID uuid.UUID) error
GetTimeLimitedV2OrderCredsByOrderItem(itemID uuid.UUID) (*TimeLimitedV2Creds, error)
GetCountActiveOrderCreds(ctx context.Context, dbi sqlx.ExtContext, orderID uuid.UUID, now time.Time) (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 @@ -797,20 +796,11 @@ func (pg *Postgres) DeleteSingleUseOrderCredsByOrderTx(ctx context.Context, tx *

// DeleteTimeLimitedV2OrderCredsByOrderTx performs a hard delete for all time limited v2 order
// credentials for a given OrderID.
func (pg *Postgres) DeleteTimeLimitedV2OrderCredsByOrderTx(ctx context.Context, dbi sqlx.ExtContext, orderID uuid.UUID, itemIDs ...uuid.UUID) error {
// Legacy, if the request id matches the item id on the tlv2 creds, we actually want to delete the record.
// Otherwise we will keep these credentials here for multiple device refresh capabilities.
const q = "DELETE FROM time_limited_v2_order_creds WHERE order_id = ? AND item_id in (?)"
query, args, err := sqlx.In(q, orderID, itemIDs)
func (pg *Postgres) DeleteTimeLimitedV2OrderCredsByOrderTx(ctx context.Context, tx *sqlx.Tx, orderID uuid.UUID) error {
_, err := tx.ExecContext(ctx, `delete from time_limited_v2_order_creds where order_id = $1`, orderID)
if err != nil {
return fmt.Errorf("error creating delete query for order with item ids: %w", err)
}

query = dbi.Rebind(query)
if _, err := dbi.ExecContext(ctx, query, args...); err != nil {
return fmt.Errorf("error deleting time limited v2 order creds: %w", err)
}

return nil
}

Expand Down Expand Up @@ -1036,19 +1026,6 @@ 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, now time.Time) (int, error) {
const q = `SELECT COUNT(1) FROM time_limited_v2_order_creds
WHERE order_id = $1 AND valid_from < $2 AND valid_to > $2 GROUP BY request_id`

var activeCredCount int
if err := sqlx.GetContext(ctx, dbi, &activeCredCount, q, orderID, now); 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
19 changes: 0 additions & 19 deletions services/skus/datastore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,25 +151,6 @@ func (suite *PostgresTestSuite) TestGetOrderByExternalID() {
}
}

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

ctx = context.WithValue(ctx, appctx.WhitelistSKUsCTXKey, []string{
devBraveFirewallVPNPremiumTimeLimited,
devBraveSearchPremiumYearTimeLimited,
})

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

actual, err := suite.storage.GetCountActiveOrderCreds(ctx, suite.storage.RawDB(), creds[0].OrderID, time.Now())
suite.Require().NoError(err)

const expected = 2

suite.Assert().Equal(expected, actual)
}

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