Skip to content

Commit

Permalink
feat: remove oidc4vp transaction on wallet error notification (#1771)
Browse files Browse the repository at this point in the history
Signed-off-by: Misha Sizov <[email protected]>
  • Loading branch information
mishasizov-SK authored Oct 4, 2024
1 parent 32a8f60 commit 168b811
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 658 deletions.
2 changes: 1 addition & 1 deletion pkg/kms/aws/service_mocks.go

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

2 changes: 1 addition & 1 deletion pkg/kms/mocks/kms_mocks.go

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

1 change: 1 addition & 0 deletions pkg/service/oidc4vp/oidc4vp_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ type transactionManager interface {
DeleteReceivedClaims(claimsID string) error
GetByOneTimeToken(nonce string) (*Transaction, bool, error)
Get(txID TxID) (*Transaction, error)
Delete(txID TxID) error
}

type requestObjectStore interface {
Expand Down
6 changes: 6 additions & 0 deletions pkg/service/oidc4vp/oidc4vp_wallet_notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ func (s *Service) HandleWalletNotification(ctx context.Context, req *WalletNotif
return err
}

// Delete tx from store.
err = s.transactionManager.Delete(req.TxID)
if err != nil {
return err
}

return nil
}

Expand Down
47 changes: 47 additions & 0 deletions pkg/service/oidc4vp/oidc4vp_wallet_notification_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ func TestService_HandleWalletNotification_SupportedAuthResponseErrorTypes(t *tes
return nil
})

transactionManager.EXPECT().
Delete(transactionID).Times(1).
Return(nil)

s := oidc4vp.NewService(&oidc4vp.Config{
EventSvc: eventService,
EventTopic: spi.VerifierEventTopic,
Expand Down Expand Up @@ -228,6 +232,10 @@ func TestService_HandleWalletNotification_EdgeCases(t *testing.T) {
OrganizationID: profileOrgID,
WebHook: profileWebHook,
}, nil)

transactionManager.EXPECT().
Delete(transactionID).Times(1).
Return(nil)
},
check: func(t *testing.T, err error) {
assert.NoError(t, err)
Expand Down Expand Up @@ -375,6 +383,45 @@ func TestService_HandleWalletNotification_EdgeCases(t *testing.T) {
ErrorDescription: "error description",
},
},
{
name: "Error: failed to delete transaction",
fields: fields{
setup: func() {
transactionManager.EXPECT().
Get(transactionID).Times(1).
Return(&oidc4vp.Transaction{
ID: transactionID,
ProfileID: profileID,
ProfileVersion: profileVersion,
}, nil)

profileService.EXPECT().
GetProfile(profileID, profileVersion).
Return(&profileapi.Verifier{
ID: profileID,
Version: profileVersion,
OrganizationID: profileOrgID,
WebHook: profileWebHook,
}, nil)

eventService.EXPECT().
Publish(gomock.Any(), spi.VerifierEventTopic, gomock.Any()).
Return(nil)

transactionManager.EXPECT().
Delete(transactionID).Times(1).
Return(errors.New("transaction service error"))
},
check: func(t *testing.T, err error) {
assert.ErrorContains(t, err, "transaction service error")
},
},
notification: &oidc4vp.WalletNotification{
TxID: transactionID,
Error: "invalid_scope",
ErrorDescription: "error description",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
14 changes: 13 additions & 1 deletion pkg/service/oidc4vp/txmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ type txStore interface {
) (TxID, *Transaction, error)
Update(update TransactionUpdate, profileTransactionDataTTL int32) error
Get(txID TxID) (*Transaction, error)
Delete(txID TxID) error
}

type txClaimsStore interface {
Expand Down Expand Up @@ -156,7 +157,7 @@ func (tm *TxManager) StoreReceivedClaims(
return tm.txStore.Update(TransactionUpdate{ID: txID, ReceivedClaimsID: receivedClaimsID}, profileTransactionDataTTL)
}

// Get transaction id.
// Get transaction by TxID.
func (tm *TxManager) Get(txID TxID) (*Transaction, error) {
tx, err := tm.txStore.Get(txID)
if errors.Is(err, ErrDataNotFound) {
Expand Down Expand Up @@ -185,6 +186,17 @@ func (tm *TxManager) Get(txID TxID) (*Transaction, error) {
return tx, nil
}

// Delete transaction by TxID.
// Note, that given func does not remove associated claims from store.
func (tm *TxManager) Delete(txID TxID) error {
err := tm.txStore.Delete(txID)
if err != nil {
return fmt.Errorf("delete tx from store: %w", err)
}

return nil
}

// GetByOneTimeToken get transaction by nonce and then delete nonce.
func (tm *TxManager) GetByOneTimeToken(nonce string) (*Transaction, bool, error) {
txID, valid, err := tm.nonceStore.GetAndDelete(nonce)
Expand Down
37 changes: 37 additions & 0 deletions pkg/service/oidc4vp/txmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"testing"

"github.com/golang/mock/gomock"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/trustbloc/vc-go/presexch"
Expand Down Expand Up @@ -557,6 +558,42 @@ func TestTxManagerDeleteReceivedClaims(t *testing.T) {
})
}

func TestTxManagerDeleteTransaction(t *testing.T) {
t.Run("Success", func(t *testing.T) {
txID := oidc4vp.TxID(uuid.NewString())

store := NewMockTxStore(gomock.NewController(t))
store.EXPECT().Delete(txID).Return(nil)

claimsStore := NewMockTxClaimsStore(gomock.NewController(t))
nonceStore := NewMockTxNonceStore(gomock.NewController(t))
crypto := NewMockDataProtector(gomock.NewController(t))

manager := oidc4vp.NewTxManager(nonceStore, store, claimsStore, crypto,
testutil.DocumentLoader(t))

err := manager.Delete(txID)
require.NoError(t, err)
})

t.Run("Error", func(t *testing.T) {
txID := oidc4vp.TxID(uuid.NewString())

store := NewMockTxStore(gomock.NewController(t))
store.EXPECT().Delete(txID).Return(errors.New("some error"))

claimsStore := NewMockTxClaimsStore(gomock.NewController(t))
nonceStore := NewMockTxNonceStore(gomock.NewController(t))
crypto := NewMockDataProtector(gomock.NewController(t))

manager := oidc4vp.NewTxManager(nonceStore, store, claimsStore, crypto,
testutil.DocumentLoader(t))

err := manager.Delete(txID)
require.Contains(t, err.Error(), "some error")
})
}

func TestClaimsToRaw(t *testing.T) {
t.Run("data nil", func(t *testing.T) {
manager := oidc4vp.NewTxManager(nil, nil, nil, nil,
Expand Down
20 changes: 20 additions & 0 deletions pkg/storage/mongodb/oidc4vptxstore/oidc4vp_tx_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,26 @@ func (p *TxStore) Get(strID oidc4vp.TxID) (*oidc4vp.Transaction, error) {
return txFromDocument(txDoc)
}

// Delete deletes oidc4vp.Transaction from store.
func (p *TxStore) Delete(strID oidc4vp.TxID) error {
ctxWithTimeout, cancel := p.mongoClient.ContextWithTimeout()
defer cancel()

collection := p.mongoClient.Database().Collection(txCollection)

id, err := txIDFromString(strID)
if err != nil {
return err
}

_, err = collection.DeleteOne(ctxWithTimeout, bson.M{"_id": id})
if err != nil {
return fmt.Errorf("delete tx: %w", err)
}

return nil
}

func (p *TxStore) Update(update oidc4vp.TransactionUpdate, _ int32) error {
ctxWithTimeout, cancel := p.mongoClient.ContextWithTimeout()
defer cancel()
Expand Down
Loading

0 comments on commit 168b811

Please sign in to comment.