package com.alibaba.csp.sentinel.dashboard.controller; import java.util.Date; import java.util.List; import com.alibaba.csp.sentinel.dashboard.auth.AuthAction; import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType; import com.alibaba.csp.sentinel.dashboard.controller.base.BaseRuleController; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.slots.block.RuleConstant; import com.alibaba.csp.sentinel.util.StringUtil; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity; import com.alibaba.csp.sentinel.dashboard.domain.Result; import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * 授权规则控制器 * * @author zyf * @date 2022-04-13 */ @RestController @RequestMapping(value = "/authority") public class AuthorityRuleController extends BaseRuleController { private final Logger logger = LoggerFactory.getLogger(AuthorityRuleController.class); @Autowired private RuleRepository repository; @Autowired @Qualifier("authorityRuleNacosProvider") private DynamicRuleProvider> ruleProvider; @Autowired @Qualifier("authorityRuleNacosPublisher") private DynamicRulePublisher> rulePublisher; @GetMapping("/rules") @AuthAction(PrivilegeType.READ_RULE) public Result> apiQueryAllRulesForMachine(@RequestParam String app, @RequestParam String ip, @RequestParam Integer port) { if (StringUtil.isEmpty(app)) { return Result.ofFail(-1, "app cannot be null or empty"); } if (StringUtil.isEmpty(ip)) { return Result.ofFail(-1, "ip cannot be null or empty"); } if (port == null || port <= 0) { return Result.ofFail(-1, "Invalid parameter: port"); } try { List rules = ruleProvider.getRules(app); rules = repository.saveAll(rules); return Result.ofSuccess(rules); } catch (Throwable throwable) { logger.error("Error when querying authority rules", throwable); return Result.ofFail(-1, throwable.getMessage()); } } private Result checkEntityInternal(AuthorityRuleEntity entity) { if (entity == null) { return Result.ofFail(-1, "bad rule body"); } if (StringUtil.isBlank(entity.getApp())) { return Result.ofFail(-1, "app can't be null or empty"); } if (StringUtil.isBlank(entity.getIp())) { return Result.ofFail(-1, "ip can't be null or empty"); } if (entity.getPort() == null || entity.getPort() <= 0) { return Result.ofFail(-1, "port can't be null"); } if (entity.getRule() == null) { return Result.ofFail(-1, "rule can't be null"); } if (StringUtil.isBlank(entity.getResource())) { return Result.ofFail(-1, "resource name cannot be null or empty"); } if (StringUtil.isBlank(entity.getLimitApp())) { return Result.ofFail(-1, "limitApp should be valid"); } if (entity.getStrategy() != RuleConstant.AUTHORITY_WHITE && entity.getStrategy() != RuleConstant.AUTHORITY_BLACK) { return Result.ofFail(-1, "Unknown strategy (must be blacklist or whitelist)"); } return null; } @PostMapping("/rule") @AuthAction(PrivilegeType.WRITE_RULE) public Result apiAddAuthorityRule(@RequestBody AuthorityRuleEntity entity) { Result checkResult = checkEntityInternal(entity); if (checkResult != null) { return checkResult; } entity.setId(null); Date date = new Date(); entity.setGmtCreate(date); entity.setGmtModified(date); try { entity = repository.save(entity); publishRules(entity.getApp()); } catch (Throwable throwable) { logger.error("Failed to add authority rule", throwable); return Result.ofThrowable(-1, throwable); } return Result.ofSuccess(entity); } @PutMapping("/rule/{id}") @AuthAction(PrivilegeType.WRITE_RULE) public Result apiUpdateParamFlowRule(@PathVariable("id") Long id, @RequestBody AuthorityRuleEntity entity) { if (id == null || id <= 0) { return Result.ofFail(-1, "Invalid id"); } Result checkResult = checkEntityInternal(entity); if (checkResult != null) { return checkResult; } entity.setId(id); Date date = new Date(); entity.setGmtCreate(null); entity.setGmtModified(date); try { entity = repository.save(entity); if (entity == null) { return Result.ofFail(-1, "Failed to save authority rule"); } publishRules(entity.getApp()); } catch (Throwable throwable) { logger.error("Failed to save authority rule", throwable); return Result.ofThrowable(-1, throwable); } return Result.ofSuccess(entity); } @DeleteMapping("/rule/{id}") @AuthAction(PrivilegeType.DELETE_RULE) public Result apiDeleteRule(@PathVariable("id") Long id) { if (id == null) { return Result.ofFail(-1, "id cannot be null"); } AuthorityRuleEntity oldEntity = repository.findById(id); if (oldEntity == null) { return Result.ofSuccess(null); } try { repository.delete(id); publishRules(oldEntity.getApp()); } catch (Exception e) { return Result.ofFail(-1, e.getMessage()); } return Result.ofSuccess(id); } private void publishRules(String app) throws Exception { List rules = repository.findAllByApp(app); rulePublisher.publish(app, rules); //延迟加载 delayTime(); } }