code.vegaprotocol.io/vega@v0.79.0/wallet/api/admin_update_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 TestAdminUpdatePermissions(t *testing.T) {
    35  	t.Run("Documentation matches the code", testAdminUpdatePermissionsSchemaCorrect)
    36  	t.Run("Updating permissions with invalid params fails", testUpdatingPermissionsWithInvalidParamsFails)
    37  	t.Run("Updating permissions with valid params succeeds", testUpdatingPermissionsWithValidParamsSucceeds)
    38  	t.Run("Updating permissions from wallet that does not exists fails", testUpdatingPermissionsFromWalletThatDoesNotExistsFails)
    39  	t.Run("Getting internal error during wallet verification fails", testAdminUpdatePermissionsGettingInternalErrorDuringWalletVerificationFails)
    40  	t.Run("Getting internal error during wallet retrieval fails", testAdminUpdatePermissionsGettingInternalErrorDuringWalletRetrievalFails)
    41  	t.Run("Getting internal error during wallet saving fails", testAdminUpdatePermissionsGettingInternalErrorDuringWalletSavingFails)
    42  }
    43  
    44  func testAdminUpdatePermissionsSchemaCorrect(t *testing.T) {
    45  	assertEqualSchema(t, "admin.update_permissions", api.AdminUpdatePermissionsParams{}, api.AdminUpdatePermissionsResult{})
    46  }
    47  
    48  func testUpdatingPermissionsWithInvalidParamsFails(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.AdminUpdatePermissionsParams{
    65  				Wallet:   "",
    66  				Hostname: vgrand.RandomStr(5),
    67  			},
    68  			expectedError: api.ErrWalletIsRequired,
    69  		}, {
    70  			name: "with empty hostname",
    71  			params: api.AdminUpdatePermissionsParams{
    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 := newUpdatePermissionsHandler(tt)
    86  
    87  			// when
    88  			result, errorDetails := handler.handle(t, ctx, tc.params)
    89  
    90  			// then
    91  			assertInvalidParams(tt, errorDetails, tc.expectedError)
    92  			assert.Empty(tt, result)
    93  		})
    94  	}
    95  }
    96  
    97  func testUpdatingPermissionsWithValidParamsSucceeds(t *testing.T) {
    98  	// given
    99  	ctx := context.Background()
   100  	hostname := vgrand.RandomStr(5)
   101  	expectedWallet, firstKey := walletWithKey(t)
   102  	permissions := wallet.Permissions{
   103  		PublicKeys: wallet.PublicKeysPermission{
   104  			Access: "read",
   105  			AllowedKeys: []string{
   106  				firstKey.PublicKey(),
   107  			},
   108  		},
   109  	}
   110  
   111  	// setup
   112  	handler := newUpdatePermissionsHandler(t)
   113  	// -- expected calls
   114  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   115  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   116  	handler.walletStore.EXPECT().GetWallet(ctx, expectedWallet.Name()).Times(1).Return(expectedWallet, nil)
   117  	handler.walletStore.EXPECT().UpdateWallet(ctx, expectedWallet).Times(1).Return(nil)
   118  
   119  	// when
   120  	result, errorDetails := handler.handle(t, ctx, api.AdminUpdatePermissionsParams{
   121  		Wallet:      expectedWallet.Name(),
   122  		Hostname:    hostname,
   123  		Permissions: permissions,
   124  	})
   125  
   126  	// then
   127  	require.Nil(t, errorDetails)
   128  	assert.Equal(t, permissions, result.Permissions)
   129  	assert.Equal(t, permissions, expectedWallet.Permissions(hostname))
   130  }
   131  
   132  func testUpdatingPermissionsFromWalletThatDoesNotExistsFails(t *testing.T) {
   133  	// given
   134  	ctx := context.Background()
   135  	name := vgrand.RandomStr(5)
   136  
   137  	// setup
   138  	handler := newUpdatePermissionsHandler(t)
   139  	// -- expected calls
   140  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(false, nil)
   141  
   142  	// when
   143  	result, errorDetails := handler.handle(t, ctx, api.AdminUpdatePermissionsParams{
   144  		Wallet:   name,
   145  		Hostname: vgrand.RandomStr(5),
   146  	})
   147  
   148  	// then
   149  	require.NotNil(t, errorDetails)
   150  	require.Empty(t, result)
   151  	assertInvalidParams(t, errorDetails, api.ErrWalletDoesNotExist)
   152  }
   153  
   154  func testAdminUpdatePermissionsGettingInternalErrorDuringWalletVerificationFails(t *testing.T) {
   155  	// given
   156  	ctx := context.Background()
   157  	name := vgrand.RandomStr(5)
   158  
   159  	// setup
   160  	handler := newUpdatePermissionsHandler(t)
   161  	// -- expected calls
   162  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(false, assert.AnError)
   163  
   164  	// when
   165  	result, errorDetails := handler.handle(t, ctx, api.AdminUpdatePermissionsParams{
   166  		Wallet:   name,
   167  		Hostname: vgrand.RandomStr(5),
   168  	})
   169  
   170  	// then
   171  	require.NotNil(t, errorDetails)
   172  	require.Empty(t, result)
   173  	assertInternalError(t, errorDetails, fmt.Errorf("could not verify the wallet exists: %w", assert.AnError))
   174  }
   175  
   176  func testAdminUpdatePermissionsGettingInternalErrorDuringWalletRetrievalFails(t *testing.T) {
   177  	// given
   178  	ctx := context.Background()
   179  	name := vgrand.RandomStr(5)
   180  
   181  	// setup
   182  	handler := newUpdatePermissionsHandler(t)
   183  	// -- expected calls
   184  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(true, nil)
   185  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, name).Times(1).Return(true, nil)
   186  	handler.walletStore.EXPECT().GetWallet(ctx, name).Times(1).Return(nil, assert.AnError)
   187  
   188  	// when
   189  	result, errorDetails := handler.handle(t, ctx, api.AdminUpdatePermissionsParams{
   190  		Wallet:   name,
   191  		Hostname: vgrand.RandomStr(5),
   192  	})
   193  
   194  	// then
   195  	require.NotNil(t, errorDetails)
   196  	require.Empty(t, result)
   197  	assertInternalError(t, errorDetails, fmt.Errorf("could not retrieve the wallet: %w", assert.AnError))
   198  }
   199  
   200  func testAdminUpdatePermissionsGettingInternalErrorDuringWalletSavingFails(t *testing.T) {
   201  	// given
   202  	ctx := context.Background()
   203  	expectedWallet, _, err := wallet.NewHDWallet(vgrand.RandomStr(5))
   204  	if err != nil {
   205  		t.Fatal(err)
   206  	}
   207  
   208  	// setup
   209  	handler := newUpdatePermissionsHandler(t)
   210  	// -- expected calls
   211  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   212  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   213  	handler.walletStore.EXPECT().GetWallet(ctx, expectedWallet.Name()).Times(1).Return(expectedWallet, nil)
   214  	handler.walletStore.EXPECT().UpdateWallet(ctx, expectedWallet).Times(1).Return(assert.AnError)
   215  
   216  	// when
   217  	result, errorDetails := handler.handle(t, ctx, api.AdminUpdatePermissionsParams{
   218  		Wallet:      expectedWallet.Name(),
   219  		Hostname:    vgrand.RandomStr(5),
   220  		Permissions: wallet.Permissions{},
   221  	})
   222  
   223  	// then
   224  	require.NotNil(t, errorDetails)
   225  	require.Empty(t, result)
   226  	assertInternalError(t, errorDetails, fmt.Errorf("could not save the wallet: %w", assert.AnError))
   227  }
   228  
   229  type updatePermissionsHandler struct {
   230  	*api.AdminUpdatePermissions
   231  	ctrl        *gomock.Controller
   232  	walletStore *mocks.MockWalletStore
   233  }
   234  
   235  func (h *updatePermissionsHandler) handle(t *testing.T, ctx context.Context, params jsonrpc.Params) (api.AdminUpdatePermissionsResult, *jsonrpc.ErrorDetails) {
   236  	t.Helper()
   237  
   238  	rawResult, err := h.Handle(ctx, params)
   239  	if rawResult != nil {
   240  		result, ok := rawResult.(api.AdminUpdatePermissionsResult)
   241  		if !ok {
   242  			t.Fatal("AdminUpdatePermissions handler result is not a AdminUpdatePermissionsResult")
   243  		}
   244  		return result, err
   245  	}
   246  	return api.AdminUpdatePermissionsResult{}, err
   247  }
   248  
   249  func newUpdatePermissionsHandler(t *testing.T) *updatePermissionsHandler {
   250  	t.Helper()
   251  
   252  	ctrl := gomock.NewController(t)
   253  	walletStore := mocks.NewMockWalletStore(ctrl)
   254  
   255  	return &updatePermissionsHandler{
   256  		AdminUpdatePermissions: api.NewAdminUpdatePermissions(walletStore),
   257  		ctrl:                   ctrl,
   258  		walletStore:            walletStore,
   259  	}
   260  }