diff --git a/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppController.java b/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppController.java index ea6161d50a34b8ababb4636ea5f5d72ed955f293..0c4b97211111d0b5a60dcf6183bb4712185496cb 100644 --- a/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppController.java +++ b/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/AppController.java @@ -54,7 +54,7 @@ public class AppController { if (entity == null) { throw new NotFoundException("app not found for appId " + appId); } - appService.delete(entity.getId(), operator); + adminService.deleteApp(entity, operator); } @RequestMapping(value = "/apps/{appId:.+}", method = RequestMethod.PUT) @@ -91,5 +91,4 @@ public class AppController { public boolean isAppIdUnique(@PathVariable("appId") String appId) { return appService.isAppIdUnique(appId); } - } diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppNamespaceRepository.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppNamespaceRepository.java index 99510958c5f7f370d8ff8276ab18cce7d3b53afb..4fae7ceb80e6aaa98870dd9905fc38c084061d83 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppNamespaceRepository.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppNamespaceRepository.java @@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.common.entity.AppNamespace; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; @@ -24,4 +26,7 @@ public interface AppNamespaceRepository extends PagingAndSortingRepository findFirst500ByIdGreaterThanOrderByIdAsc(long id); + @Modifying + @Query("UPDATE AppNamespace SET IsDeleted=1,DataChange_LastModifiedBy = ?2 WHERE AppId=?1") + int batchDeleteByAppId(String appId, String operator); } diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppRepository.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppRepository.java index f665307d514c2126823e4f0d5e8f9c0e25a5998e..10ce0c0a178fddc0ea5aaedf13fd940290b4526c 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppRepository.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AppRepository.java @@ -14,5 +14,4 @@ public interface AppRepository extends PagingAndSortingRepository { List findByName(@Param("name") String name); App findByAppId(String appId); - } diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/GrayReleaseRuleRepository.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/GrayReleaseRuleRepository.java index 0eb39de0f5686905c15d4fdc56612156042705f2..68a4425f375573ced736af05b92064a973cd0820 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/GrayReleaseRuleRepository.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/GrayReleaseRuleRepository.java @@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.biz.repository; import com.ctrip.framework.apollo.biz.entity.GrayReleaseRule; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; @@ -17,4 +19,7 @@ public interface GrayReleaseRuleRepository extends PagingAndSortingRepository findFirst500ByIdGreaterThanOrderByIdAsc(Long id); + @Modifying + @Query("UPDATE GrayReleaseRule SET IsDeleted=1, DataChange_LastModifiedBy = ?4 where appId=?1 and clusterName=?2 and namespaceName = ?3") + int batchDelete(String appId, String clusterName, String namespaceName, String operator); } diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AdminService.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AdminService.java index 63ea9af68a90343790b22d800f5a2b05dcee79bc..8239565567af9bce90ae7af45b9de307404b2f73 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AdminService.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AdminService.java @@ -1,12 +1,19 @@ package com.ctrip.framework.apollo.biz.service; +import com.ctrip.framework.apollo.biz.entity.Cluster; import com.ctrip.framework.apollo.common.entity.App; +import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.core.ConfigConsts; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.Objects; + @Service public class AdminService { @@ -19,6 +26,8 @@ public class AdminService { @Autowired private NamespaceService namespaceService; + private final static Logger logger = LoggerFactory.getLogger(AdminService.class); + @Transactional public App createNewApp(App app) { String createBy = app.getDataChangeCreatedBy(); @@ -35,5 +44,25 @@ public class AdminService { return app; } + @Transactional + public void deleteApp(App app, String operator) { + String appId = app.getAppId(); + + logger.info("{} is deleting App:{}", operator, appId); + List managedClusters = clusterService.findClusters(appId); + + // 1. delete clusters + if (Objects.nonNull(managedClusters)) { + for (Cluster cluster : managedClusters) { + clusterService.delete(cluster.getId(), operator); + } + } + + // 2. delete appNamespace + appNamespaceService.batchDelete(appId, operator); + + // 3. delete app + appService.delete(app.getId(), operator); + } } diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppNamespaceService.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppNamespaceService.java index 92d3701f33502bf5f508f42df81c290bfef2e1b2..83ebe738b682e01d257fe962767114c5794cef3b 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppNamespaceService.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/AppNamespaceService.java @@ -137,4 +137,9 @@ public class AppNamespaceService { namespaceService.save(namespace); } } + + @Transactional + public void batchDelete(String appId, String operator) { + appNamespaceRepository.batchDeleteByAppId(appId, operator); + } } diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ClusterService.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ClusterService.java index f2f39663037c1719cea9b87f6d14efdef5b33f92..cd404dd504780117d60593224b1b0c5b9d2965bf 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ClusterService.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ClusterService.java @@ -137,4 +137,7 @@ public class ClusterService { return clusterRepository.findByParentClusterId(parentCluster.getId()); } + public List findClusters(String appId) { + return clusterRepository.findByAppId(appId); + } } diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/GrayReleaseRuleService.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/GrayReleaseRuleService.java new file mode 100644 index 0000000000000000000000000000000000000000..30f9427cb7bb868408ffefa58c7d4d0da838775e --- /dev/null +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/GrayReleaseRuleService.java @@ -0,0 +1,18 @@ +package com.ctrip.framework.apollo.biz.service; + +import com.ctrip.framework.apollo.biz.repository.GrayReleaseRuleRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class GrayReleaseRuleService { + + @Autowired + private GrayReleaseRuleRepository grayReleaseRuleRepository; + + @Transactional + public void batchDelete(String appId, String clusterName, String namespaceName, String operator) { + grayReleaseRuleRepository.batchDelete(appId, clusterName, namespaceName, operator); + } +} diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java index 933873aca07589928f4aff8f6d381e6cbaa6df45..75e264ccc56e45b131f199b3b0df5beaa26b8466 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/NamespaceService.java @@ -59,6 +59,8 @@ public class NamespaceService { @Autowired private ReleaseHistoryService releaseHistoryService; @Autowired + private GrayReleaseRuleService grayReleaseRuleService; + @Autowired private NamespaceLockService namespaceLockService; @Autowired private InstanceService instanceService; @@ -263,17 +265,18 @@ public class NamespaceService { itemService.batchDelete(namespace.getId(), operator); commitService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator); - if (!isChildNamespace(namespace)) { - releaseService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator); - } + releaseService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator); + grayReleaseRuleService.batchDelete(appId, clusterName, namespace.getNamespaceName(), operator); - //delete child namespace - Namespace childNamespace = findChildNamespace(namespace); - if (childNamespace != null) { - namespaceBranchService.deleteBranch(appId, clusterName, namespaceName, - childNamespace.getClusterName(), NamespaceBranchStatus.DELETED, operator); - //delete child namespace's releases. Notice: delete child namespace will not delete child namespace's releases - releaseService.batchDelete(appId, childNamespace.getClusterName(), namespaceName, operator); + if (!isChildNamespace(namespace)) { + //delete child namespace + Namespace childNamespace = findChildNamespace(namespace); + if (childNamespace != null) { + namespaceBranchService.deleteBranch(appId, clusterName, namespaceName, + childNamespace.getClusterName(), NamespaceBranchStatus.DELETED, operator); + //delete child namespace's releases. Notice: delete child namespace will not delete child namespace's releases + releaseService.batchDelete(appId, childNamespace.getClusterName(), namespaceName, operator); + } } releaseHistoryService.batchDelete(appId, clusterName, namespaceName, operator); @@ -394,6 +397,4 @@ public class NamespaceService { return false; } - - } diff --git a/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/service/AdminServiceTest.java b/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/service/AdminServiceTest.java index f7b6cd4d4fa62eb0b10f786894550b349e1ba195..0aeb63829f53e5d7d2e49d74e6ac9d8a0895abe5 100644 --- a/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/service/AdminServiceTest.java +++ b/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/service/AdminServiceTest.java @@ -8,15 +8,13 @@ import com.ctrip.framework.apollo.biz.repository.AppRepository; import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.common.exception.ServiceException; import com.ctrip.framework.apollo.core.ConfigConsts; - +import java.util.Date; +import java.util.List; import org.junit.Assert; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; -import java.util.Date; -import java.util.List; - -public class AdminServiceTest extends AbstractIntegrationTest{ +public class AdminServiceTest extends AbstractIntegrationTest { @Autowired private AdminService adminService; @@ -33,6 +31,9 @@ public class AdminServiceTest extends AbstractIntegrationTest{ @Autowired private NamespaceService namespaceService; + @Autowired + private AppNamespaceService appNamespaceService; + @Test public void testCreateNewApp() { String appId = "someAppId"; @@ -79,4 +80,37 @@ public class AdminServiceTest extends AbstractIntegrationTest{ adminService.createNewApp(app); } + @Test + public void testDeleteApp() { + String appId = "someAppId"; + App app = new App(); + app.setAppId(appId); + app.setName("someAppName"); + String owner = "someOwnerName"; + app.setOwnerName(owner); + app.setOwnerEmail("someOwnerName@ctrip.com"); + app.setDataChangeCreatedBy(owner); + app.setDataChangeLastModifiedBy(owner); + app.setDataChangeCreatedTime(new Date()); + + app = adminService.createNewApp(app); + + Assert.assertEquals(appId, app.getAppId()); + + Assert.assertEquals(1, appNamespaceService.findByAppId(appId).size()); + + Assert.assertEquals(1, clusterService.findClusters(appId).size()); + + Assert.assertEquals(1, namespaceService.findNamespaces(appId, ConfigConsts.CLUSTER_NAME_DEFAULT).size()); + + adminService.deleteApp(app, owner); + + Assert.assertEquals(0, appNamespaceService.findByAppId(appId).size()); + + Assert.assertEquals(0, clusterService.findClusters(appId).size()); + + Assert + .assertEquals(0, namespaceService.findByAppIdAndNamespaceName(appId, ConfigConsts.CLUSTER_NAME_DEFAULT).size()); + } + } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerRoleRepository.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerRoleRepository.java index e967094eb828f70831eaf348b35e69748021abbe..a8a2894a6ff8d8598a7154ffd1f2b4029cf0884d 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerRoleRepository.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/repository/ConsumerRoleRepository.java @@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.openapi.repository; import com.ctrip.framework.apollo.openapi.entity.ConsumerRole; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; @@ -23,4 +25,8 @@ public interface ConsumerRoleRepository extends PagingAndSortingRepository findByRoleId(long roleId); ConsumerRole findByConsumerIdAndRoleId(long consumerId, long roleId); + + @Modifying + @Query("UPDATE ConsumerRole SET IsDeleted=1, DataChange_LastModifiedBy = ?2 WHERE RoleId in ?1") + Integer batchDeleteByRoleIds(List roleIds, String operator); } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java index 17c6fe6b6944d912b229e2793f619cf2b9dd1199..1242b899f1e21604ff8413f26f19ebafe37605ff 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java @@ -1,8 +1,6 @@ package com.ctrip.framework.apollo.portal.api; -import com.google.common.base.Joiner; - import com.ctrip.framework.apollo.common.dto.AppDTO; import com.ctrip.framework.apollo.common.dto.AppNamespaceDTO; import com.ctrip.framework.apollo.common.dto.ClusterDTO; @@ -17,7 +15,12 @@ import com.ctrip.framework.apollo.common.dto.PageDTO; import com.ctrip.framework.apollo.common.dto.ReleaseDTO; import com.ctrip.framework.apollo.common.dto.ReleaseHistoryDTO; import com.ctrip.framework.apollo.core.enums.Env; - +import com.google.common.base.Joiner; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; import org.springframework.boot.actuate.health.Health; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; @@ -29,12 +32,6 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - @Service public class AdminServiceAPI { @@ -61,6 +58,10 @@ public class AdminServiceAPI { public void updateApp(Env env, AppDTO app) { restTemplate.put(env, "apps/{appId}", app, app.getAppId()); } + + public void deleteApp(Env env, String appId, String operator) { + restTemplate.delete(env, "/apps/{appId}?operator={operator}", appId, operator); + } } @@ -73,30 +74,30 @@ public class AdminServiceAPI { public List findNamespaceByCluster(String appId, Env env, String clusterName) { NamespaceDTO[] namespaceDTOs = restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces", - NamespaceDTO[].class, appId, - clusterName); + NamespaceDTO[].class, appId, + clusterName); return Arrays.asList(namespaceDTOs); } public NamespaceDTO loadNamespace(String appId, Env env, String clusterName, - String namespaceName) { + String namespaceName) { return restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}", - NamespaceDTO.class, appId, clusterName, namespaceName); + NamespaceDTO.class, appId, clusterName, namespaceName); } public NamespaceDTO findPublicNamespaceForAssociatedNamespace(Env env, String appId, String clusterName, - String namespaceName) { + String namespaceName) { return restTemplate .get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/associated-public-namespace", - NamespaceDTO.class, appId, clusterName, namespaceName); + NamespaceDTO.class, appId, clusterName, namespaceName); } public NamespaceDTO createNamespace(Env env, NamespaceDTO namespace) { return restTemplate .post(env, "apps/{appId}/clusters/{clusterName}/namespaces", namespace, NamespaceDTO.class, - namespace.getAppId(), namespace.getClusterName()); + namespace.getAppId(), namespace.getClusterName()); } public AppNamespaceDTO createAppNamespace(Env env, AppNamespaceDTO appNamespace) { @@ -107,8 +108,8 @@ public class AdminServiceAPI { public void deleteNamespace(Env env, String appId, String clusterName, String namespaceName, String operator) { restTemplate .delete(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}?operator={operator}", appId, - clusterName, - namespaceName, operator); + clusterName, + namespaceName, operator); } public Map getNamespacePublishInfo(Env env, String appId) { @@ -116,17 +117,17 @@ public class AdminServiceAPI { } public List getPublicAppNamespaceAllNamespaces(Env env, String publicNamespaceName, - int page, int size) { + int page, int size) { NamespaceDTO[] namespaceDTOs = restTemplate.get(env, "/appnamespaces/{publicNamespaceName}/namespaces?page={page}&size={size}", - NamespaceDTO[].class, publicNamespaceName, page, size); + NamespaceDTO[].class, publicNamespaceName, page, size); return Arrays.asList(namespaceDTOs); } public int countPublicAppNamespaceAssociatedNamespaces(Env env, String publicNamesapceName) { Integer count = restTemplate.get(env, "/appnamespaces/{publicNamespaceName}/associated-namespaces/count", Integer.class, - publicNamesapceName); + publicNamesapceName); return count == null ? 0 : count; } @@ -139,30 +140,30 @@ public class AdminServiceAPI { public List findItems(String appId, Env env, String clusterName, String namespaceName) { ItemDTO[] itemDTOs = restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", - ItemDTO[].class, appId, clusterName, namespaceName); + ItemDTO[].class, appId, clusterName, namespaceName); return Arrays.asList(itemDTOs); } public ItemDTO loadItem(Env env, String appId, String clusterName, String namespaceName, String key) { return restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key}", - ItemDTO.class, appId, clusterName, namespaceName, key); + ItemDTO.class, appId, clusterName, namespaceName, key); } public void updateItemsByChangeSet(String appId, Env env, String clusterName, String namespace, - ItemChangeSets changeSets) { + ItemChangeSets changeSets) { restTemplate.post(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/itemset", - changeSets, Void.class, appId, clusterName, namespace); + changeSets, Void.class, appId, clusterName, namespace); } public void updateItem(String appId, Env env, String clusterName, String namespace, long itemId, ItemDTO item) { restTemplate.put(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}", - item, appId, clusterName, namespace, itemId); + item, appId, clusterName, namespace, itemId); } public ItemDTO createItem(String appId, Env env, String clusterName, String namespace, ItemDTO item) { return restTemplate.post(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", - item, ItemDTO.class, appId, clusterName, namespace); + item, ItemDTO.class, appId, clusterName, namespace); } public void deleteItem(Env env, long itemId, String operator) { @@ -176,25 +177,25 @@ public class AdminServiceAPI { public List findClustersByApp(String appId, Env env) { ClusterDTO[] clusterDTOs = restTemplate.get(env, "apps/{appId}/clusters", ClusterDTO[].class, - appId); + appId); return Arrays.asList(clusterDTOs); } public ClusterDTO loadCluster(String appId, Env env, String clusterName) { return restTemplate.get(env, "apps/{appId}/clusters/{clusterName}", ClusterDTO.class, - appId, clusterName); + appId, clusterName); } public boolean isClusterUnique(String appId, Env env, String clusterName) { return restTemplate .get(env, "apps/{appId}/cluster/{clusterName}/unique", Boolean.class, - appId, clusterName); + appId, clusterName); } public ClusterDTO create(Env env, ClusterDTO cluster) { return restTemplate.post(env, "apps/{appId}/clusters", cluster, ClusterDTO.class, - cluster.getAppId()); + cluster.getAppId()); } @@ -225,7 +226,7 @@ public class AdminServiceAPI { } public List findAllReleases(String appId, Env env, String clusterName, String namespaceName, int page, - int size) { + int size) { ReleaseDTO[] releaseDTOs = restTemplate.get( env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/all?page={page}&size={size}", ReleaseDTO[].class, @@ -234,8 +235,8 @@ public class AdminServiceAPI { } public List findActiveReleases(String appId, Env env, String clusterName, String namespaceName, - int page, - int size) { + int page, + int size) { ReleaseDTO[] releaseDTOs = restTemplate.get( env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/active?page={page}&size={size}", ReleaseDTO[].class, @@ -244,16 +245,16 @@ public class AdminServiceAPI { } public ReleaseDTO loadLatestRelease(String appId, Env env, String clusterName, - String namespace) { + String namespace) { ReleaseDTO releaseDTO = restTemplate .get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest", - ReleaseDTO.class, appId, clusterName, namespace); + ReleaseDTO.class, appId, clusterName, namespace); return releaseDTO; } public ReleaseDTO createRelease(String appId, Env env, String clusterName, String namespace, - String releaseName, String releaseComment, String operator, - boolean isEmergencyPublish) { + String releaseName, String releaseComment, String operator, + boolean isEmergencyPublish) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8")); MultiValueMap parameters = new LinkedMultiValueMap<>(); @@ -270,22 +271,22 @@ public class AdminServiceAPI { } public ReleaseDTO updateAndPublish(String appId, Env env, String clusterName, String namespace, - String releaseName, String releaseComment, String branchName, - boolean isEmergencyPublish, boolean deleteBranch, ItemChangeSets changeSets) { + String releaseName, String releaseComment, String branchName, + boolean isEmergencyPublish, boolean deleteBranch, ItemChangeSets changeSets) { return restTemplate.post(env, - "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/updateAndPublish?" - + "releaseName={releaseName}&releaseComment={releaseComment}&branchName={branchName}" - + "&deleteBranch={deleteBranch}&isEmergencyPublish={isEmergencyPublish}", - changeSets, ReleaseDTO.class, appId, clusterName, namespace, - releaseName, releaseComment, branchName, deleteBranch, isEmergencyPublish); + "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/updateAndPublish?" + + "releaseName={releaseName}&releaseComment={releaseComment}&branchName={branchName}" + + "&deleteBranch={deleteBranch}&isEmergencyPublish={isEmergencyPublish}", + changeSets, ReleaseDTO.class, appId, clusterName, namespace, + releaseName, releaseComment, branchName, deleteBranch, isEmergencyPublish); } public void rollback(Env env, long releaseId, String operator) { restTemplate.put(env, - "releases/{releaseId}/rollback?operator={operator}", - null, releaseId, operator); + "releases/{releaseId}/rollback?operator={operator}", + null, releaseId, operator); } } @@ -295,9 +296,9 @@ public class AdminServiceAPI { public List find(String appId, Env env, String clusterName, String namespaceName, int page, int size) { CommitDTO[] commitDTOs = restTemplate.get(env, - "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/commit?page={page}&size={size}", - CommitDTO[].class, - appId, clusterName, namespaceName, page, size); + "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/commit?page={page}&size={size}", + CommitDTO[].class, + appId, clusterName, namespaceName, page, size); return Arrays.asList(commitDTOs); } @@ -308,8 +309,8 @@ public class AdminServiceAPI { public NamespaceLockDTO getNamespaceLockOwner(String appId, Env env, String clusterName, String namespaceName) { return restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock", - NamespaceLockDTO.class, - appId, clusterName, namespaceName); + NamespaceLockDTO.class, + appId, clusterName, namespaceName); } } @@ -328,33 +329,33 @@ public class AdminServiceAPI { entity = restTemplate .get(env, "/instances/by-release?releaseId={releaseId}&page={page}&size={size}", pageInstanceDtoType, - releaseId, page, size); + releaseId, page, size); return entity.getBody(); } public List getByReleasesNotIn(String appId, Env env, String clusterName, String namespaceName, - Set releaseIds) { + Set releaseIds) { InstanceDTO[] instanceDTOs = restTemplate.get(env, - "/instances/by-namespace-and-releases-not-in?appId={appId}&clusterName={clusterName}&namespaceName={namespaceName}&releaseIds={releaseIds}", - InstanceDTO[].class, appId, clusterName, namespaceName, joiner.join(releaseIds)); + "/instances/by-namespace-and-releases-not-in?appId={appId}&clusterName={clusterName}&namespaceName={namespaceName}&releaseIds={releaseIds}", + InstanceDTO[].class, appId, clusterName, namespaceName, joiner.join(releaseIds)); return Arrays.asList(instanceDTOs); } public PageDTO getByNamespace(String appId, Env env, String clusterName, String namespaceName, - String instanceAppId, - int page, int size) { + String instanceAppId, + int page, int size) { ResponseEntity> entity = restTemplate.get(env, - "/instances/by-namespace?appId={appId}" - + "&clusterName={clusterName}&namespaceName={namespaceName}&instanceAppId={instanceAppId}" - + "&page={page}&size={size}", - pageInstanceDtoType, appId, clusterName, namespaceName, instanceAppId, page, size); + "/instances/by-namespace?appId={appId}" + + "&clusterName={clusterName}&namespaceName={namespaceName}&instanceAppId={instanceAppId}" + + "&page={page}&size={size}", + pageInstanceDtoType, appId, clusterName, namespaceName, instanceAppId, page, size); return entity.getBody(); } @@ -362,8 +363,8 @@ public class AdminServiceAPI { Integer count = restTemplate.get(env, - "/instances/by-namespace/count?appId={appId}&clusterName={clusterName}&namespaceName={namespaceName}", - Integer.class, appId, clusterName, namespaceName); + "/instances/by-namespace/count?appId={appId}&clusterName={clusterName}&namespaceName={namespaceName}", + Integer.class, appId, clusterName, namespaceName); if (count == null) { return 0; } @@ -375,39 +376,39 @@ public class AdminServiceAPI { public static class NamespaceBranchAPI extends API { public NamespaceDTO createBranch(String appId, Env env, String clusterName, - String namespaceName, String operator) { + String namespaceName, String operator) { return restTemplate .post(env, "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches?operator={operator}", - null, NamespaceDTO.class, appId, clusterName, namespaceName, operator); + null, NamespaceDTO.class, appId, clusterName, namespaceName, operator); } public NamespaceDTO findBranch(String appId, Env env, String clusterName, - String namespaceName) { + String namespaceName) { return restTemplate.get(env, "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches", - NamespaceDTO.class, appId, clusterName, namespaceName); + NamespaceDTO.class, appId, clusterName, namespaceName); } public GrayReleaseRuleDTO findBranchGrayRules(String appId, Env env, String clusterName, - String namespaceName, String branchName) { + String namespaceName, String branchName) { return restTemplate .get(env, "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules", - GrayReleaseRuleDTO.class, appId, clusterName, namespaceName, branchName); + GrayReleaseRuleDTO.class, appId, clusterName, namespaceName, branchName); } public void updateBranchGrayRules(String appId, Env env, String clusterName, - String namespaceName, String branchName, GrayReleaseRuleDTO rules) { + String namespaceName, String branchName, GrayReleaseRuleDTO rules) { restTemplate .put(env, "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules", - rules, appId, clusterName, namespaceName, branchName); + rules, appId, clusterName, namespaceName, branchName); } public void deleteBranch(String appId, Env env, String clusterName, - String namespaceName, String branchName, String operator) { + String namespaceName, String branchName, String operator) { restTemplate.delete(env, - "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}?operator={operator}", - appId, clusterName, namespaceName, branchName, operator); + "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}?operator={operator}", + appId, clusterName, namespaceName, branchName, operator); } } @@ -420,24 +421,24 @@ public class AdminServiceAPI { public PageDTO findReleaseHistoriesByNamespace(String appId, Env env, String clusterName, - String namespaceName, int page, int size) { + String namespaceName, int page, int size) { return restTemplate.get(env, - "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/histories?page={page}&size={size}", - type, appId, clusterName, namespaceName, page, size).getBody(); + "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/histories?page={page}&size={size}", + type, appId, clusterName, namespaceName, page, size).getBody(); } public PageDTO findByReleaseIdAndOperation(Env env, long releaseId, int operation, int page, - int size) { + int size) { return restTemplate.get(env, - "/releases/histories/by_release_id_and_operation?releaseId={releaseId}&operation={operation}&page={page}&size={size}", - type, releaseId, operation, page, size).getBody(); + "/releases/histories/by_release_id_and_operation?releaseId={releaseId}&operation={operation}&page={page}&size={size}", + type, releaseId, operation, page, size).getBody(); } public PageDTO findByPreviousReleaseIdAndOperation(Env env, long previousReleaseId, - int operation, int page, int size) { + int operation, int page, int size) { return restTemplate.get(env, - "/releases/histories/by_previous_release_id_and_operation?previousReleaseId={releaseId}&operation={operation}&page={page}&size={size}", - type, previousReleaseId, operation, page, size).getBody(); + "/releases/histories/by_previous_release_id_and_operation?previousReleaseId={releaseId}&operation={operation}&page={page}&size={size}", + type, previousReleaseId, operation, page, size).getBody(); } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/AppController.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/AppController.java index a7080a0b26e914cf3cd0dd6a912e206036787409..a9f725ae4b14c958dd83c1645acf3015dc458b18 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/AppController.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/AppController.java @@ -1,8 +1,6 @@ package com.ctrip.framework.apollo.portal.controller; -import com.google.common.collect.Sets; - import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.http.MultiResponseEntity; @@ -14,12 +12,16 @@ import com.ctrip.framework.apollo.portal.component.PortalSettings; import com.ctrip.framework.apollo.portal.entity.model.AppModel; import com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo; import com.ctrip.framework.apollo.portal.listener.AppCreationEvent; +import com.ctrip.framework.apollo.portal.listener.AppDeletionEvent; import com.ctrip.framework.apollo.portal.listener.AppInfoChangedEvent; import com.ctrip.framework.apollo.portal.service.AppService; import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.util.RoleUtils; - +import com.google.common.collect.Sets; +import java.util.List; +import java.util.Objects; +import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Pageable; @@ -36,10 +38,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.HttpClientErrorException; -import java.util.List; -import java.util.Objects; -import java.util.Set; - @RestController @RequestMapping("/apps") @@ -82,8 +80,9 @@ public class AppController { Set admins = appModel.getAdmins(); if (!CollectionUtils.isEmpty(admins)) { - rolePermissionService.assignRoleToUsers(RoleUtils.buildAppMasterRoleName(createdApp.getAppId()), - admins, userInfoHolder.getUser().getUserId()); + rolePermissionService + .assignRoleToUsers(RoleUtils.buildAppMasterRoleName(createdApp.getAppId()), + admins, userInfoHolder.getUser().getUserId()); } return createdApp; @@ -113,8 +112,8 @@ public class AppController { response.addResponseEntity(RichResponseEntity.ok(appService.createEnvNavNode(env, appId))); } catch (Exception e) { response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR, - "load env:" + env.name() + " cluster error." + e - .getMessage())); + "load env:" + env.name() + " cluster error." + e + .getMessage())); } } return response; @@ -124,8 +123,9 @@ public class AppController { "application/json"}) public ResponseEntity create(@PathVariable String env, @RequestBody App app) { - RequestPrecondition.checkArgumentsNotEmpty(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName(), - app.getOrgId(), app.getOrgName()); + RequestPrecondition.checkArgumentsNotEmpty(app.getName(), app.getAppId(), app.getOwnerEmail(), + app.getOwnerName(), + app.getOrgId(), app.getOrgName()); if (!InputValidator.isValidClusterNamespace(app.getAppId())) { throw new BadRequestException(InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE); } @@ -141,6 +141,15 @@ public class AppController { return appService.load(appId); } + + @PreAuthorize(value = "@permissionValidator.isSuperAdmin()") + @RequestMapping(value = "/{appId:.+}", method = RequestMethod.DELETE) + public void deleteApp(@PathVariable String appId) { + App app = appService.deleteAppInLocal(appId); + + publisher.publishEvent(new AppDeletionEvent(app)); + } + @RequestMapping(value = "/{appId}/miss_envs", method = RequestMethod.GET) public MultiResponseEntity findMissEnvs(@PathVariable String appId) { @@ -154,9 +163,9 @@ public class AppController { response.addResponseEntity(RichResponseEntity.ok(env)); } else { response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR, - String.format("load appId:%s from env %s error.", appId, - env) - + e.getMessage())); + String.format("load appId:%s from env %s error.", appId, + env) + + e.getMessage())); } } } @@ -175,16 +184,17 @@ public class AppController { RequestPrecondition.checkArgumentsNotEmpty(appId, appName, ownerName, orgId, orgName); if (!InputValidator.isValidClusterNamespace(appModel.getAppId())) { - throw new BadRequestException(String.format("AppId格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE)); + throw new BadRequestException( + String.format("AppId格式错误: %s", InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE)); } return App.builder() - .appId(appId) - .name(appName) - .ownerName(ownerName) - .orgId(orgId) - .orgName(orgName) - .build(); + .appId(appId) + .name(appName) + .ownerName(ownerName) + .orgId(orgId) + .orgName(orgName) + .build(); } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppDeletionEvent.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppDeletionEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..3755fa0f96a297a6583a6c587f227aba9055ec63 --- /dev/null +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppDeletionEvent.java @@ -0,0 +1,17 @@ +package com.ctrip.framework.apollo.portal.listener; + +import com.ctrip.framework.apollo.common.entity.App; +import com.google.common.base.Preconditions; +import org.springframework.context.ApplicationEvent; + +public class AppDeletionEvent extends ApplicationEvent { + + public AppDeletionEvent(Object source) { + super(source); + } + + public App getApp() { + Preconditions.checkState(source != null); + return (App) this.source; + } +} diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedListener.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedListener.java index e45bb22ec64610aea5f1d2f628899e266899ddb1..8ef56cd19a90a691f4f5073fae95dd3abde2a178 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedListener.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/listener/AppInfoChangedListener.java @@ -5,6 +5,7 @@ import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.enums.Env; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.component.PortalSettings; +import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.tracer.Tracer; import org.slf4j.Logger; @@ -24,7 +25,6 @@ public class AppInfoChangedListener { @Autowired private PortalSettings portalSettings; - @EventListener public void onAppInfoChange(AppInfoChangedEvent event) { AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp()); @@ -39,7 +39,22 @@ public class AppInfoChangedListener { Tracer.logError(String.format("Update app's info failed. Env = %s, AppId = %s", env, appId), e); } } - } + @EventListener + public void onAppDelete(AppDeletionEvent event) { + AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp()); + String appId = appDTO.getAppId(); + String operator = appDTO.getDataChangeLastModifiedBy(); + + List envs = portalSettings.getActiveEnvs(); + for (Env env : envs) { + try { + appAPI.deleteApp(env, appId, operator); + } catch (Throwable e) { + logger.error("Delete app failed. Env = {}, AppId = {}", env, appId, e); + Tracer.logError(String.format("Delete app failed. Env = %s, AppId = %s", env, appId), e); + } + } + } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppNamespaceRepository.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppNamespaceRepository.java index 59b1780060c07eba49220b93ef84c670810d6ac2..4af7fa41934888857c1afc76ced35e844560b2ca 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppNamespaceRepository.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppNamespaceRepository.java @@ -1,10 +1,10 @@ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.common.entity.AppNamespace; - -import org.springframework.data.repository.PagingAndSortingRepository; - import java.util.List; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.PagingAndSortingRepository; public interface AppNamespaceRepository extends PagingAndSortingRepository { @@ -16,4 +16,7 @@ public interface AppNamespaceRepository extends PagingAndSortingRepository findByIsPublicTrue(); + @Modifying + @Query("UPDATE AppNamespace SET IsDeleted=1,DataChange_LastModifiedBy=?2 WHERE AppId=?1") + int batchDeleteByAppId(String appId, String operator); } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppRepository.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppRepository.java index ac095dd7f7b6ba0613c4ab78a83e958821358234..bc2a424e9e8b412acb4537d4dd3b06b14ecc9cab 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppRepository.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/AppRepository.java @@ -3,6 +3,8 @@ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.common.entity.App; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; @@ -17,4 +19,7 @@ public interface AppRepository extends PagingAndSortingRepository { List findByAppIdIn(Set appIds); + @Modifying + @Query("UPDATE App SET IsDeleted=1,DataChange_LastModifiedBy = ?2 WHERE AppId=?1") + int deleteApp(String appId, String operator); } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/FavoriteRepository.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/FavoriteRepository.java index c88b7adc584552af056b3e325e2faa6593177535..944e41ecffa8790d41b3ec4a7c4a4cc3bf4df179 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/FavoriteRepository.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/FavoriteRepository.java @@ -3,6 +3,8 @@ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.portal.entity.po.Favorite; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.List; @@ -16,4 +18,8 @@ public interface FavoriteRepository extends PagingAndSortingRepository findByPermissionTypeInAndTargetId(Collection permissionTypes, String targetId); + + @Query("SELECT p.id from Permission p where p.targetId = ?1 or p.targetId like CONCAT(?1, '+%'))") + List findPermissionIdsByAppId(String appId); + + @Modifying + @Query("UPDATE Permission SET IsDeleted=1, DataChange_LastModifiedBy = ?2 WHERE Id in ?1") + Integer batchDelete(List permissionIds, String operator); } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RolePermissionRepository.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RolePermissionRepository.java index 6734242a06e54dbb1bc229638cbb6d227e745193..de4bc2880030b52de76400446906b54f720323d2 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RolePermissionRepository.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RolePermissionRepository.java @@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.portal.entity.po.RolePermission; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.Collection; @@ -17,4 +19,7 @@ public interface RolePermissionRepository extends PagingAndSortingRepository findByRoleIdIn(Collection roleId); + @Modifying + @Query("UPDATE RolePermission SET IsDeleted=1, DataChange_LastModifiedBy = ?2 WHERE PermissionId in ?1") + Integer batchDeleteByPermissionIds(List permissionIds, String operator); } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RoleRepository.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RoleRepository.java index b203ae7b4d3a0ebfa3304e3d61550e3e590a8085..06120f0001b0921200917b1b01ef6e7fbed4da0f 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RoleRepository.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/RoleRepository.java @@ -1,15 +1,28 @@ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.portal.entity.po.Role; - +import java.util.List; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; /** * @author Jason Song(song_s@ctrip.com) */ public interface RoleRepository extends PagingAndSortingRepository { + /** * find role by role name */ Role findTopByRoleName(String roleName); + + @Query("SELECT r.id from Role r where (r.roleName = CONCAT('Master+', ?1) " + + "OR r.roleName like CONCAT('ModifyNamespace+', ?1, '+%') " + + "OR r.roleName like CONCAT('ReleaseNamespace+', ?1, '+%'))") + List findRoleIdsByAppId(String appId); + + @Modifying + @Query("UPDATE Role SET IsDeleted=1, DataChange_LastModifiedBy = ?2 WHERE Id in ?1") + Integer batchDelete(List roleIds, String operator); } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/UserRoleRepository.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/UserRoleRepository.java index a6d6d684c7b5a3260906182be7389a19ab006797..f7e3329dee5218b54632ab0d7f15219c505237c4 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/UserRoleRepository.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/repository/UserRoleRepository.java @@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.portal.repository; import com.ctrip.framework.apollo.portal.entity.po.UserRole; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import java.util.Collection; @@ -26,4 +28,8 @@ public interface UserRoleRepository extends PagingAndSortingRepository findByUserIdInAndRoleId(Collection userId, long roleId); + @Modifying + @Query("UPDATE UserRole SET IsDeleted=1, DataChange_LastModifiedBy = ?2 WHERE RoleId in ?1") + Integer batchDeleteByRoleIds(List roleIds, String operator); + } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppNamespaceService.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppNamespaceService.java index 62e21c8aae20a52187a9b2a3386cc1ed5e8715d7..ceab80c8334543117516a3ed9b429281f804c2be 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppNamespaceService.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppNamespaceService.java @@ -118,4 +118,7 @@ public class AppNamespaceService { return createdAppNamespace; } + public void batchDeleteByAppId(String appId, String operator) { + appNamespaceRepository.batchDeleteByAppId(appId, operator); + } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java index 15d5316e6b8ae47d51dd1065f415575cdc003e56..21d58ad6d4cb773c0efae0b60b22e7a35a9ff306 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java @@ -41,6 +41,10 @@ public class AppService { @Autowired private RoleInitializationService roleInitializationService; @Autowired + private RolePermissionService rolePermissionService; + @Autowired + private FavoriteService favoriteService; + @Autowired private UserService userService; @@ -139,4 +143,29 @@ public class AppService { return node; } + @Transactional + public App deleteAppInLocal(String appId) { + App managedApp = appRepository.findByAppId(appId); + if (managedApp == null) { + throw new BadRequestException(String.format("App not exists. AppId = %s", appId)); + } + String operator = userInfoHolder.getUser().getUserId(); + + //this operator is passed to com.ctrip.framework.apollo.portal.listener.AppInfoChangedListener.onAppDelete + managedApp.setDataChangeLastModifiedBy(operator); + + //删除portal数据库中的app + appRepository.deleteApp(appId, operator); + + //删除portal数据库中的appNamespace + appNamespaceService.batchDeleteByAppId(appId, operator); + + //删除portal数据库中的收藏表 + favoriteService.batchDeleteByAppId(appId, operator); + + //删除portal数据库中Permission、Role相关数据 + rolePermissionService.deleteRolePermissionsByAppId(appId, operator); + + return managedApp; + } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/FavoriteService.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/FavoriteService.java index 7597bf7463062b3cac8e008813dfec20c6710129..ed27daa54e2567f6e23288edda178e8e4541ca53 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/FavoriteService.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/FavoriteService.java @@ -1,21 +1,19 @@ package com.ctrip.framework.apollo.portal.service; import com.ctrip.framework.apollo.common.exception.BadRequestException; -import com.ctrip.framework.apollo.portal.entity.po.Favorite; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; +import com.ctrip.framework.apollo.portal.entity.po.Favorite; import com.ctrip.framework.apollo.portal.repository.FavoriteRepository; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.spi.UserService; - +import java.util.Arrays; +import java.util.List; +import java.util.Objects; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - @Service public class FavoriteService { @@ -110,4 +108,7 @@ public class FavoriteService { } } + public void batchDeleteByAppId(String appId, String operator) { + favoriteRepository.batchDeleteByAppId(appId, operator); + } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/RolePermissionService.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/RolePermissionService.java index e9ca345a1c123dc7637bd6acebbaf867e228eea6..1fc872737cd4192eecf8afa18a8d69c9fa981ef1 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/RolePermissionService.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/RolePermissionService.java @@ -56,4 +56,8 @@ public interface RolePermissionService { */ public Set createPermissions(Set permissions); + /** + * delete permissions when delete app. + */ + public void deleteRolePermissionsByAppId(String appId, String operator); } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultRolePermissionService.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultRolePermissionService.java index f4dd42a84b23b293d8d3fc9b25f370718684b2f3..9af31fd8dc1117f71e0688424b36eba7955cd812 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultRolePermissionService.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/spi/defaultimpl/DefaultRolePermissionService.java @@ -1,5 +1,7 @@ package com.ctrip.framework.apollo.portal.spi.defaultimpl; +import com.ctrip.framework.apollo.common.entity.BaseEntity; +import com.ctrip.framework.apollo.openapi.repository.ConsumerRoleRepository; import com.ctrip.framework.apollo.portal.component.config.PortalConfig; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.entity.po.Permission; @@ -16,6 +18,8 @@ import com.google.common.collect.FluentIterable; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; +import java.util.function.Function; +import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -36,7 +40,8 @@ public class DefaultRolePermissionService implements RolePermissionService { private PermissionRepository permissionRepository; @Autowired private PortalConfig portalConfig; - + @Autowired + private ConsumerRoleRepository consumerRoleRepository; /** * Create role with permissions, note that role name should be unique @@ -220,4 +225,30 @@ public class DefaultRolePermissionService implements RolePermissionService { return FluentIterable.from(results).toSet(); } + @Transactional + @Override + public void deleteRolePermissionsByAppId(String appId, String operator) { + List permissionIds = permissionRepository.findPermissionIdsByAppId(appId); + + if (!permissionIds.isEmpty()) { + // 1. delete Permission + permissionRepository.batchDelete(permissionIds, operator); + + // 2. delete Role Permission + rolePermissionRepository.batchDeleteByPermissionIds(permissionIds, operator); + } + + List roleIds = roleRepository.findRoleIdsByAppId(appId); + + if (!roleIds.isEmpty()) { + // 3. delete Role + roleRepository.batchDelete(roleIds, operator); + + // 4. delete User Role + userRoleRepository.batchDeleteByRoleIds(roleIds, operator); + + // 5. delete Consumer Role + consumerRoleRepository.batchDeleteByRoleIds(roleIds, operator); + } + } }