未验证 提交 d23e60e1 编写于 作者: J Jason Song 提交者: GitHub

Merge pull request #1276 from nobodyiam/delete-app-api

add delete app api
...@@ -54,7 +54,7 @@ public class AppController { ...@@ -54,7 +54,7 @@ public class AppController {
if (entity == null) { if (entity == null) {
throw new NotFoundException("app not found for appId " + appId); 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) @RequestMapping(value = "/apps/{appId:.+}", method = RequestMethod.PUT)
...@@ -91,5 +91,4 @@ public class AppController { ...@@ -91,5 +91,4 @@ public class AppController {
public boolean isAppIdUnique(@PathVariable("appId") String appId) { public boolean isAppIdUnique(@PathVariable("appId") String appId) {
return appService.isAppIdUnique(appId); return appService.isAppIdUnique(appId);
} }
} }
...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.biz.repository; ...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.biz.repository;
import com.ctrip.framework.apollo.common.entity.AppNamespace; 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 org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List; import java.util.List;
...@@ -24,4 +26,7 @@ public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNa ...@@ -24,4 +26,7 @@ public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNa
List<AppNamespace> findFirst500ByIdGreaterThanOrderByIdAsc(long id); List<AppNamespace> findFirst500ByIdGreaterThanOrderByIdAsc(long id);
@Modifying
@Query("UPDATE AppNamespace SET IsDeleted=1,DataChange_LastModifiedBy = ?2 WHERE AppId=?1")
int batchDeleteByAppId(String appId, String operator);
} }
...@@ -14,5 +14,4 @@ public interface AppRepository extends PagingAndSortingRepository<App, Long> { ...@@ -14,5 +14,4 @@ public interface AppRepository extends PagingAndSortingRepository<App, Long> {
List<App> findByName(@Param("name") String name); List<App> findByName(@Param("name") String name);
App findByAppId(String appId); App findByAppId(String appId);
} }
...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.biz.repository; ...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.biz.repository;
import com.ctrip.framework.apollo.biz.entity.GrayReleaseRule; 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 org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List; import java.util.List;
...@@ -17,4 +19,7 @@ public interface GrayReleaseRuleRepository extends PagingAndSortingRepository<Gr ...@@ -17,4 +19,7 @@ public interface GrayReleaseRuleRepository extends PagingAndSortingRepository<Gr
List<GrayReleaseRule> findFirst500ByIdGreaterThanOrderByIdAsc(Long id); List<GrayReleaseRule> 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);
} }
package com.ctrip.framework.apollo.biz.service; 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.entity.App;
import com.ctrip.framework.apollo.common.exception.NotFoundException;
import com.ctrip.framework.apollo.core.ConfigConsts; 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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Objects;
@Service @Service
public class AdminService { public class AdminService {
...@@ -19,6 +26,8 @@ public class AdminService { ...@@ -19,6 +26,8 @@ public class AdminService {
@Autowired @Autowired
private NamespaceService namespaceService; private NamespaceService namespaceService;
private final static Logger logger = LoggerFactory.getLogger(AdminService.class);
@Transactional @Transactional
public App createNewApp(App app) { public App createNewApp(App app) {
String createBy = app.getDataChangeCreatedBy(); String createBy = app.getDataChangeCreatedBy();
...@@ -35,5 +44,25 @@ public class AdminService { ...@@ -35,5 +44,25 @@ public class AdminService {
return app; return app;
} }
@Transactional
public void deleteApp(App app, String operator) {
String appId = app.getAppId();
logger.info("{} is deleting App:{}", operator, appId);
List<Cluster> 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);
}
} }
...@@ -137,4 +137,9 @@ public class AppNamespaceService { ...@@ -137,4 +137,9 @@ public class AppNamespaceService {
namespaceService.save(namespace); namespaceService.save(namespace);
} }
} }
@Transactional
public void batchDelete(String appId, String operator) {
appNamespaceRepository.batchDeleteByAppId(appId, operator);
}
} }
...@@ -137,4 +137,7 @@ public class ClusterService { ...@@ -137,4 +137,7 @@ public class ClusterService {
return clusterRepository.findByParentClusterId(parentCluster.getId()); return clusterRepository.findByParentClusterId(parentCluster.getId());
} }
public List<Cluster> findClusters(String appId) {
return clusterRepository.findByAppId(appId);
}
} }
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);
}
}
...@@ -59,6 +59,8 @@ public class NamespaceService { ...@@ -59,6 +59,8 @@ public class NamespaceService {
@Autowired @Autowired
private ReleaseHistoryService releaseHistoryService; private ReleaseHistoryService releaseHistoryService;
@Autowired @Autowired
private GrayReleaseRuleService grayReleaseRuleService;
@Autowired
private NamespaceLockService namespaceLockService; private NamespaceLockService namespaceLockService;
@Autowired @Autowired
private InstanceService instanceService; private InstanceService instanceService;
...@@ -263,17 +265,18 @@ public class NamespaceService { ...@@ -263,17 +265,18 @@ public class NamespaceService {
itemService.batchDelete(namespace.getId(), operator); itemService.batchDelete(namespace.getId(), operator);
commitService.batchDelete(appId, clusterName, namespace.getNamespaceName(), 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 if (!isChildNamespace(namespace)) {
Namespace childNamespace = findChildNamespace(namespace); //delete child namespace
if (childNamespace != null) { Namespace childNamespace = findChildNamespace(namespace);
namespaceBranchService.deleteBranch(appId, clusterName, namespaceName, if (childNamespace != null) {
childNamespace.getClusterName(), NamespaceBranchStatus.DELETED, operator); namespaceBranchService.deleteBranch(appId, clusterName, namespaceName,
//delete child namespace's releases. Notice: delete child namespace will not delete child namespace's releases childNamespace.getClusterName(), NamespaceBranchStatus.DELETED, operator);
releaseService.batchDelete(appId, childNamespace.getClusterName(), namespaceName, 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); releaseHistoryService.batchDelete(appId, clusterName, namespaceName, operator);
...@@ -394,6 +397,4 @@ public class NamespaceService { ...@@ -394,6 +397,4 @@ public class NamespaceService {
return false; return false;
} }
} }
...@@ -8,15 +8,13 @@ import com.ctrip.framework.apollo.biz.repository.AppRepository; ...@@ -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.entity.App;
import com.ctrip.framework.apollo.common.exception.ServiceException; import com.ctrip.framework.apollo.common.exception.ServiceException;
import com.ctrip.framework.apollo.core.ConfigConsts; import com.ctrip.framework.apollo.core.ConfigConsts;
import java.util.Date;
import java.util.List;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date; public class AdminServiceTest extends AbstractIntegrationTest {
import java.util.List;
public class AdminServiceTest extends AbstractIntegrationTest{
@Autowired @Autowired
private AdminService adminService; private AdminService adminService;
...@@ -33,6 +31,9 @@ public class AdminServiceTest extends AbstractIntegrationTest{ ...@@ -33,6 +31,9 @@ public class AdminServiceTest extends AbstractIntegrationTest{
@Autowired @Autowired
private NamespaceService namespaceService; private NamespaceService namespaceService;
@Autowired
private AppNamespaceService appNamespaceService;
@Test @Test
public void testCreateNewApp() { public void testCreateNewApp() {
String appId = "someAppId"; String appId = "someAppId";
...@@ -79,4 +80,37 @@ public class AdminServiceTest extends AbstractIntegrationTest{ ...@@ -79,4 +80,37 @@ public class AdminServiceTest extends AbstractIntegrationTest{
adminService.createNewApp(app); 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());
}
} }
...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.openapi.repository; ...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.openapi.repository;
import com.ctrip.framework.apollo.openapi.entity.ConsumerRole; 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 org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List; import java.util.List;
...@@ -23,4 +25,8 @@ public interface ConsumerRoleRepository extends PagingAndSortingRepository<Consu ...@@ -23,4 +25,8 @@ public interface ConsumerRoleRepository extends PagingAndSortingRepository<Consu
List<ConsumerRole> findByRoleId(long roleId); List<ConsumerRole> findByRoleId(long roleId);
ConsumerRole findByConsumerIdAndRoleId(long consumerId, 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<Long> roleIds, String operator);
} }
package com.ctrip.framework.apollo.portal.controller; 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.entity.App;
import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.BadRequestException;
import com.ctrip.framework.apollo.common.http.MultiResponseEntity; import com.ctrip.framework.apollo.common.http.MultiResponseEntity;
...@@ -14,12 +12,16 @@ import com.ctrip.framework.apollo.portal.component.PortalSettings; ...@@ -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.model.AppModel;
import com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo; import com.ctrip.framework.apollo.portal.entity.vo.EnvClusterInfo;
import com.ctrip.framework.apollo.portal.listener.AppCreationEvent; 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.listener.AppInfoChangedEvent;
import com.ctrip.framework.apollo.portal.service.AppService; import com.ctrip.framework.apollo.portal.service.AppService;
import com.ctrip.framework.apollo.portal.service.RolePermissionService; import com.ctrip.framework.apollo.portal.service.RolePermissionService;
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
import com.ctrip.framework.apollo.portal.util.RoleUtils; 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.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
...@@ -36,10 +38,6 @@ import org.springframework.web.bind.annotation.RequestParam; ...@@ -36,10 +38,6 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@RestController @RestController
@RequestMapping("/apps") @RequestMapping("/apps")
...@@ -82,8 +80,9 @@ public class AppController { ...@@ -82,8 +80,9 @@ public class AppController {
Set<String> admins = appModel.getAdmins(); Set<String> admins = appModel.getAdmins();
if (!CollectionUtils.isEmpty(admins)) { if (!CollectionUtils.isEmpty(admins)) {
rolePermissionService.assignRoleToUsers(RoleUtils.buildAppMasterRoleName(createdApp.getAppId()), rolePermissionService
admins, userInfoHolder.getUser().getUserId()); .assignRoleToUsers(RoleUtils.buildAppMasterRoleName(createdApp.getAppId()),
admins, userInfoHolder.getUser().getUserId());
} }
return createdApp; return createdApp;
...@@ -113,8 +112,8 @@ public class AppController { ...@@ -113,8 +112,8 @@ public class AppController {
response.addResponseEntity(RichResponseEntity.ok(appService.createEnvNavNode(env, appId))); response.addResponseEntity(RichResponseEntity.ok(appService.createEnvNavNode(env, appId)));
} catch (Exception e) { } catch (Exception e) {
response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR, response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR,
"load env:" + env.name() + " cluster error." + e "load env:" + env.name() + " cluster error." + e
.getMessage())); .getMessage()));
} }
} }
return response; return response;
...@@ -124,8 +123,9 @@ public class AppController { ...@@ -124,8 +123,9 @@ public class AppController {
"application/json"}) "application/json"})
public ResponseEntity<Void> create(@PathVariable String env, @RequestBody App app) { public ResponseEntity<Void> create(@PathVariable String env, @RequestBody App app) {
RequestPrecondition.checkArgumentsNotEmpty(app.getName(), app.getAppId(), app.getOwnerEmail(), app.getOwnerName(), RequestPrecondition.checkArgumentsNotEmpty(app.getName(), app.getAppId(), app.getOwnerEmail(),
app.getOrgId(), app.getOrgName()); app.getOwnerName(),
app.getOrgId(), app.getOrgName());
if (!InputValidator.isValidClusterNamespace(app.getAppId())) { if (!InputValidator.isValidClusterNamespace(app.getAppId())) {
throw new BadRequestException(InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE); throw new BadRequestException(InputValidator.INVALID_CLUSTER_NAMESPACE_MESSAGE);
} }
...@@ -141,6 +141,15 @@ public class AppController { ...@@ -141,6 +141,15 @@ public class AppController {
return appService.load(appId); 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) @RequestMapping(value = "/{appId}/miss_envs", method = RequestMethod.GET)
public MultiResponseEntity<Env> findMissEnvs(@PathVariable String appId) { public MultiResponseEntity<Env> findMissEnvs(@PathVariable String appId) {
...@@ -154,9 +163,9 @@ public class AppController { ...@@ -154,9 +163,9 @@ public class AppController {
response.addResponseEntity(RichResponseEntity.ok(env)); response.addResponseEntity(RichResponseEntity.ok(env));
} else { } else {
response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR, response.addResponseEntity(RichResponseEntity.error(HttpStatus.INTERNAL_SERVER_ERROR,
String.format("load appId:%s from env %s error.", appId, String.format("load appId:%s from env %s error.", appId,
env) env)
+ e.getMessage())); + e.getMessage()));
} }
} }
} }
...@@ -175,16 +184,17 @@ public class AppController { ...@@ -175,16 +184,17 @@ public class AppController {
RequestPrecondition.checkArgumentsNotEmpty(appId, appName, ownerName, orgId, orgName); RequestPrecondition.checkArgumentsNotEmpty(appId, appName, ownerName, orgId, orgName);
if (!InputValidator.isValidClusterNamespace(appModel.getAppId())) { 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() return App.builder()
.appId(appId) .appId(appId)
.name(appName) .name(appName)
.ownerName(ownerName) .ownerName(ownerName)
.orgId(orgId) .orgId(orgId)
.orgName(orgName) .orgName(orgName)
.build(); .build();
} }
} }
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;
}
}
...@@ -5,6 +5,7 @@ import com.ctrip.framework.apollo.common.utils.BeanUtils; ...@@ -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.core.enums.Env;
import com.ctrip.framework.apollo.portal.api.AdminServiceAPI; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI;
import com.ctrip.framework.apollo.portal.component.PortalSettings; import com.ctrip.framework.apollo.portal.component.PortalSettings;
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
import com.ctrip.framework.apollo.tracer.Tracer; import com.ctrip.framework.apollo.tracer.Tracer;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -24,7 +25,6 @@ public class AppInfoChangedListener { ...@@ -24,7 +25,6 @@ public class AppInfoChangedListener {
@Autowired @Autowired
private PortalSettings portalSettings; private PortalSettings portalSettings;
@EventListener @EventListener
public void onAppInfoChange(AppInfoChangedEvent event) { public void onAppInfoChange(AppInfoChangedEvent event) {
AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp()); AppDTO appDTO = BeanUtils.transfrom(AppDTO.class, event.getApp());
...@@ -39,7 +39,22 @@ public class AppInfoChangedListener { ...@@ -39,7 +39,22 @@ public class AppInfoChangedListener {
Tracer.logError(String.format("Update app's info failed. Env = %s, AppId = %s", env, appId), e); 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<Env> 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);
}
}
}
} }
package com.ctrip.framework.apollo.portal.repository; package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.common.entity.AppNamespace; import com.ctrip.framework.apollo.common.entity.AppNamespace;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List; 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<AppNamespace, Long> { public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNamespace, Long> {
...@@ -16,4 +16,7 @@ public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNa ...@@ -16,4 +16,7 @@ public interface AppNamespaceRepository extends PagingAndSortingRepository<AppNa
List<AppNamespace> findByIsPublicTrue(); List<AppNamespace> findByIsPublicTrue();
@Modifying
@Query("UPDATE AppNamespace SET IsDeleted=1,DataChange_LastModifiedBy=?2 WHERE AppId=?1")
int batchDeleteByAppId(String appId, String operator);
} }
...@@ -3,6 +3,8 @@ package com.ctrip.framework.apollo.portal.repository; ...@@ -3,6 +3,8 @@ package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.common.entity.App; import com.ctrip.framework.apollo.common.entity.App;
import org.springframework.data.domain.Pageable; 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 org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List; import java.util.List;
...@@ -17,4 +19,7 @@ public interface AppRepository extends PagingAndSortingRepository<App, Long> { ...@@ -17,4 +19,7 @@ public interface AppRepository extends PagingAndSortingRepository<App, Long> {
List<App> findByAppIdIn(Set<String> appIds); List<App> findByAppIdIn(Set<String> appIds);
@Modifying
@Query("UPDATE App SET IsDeleted=1,DataChange_LastModifiedBy = ?2 WHERE AppId=?1")
int deleteApp(String appId, String operator);
} }
...@@ -3,6 +3,8 @@ package com.ctrip.framework.apollo.portal.repository; ...@@ -3,6 +3,8 @@ package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.portal.entity.po.Favorite; import com.ctrip.framework.apollo.portal.entity.po.Favorite;
import org.springframework.data.domain.Pageable; 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 org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List; import java.util.List;
...@@ -16,4 +18,8 @@ public interface FavoriteRepository extends PagingAndSortingRepository<Favorite, ...@@ -16,4 +18,8 @@ public interface FavoriteRepository extends PagingAndSortingRepository<Favorite,
Favorite findFirstByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(String userId); Favorite findFirstByUserIdOrderByPositionAscDataChangeCreatedTimeAsc(String userId);
Favorite findByUserIdAndAppId(String userId, String appId); Favorite findByUserIdAndAppId(String userId, String appId);
@Modifying
@Query("UPDATE Favorite SET IsDeleted=1,DataChange_LastModifiedBy = ?2 WHERE AppId=?1")
int batchDeleteByAppId(String appId, String operator);
} }
...@@ -2,10 +2,13 @@ package com.ctrip.framework.apollo.portal.repository; ...@@ -2,10 +2,13 @@ package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.portal.entity.po.Permission; import com.ctrip.framework.apollo.portal.entity.po.Permission;
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.PagingAndSortingRepository;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.springframework.data.repository.query.Param;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
...@@ -21,4 +24,11 @@ public interface PermissionRepository extends PagingAndSortingRepository<Permiss ...@@ -21,4 +24,11 @@ public interface PermissionRepository extends PagingAndSortingRepository<Permiss
*/ */
List<Permission> findByPermissionTypeInAndTargetId(Collection<String> permissionTypes, List<Permission> findByPermissionTypeInAndTargetId(Collection<String> permissionTypes,
String targetId); String targetId);
@Query("SELECT p.id from Permission p where p.targetId = ?1 or p.targetId like CONCAT(?1, '+%'))")
List<Long> findPermissionIdsByAppId(String appId);
@Modifying
@Query("UPDATE Permission SET IsDeleted=1, DataChange_LastModifiedBy = ?2 WHERE Id in ?1")
Integer batchDelete(List<Long> permissionIds, String operator);
} }
...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.portal.repository; ...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.portal.entity.po.RolePermission; 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 org.springframework.data.repository.PagingAndSortingRepository;
import java.util.Collection; import java.util.Collection;
...@@ -17,4 +19,7 @@ public interface RolePermissionRepository extends PagingAndSortingRepository<Rol ...@@ -17,4 +19,7 @@ public interface RolePermissionRepository extends PagingAndSortingRepository<Rol
*/ */
List<RolePermission> findByRoleIdIn(Collection<Long> roleId); List<RolePermission> findByRoleIdIn(Collection<Long> roleId);
@Modifying
@Query("UPDATE RolePermission SET IsDeleted=1, DataChange_LastModifiedBy = ?2 WHERE PermissionId in ?1")
Integer batchDeleteByPermissionIds(List<Long> permissionIds, String operator);
} }
package com.ctrip.framework.apollo.portal.repository; package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.portal.entity.po.Role; 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.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public interface RoleRepository extends PagingAndSortingRepository<Role, Long> { public interface RoleRepository extends PagingAndSortingRepository<Role, Long> {
/** /**
* find role by role name * find role by role name
*/ */
Role findTopByRoleName(String roleName); 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<Long> findRoleIdsByAppId(String appId);
@Modifying
@Query("UPDATE Role SET IsDeleted=1, DataChange_LastModifiedBy = ?2 WHERE Id in ?1")
Integer batchDelete(List<Long> roleIds, String operator);
} }
...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.portal.repository; ...@@ -2,6 +2,8 @@ package com.ctrip.framework.apollo.portal.repository;
import com.ctrip.framework.apollo.portal.entity.po.UserRole; 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 org.springframework.data.repository.PagingAndSortingRepository;
import java.util.Collection; import java.util.Collection;
...@@ -26,4 +28,8 @@ public interface UserRoleRepository extends PagingAndSortingRepository<UserRole, ...@@ -26,4 +28,8 @@ public interface UserRoleRepository extends PagingAndSortingRepository<UserRole,
*/ */
List<UserRole> findByUserIdInAndRoleId(Collection<String> userId, long roleId); List<UserRole> findByUserIdInAndRoleId(Collection<String> userId, long roleId);
@Modifying
@Query("UPDATE UserRole SET IsDeleted=1, DataChange_LastModifiedBy = ?2 WHERE RoleId in ?1")
Integer batchDeleteByRoleIds(List<Long> roleIds, String operator);
} }
...@@ -118,4 +118,7 @@ public class AppNamespaceService { ...@@ -118,4 +118,7 @@ public class AppNamespaceService {
return createdAppNamespace; return createdAppNamespace;
} }
public void batchDeleteByAppId(String appId, String operator) {
appNamespaceRepository.batchDeleteByAppId(appId, operator);
}
} }
...@@ -41,6 +41,10 @@ public class AppService { ...@@ -41,6 +41,10 @@ public class AppService {
@Autowired @Autowired
private RoleInitializationService roleInitializationService; private RoleInitializationService roleInitializationService;
@Autowired @Autowired
private RolePermissionService rolePermissionService;
@Autowired
private FavoriteService favoriteService;
@Autowired
private UserService userService; private UserService userService;
...@@ -139,4 +143,29 @@ public class AppService { ...@@ -139,4 +143,29 @@ public class AppService {
return node; 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;
}
} }
package com.ctrip.framework.apollo.portal.service; package com.ctrip.framework.apollo.portal.service;
import com.ctrip.framework.apollo.common.exception.BadRequestException; 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.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.repository.FavoriteRepository;
import com.ctrip.framework.apollo.portal.spi.UserInfoHolder; import com.ctrip.framework.apollo.portal.spi.UserInfoHolder;
import com.ctrip.framework.apollo.portal.spi.UserService; 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.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@Service @Service
public class FavoriteService { public class FavoriteService {
...@@ -110,4 +108,7 @@ public class FavoriteService { ...@@ -110,4 +108,7 @@ public class FavoriteService {
} }
} }
public void batchDeleteByAppId(String appId, String operator) {
favoriteRepository.batchDeleteByAppId(appId, operator);
}
} }
...@@ -56,4 +56,8 @@ public interface RolePermissionService { ...@@ -56,4 +56,8 @@ public interface RolePermissionService {
*/ */
public Set<Permission> createPermissions(Set<Permission> permissions); public Set<Permission> createPermissions(Set<Permission> permissions);
/**
* delete permissions when delete app.
*/
public void deleteRolePermissionsByAppId(String appId, String operator);
} }
package com.ctrip.framework.apollo.portal.spi.defaultimpl; 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.component.config.PortalConfig;
import com.ctrip.framework.apollo.portal.entity.bo.UserInfo; import com.ctrip.framework.apollo.portal.entity.bo.UserInfo;
import com.ctrip.framework.apollo.portal.entity.po.Permission; import com.ctrip.framework.apollo.portal.entity.po.Permission;
...@@ -16,6 +18,8 @@ import com.google.common.collect.FluentIterable; ...@@ -16,6 +18,8 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.Sets; 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.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
...@@ -36,7 +40,8 @@ public class DefaultRolePermissionService implements RolePermissionService { ...@@ -36,7 +40,8 @@ public class DefaultRolePermissionService implements RolePermissionService {
private PermissionRepository permissionRepository; private PermissionRepository permissionRepository;
@Autowired @Autowired
private PortalConfig portalConfig; private PortalConfig portalConfig;
@Autowired
private ConsumerRoleRepository consumerRoleRepository;
/** /**
* Create role with permissions, note that role name should be unique * Create role with permissions, note that role name should be unique
...@@ -220,4 +225,30 @@ public class DefaultRolePermissionService implements RolePermissionService { ...@@ -220,4 +225,30 @@ public class DefaultRolePermissionService implements RolePermissionService {
return FluentIterable.from(results).toSet(); return FluentIterable.from(results).toSet();
} }
@Transactional
@Override
public void deleteRolePermissionsByAppId(String appId, String operator) {
List<Long> permissionIds = permissionRepository.findPermissionIdsByAppId(appId);
if (!permissionIds.isEmpty()) {
// 1. delete Permission
permissionRepository.batchDelete(permissionIds, operator);
// 2. delete Role Permission
rolePermissionRepository.batchDeleteByPermissionIds(permissionIds, operator);
}
List<Long> 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);
}
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册