diff --git a/server/home/home-web/src/main/java/io/holoinsight/server/home/web/controller/AlarmDingDingRobotFacadeImpl.java b/server/home/home-web/src/main/java/io/holoinsight/server/home/web/controller/AlarmDingDingRobotFacadeImpl.java index 2b579a0e3..cbf42a3b4 100644 --- a/server/home/home-web/src/main/java/io/holoinsight/server/home/web/controller/AlarmDingDingRobotFacadeImpl.java +++ b/server/home/home-web/src/main/java/io/holoinsight/server/home/web/controller/AlarmDingDingRobotFacadeImpl.java @@ -8,7 +8,6 @@ import io.holoinsight.server.home.biz.service.AlertDingDingRobotService; import io.holoinsight.server.home.biz.service.UserOpLogService; import io.holoinsight.server.home.common.service.RequestContextAdapter; -import io.holoinsight.server.home.common.util.MonitorException; import io.holoinsight.server.home.common.util.scope.AuthTargetType; import io.holoinsight.server.home.common.util.scope.MonitorScope; import io.holoinsight.server.home.common.util.scope.MonitorUser; @@ -19,8 +18,8 @@ import io.holoinsight.server.home.facade.page.MonitorPageRequest; import io.holoinsight.server.home.facade.page.MonitorPageResult; import io.holoinsight.server.home.web.common.ManageCallback; -import io.holoinsight.server.home.web.common.ParaCheckUtil; import io.holoinsight.server.home.web.interceptor.MonitorScopeAuth; +import io.holoinsight.server.home.web.security.LevelAuthorizationAccess; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.DeleteMapping; @@ -42,7 +41,7 @@ @RequestMapping("/webapi/alarmDingDingRobot") public class AlarmDingDingRobotFacadeImpl extends BaseFacade { - private static final String dingdingUrlPrefix = + public static final String dingdingUrlPrefix = "https://oapi.dingtalk.com/robot/send?access_token="; @Autowired @@ -54,19 +53,16 @@ public class AlarmDingDingRobotFacadeImpl extends BaseFacade { @Autowired private RequestContextAdapter requestContextAdapter; + @LevelAuthorizationAccess(paramConfigs = {"PARAMETER" + ":$!alarmDingDingRobotDTO"}, + levelAuthorizationCheckeClass = "io.holoinsight.server.home.web.security.custom.AlarmDingDingRobotFacadeImplChecker") @PostMapping("/create") @ResponseBody @MonitorScopeAuth(targetType = AuthTargetType.TENANT, needPower = PowerConstants.EDIT) - public JsonResult save(@RequestBody AlarmDingDingRobotDTO alarmDingDingRobotDTO) { + public JsonResult create(@RequestBody AlarmDingDingRobotDTO alarmDingDingRobotDTO) { final JsonResult result = new JsonResult<>(); facadeTemplate.manage(result, new ManageCallback() { @Override - public void checkParameter() { - ParaCheckUtil.checkParaNotBlank(alarmDingDingRobotDTO.getGroupName(), "groupName"); - ParaCheckUtil.checkParaStartWith(alarmDingDingRobotDTO.getRobotUrl(), dingdingUrlPrefix, - "robotUrl"); - ParaCheckUtil.checkParaId(alarmDingDingRobotDTO.getId()); - } + public void checkParameter() {} @Override public void doManage() { @@ -94,6 +90,8 @@ public void doManage() { return result; } + @LevelAuthorizationAccess(paramConfigs = {"PARAMETER" + ":$!alarmDingDingRobotDTO"}, + levelAuthorizationCheckeClass = "io.holoinsight.server.home.web.security.custom.AlarmDingDingRobotFacadeImplChecker") @PostMapping("/update") @ResponseBody @MonitorScopeAuth(targetType = AuthTargetType.TENANT, needPower = PowerConstants.EDIT) @@ -101,27 +99,13 @@ public JsonResult update(@RequestBody AlarmDingDingRobotDTO alarmDingDi final JsonResult result = new JsonResult<>(); facadeTemplate.manage(result, new ManageCallback() { @Override - public void checkParameter() { - ParaCheckUtil.checkParaNotNull(alarmDingDingRobotDTO.getId(), "id"); - ParaCheckUtil.checkParaNotNull(alarmDingDingRobotDTO.getTenant(), "tenant"); - ParaCheckUtil.checkParaStartWith(alarmDingDingRobotDTO.getRobotUrl(), dingdingUrlPrefix, - "robotUrl"); - ParaCheckUtil.checkEquals(alarmDingDingRobotDTO.getTenant(), - RequestContext.getContext().ms.getTenant(), "tenant is illegal"); - - } + public void checkParameter() {} @Override public void doManage() { AlarmDingDingRobotDTO item = alarmDingDingRobotService .queryById(alarmDingDingRobotDTO.getId(), RequestContext.getContext().ms.getTenant()); - if (null == item) { - throw new MonitorException("cannot find record: " + alarmDingDingRobotDTO.getId()); - } - if (!item.getTenant().equalsIgnoreCase(alarmDingDingRobotDTO.getTenant())) { - throw new MonitorException("the tenant parameter is invalid"); - } MonitorUser mu = RequestContext.getContext().mu; if (null != mu) { @@ -143,6 +127,8 @@ public void doManage() { return result; } + @LevelAuthorizationAccess(paramConfigs = {"PARAMETER" + ":$!id"}, + levelAuthorizationCheckeClass = "io.holoinsight.server.home.web.security.custom.AlarmDingDingRobotFacadeImplChecker") @GetMapping("/query/{id}") @ResponseBody @MonitorScopeAuth(targetType = AuthTargetType.TENANT, needPower = PowerConstants.VIEW) @@ -150,9 +136,7 @@ public JsonResult queryById(@PathVariable("id") Long id) final JsonResult result = new JsonResult<>(); facadeTemplate.manage(result, new ManageCallback() { @Override - public void checkParameter() { - ParaCheckUtil.checkParaNotNull(id, "id"); - } + public void checkParameter() {} @Override public void doManage() { @@ -166,15 +150,15 @@ public void doManage() { return result; } + @LevelAuthorizationAccess(paramConfigs = {"PARAMETER" + ":$!id"}, + levelAuthorizationCheckeClass = "io.holoinsight.server.home.web.security.custom.AlarmDingDingRobotFacadeImplChecker") @DeleteMapping(value = "/delete/{id}") @MonitorScopeAuth(targetType = AuthTargetType.TENANT, needPower = PowerConstants.EDIT) public JsonResult deleteById(@PathVariable("id") Long id) { final JsonResult result = new JsonResult<>(); facadeTemplate.manage(result, new ManageCallback() { @Override - public void checkParameter() { - ParaCheckUtil.checkParaNotNull(id, "id"); - } + public void checkParameter() {} @Override public void doManage() { @@ -197,6 +181,8 @@ public void doManage() { return result; } + @LevelAuthorizationAccess(paramConfigs = {"PARAMETER" + ":$!pageRequest"}, + levelAuthorizationCheckeClass = "io.holoinsight.server.home.web.security.custom.AlarmDingDingRobotFacadeImplChecker") @PostMapping("/pageQuery") @ResponseBody @MonitorScopeAuth(targetType = AuthTargetType.TENANT, needPower = PowerConstants.VIEW) @@ -205,9 +191,7 @@ public JsonResult> pageQuery( final JsonResult> result = new JsonResult<>(); facadeTemplate.manage(result, new ManageCallback() { @Override - public void checkParameter() { - ParaCheckUtil.checkParaNotNull(pageRequest.getTarget(), "target"); - } + public void checkParameter() {} @Override public void doManage() { diff --git a/server/home/home-web/src/main/java/io/holoinsight/server/home/web/security/LevelAuthorizationCheck.java b/server/home/home-web/src/main/java/io/holoinsight/server/home/web/security/LevelAuthorizationCheck.java index 8f83c0a13..e2c4359d0 100644 --- a/server/home/home-web/src/main/java/io/holoinsight/server/home/web/security/LevelAuthorizationCheck.java +++ b/server/home/home-web/src/main/java/io/holoinsight/server/home/web/security/LevelAuthorizationCheck.java @@ -29,4 +29,6 @@ default boolean checkSqlName(String sqlName) { } return true; } + + } diff --git a/server/home/home-web/src/main/java/io/holoinsight/server/home/web/security/custom/AlarmDingDingRobotFacadeImplChecker.java b/server/home/home-web/src/main/java/io/holoinsight/server/home/web/security/custom/AlarmDingDingRobotFacadeImplChecker.java new file mode 100644 index 000000000..9e4daca45 --- /dev/null +++ b/server/home/home-web/src/main/java/io/holoinsight/server/home/web/security/custom/AlarmDingDingRobotFacadeImplChecker.java @@ -0,0 +1,213 @@ +/* + * Copyright 2022 Holoinsight Project Authors. Licensed under Apache-2.0. + */ +package io.holoinsight.server.home.web.security.custom; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.google.common.reflect.TypeToken; +import io.holoinsight.server.common.J; +import io.holoinsight.server.home.common.service.RequestContextAdapter; +import io.holoinsight.server.home.common.util.scope.MonitorScope; +import io.holoinsight.server.home.common.util.scope.MonitorUser; +import io.holoinsight.server.home.common.util.scope.RequestContext; +import io.holoinsight.server.home.dal.mapper.AlarmDingDingRobotMapper; +import io.holoinsight.server.home.dal.model.AlarmDingDingRobot; +import io.holoinsight.server.home.dal.model.dto.AlarmDingDingRobotDTO; +import io.holoinsight.server.home.facade.page.MonitorPageRequest; +import io.holoinsight.server.home.web.security.LevelAuthorizationCheck; +import io.holoinsight.server.home.web.security.LevelAuthorizationMetaData; +import io.holoinsight.server.home.web.security.ParameterSecurityService; +import lombok.extern.slf4j.Slf4j; +import org.aopalliance.intercept.MethodInvocation; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Map; + +import static io.holoinsight.server.home.web.controller.AlarmDingDingRobotFacadeImpl.dingdingUrlPrefix; + +/** + * @author masaimu + * @version 2024-01-29 11:32:00 + */ +@Slf4j +@Service +public class AlarmDingDingRobotFacadeImplChecker implements LevelAuthorizationCheck { + + @Autowired + private AlarmDingDingRobotMapper alarmDingDingRobotMapper; + @Autowired + private ParameterSecurityService parameterSecurityService; + + @Autowired + private RequestContextAdapter requestContextAdapter; + + @Override + public boolean check(LevelAuthorizationMetaData levelAuthMetaData, + MethodInvocation methodInvocation) { + MonitorScope ms = RequestContext.getContext().ms; + String workspace = this.requestContextAdapter.getWorkspace(true); + String tenant = ms.getTenant(); + + List parameters = levelAuthMetaData.getParameters(); + String methodName = methodInvocation.getMethod().getName(); + return checkParameters(methodName, parameters, tenant, workspace); + } + + private boolean checkParameters(String methodName, List parameters, String tenant, + String workspace) { + switch (methodName) { + case "create": + case "update": + return checkAlarmDingDingRobotDTO(methodName, parameters, tenant, workspace); + case "queryById": + case "deleteById": + return checkId(parameters, tenant, workspace); + case "pageQuery": + return checkPageRequest(methodName, parameters, tenant, workspace); + default: + return true; + } + } + + private boolean checkPageRequest(String methodName, List parameters, String tenant, + String workspace) { + if (CollectionUtils.isEmpty(parameters) || StringUtils.isBlank(parameters.get(0))) { + return false; + } + String parameter = parameters.get(0); + MonitorPageRequest pageRequest = J.fromJson(parameter, + new TypeToken>() {}.getType()); + + if (pageRequest.getFrom() != null && pageRequest.getTo() != null) { + if (pageRequest.getFrom() > pageRequest.getTo()) { + log.error("fail to check time range for start {} larger than end {}", pageRequest.getFrom(), + pageRequest.getTo()); + return false; + } + } + + AlarmDingDingRobotDTO target = pageRequest.getTarget(); + if (target == null) { + log.error("fail to check target, target can not be null"); + return false; + } + return checkAlarmDingDingRobotDTO(methodName, target, tenant, workspace); + } + + private boolean checkId(List parameters, String tenant, String workspace) { + if (CollectionUtils.isEmpty(parameters) || !StringUtils.isNumeric(parameters.get(0))) { + log.error("parameters {} is empty or is not numeric.", parameters); + return false; + } + Long id = Long.parseLong(parameters.get(0)); + return checkId(id, tenant, workspace); + } + + private boolean checkAlarmDingDingRobotDTO(String methodName, List parameters, + String tenant, String workspace) { + if (CollectionUtils.isEmpty(parameters) || StringUtils.isBlank(parameters.get(0))) { + return false; + } + log.info("checkParameters {} parameter {}", methodName, parameters.get(0)); + AlarmDingDingRobotDTO dto = J.fromJson(parameters.get(0), AlarmDingDingRobotDTO.class); + return checkAlarmDingDingRobotDTO(methodName, dto, tenant, workspace); + } + + private boolean checkAlarmDingDingRobotDTO(String methodName, AlarmDingDingRobotDTO dto, + String tenant, String workspace) { + if (methodName.equals("create")) { + if (dto.getId() != null) { + log.error("fail to check {} for id is not null", methodName); + return false; + } + if (StringUtils.isBlank(dto.getGroupName())) { + log.error("group name can not be blank."); + return false; + } + } + + if (methodName.equals("update")) { + if (dto.getId() == null) { + log.error("fail to check {} for id is null", methodName); + return false; + } + if (!checkId(dto.getId(), tenant, workspace)) { + return false; + } + } + + if (StringUtils.isNotEmpty(dto.getRobotUrl()) + && !dto.getRobotUrl().startsWith(dingdingUrlPrefix)) { + log.error("invalid robotUrl {}", dto.getRobotUrl()); + return false; + } + + if (StringUtils.isNotEmpty(dto.getCreator()) && !checkSqlField(dto.getCreator())) { + log.error("fail to check {} for invalid creator {}", methodName, dto.getCreator()); + return false; + } + + if (StringUtils.isNotEmpty(dto.getModifier()) && !checkSqlField(dto.getModifier())) { + log.error("fail to check {} for invalid modifier {}", methodName, dto.getModifier()); + return false; + } + + if (StringUtils.isNotEmpty(dto.getGroupName()) && !checkSqlField(dto.getGroupName())) { + log.error("fail to check {} for invalid group name {}", methodName, dto.getGroupName()); + return false; + } + + if (StringUtils.isNotEmpty(dto.getTenant()) && !StringUtils.equals(dto.getTenant(), tenant)) { + log.error("fail to check {} for invalid tenant {} for valid tenant {}", methodName, + dto.getTenant(), tenant); + return false; + } + + if (StringUtils.isNotEmpty(dto.getWorkspace()) + && !StringUtils.equals(dto.getWorkspace(), workspace)) { + log.error("fail to check {} for invalid workspace {} for valid workspace {}", methodName, + dto.getWorkspace(), workspace); + return false; + } + + if (StringUtils.isNotEmpty(dto.getExtra()) && !checkUserIds(dto.getExtra())) { + log.error("fail to check {} that userIds in extra {}", methodName, dto.getExtra()); + return false; + } + + return true; + } + + private boolean checkUserIds(String extra) { + Map extraMap = J.toMap(extra); + List userIds = (List) extraMap.get("userIds"); + if (CollectionUtils.isEmpty(userIds)) { + return true; + } + MonitorUser mu = RequestContext.getContext().mu; + for (String uid : userIds) { + if (!this.parameterSecurityService.checkUserTenantAndWorkspace(uid, mu)) { + log.error("fail to check uid {}", uid); + return false; + } + } + return true; + } + + private boolean checkId(Long id, String tenant, String workspace) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("id", id); + queryWrapper.eq("tenant", tenant); + queryWrapper.eq("workspace", workspace); + List exist = this.alarmDingDingRobotMapper.selectList(queryWrapper); + if (CollectionUtils.isEmpty(exist)) { + log.error("fail to check id for no existed {} {} {}", id, tenant, workspace); + return false; + } + return true; + } +} diff --git a/server/home/home-web/src/main/java/io/holoinsight/server/home/web/security/custom/AlertTemplateFacadeImplChecker.java b/server/home/home-web/src/main/java/io/holoinsight/server/home/web/security/custom/AlertTemplateFacadeImplChecker.java index 377f31979..061832652 100644 --- a/server/home/home-web/src/main/java/io/holoinsight/server/home/web/security/custom/AlertTemplateFacadeImplChecker.java +++ b/server/home/home-web/src/main/java/io/holoinsight/server/home/web/security/custom/AlertTemplateFacadeImplChecker.java @@ -87,8 +87,12 @@ private boolean checkPageRequest(String methodName, List parameters, Str } } - AlertTemplateDTO templateDTO = pageRequest.getTarget(); - return checkAlertNotificationTemplateDTO(methodName, templateDTO, tenant, workspace); + AlertTemplateDTO target = pageRequest.getTarget(); + if (target == null) { + log.error("fail to check target, target can not be null"); + return false; + } + return checkAlertNotificationTemplateDTO(methodName, target, tenant, workspace); } private boolean checkId(List parameters, String tenant, String workspace) {