From 11cf42beddcbfae07ae6b41bd0c6b2d507e39fef Mon Sep 17 00:00:00 2001 From: Alex Jbanca Date: Tue, 5 Nov 2024 16:00:28 +0200 Subject: [PATCH] fix(BrowserConnect)_: Send client event when the dApp permissions have been revoked --- services/connector/api.go | 4 +- services/connector/commands/client_handler.go | 35 +++++++++++++- .../connector/commands/client_handler_test.go | 48 ++++++++++++++++++- services/connector/commands/rpc_traits.go | 5 ++ services/connector/commands/test_helpers.go | 2 +- 5 files changed, 88 insertions(+), 6 deletions(-) diff --git a/services/connector/api.go b/services/connector/api.go index 58b851b86..3ff9f7ecf 100644 --- a/services/connector/api.go +++ b/services/connector/api.go @@ -22,7 +22,7 @@ type API struct { func NewAPI(s *Service) *API { r := NewCommandRegistry() - c := commands.NewClientSideHandler() + c := commands.NewClientSideHandler(s.db) // Transactions and signing r.Register("eth_sendTransaction", &commands.SendTransactionCommand{ @@ -121,7 +121,7 @@ func (api *API) CallRPC(ctx context.Context, inputJSON string) (interface{}, err func (api *API) RecallDAppPermission(origin string) error { // TODO: close the websocket connection - return persistence.DeleteDApp(api.s.db, origin) + return api.c.RecallDAppPermissions(commands.RecallDAppPermissionsArgs{URL: origin}) } func (api *API) GetPermittedDAppsList() ([]persistence.DApp, error) { diff --git a/services/connector/commands/client_handler.go b/services/connector/commands/client_handler.go index a2114f345..a1334d5df 100644 --- a/services/connector/commands/client_handler.go +++ b/services/connector/commands/client_handler.go @@ -2,6 +2,7 @@ package commands import ( "crypto/sha256" + "database/sql" "encoding/hex" "encoding/json" "fmt" @@ -9,6 +10,7 @@ import ( "time" "github.com/status-im/status-go/eth-node/types" + persistence "github.com/status-im/status-go/services/connector/database" "github.com/status-im/status-go/signal" "github.com/status-im/status-go/transactions" ) @@ -23,6 +25,8 @@ var ( ErrPersonalSignRejectedByUser = fmt.Errorf("personal sign was rejected by user") ErrEmptyRequestID = fmt.Errorf("empty requestID") ErrAnotherConnectorOperationIsAwaitingFor = fmt.Errorf("another connector operation is awaiting for user input") + ErrEmptyUrl = fmt.Errorf("empty URL") + ErrDAppDoesNotHavePermissions = fmt.Errorf("dApp does not have permissions") ) type MessageType int @@ -40,12 +44,14 @@ type Message struct { } type ClientSideHandler struct { + Db *sql.DB responseChannel chan Message isRequestRunning int32 } -func NewClientSideHandler() *ClientSideHandler { +func NewClientSideHandler(db *sql.DB) *ClientSideHandler { return &ClientSideHandler{ + Db: db, responseChannel: make(chan Message, 1), // Buffer of 1 to avoid blocking isRequestRunning: 0, } @@ -115,6 +121,33 @@ func (c *ClientSideHandler) RequestAccountsRejected(args RejectedArgs) error { return nil } +func (c *ClientSideHandler) RecallDAppPermissions(args RecallDAppPermissionsArgs) error { + if args.URL == "" { + return ErrEmptyUrl + } + + dApp, err := persistence.SelectDAppByUrl(c.Db, args.URL) + if err != nil { + return err + } + + if dApp == nil { + return ErrDAppDoesNotHavePermissions + } + + err = persistence.DeleteDApp(c.Db, dApp.URL) + if err != nil { + return err + } + + signal.SendConnectorDAppPermissionRevoked(signal.ConnectorDApp{ + URL: dApp.URL, + Name: dApp.Name, + IconURL: dApp.IconURL, + }) + return nil +} + func (c *ClientSideHandler) RequestSendTransaction(dApp signal.ConnectorDApp, chainID uint64, txArgs *transactions.SendTxArgs) (types.Hash, error) { if !c.setRequestRunning() { return types.Hash{}, ErrAnotherConnectorOperationIsAwaitingFor diff --git a/services/connector/commands/client_handler_test.go b/services/connector/commands/client_handler_test.go index c28a344b0..d7c74496a 100644 --- a/services/connector/commands/client_handler_test.go +++ b/services/connector/commands/client_handler_test.go @@ -4,11 +4,17 @@ import ( "testing" "time" + "github.com/status-im/status-go/eth-node/types" + persistence "github.com/status-im/status-go/services/connector/database" + "github.com/stretchr/testify/assert" ) func TestClientHandlerTimeout(t *testing.T) { - clientHandler := NewClientSideHandler() + db, cleanup := createWalletDB(t) + t.Cleanup(cleanup) + + clientHandler := NewClientSideHandler(db) backupWalletResponseMaxInterval := WalletResponseMaxInterval WalletResponseMaxInterval = 1 * time.Millisecond @@ -19,10 +25,48 @@ func TestClientHandlerTimeout(t *testing.T) { } func TestRequestRejectedWhileWaiting(t *testing.T) { - clientHandler := NewClientSideHandler() + db, cleanup := createWalletDB(t) + t.Cleanup(cleanup) + + clientHandler := NewClientSideHandler(db) clientHandler.setRequestRunning() _, _, err := clientHandler.RequestShareAccountForDApp(testDAppData) assert.Equal(t, ErrAnotherConnectorOperationIsAwaitingFor, err) } + +func TestRecallDAppPermission(t *testing.T) { + db, cleanup := createWalletDB(t) + t.Cleanup(cleanup) + + dapp := persistence.DApp{ + Name: "Test DApp", + URL: "http://testDAppURL", + IconURL: "http://testDAppIconUrl", + SharedAccount: types.HexToAddress("0x1234567890"), + ChainID: 0x1, + } + + err := persistence.UpsertDApp(db, &dapp) + assert.NoError(t, err) + + persistedDapp, err := persistence.SelectDAppByUrl(db, dapp.URL) + assert.Equal(t, persistedDapp, &dapp) + assert.NoError(t, err) + + clientHandler := NewClientSideHandler(db) + err = clientHandler.RecallDAppPermissions(RecallDAppPermissionsArgs{URL: dapp.URL}) + assert.NoError(t, err) + + err = clientHandler.RecallDAppPermissions(RecallDAppPermissionsArgs{}) + assert.ErrorIs(t, err, ErrEmptyUrl) + + err = clientHandler.RecallDAppPermissions(RecallDAppPermissionsArgs{URL: dapp.URL}) + assert.ErrorIs(t, err, ErrDAppDoesNotHavePermissions) + + recalledDapp, err := persistence.SelectDAppByUrl(db, dapp.URL) + + assert.Equal(t, recalledDapp, (*persistence.DApp)(nil)) + assert.NoError(t, err) +} diff --git a/services/connector/commands/rpc_traits.go b/services/connector/commands/rpc_traits.go index 8c229f089..0a680021f 100644 --- a/services/connector/commands/rpc_traits.go +++ b/services/connector/commands/rpc_traits.go @@ -65,10 +65,15 @@ type RejectedArgs struct { RequestID string `json:"requestId"` } +type RecallDAppPermissionsArgs struct { + URL string `json:"url"` +} + type ClientSideHandlerInterface interface { RequestShareAccountForDApp(dApp signal.ConnectorDApp) (types.Address, uint64, error) RequestAccountsAccepted(args RequestAccountsAcceptedArgs) error RequestAccountsRejected(args RejectedArgs) error + RecallDAppPermissions(args RecallDAppPermissionsArgs) error RequestSendTransaction(dApp signal.ConnectorDApp, chainID uint64, txArgs *transactions.SendTxArgs) (types.Hash, error) SendTransactionAccepted(args SendTransactionAcceptedArgs) error diff --git a/services/connector/commands/test_helpers.go b/services/connector/commands/test_helpers.go index 463d284db..eb5897683 100644 --- a/services/connector/commands/test_helpers.go +++ b/services/connector/commands/test_helpers.go @@ -81,7 +81,7 @@ func setupCommand(t *testing.T, method string) (state testState, close func()) { }) require.NoError(t, err) - state.handler = NewClientSideHandler() + state.handler = NewClientSideHandler(state.db) state.mockCtrl = gomock.NewController(t) state.rpcClient = mock_rpcclient.NewMockClientInterface(state.mockCtrl)