diff --git a/management/server/user.go b/management/server/user.go index 7c0a3088d..0a711389a 100644 --- a/management/server/user.go +++ b/management/server/user.go @@ -1337,6 +1337,10 @@ func (am *DefaultAccountManager) deleteRegularUser(ctx context.Context, accountI return fmt.Errorf("failed to get user to delete: %w", err) } + if targetUser.Role == types.UserRoleOwner && targetUser.Id != initiatorUserID { + return status.NewOwnerDeletePermissionError() + } + settings, err = transaction.GetAccountSettings(ctx, store.LockingStrengthNone, accountID) if err != nil { return fmt.Errorf("failed to get account settings: %w", err) diff --git a/management/server/user_test.go b/management/server/user_test.go index 3a2414540..ec0bbc54e 100644 --- a/management/server/user_test.go +++ b/management/server/user_test.go @@ -942,6 +942,49 @@ func TestUser_DeleteUser_regularUser(t *testing.T) { } +func TestUser_deleteRegularUser_RejectsOwner(t *testing.T) { + s, cleanup, err := store.NewTestStoreFromSQL(context.Background(), "", t.TempDir()) + require.NoError(t, err) + t.Cleanup(cleanup) + + account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", "", "", false) + account.Users[mockTargetUserId] = &types.User{ + Id: mockTargetUserId, + Issued: types.UserIssuedAPI, + Role: types.UserRoleOwner, + } + require.NoError(t, s.SaveAccount(context.Background(), account)) + + am := DefaultAccountManager{Store: s} + + _, err = am.deleteRegularUser(context.Background(), mockAccountID, mockUserID, &types.UserInfo{ID: mockTargetUserId}) + assert.EqualError(t, err, status.NewOwnerDeletePermissionError().Error()) +} + +func TestUser_deleteRegularUser_InitiatorOwnerDeletesThemself(t *testing.T) { + s, cleanup, err := store.NewTestStoreFromSQL(context.Background(), "", t.TempDir()) + require.NoError(t, err) + t.Cleanup(cleanup) + + account := newAccountWithId(context.Background(), mockAccountID, mockUserID, "", "", "", false) + require.NoError(t, s.SaveAccount(context.Background(), account)) + + networkMapControllerMock := network_map.NewMockController(gomock.NewController(t)) + networkMapControllerMock.EXPECT().OnPeersDeleted(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + + am := DefaultAccountManager{ + Store: s, + eventStore: &activity.InMemoryEventStore{}, + networkMapController: networkMapControllerMock, + } + + _, err = am.deleteRegularUser(context.Background(), mockAccountID, mockUserID, &types.UserInfo{ID: mockUserID}) + require.NoError(t, err) + + _, err = s.GetUserByUserID(context.Background(), store.LockingStrengthNone, mockUserID) + assert.Equal(t, status.NewUserNotFoundError(mockUserID), err) +} + func TestUser_DeleteUser_RegularUsers(t *testing.T) { store, cleanup, err := store.NewTestStoreFromSQL(context.Background(), "", t.TempDir()) if err != nil {