fix(BrowserConnect)_: Send client event when the dApp permissions have been revoked

This commit is contained in:
Alex Jbanca 2024-11-05 16:00:28 +02:00 committed by Anthony Laibe
parent 3f96b8430b
commit 11cf42bedd
5 changed files with 88 additions and 6 deletions

View File

@ -22,7 +22,7 @@ type API struct {
func NewAPI(s *Service) *API { func NewAPI(s *Service) *API {
r := NewCommandRegistry() r := NewCommandRegistry()
c := commands.NewClientSideHandler() c := commands.NewClientSideHandler(s.db)
// Transactions and signing // Transactions and signing
r.Register("eth_sendTransaction", &commands.SendTransactionCommand{ 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 { func (api *API) RecallDAppPermission(origin string) error {
// TODO: close the websocket connection // 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) { func (api *API) GetPermittedDAppsList() ([]persistence.DApp, error) {

View File

@ -2,6 +2,7 @@ package commands
import ( import (
"crypto/sha256" "crypto/sha256"
"database/sql"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -9,6 +10,7 @@ import (
"time" "time"
"github.com/status-im/status-go/eth-node/types" "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/signal"
"github.com/status-im/status-go/transactions" "github.com/status-im/status-go/transactions"
) )
@ -23,6 +25,8 @@ var (
ErrPersonalSignRejectedByUser = fmt.Errorf("personal sign was rejected by user") ErrPersonalSignRejectedByUser = fmt.Errorf("personal sign was rejected by user")
ErrEmptyRequestID = fmt.Errorf("empty requestID") ErrEmptyRequestID = fmt.Errorf("empty requestID")
ErrAnotherConnectorOperationIsAwaitingFor = fmt.Errorf("another connector operation is awaiting for user input") 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 type MessageType int
@ -40,12 +44,14 @@ type Message struct {
} }
type ClientSideHandler struct { type ClientSideHandler struct {
Db *sql.DB
responseChannel chan Message responseChannel chan Message
isRequestRunning int32 isRequestRunning int32
} }
func NewClientSideHandler() *ClientSideHandler { func NewClientSideHandler(db *sql.DB) *ClientSideHandler {
return &ClientSideHandler{ return &ClientSideHandler{
Db: db,
responseChannel: make(chan Message, 1), // Buffer of 1 to avoid blocking responseChannel: make(chan Message, 1), // Buffer of 1 to avoid blocking
isRequestRunning: 0, isRequestRunning: 0,
} }
@ -115,6 +121,33 @@ func (c *ClientSideHandler) RequestAccountsRejected(args RejectedArgs) error {
return nil 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) { func (c *ClientSideHandler) RequestSendTransaction(dApp signal.ConnectorDApp, chainID uint64, txArgs *transactions.SendTxArgs) (types.Hash, error) {
if !c.setRequestRunning() { if !c.setRequestRunning() {
return types.Hash{}, ErrAnotherConnectorOperationIsAwaitingFor return types.Hash{}, ErrAnotherConnectorOperationIsAwaitingFor

View File

@ -4,11 +4,17 @@ import (
"testing" "testing"
"time" "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" "github.com/stretchr/testify/assert"
) )
func TestClientHandlerTimeout(t *testing.T) { func TestClientHandlerTimeout(t *testing.T) {
clientHandler := NewClientSideHandler() db, cleanup := createWalletDB(t)
t.Cleanup(cleanup)
clientHandler := NewClientSideHandler(db)
backupWalletResponseMaxInterval := WalletResponseMaxInterval backupWalletResponseMaxInterval := WalletResponseMaxInterval
WalletResponseMaxInterval = 1 * time.Millisecond WalletResponseMaxInterval = 1 * time.Millisecond
@ -19,10 +25,48 @@ func TestClientHandlerTimeout(t *testing.T) {
} }
func TestRequestRejectedWhileWaiting(t *testing.T) { func TestRequestRejectedWhileWaiting(t *testing.T) {
clientHandler := NewClientSideHandler() db, cleanup := createWalletDB(t)
t.Cleanup(cleanup)
clientHandler := NewClientSideHandler(db)
clientHandler.setRequestRunning() clientHandler.setRequestRunning()
_, _, err := clientHandler.RequestShareAccountForDApp(testDAppData) _, _, err := clientHandler.RequestShareAccountForDApp(testDAppData)
assert.Equal(t, ErrAnotherConnectorOperationIsAwaitingFor, err) 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)
}

View File

@ -65,10 +65,15 @@ type RejectedArgs struct {
RequestID string `json:"requestId"` RequestID string `json:"requestId"`
} }
type RecallDAppPermissionsArgs struct {
URL string `json:"url"`
}
type ClientSideHandlerInterface interface { type ClientSideHandlerInterface interface {
RequestShareAccountForDApp(dApp signal.ConnectorDApp) (types.Address, uint64, error) RequestShareAccountForDApp(dApp signal.ConnectorDApp) (types.Address, uint64, error)
RequestAccountsAccepted(args RequestAccountsAcceptedArgs) error RequestAccountsAccepted(args RequestAccountsAcceptedArgs) error
RequestAccountsRejected(args RejectedArgs) error RequestAccountsRejected(args RejectedArgs) error
RecallDAppPermissions(args RecallDAppPermissionsArgs) error
RequestSendTransaction(dApp signal.ConnectorDApp, chainID uint64, txArgs *transactions.SendTxArgs) (types.Hash, error) RequestSendTransaction(dApp signal.ConnectorDApp, chainID uint64, txArgs *transactions.SendTxArgs) (types.Hash, error)
SendTransactionAccepted(args SendTransactionAcceptedArgs) error SendTransactionAccepted(args SendTransactionAcceptedArgs) error

View File

@ -81,7 +81,7 @@ func setupCommand(t *testing.T, method string) (state testState, close func()) {
}) })
require.NoError(t, err) require.NoError(t, err)
state.handler = NewClientSideHandler() state.handler = NewClientSideHandler(state.db)
state.mockCtrl = gomock.NewController(t) state.mockCtrl = gomock.NewController(t)
state.rpcClient = mock_rpcclient.NewMockClientInterface(state.mockCtrl) state.rpcClient = mock_rpcclient.NewMockClientInterface(state.mockCtrl)