refactor(系统设置): 服务集成添加插件权限校验

--bug=1029851 --user=陈建星 系统设置-系统-插件管理-禁用插件 https://www.tapd.cn/55049933/s/1411154
This commit is contained in:
AgAngle 2023-09-01 14:55:32 +08:00 committed by fit2-zhao
parent c1108b48db
commit 12505ffbfd
6 changed files with 181 additions and 54 deletions

View File

@ -0,0 +1,37 @@
package io.metersphere.sdk.service;
import io.metersphere.system.domain.PluginOrganization;
import io.metersphere.system.domain.PluginOrganizationExample;
import io.metersphere.system.mapper.PluginOrganizationMapper;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@Service
@Transactional(rollbackFor = Exception.class)
public class BasePluginOrganizationService {
@Resource
private PluginOrganizationMapper pluginOrganizationMapper;
public List<PluginOrganization> getByPluginIds(List<String> pluginIds) {
PluginOrganizationExample example = new PluginOrganizationExample();
example.createCriteria().andPluginIdIn(pluginIds);
return pluginOrganizationMapper.selectByExample(example);
}
public List<PluginOrganization> getByPluginIdAndOrgId(String pluginId, String orgId) {
if (StringUtils.isBlank(orgId)) {
return new ArrayList<>(0);
}
PluginOrganizationExample example = new PluginOrganizationExample();
example.createCriteria()
.andPluginIdEqualTo(pluginId)
.andOrganizationIdEqualTo(orgId);
return pluginOrganizationMapper.selectByExample(example);
}
}

View File

