mirror of https://github.com/apache/cloudstack.git
Merge f384872d0f into bce3e54a7e
This commit is contained in:
commit
67dc24df79
|
|
@ -99,4 +99,6 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long>, StateDao<
|
|||
List<VMTemplateVO> listByIds(List<Long> ids);
|
||||
|
||||
List<Long> listIdsByTemplateTag(String tag);
|
||||
|
||||
List<Long> listByUserdataIdsNotAccount(List<Long> userdataIds, long accountId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -863,4 +863,22 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||
}
|
||||
return rows > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> listByUserdataIdsNotAccount(List<Long> userdataIds, long accountId) {
|
||||
if (CollectionUtils.isEmpty(userdataIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
GenericSearchBuilder<VMTemplateVO, Long> sb = createSearchBuilder(Long.class);
|
||||
sb.selectFields(sb.entity().getId());
|
||||
sb.and("userDataId", sb.entity().getUserDataId(), SearchCriteria.Op.EQ);
|
||||
sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
|
||||
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.NEQ);
|
||||
sb.done();
|
||||
SearchCriteria<Long> sc = sb.create();
|
||||
sc.setParameters("userDataId", userdataIds.toArray());
|
||||
sc.setParameters("state", VirtualMachineTemplate.State.Active.toString());
|
||||
sc.setParameters("accountId", accountId);
|
||||
return customSearch(sc, null);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
// under the License.
|
||||
package com.cloud.user.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.user.UserDataVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
|
|
@ -25,6 +27,8 @@ public interface UserDataDao extends GenericDao<UserDataVO, Long> {
|
|||
|
||||
public UserDataVO findByName(long accountId, long domainId, String name);
|
||||
|
||||
List<Long> listIdsByAccountId(long accountId);
|
||||
|
||||
int removeByAccountId(long accountId);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,11 @@
|
|||
// under the License.
|
||||
package com.cloud.user.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.user.UserDataVO;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.GenericSearchBuilder;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
|
@ -64,6 +67,18 @@ public class UserDataDaoImpl extends GenericDaoBase<UserDataVO, Long> implements
|
|||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> listIdsByAccountId(long accountId) {
|
||||
GenericSearchBuilder<UserDataVO, Long> sb = createSearchBuilder(Long.class);
|
||||
sb.selectFields(sb.entity().getId());
|
||||
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
sb.done();
|
||||
SearchCriteria<Long> sc = sb.create();
|
||||
sc.setParameters("accountId", accountId);
|
||||
return customSearch(sc, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int removeByAccountId(long accountId) {
|
||||
SearchCriteria<UserDataVO> sc = userdataSearch.create();
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package com.cloud.storage.dao;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
|
@ -47,6 +48,7 @@ import com.cloud.storage.Storage;
|
|||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.db.Filter;
|
||||
import com.cloud.utils.db.GenericSearchBuilder;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
|
|
@ -207,4 +209,49 @@ public class VMTemplateDaoImplTest {
|
|||
VMTemplateVO readyTemplate = templateDao.findSystemVMReadyTemplate(zoneId, Hypervisor.HypervisorType.KVM, CPU.CPUArch.arm64.getType());
|
||||
Assert.assertEquals(CPU.CPUArch.arm64, readyTemplate.getArch());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listByUserdataIdsNotAccount_ReturnsEmptyListWhenUserdataIdsIsEmpty() {
|
||||
List<Long> result = templateDao.listByUserdataIdsNotAccount(Collections.emptyList(), 1L);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listByUserdataIdsNotAccount_ReturnsMatchingTemplates() {
|
||||
List<Long> userdataIds = Arrays.asList(1L, 2L);
|
||||
long accountId = 3L;
|
||||
|
||||
GenericSearchBuilder<VMTemplateVO, Long> sb = mock(GenericSearchBuilder.class);
|
||||
when(sb.entity()).thenReturn(mock(VMTemplateVO.class));
|
||||
SearchCriteria<Long> sc = mock(SearchCriteria.class);
|
||||
doReturn(sb).when(templateDao).createSearchBuilder(Long.class);
|
||||
doReturn(sc).when(sb).create();
|
||||
doReturn(Arrays.asList(10L, 20L)).when(templateDao).customSearch(sc, null);
|
||||
|
||||
List<Long> result = templateDao.listByUserdataIdsNotAccount(userdataIds, accountId);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.size());
|
||||
assertTrue(result.contains(10L));
|
||||
assertTrue(result.contains(20L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listByUserdataIdsNotAccount_ReturnsEmptyListWhenNoMatchingTemplates() {
|
||||
List<Long> userdataIds = Arrays.asList(1L, 2L);
|
||||
long accountId = 3L;
|
||||
|
||||
GenericSearchBuilder<VMTemplateVO, Long> sb = mock(GenericSearchBuilder.class);
|
||||
when(sb.entity()).thenReturn(mock(VMTemplateVO.class));
|
||||
SearchCriteria<Long> sc = mock(SearchCriteria.class);
|
||||
doReturn(sb).when(templateDao).createSearchBuilder(Long.class);
|
||||
doReturn(sc).when(sb).create();
|
||||
doReturn(Collections.emptyList()).when(templateDao).customSearch(sc, null);
|
||||
|
||||
List<Long> result = templateDao.listByUserdataIdsNotAccount(userdataIds, accountId);
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.user.dao;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.cloud.user.UserDataVO;
|
||||
import com.cloud.utils.db.GenericSearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class UserDataDaoImplTest {
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
UserDataDaoImpl userDataDaoImpl;
|
||||
|
||||
@Test
|
||||
public void listIdsByAccountId_ReturnsEmptyListWhenNoIdsFound() {
|
||||
long accountId = 1L;
|
||||
|
||||
GenericSearchBuilder<UserDataVO, Long> sb = mock(GenericSearchBuilder.class);
|
||||
when(sb.entity()).thenReturn(mock(UserDataVO.class));
|
||||
SearchCriteria<Long> sc = mock(SearchCriteria.class);
|
||||
doReturn(sb).when(userDataDaoImpl).createSearchBuilder(Long.class);
|
||||
doReturn(sc).when(sb).create();
|
||||
doReturn(Collections.emptyList()).when(userDataDaoImpl).customSearch(sc, null);
|
||||
|
||||
List<Long> result = userDataDaoImpl.listIdsByAccountId(accountId);
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listIdsByAccountId_ReturnsListOfIdsWhenFound() {
|
||||
long accountId = 1L;
|
||||
|
||||
GenericSearchBuilder<UserDataVO, Long> sb = mock(GenericSearchBuilder.class);
|
||||
when(sb.entity()).thenReturn(mock(UserDataVO.class));
|
||||
SearchCriteria<Long> sc = mock(SearchCriteria.class);
|
||||
doReturn(sb).when(userDataDaoImpl).createSearchBuilder(Long.class);
|
||||
doReturn(sc).when(sb).create();
|
||||
doReturn(Arrays.asList(10L, 20L)).when(userDataDaoImpl).customSearch(sc, null);
|
||||
|
||||
List<Long> result = userDataDaoImpl.listIdsByAccountId(accountId);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.size());
|
||||
assertTrue(result.contains(10L));
|
||||
assertTrue(result.contains(20L));
|
||||
}
|
||||
}
|
||||
|
|
@ -475,6 +475,21 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||
_querySelectors = querySelectors;
|
||||
}
|
||||
|
||||
protected void deleteUserDataForAccount(long accountId) {
|
||||
List<Long> userdataIdsList = userDataDao.listIdsByAccountId(accountId);
|
||||
if (CollectionUtils.isEmpty(userdataIdsList)) {
|
||||
return;
|
||||
}
|
||||
List<Long> conflictingTemplateIds = _templateDao.listByUserdataIdsNotAccount(userdataIdsList, accountId);
|
||||
if (CollectionUtils.isNotEmpty(conflictingTemplateIds)) {
|
||||
logger.warn("User data IDs {} owned by account ID {} cannot be deleted as some of them are " +
|
||||
"linked to templates {} not owned by the account.", userdataIdsList, accountId,
|
||||
conflictingTemplateIds);
|
||||
throw new CloudRuntimeException("User data owned by account linked to templates not owned by the account");
|
||||
}
|
||||
userDataDao.removeByAccountId(accountId);
|
||||
}
|
||||
|
||||
protected void deleteWebhooksForAccount(long accountId) {
|
||||
try {
|
||||
WebhookHelper webhookService = ComponentContext.getDelegateComponentOfType(WebhookHelper.class);
|
||||
|
|
@ -1200,7 +1215,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
|
|||
}
|
||||
|
||||
// Delete registered UserData
|
||||
userDataDao.removeByAccountId(accountId);
|
||||
deleteUserDataForAccount(accountId);
|
||||
|
||||
// Delete Webhooks
|
||||
deleteWebhooksForAccount(accountId);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import java.net.InetAddress;
|
|||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -198,7 +199,7 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
|
|||
sshkeyList.add(sshkey);
|
||||
Mockito.when(_sshKeyPairDao.listKeyPairs(Mockito.anyLong(), Mockito.anyLong())).thenReturn(sshkeyList);
|
||||
Mockito.when(_sshKeyPairDao.remove(Mockito.anyLong())).thenReturn(true);
|
||||
Mockito.when(userDataDao.removeByAccountId(Mockito.anyLong())).thenReturn(222);
|
||||
Mockito.doNothing().when(accountManagerImpl).deleteUserDataForAccount(Mockito.anyLong());
|
||||
Mockito.doNothing().when(accountManagerImpl).deleteWebhooksForAccount(Mockito.anyLong());
|
||||
Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations((Account) any());
|
||||
|
||||
|
|
@ -1589,4 +1590,41 @@ public class AccountManagerImplTest extends AccountManagetImplTestBase {
|
|||
|
||||
accountManagerImpl.checkCallerApiPermissionsForUserOrAccountOperations(accountMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteUserDataForAccountWhenNoUserDataExists() {
|
||||
long accountId = 1L;
|
||||
Mockito.when(userDataDao.listIdsByAccountId(accountId)).thenReturn(Collections.emptyList());
|
||||
|
||||
accountManagerImpl.deleteUserDataForAccount(accountId);
|
||||
|
||||
Mockito.verify(userDataDao, Mockito.times(1)).listIdsByAccountId(accountId);
|
||||
Mockito.verify(userDataDao, Mockito.times(0)).removeByAccountId(accountId);
|
||||
Mockito.verifyNoInteractions(_templateDao);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteUserDataForAccountWhenNoConflictingTemplatesExist() {
|
||||
long accountId = 1L;
|
||||
List<Long> userdataIds = List.of(101L, 102L);
|
||||
Mockito.when(userDataDao.listIdsByAccountId(accountId)).thenReturn(userdataIds);
|
||||
Mockito.when(_templateDao.listByUserdataIdsNotAccount(userdataIds, accountId)).thenReturn(Collections.emptyList());
|
||||
|
||||
accountManagerImpl.deleteUserDataForAccount(accountId);
|
||||
|
||||
Mockito.verify(userDataDao, Mockito.times(1)).listIdsByAccountId(accountId);
|
||||
Mockito.verify(_templateDao, Mockito.times(1)).listByUserdataIdsNotAccount(userdataIds, accountId);
|
||||
Mockito.verify(userDataDao, Mockito.times(1)).removeByAccountId(accountId);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void deleteUserDataForAccountWhenConflictingTemplatesExist() {
|
||||
long accountId = 1L;
|
||||
List<Long> userdataIds = List.of(101L, 102L);
|
||||
List<Long> conflictingTemplateIds = List.of(201L, 202L);
|
||||
Mockito.when(userDataDao.listIdsByAccountId(accountId)).thenReturn(userdataIds);
|
||||
Mockito.when(_templateDao.listByUserdataIdsNotAccount(userdataIds, accountId)).thenReturn(conflictingTemplateIds);
|
||||
|
||||
accountManagerImpl.deleteUserDataForAccount(accountId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue