code.vegaprotocol.io/vega@v0.79.0/wallet/api/admin_revoke_permissions_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package api_test
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"testing"
    22  
    23  	"code.vegaprotocol.io/vega/libs/jsonrpc"
    24  	vgrand "code.vegaprotocol.io/vega/libs/rand"
    25  	"code.vegaprotocol.io/vega/wallet/api"
    26  	"code.vegaprotocol.io/vega/wallet/api/mocks"
    27  	"code.vegaprotocol.io/vega/wallet/wallet"
    28  
    29  	"github.com/golang/mock/gomock"
    30  	"github.com/stretchr/testify/assert"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  func TestAdminRevokePermissions(t *testing.T) {
    35  	t.Run("Documentation matches the code", testAdminRevokePermissionsSchemaCorrect)
    36  	t.Run("Revoking permissions with invalid params fails", testRevokingPermissionsWithInvalidParamsFails)
    37  	t.Run("Revoking permissions with valid params succeeds", testRevokingPermissionsWithValidParamsSucceeds)
    38  	t.Run("Revoking permissions from wallet that does not exists fails", testRevokingPermissionsFromWalletThatDoesNotExistsFails)
    39  	t.Run("Getting internal error during wallet verification fails", testAdminRevokePermissionsGettingInternalErrorDuringWalletVerificationFails)
    40  	t.Run("Getting internal error during wallet retrieval fails", testAdminRevokePermissionsGettingInternalErrorDuringWalletRetrievalFails)
    41  	t.Run("Getting internal error during wallet saving fails", testAdminRevokePermissionsGettingInternalErrorDuringWalletSavingFails)
    42  }
    43  
    44  func testAdminRevokePermissionsSchemaCorrect(t *testing.T) {
    45  	assertEqualSchema(t, "admin.revoke_permissions", api.AdminRevokePermissionsParams{}, nil)
    46  }
    47  
    48  func testRevokingPermissionsWithInvalidParamsFails(t *testing.T) {
    49  	tcs := []struct {
    50  		name          string
    51  		params        interface{}
    52  		expectedError error
    53  	}{
    54  		{
    55  			name:          "with nil params",
    56  			params:        nil,
    57  			expectedError: api.ErrParamsRequired,
    58  		}, {
    59  			name:          "with wrong type of params",
    60  			params:        "test",
    61  			expectedError: api.ErrParamsDoNotMatch,
    62  		}, {
    63  			name: "with empty name",
    64  			params: api.AdminRevokePermissionsParams{
    65  				Wallet:   "",
    66  				Hostname: vgrand.RandomStr(5),
    67  			},
    68  			expectedError: api.ErrWalletIsRequired,
    69  		}, {
    70  			name: "with empty hostname",
    71  			params: api.AdminRevokePermissionsParams{
    72  				Wallet:   vgrand.RandomStr(5),
    73  				Hostname: "",
    74  			},
    75  			expectedError: api.ErrHostnameIsRequired,
    76  		},
    77  	}
    78  
    79  	for _, tc := range tcs {
    80  		t.Run(tc.name, func(tt *testing.T) {
    81  			// given
    82  			ctx := context.Background()
    83  
    84  			// setup
    85  			handler := newRevokePermissionsHandler(tt)
    86  
    87  			// when
    88  			errorDetails := handler.handle(t, ctx, tc.params)
    89  
    90  			// then
    91  			assertInvalidParams(tt, errorDetails, tc.expectedError)
    92  		})
    93  	}
    94  }
    95  
    96  func testRevokingPermissionsWithValidParamsSucceeds(t *testing.T) {
    97  	// given
    98  	ctx := context.Background()
    99  	hostname1 := vgrand.RandomStr(5)
   100  	expectedWallet, firstKey := walletWithKey(t)
   101  	if err := expectedWallet.UpdatePermissions(hostname1, wallet.Permissions{
   102  		PublicKeys: wallet.PublicKeysPermission{
   103  			Access: "read",
   104  			AllowedKeys: []string{
   105  				firstKey.PublicKey(),
   106  			},
   107  		},
   108  	}); err != nil {
   109  		t.Fatalf("could not update permissions for test: %v", err)
   110  	}
   111  	hostname2 := vgrand.RandomStr(5)
   112  	permissions2 := wallet.Permissions{
   113  		PublicKeys: wallet.PublicKeysPermission{
   114  			Access: "read",
   115  			AllowedKeys: []string{
   116  				firstKey.PublicKey(),
   117  			},
   118  		},
   119  	}
   120  	if err := expectedWallet.UpdatePermissions(hostname2, permissions2); err != nil {
   121  		t.Fatalf("could not update permissions for test: %v", err)
   122  	}
   123  
   124  	// setup
   125  	handler := newRevokePermissionsHandler(t)
   126  	// -- expected calls
   127  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   128  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   129  	handler.walletStore.EXPECT().GetWallet(ctx, expectedWallet.Name()).Times(1).Return(expectedWallet, nil)
   130  	handler.walletStore.EXPECT().UpdateWallet(ctx, expectedWallet).Times(1).Return(nil)
   131  
   132  	// when
   133  	errorDetails := handler.handle(t, ctx, api.AdminRevokePermissionsParams{
   134  		Wallet:   expectedWallet.Name(),
   135  		Hostname: hostname1,
   136  	})
   137  
   138  	// then
   139  	require.Nil(t, errorDetails)
   140  	assert.Equal(t, wallet.DefaultPermissions(), expectedWallet.Permissions(hostname1))
   141  	assert.Equal(t, permissions2, expectedWallet.Permissions(hostname2))
   142  }
   143  
   144  func testRevokingPermissionsFromWalletThatDoesNotExistsFails(t *testing.T) {
   145  	// given
   146  	ctx := context.Background()
   147  	name := vgrand.RandomStr(5)
   148  
   149  	// setup
   150  	handler := newRevokePermissionsHandler(t)
   151  	// -- expected calls
   152  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(false, nil)
   153  
   154  	// when
   155  	errorDetails := handler.handle(t, ctx, api.AdminRevokePermissionsParams{
   156  		Wallet:   name,
   157  		Hostname: vgrand.RandomStr(5),
   158  	})
   159  
   160  	// then
   161  	require.NotNil(t, errorDetails)
   162  	assertInvalidParams(t, errorDetails, api.ErrWalletDoesNotExist)
   163  }
   164  
   165  func testAdminRevokePermissionsGettingInternalErrorDuringWalletVerificationFails(t *testing.T) {
   166  	// given
   167  	ctx := context.Background()
   168  	name := vgrand.RandomStr(5)
   169  
   170  	// setup
   171  	handler := newRevokePermissionsHandler(t)
   172  	// -- expected calls
   173  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(false, assert.AnError)
   174  
   175  	// when
   176  	errorDetails := handler.handle(t, ctx, api.AdminRevokePermissionsParams{
   177  		Wallet:   name,
   178  		Hostname: vgrand.RandomStr(5),
   179  	})
   180  
   181  	// then
   182  	require.NotNil(t, errorDetails)
   183  	assertInternalError(t, errorDetails, fmt.Errorf("could not verify the wallet exists: %w", assert.AnError))
   184  }
   185  
   186  func testAdminRevokePermissionsGettingInternalErrorDuringWalletRetrievalFails(t *testing.T) {
   187  	// given
   188  	ctx := context.Background()
   189  	name := vgrand.RandomStr(5)
   190  
   191  	// setup
   192  	handler := newRevokePermissionsHandler(t)
   193  	// -- expected calls
   194  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(true, nil)
   195  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, name).Times(1).Return(true, nil)
   196  	handler.walletStore.EXPECT().GetWallet(ctx, name).Times(1).Return(nil, assert.AnError)
   197  
   198  	// when
   199  	errorDetails := handler.handle(t, ctx, api.AdminRevokePermissionsParams{
   200  		Wallet:   name,
   201  		Hostname: vgrand.RandomStr(5),
   202  	})
   203  
   204  	// then
   205  	require.NotNil(t, errorDetails)
   206  	assertInternalError(t, errorDetails, fmt.Errorf("could not retrieve the wallet: %w", assert.AnError))
   207  }
   208  
   209  func testAdminRevokePermissionsGettingInternalErrorDuringWalletSavingFails(t *testing.T) {
   210  	// given
   211  	ctx := context.Background()
   212  	expectedWallet, _, err := wallet.NewHDWallet(vgrand.RandomStr(5))
   213  	if err != nil {
   214  		t.Fatal(err)
   215  	}
   216  
   217  	// setup
   218  	handler := newRevokePermissionsHandler(t)
   219  	// -- expected calls
   220  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   221  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   222  	handler.walletStore.EXPECT().GetWallet(ctx, expectedWallet.Name()).Times(1).Return(expectedWallet, nil)
   223  	handler.walletStore.EXPECT().UpdateWallet(ctx, expectedWallet).Times(1).Return(assert.AnError)
   224  
   225  	// when
   226  	errorDetails := handler.handle(t, ctx, api.AdminRevokePermissionsParams{
   227  		Wallet:   expectedWallet.Name(),
   228  		Hostname: vgrand.RandomStr(5),
   229  	})
   230  
   231  	// then
   232  	require.NotNil(t, errorDetails)
   233  	assertInternalError(t, errorDetails, fmt.Errorf("could not save the wallet: %w", assert.AnError))
   234  }
   235  
   236  type revokePermissionsHandler struct {
   237  	*api.AdminRevokePermissions
   238  	ctrl        *gomock.Controller
   239  	walletStore *mocks.MockWalletStore
   240  }
   241  
   242  func (h *revokePermissionsHandler) handle(t *testing.T, ctx context.Context, params jsonrpc.Params) *jsonrpc.ErrorDetails {
   243  	t.Helper()
   244  
   245  	rawResult, err := h.Handle(ctx, params)
   246  	require.Empty(t, rawResult)
   247  	return err
   248  }
   249  
   250  func newRevokePermissionsHandler(t *testing.T) *revokePermissionsHandler {
   251  	t.Helper()
   252  
   253  	ctrl := gomock.NewController(t)
   254  	walletStore := mocks.NewMockWalletStore(ctrl)
   255  
   256  	return &revokePermissionsHandler{
   257  		AdminRevokePermissions: api.NewAdminRevokePermissions(walletStore),
   258  		ctrl:                   ctrl,
   259  		walletStore:            walletStore,
   260  	}
   261  }