@ -0,0 +1,34 @@
package io.metersphere.sdk.service;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.system.domain.Plugin;
import io.metersphere.system.mapper.PluginMapper;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import static io.metersphere.sdk.controller.handler.result.CommonResultCode.PLUGIN_ENABLE;
import static io.metersphere.sdk.controller.handler.result.CommonResultCode.PLUGIN_PERMISSION;
/**
* @author jianxing
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class BasePluginService {
@Resource
private PluginMapper pluginMapper;
@Resource
private BasePluginOrganizationService basePluginOrganizationService;
public void checkPluginEnableAndPermission(String pluginId, String orgId) {
Plugin plugin = pluginMapper.selectByPrimaryKey(pluginId);
if (!plugin.getEnable()) {
throw new MSException(PLUGIN_ENABLE);
}
if (!plugin.getGlobal() && CollectionUtils.isEmpty(basePluginOrganizationService.getByPluginIdAndOrgId(pluginId, orgId))) {
throw new MSException(PLUGIN_PERMISSION);
}
}
}

View File

@ -3,21 +3,18 @@ package io.metersphere.sdk.service;
import io.metersphere.plugin.platform.api.Platform;
import io.metersphere.plugin.platform.dto.PlatformRequest;
import io.metersphere.sdk.constants.PluginScenarioType;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.system.domain.*;
import io.metersphere.system.mapper.PluginMapper;
import io.metersphere.system.mapper.PluginOrganizationMapper;
import io.metersphere.system.mapper.ServiceIntegrationMapper;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import static io.metersphere.sdk.controller.handler.result.CommonResultCode.PLUGIN_ENABLE;
import static io.metersphere.sdk.controller.handler.result.CommonResultCode.PLUGIN_PERMISSION;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
@ -30,7 +27,9 @@ public class PlatformPluginService {
@Resource
private PluginMapper pluginMapper;
@Resource
private PluginOrganizationMapper pluginOrganizationMapper;
private BasePluginOrganizationService basePluginOrganizationService;
@Resource
private BasePluginService basePluginService;
/**
* 获取平台实例
@ -41,12 +40,7 @@ public class PlatformPluginService {
* @return
*/
public Platform getPlatform(String pluginId, String orgId, String integrationConfig) {
if (StringUtils.isNotBlank(orgId)) {
// 服务集成的测试链接不需要校验插件开启和状态
Plugin plugin = pluginMapper.selectByPrimaryKey(pluginId);
checkPluginEnable(plugin);
checkPluginPermission(pluginId, orgId, plugin);
}
basePluginService.checkPluginEnableAndPermission(pluginId, orgId);
PlatformRequest pluginRequest = new PlatformRequest();
pluginRequest.setIntegrationConfig(integrationConfig);
pluginRequest.setOrganizationId(orgId);
@ -60,49 +54,34 @@ public class PlatformPluginService {
return getPlatform(pluginId, orgId, new String(serviceIntegration.getConfiguration()));
}
/**
* 校验该组织是否能访问插件
* @param pluginId
* @param orgId
* @param plugin
*/
private void checkPluginPermission(String pluginId, String orgId, Plugin plugin) {
if (plugin.getGlobal()) {
return;
}
PluginOrganizationExample example = new PluginOrganizationExample();
example.createCriteria()
.andOrganizationIdEqualTo(orgId)
.andPluginIdEqualTo(pluginId);
List<PluginOrganization> pluginOrganizations = pluginOrganizationMapper.selectByExample(example);
for (PluginOrganization pluginOrganization : pluginOrganizations) {
if (StringUtils.equals(pluginOrganization.getOrganizationId(), orgId)) {
return;
}
}
throw new MSException(PLUGIN_PERMISSION);
}
/**
* 校验插件是否启用
* @param plugin
*/
private static void checkPluginEnable(Plugin plugin) {
if (BooleanUtils.isFalse(plugin.getEnable())) {
throw new MSException(PLUGIN_ENABLE);
}
}
private ServiceIntegration getServiceIntegrationByPluginId(String pluginId) {
ServiceIntegrationExample example = new ServiceIntegrationExample();
example.createCriteria().andPluginIdEqualTo(pluginId);
return serviceIntegrationMapper.selectByExampleWithBLOBs(example).get(0);
}
public List<Plugin> getPlatformPlugins() {
public List<Plugin> getEnabledPlatformPlugins() {
PluginExample example = new PluginExample();
example.createCriteria()
.andEnableEqualTo(true)
.andScenarioEqualTo(PluginScenarioType.PLATFORM.name());
return pluginMapper.selectByExample(example);
}
public List<Plugin> getOrgEnabledPlatformPlugins(String orgId) {
List<Plugin> plugins = getEnabledPlatformPlugins();
List<String> unGlobalIds = plugins.stream().filter(i -> !i.getGlobal()).map(Plugin::getId).toList();
// 如果没有非全局直接返回全局插件
if (CollectionUtils.isEmpty(unGlobalIds)) {
return plugins;
}
// 查询当前组织下的插件列表
List<PluginOrganization> pluginOrganizations = basePluginOrganizationService.getByPluginIds(unGlobalIds);
Set<String> orgPluginIdSet = pluginOrganizations.stream()
.filter(i -> StringUtils.equals(i.getOrganizationId(), orgId))
.map(PluginOrganization::getPluginId)
.collect(Collectors.toSet());
// 返回全局插件和当前组织下的插件
return plugins.stream().filter(i -> i.getGlobal() || orgPluginIdSet.contains(i.getId())).collect(Collectors.toList());
}
}

View File

@ -60,9 +60,6 @@ public class ServiceIntegrationLogService {
public LogDTO deleteLog(String id) {
ServiceIntegration serviceIntegration = serviceIntegrationService.get(id);
if (serviceIntegration == null) {
return null;
}
LogDTO dto = new LogDTO(
OperationLogConstants.ORGANIZATION,
null,

View File

@ -3,6 +3,7 @@ package io.metersphere.system.service;
import io.metersphere.plugin.platform.api.AbstractPlatformPlugin;
import io.metersphere.plugin.platform.api.Platform;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.service.BasePluginService;
import io.metersphere.sdk.service.PlatformPluginService;
import io.metersphere.sdk.service.PluginLoadService;
import io.metersphere.sdk.util.BeanUtils;
@ -41,6 +42,8 @@ public class ServiceIntegrationService {
@Resource
private PlatformPluginService platformPluginService;
@Resource
private BasePluginService basePluginService;
@Resource
private PluginService pluginService;
public static final String PLUGIN_IMAGE_GET_PATH = "/plugin/image/%s?imagePath=%s";
@ -50,7 +53,7 @@ public class ServiceIntegrationService {
Map<String, ServiceIntegration> serviceIntegrationMap = getServiceIntegrationByOrgId(organizationId).stream()
.collect(Collectors.toMap(ServiceIntegration::getPluginId, i -> i));
List<Plugin> plugins = platformPluginService.getPlatformPlugins();
List<Plugin> plugins = platformPluginService.getOrgEnabledPlatformPlugins(organizationId);
return plugins.stream().map(plugin -> {
AbstractPlatformPlugin msPluginInstance = pluginLoadService.getPlatformPluginInstance(plugin.getId());
// 获取插件基础信息
@ -81,6 +84,7 @@ public class ServiceIntegrationService {
}
public ServiceIntegration add(ServiceIntegrationUpdateRequest request) {
basePluginService.checkPluginEnableAndPermission(request.getPluginId(), request.getOrganizationId());
ServiceIntegration serviceIntegration = new ServiceIntegration();
BeanUtils.copyBean(serviceIntegration, request);
serviceIntegration.setId(UUID.randomUUID().toString());
@ -91,6 +95,7 @@ public class ServiceIntegrationService {
}
public ServiceIntegration update(ServiceIntegrationUpdateRequest request) {
basePluginService.checkPluginEnableAndPermission(request.getPluginId(), request.getOrganizationId());
checkResourceExist(request.getId());
ServiceIntegration serviceIntegration = new ServiceIntegration();
// 组织不能修改
@ -109,6 +114,8 @@ public class ServiceIntegrationService {
public void delete(String id) {
checkResourceExist(id);
ServiceIntegration serviceIntegration = serviceIntegrationMapper.selectByPrimaryKey(id);
basePluginService.checkPluginEnableAndPermission(serviceIntegration.getPluginId(), serviceIntegration.getOrganizationId());
serviceIntegrationMapper.deleteByPrimaryKey(id);
}
@ -129,13 +136,15 @@ public class ServiceIntegrationService {
}
public void validate(String id) {
ServiceIntegration serviceIntegration = checkResourceExist(id);;
Platform platform = platformPluginService.getPlatform(serviceIntegration.getPluginId(), StringUtils.EMPTY);
ServiceIntegration serviceIntegration = checkResourceExist(id);
Platform platform = platformPluginService.getPlatform(serviceIntegration.getPluginId(), serviceIntegration.getOrganizationId());
platform.validateIntegrationConfig();
}
public ServiceIntegration get(String id) {
return serviceIntegrationMapper.selectByPrimaryKey(id);
ServiceIntegration serviceIntegration = serviceIntegrationMapper.selectByPrimaryKey(id);
basePluginService.checkPluginEnableAndPermission(serviceIntegration.getPluginId(), serviceIntegration.getOrganizationId());
return serviceIntegration;
}
public Object getPluginScript(String pluginId) {

View File

@ -11,6 +11,7 @@ import io.metersphere.system.domain.Organization;
import io.metersphere.system.domain.Plugin;
import io.metersphere.system.domain.ServiceIntegration;
import io.metersphere.system.dto.ServiceIntegrationDTO;
import io.metersphere.system.mapper.PluginMapper;
import io.metersphere.system.mapper.ServiceIntegrationMapper;
import io.metersphere.system.request.PluginUpdateRequest;
import io.metersphere.system.request.ServiceIntegrationUpdateRequest;
@ -35,6 +36,8 @@ import java.util.List;
import java.util.Map;
import static io.metersphere.sdk.constants.InternalUserRole.ADMIN;
import static io.metersphere.sdk.controller.handler.result.CommonResultCode.PLUGIN_ENABLE;
import static io.metersphere.sdk.controller.handler.result.CommonResultCode.PLUGIN_PERMISSION;
import static io.metersphere.sdk.controller.handler.result.MsHttpResultCode.NOT_FOUND;
import static io.metersphere.system.controller.result.SystemResultCode.SERVICE_INTEGRATION_EXIST;
import static io.metersphere.system.service.ServiceIntegrationService.PLUGIN_IMAGE_GET_PATH;
@ -67,6 +70,8 @@ public class ServiceIntegrationControllerTests extends BaseTest {
@Resource
private PluginService pluginService;
@Resource
private PluginMapper pluginMapper;
@Resource
private MockServerClient mockServerClient;
@Value("${embedded.mockserver.host}")
private String mockServerHost;
@ -114,6 +119,16 @@ public class ServiceIntegrationControllerTests extends BaseTest {
// @@重名校验异常
assertErrorCode(this.requestPost(DEFAULT_ADD, request), SERVICE_INTEGRATION_EXIST);
// @@校验插件禁用
setPluginEnable(request.getPluginId(), false);
assertErrorCode(this.requestPost(DEFAULT_ADD, request), PLUGIN_ENABLE);
setPluginEnable(request.getPluginId(), true);
// @@校验权限
setPluginGlobal(request.getPluginId(), false);
assertErrorCode(this.requestPost(DEFAULT_ADD, request), PLUGIN_PERMISSION);
setPluginGlobal(request.getPluginId(), true);
// @@校验日志
checkLog(this.addServiceIntegration.getId(), OperationLogType.ADD);
// @@异常参数校验
@ -152,6 +167,16 @@ public class ServiceIntegrationControllerTests extends BaseTest {
// @@校验日志
checkLog(request.getId(), OperationLogType.UPDATE);
// @@校验插件禁用
setPluginEnable(request.getPluginId(), false);
assertErrorCode(this.requestPost(DEFAULT_UPDATE, request), PLUGIN_ENABLE);
setPluginEnable(request.getPluginId(), true);
// @@校验权限
setPluginGlobal(request.getPluginId(), false);
assertErrorCode(this.requestPost(DEFAULT_UPDATE, request), PLUGIN_PERMISSION);
setPluginGlobal(request.getPluginId(), true);
// @@校验 NOT_FOUND 异常
request.setId("1111");
assertErrorCode(this.requestPost(DEFAULT_UPDATE, request), NOT_FOUND);
@ -207,6 +232,16 @@ public class ServiceIntegrationControllerTests extends BaseTest {
// @@请求成功
this.requestGetWithOk(VALIDATE_GET, addServiceIntegration.getId());
// @@校验插件禁用
setPluginEnable(addServiceIntegration.getPluginId(), false);
assertErrorCode(this.requestGet(VALIDATE_GET, addServiceIntegration.getId()), PLUGIN_ENABLE);
setPluginEnable(addServiceIntegration.getPluginId(), true);
// @@校验权限
setPluginGlobal(addServiceIntegration.getPluginId(), false);
assertErrorCode(this.requestGet(VALIDATE_GET, addServiceIntegration.getId()), PLUGIN_PERMISSION);
setPluginGlobal(addServiceIntegration.getPluginId(), true);
// @@校验 NOT_FOUND 异常
assertErrorCode(this.requestGet(VALIDATE_GET, "1111"), NOT_FOUND);
@ -222,6 +257,17 @@ public class ServiceIntegrationControllerTests extends BaseTest {
Map<String, Object> integrationConfigMap = JSON.parseMap(JSON.toJSONString(integrationConfig));
// @@请求成功
this.requestPostWithOk(VALIDATE_POST, integrationConfigMap, plugin.getId());
// @@校验插件禁用
setPluginEnable(addServiceIntegration.getPluginId(), false);
assertErrorCode(this.requestPost(VALIDATE_POST, integrationConfigMap, plugin.getId()), PLUGIN_ENABLE);
setPluginEnable(addServiceIntegration.getPluginId(), true);
// @@校验权限
setPluginGlobal(addServiceIntegration.getPluginId(), false);
assertErrorCode(this.requestPost(VALIDATE_POST, integrationConfigMap, plugin.getId()), PLUGIN_PERMISSION);
setPluginGlobal(addServiceIntegration.getPluginId(), true);
// @@校验 NOT_FOUND 异常
assertErrorCode(this.requestPost(VALIDATE_POST, integrationConfigMap, "1111"), NOT_FOUND);
// @@校验权限
@ -243,6 +289,17 @@ public class ServiceIntegrationControllerTests extends BaseTest {
@Test
public void delete() throws Exception {
// @@校验插件禁用
setPluginEnable(addServiceIntegration.getPluginId(), false);
assertErrorCode(this.requestGet(DEFAULT_DELETE, addServiceIntegration.getId()), PLUGIN_ENABLE);
setPluginEnable(addServiceIntegration.getPluginId(), true);
// @@校验权限
setPluginGlobal(addServiceIntegration.getPluginId(), false);
assertErrorCode(this.requestGet(DEFAULT_DELETE, addServiceIntegration.getId()), PLUGIN_PERMISSION);
setPluginGlobal(addServiceIntegration.getPluginId(), true);
// @@请求成功
this.requestGetWithOk(DEFAULT_DELETE, addServiceIntegration.getId());
// 校验请求成功数据
@ -284,6 +341,20 @@ public class ServiceIntegrationControllerTests extends BaseTest {
return pluginService.add(request, mockMultipartFile);
}
public void setPluginEnable(String pluginId, boolean enabled) {
Plugin plugin = new Plugin();
plugin.setId(pluginId);
plugin.setEnable(enabled);
pluginMapper.updateByPrimaryKeySelective(plugin);
}
public void setPluginGlobal(String pluginId, boolean global) {
Plugin plugin = new Plugin();
plugin.setId(pluginId);
plugin.setGlobal(global);
pluginMapper.updateByPrimaryKeySelective(plugin);
}
/**
* 删除插件
* @throws Exception