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

multiple device refresh improvements #2281

Merged
merged 12 commits into from
Jan 31, 2024
44 changes: 43 additions & 1 deletion services/skus/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ 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 @@ -588,6 +589,47 @@ 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.deleteItemCreds")
husobee marked this conversation as resolved.
Show resolved Hide resolved

orderID := &inputs.ID{}
if err := inputs.DecodeAndValidateString(ctx, orderID, chi.URLParamFromCtx(ctx, "orderID")); err != nil {
husobee marked this conversation as resolved.
Show resolved Hide resolved
lg.Error().Err(err).Msg("failed to validate order id")
return handlers.ValidationError("Error validating request url parameter", map[string]interface{}{
"orderID": err.Error(),
})
}

itemID := &inputs.ID{}
if err := inputs.DecodeAndValidateString(ctx, itemID, chi.URLParamFromCtx(ctx, "itemID")); err != nil {
lg.Error().Err(err).Msg("failed to validate item id")
return handlers.ValidationError("Error validating request url parameter", map[string]interface{}{
husobee marked this conversation as resolved.
Show resolved Hide resolved
"itemID": err.Error(),
})
}

reqID := &inputs.ID{}
if err := inputs.DecodeAndValidateString(ctx, reqID, chi.URLParamFromCtx(ctx, "requestID")); err != nil {
lg.Error().Err(err).Msg("failed to validate request id")
return handlers.ValidationError("Error validating request url parameter", map[string]interface{}{
"requestID": err.Error(),
})
}

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

if err := svc.DeleteOrderCreds(ctx, *orderID.UUID(), reqID.UUID(), isSigned); err != nil {
lg.Error().Err(err).Msg("failed to delete the order credentials")
return handlers.WrapError(err, "Error deleting credentials", http.StatusBadRequest)
husobee marked this conversation as resolved.
Show resolved Hide resolved
}

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 @@ -693,7 +735,7 @@ func DeleteOrderCreds(service *Service) handlers.AppHandler {
}

isSigned := r.URL.Query().Get("isSigned") == "true"
if err := service.DeleteOrderCreds(ctx, id, isSigned); err != nil {
if err := service.DeleteOrderCreds(ctx, id, nil, isSigned); err != nil {
pavelbrm marked this conversation as resolved.
Show resolved Hide resolved
return handlers.WrapError(err, "Error deleting credentials", http.StatusBadRequest)
}

Expand Down
17 changes: 15 additions & 2 deletions services/skus/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -688,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, isSigned bool) error {
func (s *Service) DeleteOrderCreds(ctx context.Context, orderID uuid.UUID, reqID *uuid.UUID, isSigned bool) error {
pavelbrm marked this conversation as resolved.
Show resolved Hide resolved
order, err := s.Datastore.GetOrder(orderID)
if err != nil {
return err
Expand Down Expand Up @@ -720,7 +720,20 @@ func (s *Service) DeleteOrderCreds(ctx context.Context, orderID uuid.UUID, isSig
}

if doTlv2 {
if err := s.Datastore.DeleteTimeLimitedV2OrderCredsByOrderTx(ctx, tx, orderID); err != nil {
var itemIDs []*uuid.UUID
if reqID == nil {
// legacy, so put all of the orders' items in a list to be hard deleted
for _, v := range order.Items {
itemIDs = append(itemIDs, &v.ID)
pavelbrm marked this conversation as resolved.
Show resolved Hide resolved
}
} else {
// there is a request id, pass it along to the delete order creds as an "item id"
// this will allow for legacy credentials using the request id of the order's item id
// to be deleted, otherwise we do not delete said credentials for multiple device support
itemIDs = append(itemIDs, reqID)
}

if err := s.Datastore.DeleteTimeLimitedV2OrderCredsByOrderTx(ctx, tx, orderID, itemIDs...); err != nil {
return fmt.Errorf("error deleting time limited v2 order creds: %w", err)
}
}
Expand Down
14 changes: 11 additions & 3 deletions services/skus/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ 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, tx *sqlx.Tx, orderID uuid.UUID) error
DeleteTimeLimitedV2OrderCredsByOrderTx(ctx context.Context, tx *sqlx.Tx, orderID uuid.UUID, itemIDs ...*uuid.UUID) error
pavelbrm marked this conversation as resolved.
Show resolved Hide resolved
GetTimeLimitedV2OrderCredsByOrderItem(itemID uuid.UUID) (*TimeLimitedV2Creds, 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
Expand Down Expand Up @@ -796,8 +796,16 @@ 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, tx *sqlx.Tx, orderID uuid.UUID) error {
_, err := tx.ExecContext(ctx, `delete from time_limited_v2_order_creds where order_id = $1`, orderID)
func (pg *Postgres) DeleteTimeLimitedV2OrderCredsByOrderTx(ctx context.Context, tx *sqlx.Tx, orderID uuid.UUID, itemIDs ...*uuid.UUID) error {
// legacy, if the request id matches the item id on the time limited v2 creds, we actually want to delete the record,
// otherwise we will keep these credentials here for multiple device refresh capabilities
query, args, err := sqlx.In("delete from time_limited_v2_order_creds where order_id = ? and item_id in (?)", orderID, itemIDs)
pavelbrm marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return fmt.Errorf("error creating delete query for order with item ids: %w", err)
}

query = tx.Rebind(query)
_, err = tx.ExecContext(ctx, query, args...)
if err != nil {
return fmt.Errorf("error deleting time limited v2 order creds: %w", err)
}
Expand Down
32 changes: 16 additions & 16 deletions services/skus/instrumented_datastore.go

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

Loading
Loading