diff --git a/engine/schema/src/main/java/org/apache/cloudstack/network/dao/NetworkPermissionDao.java b/engine/schema/src/main/java/org/apache/cloudstack/network/dao/NetworkPermissionDao.java index 1c8d1cf48ff..e8b6322baee 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/network/dao/NetworkPermissionDao.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/network/dao/NetworkPermissionDao.java @@ -40,6 +40,13 @@ public interface NetworkPermissionDao extends GenericDao NetworkAndAccountSearch; private SearchBuilder NetworkIdSearch; + private SearchBuilder accountSearch; private GenericSearchBuilder FindNetworkIdsByAccount; protected NetworkPermissionDaoImpl() { @@ -45,6 +46,10 @@ public class NetworkPermissionDaoImpl extends GenericDaoBase sc = accountSearch.create(); + sc.setParameters("accountId", accountId); + int networkPermissionRemoved = expunge(sc); + if (networkPermissionRemoved > 0) { + logger.debug(String.format("Removed [%s] network permission(s) for the account with Id [%s]", networkPermissionRemoved, accountId)); + } + } + @Override public NetworkPermissionVO findByNetworkAndAccount(long networkId, long accountId) { SearchCriteria sc = NetworkAndAccountSearch.create(); diff --git a/server/src/main/java/com/cloud/user/AccountManagerImpl.java b/server/src/main/java/com/cloud/user/AccountManagerImpl.java index c7a510049d6..ea2df5d1530 100644 --- a/server/src/main/java/com/cloud/user/AccountManagerImpl.java +++ b/server/src/main/java/com/cloud/user/AccountManagerImpl.java @@ -76,6 +76,7 @@ import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.PublishScope; import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.network.RoutedIpv4Manager; +import org.apache.cloudstack.network.dao.NetworkPermissionDao; import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao; import org.apache.cloudstack.resourcedetail.UserDetailVO; import org.apache.cloudstack.resourcedetail.dao.UserDetailsDao; @@ -303,6 +304,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M private SSHKeyPairDao _sshKeyPairDao; @Inject private UserDataDao userDataDao; + @Inject + private NetworkPermissionDao networkPermissionDao; private List _querySelectors; @@ -898,6 +901,9 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M // delete the account from project accounts _projectAccountDao.removeAccountFromProjects(accountId); + // Delete account's network permissions + networkPermissionDao.removeAccountPermissions(accountId); + if (account.getType() != Account.Type.PROJECT) { // delete the account from group _messageBus.publish(_name, MESSAGE_REMOVE_ACCOUNT_EVENT, PublishScope.LOCAL, accountId); @@ -1943,22 +1949,23 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M return true; } - // Account that manages project(s) can't be removed - List managedProjectIds = _projectAccountDao.listAdministratedProjectIds(accountId); - if (!managedProjectIds.isEmpty()) { - StringBuilder projectIds = new StringBuilder(); - for (Long projectId : managedProjectIds) { - projectIds.append(projectId).append(", "); - } - - throw new InvalidParameterValueException(String.format("The account %s with id %d manages project(s) with ids %s and can't be removed", account, accountId, projectIds)); - } + checkIfAccountManagesProjects(accountId); CallContext.current().putContextParameter(Account.class, account.getUuid()); return deleteAccount(account, callerUserId, caller); } + protected void checkIfAccountManagesProjects(long accountId) { + List managedProjectIds = _projectAccountDao.listAdministratedProjectIds(accountId); + if (!CollectionUtils.isEmpty(managedProjectIds)) { + throw new InvalidParameterValueException(String.format( + "Unable to delete account [%s], because it manages the following project(s): %s. Please, remove the account from these projects or demote it to a regular project role first.", + accountId, managedProjectIds + )); + } + } + protected boolean isDeleteNeeded(AccountVO account, long accountId, Account caller) { if (account == null) { logger.info(String.format("The account, identified by id %d, doesn't exist", accountId )); diff --git a/server/src/test/java/com/cloud/user/AccountManagerImplTest.java b/server/src/test/java/com/cloud/user/AccountManagerImplTest.java index 5739114cb48..0f53b907251 100644 --- a/server/src/test/java/com/cloud/user/AccountManagerImplTest.java +++ b/server/src/test/java/com/cloud/user/AccountManagerImplTest.java @@ -1338,4 +1338,22 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase { Mockito.when(roleService.findRole(2L)).thenReturn(callerRole); accountManagerImpl.validateRoleChange(account, newRole, caller); } + + @Test + public void checkIfAccountManagesProjectsTestNotThrowExceptionWhenTheAccountIsNotAProjectAdministrator() { + long accountId = 1L; + List managedProjectIds = new ArrayList<>(); + + Mockito.when(_projectAccountDao.listAdministratedProjectIds(accountId)).thenReturn(managedProjectIds); + accountManagerImpl.checkIfAccountManagesProjects(accountId); + } + + @Test(expected = InvalidParameterValueException.class) + public void checkIfAccountManagesProjectsTestThrowExceptionWhenTheAccountIsAProjectAdministrator() { + long accountId = 1L; + List managedProjectIds = List.of(1L); + + Mockito.when(_projectAccountDao.listAdministratedProjectIds(accountId)).thenReturn(managedProjectIds); + accountManagerImpl.checkIfAccountManagesProjects(accountId); + } } diff --git a/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java b/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java index e97fddc0262..1b75638b125 100644 --- a/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java +++ b/server/src/test/java/com/cloud/user/AccountManagetImplTestBase.java @@ -66,6 +66,7 @@ import org.apache.cloudstack.engine.service.api.OrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.network.RoutedIpv4Manager; +import org.apache.cloudstack.network.dao.NetworkPermissionDao; import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao; import org.apache.cloudstack.resourcedetail.dao.UserDetailsDao; import org.junit.After; @@ -196,6 +197,8 @@ public class AccountManagetImplTestBase { SSHKeyPairDao _sshKeyPairDao; @Mock UserDataDao userDataDao; + @Mock + NetworkPermissionDao networkPermissionDaoMock; @Spy @InjectMocks diff --git a/ui/src/views/setting/ConfigurationValue.vue b/ui/src/views/setting/ConfigurationValue.vue index 4ae0244b746..8bae313758a 100644 --- a/ui/src/views/setting/ConfigurationValue.vue +++ b/ui/src/views/setting/ConfigurationValue.vue @@ -55,9 +55,9 @@ /> - - - + + + - +