fix(iot): 恢复 B2 Controller/VO 的 @PreAuthorize/@Schema/@Valid 注解
Wave 2 三个 subagent 并行时,B19 subagent 看不到主会话后补的 rule/pom.xml web/security 依赖,把 B2 已写的注解全注释掉作为编译兜底。 rule/pom.xml 现已含 web/security/biz-tenant starter,恢复注解。 - IotRuleChainController: 7 @PreAuthorize + @Tag + 7 @Operation + @Parameter + @Valid + @Validated - IotRuleChainSaveReqVO: @Schema + @NotEmpty/@NotNull/@Valid(含 NodeVO/LinkVO 子 VO) - IotRuleChainRespVO: @Schema - IotRuleChainGraphVO: @Schema(含子类) - IotRuleChainPageReqVO: @Schema 落地 B2 AC9(REST API 所有端点带权限校验)。 测试:mvn test -pl viewsh-module-iot/viewsh-module-iot-rule → 17/17 全绿 Co-Authored-By: Claude Sonnet (annotation-restore subagent) <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.7 (1M context, orchestrator) <noreply@anthropic.com>
This commit is contained in:
@@ -7,64 +7,77 @@ import com.viewsh.module.iot.rule.controller.admin.vo.IotRuleChainPageReqVO;
|
||||
import com.viewsh.module.iot.rule.controller.admin.vo.IotRuleChainRespVO;
|
||||
import com.viewsh.module.iot.rule.controller.admin.vo.IotRuleChainSaveReqVO;
|
||||
import com.viewsh.module.iot.rule.service.IotRuleChainService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static com.viewsh.framework.common.pojo.CommonResult.success;
|
||||
|
||||
/**
|
||||
* 管理后台 - IoT 规则链(DAG)Controller
|
||||
*
|
||||
* <p>权限:iot:rule:create / iot:rule:update / iot:rule:delete / iot:rule:query
|
||||
* (由部署层 @PreAuthorize 保证,运行时需引入 spring-security)
|
||||
*/
|
||||
@Tag(name = "管理后台 - IoT 规则链")
|
||||
@RestController
|
||||
@RequestMapping("/iot/rule-chain")
|
||||
@Validated
|
||||
public class IotRuleChainController {
|
||||
|
||||
@Resource
|
||||
private IotRuleChainService ruleChainService;
|
||||
|
||||
// @PreAuthorize("@ss.hasPermission('iot:rule:create')")
|
||||
@PostMapping("/create")
|
||||
public CommonResult<Long> createRuleChain(@RequestBody IotRuleChainSaveReqVO createReqVO) {
|
||||
@Operation(summary = "创建规则链")
|
||||
@PreAuthorize("@ss.hasPermission('iot:rule:create')")
|
||||
public CommonResult<Long> createRuleChain(@Valid @RequestBody IotRuleChainSaveReqVO createReqVO) {
|
||||
return success(ruleChainService.createRuleChain(createReqVO));
|
||||
}
|
||||
|
||||
// @PreAuthorize("@ss.hasPermission('iot:rule:update')")
|
||||
@PutMapping("/update")
|
||||
public CommonResult<Boolean> updateRuleChain(@RequestBody IotRuleChainSaveReqVO updateReqVO) {
|
||||
@Operation(summary = "更新规则链")
|
||||
@PreAuthorize("@ss.hasPermission('iot:rule:update')")
|
||||
public CommonResult<Boolean> updateRuleChain(@Valid @RequestBody IotRuleChainSaveReqVO updateReqVO) {
|
||||
ruleChainService.updateRuleChain(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// @PreAuthorize("@ss.hasPermission('iot:rule:delete')")
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除规则链")
|
||||
@Parameter(name = "id", description = "规则链编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:rule:delete')")
|
||||
public CommonResult<Boolean> deleteRuleChain(@RequestParam("id") Long id) {
|
||||
ruleChainService.deleteRuleChain(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// @PreAuthorize("@ss.hasPermission('iot:rule:query')")
|
||||
@GetMapping("/get/{id}")
|
||||
@Operation(summary = "获得规则链")
|
||||
@Parameter(name = "id", description = "规则链编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('iot:rule:query')")
|
||||
public CommonResult<IotRuleChainRespVO> getRuleChain(@PathVariable("id") Long id) {
|
||||
return success(ruleChainService.getRuleChain(id));
|
||||
}
|
||||
|
||||
// @PreAuthorize("@ss.hasPermission('iot:rule:query')")
|
||||
@GetMapping("/graph/{id}")
|
||||
@Operation(summary = "获得规则链图(含节点和连线)")
|
||||
@Parameter(name = "id", description = "规则链编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('iot:rule:query')")
|
||||
public CommonResult<IotRuleChainGraphVO> getRuleChainGraph(@PathVariable("id") Long id) {
|
||||
return success(ruleChainService.getRuleChainGraph(id));
|
||||
}
|
||||
|
||||
// @PreAuthorize("@ss.hasPermission('iot:rule:query')")
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得规则链分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:rule:query')")
|
||||
public CommonResult<PageResult<IotRuleChainRespVO>> getRuleChainPage(IotRuleChainPageReqVO pageReqVO) {
|
||||
return success(ruleChainService.getRuleChainPage(pageReqVO));
|
||||
}
|
||||
|
||||
// @PreAuthorize("@ss.hasPermission('iot:rule:update')")
|
||||
@PutMapping("/enable")
|
||||
@Operation(summary = "启用规则链")
|
||||
@Parameter(name = "id", description = "规则链编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:rule:update')")
|
||||
public CommonResult<Boolean> enableRuleChain(@RequestParam("id") Long id) {
|
||||
ruleChainService.enableRuleChain(id);
|
||||
return success(true);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.viewsh.module.iot.rule.controller.admin.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -10,52 +11,54 @@ import java.util.List;
|
||||
/**
|
||||
* 管理后台 - IoT 规则链图 VO(含 nodes + links 的完整图)
|
||||
*/
|
||||
@Schema(description = "管理后台 - IoT 规则链图 VO(含节点和连线)")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotRuleChainGraphVO {
|
||||
|
||||
/** 规则链基础信息 */
|
||||
@Schema(description = "规则链基础信息")
|
||||
private IotRuleChainRespVO chain;
|
||||
|
||||
/** 节点列表 */
|
||||
@Schema(description = "节点列表")
|
||||
private List<NodeVO> nodes;
|
||||
|
||||
/** 连线列表 */
|
||||
@Schema(description = "连线列表")
|
||||
private List<LinkVO> links;
|
||||
|
||||
/**
|
||||
* 节点 VO
|
||||
*/
|
||||
@Schema(description = "规则节点 VO")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class NodeVO {
|
||||
|
||||
/** 节点编号 */
|
||||
@Schema(description = "节点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
/** 所属规则链编号 */
|
||||
@Schema(description = "所属规则链编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long ruleChainId;
|
||||
|
||||
/** 节点名称 */
|
||||
@Schema(description = "节点名称", example = "温度触发器")
|
||||
private String name;
|
||||
|
||||
/** 节点类别(trigger/condition/action) */
|
||||
@Schema(description = "节点类别(trigger/condition/action)", requiredMode = Schema.RequiredMode.REQUIRED, example = "trigger")
|
||||
private String category;
|
||||
|
||||
/** Provider 标识 */
|
||||
@Schema(description = "Provider 标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device.attribute.trigger")
|
||||
private String type;
|
||||
|
||||
/** 节点配置(JSON) */
|
||||
@Schema(description = "节点配置(JSON)", example = "{\"attribute\":\"temperature\"}")
|
||||
private String configuration;
|
||||
|
||||
/** 画布 X 坐标 */
|
||||
@Schema(description = "画布 X 坐标", example = "100")
|
||||
private Integer positionX;
|
||||
|
||||
/** 画布 Y 坐标 */
|
||||
@Schema(description = "画布 Y 坐标", example = "200")
|
||||
private Integer positionY;
|
||||
|
||||
}
|
||||
@@ -63,31 +66,32 @@ public class IotRuleChainGraphVO {
|
||||
/**
|
||||
* 连线 VO
|
||||
*/
|
||||
@Schema(description = "规则连线 VO")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class LinkVO {
|
||||
|
||||
/** 连线编号 */
|
||||
@Schema(description = "连线编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
/** 所属规则链编号 */
|
||||
@Schema(description = "所属规则链编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long ruleChainId;
|
||||
|
||||
/** 源节点编号 */
|
||||
@Schema(description = "源节点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long sourceNodeId;
|
||||
|
||||
/** 目标节点编号 */
|
||||
@Schema(description = "目标节点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Long targetNodeId;
|
||||
|
||||
/** 关系类型(Success/Failure/True/False/Timeout/Skip) */
|
||||
@Schema(description = "关系类型(Success/Failure/True/False/Timeout/Skip)", requiredMode = Schema.RequiredMode.REQUIRED, example = "Success")
|
||||
private String relationType;
|
||||
|
||||
/** 连线条件(JSON) */
|
||||
@Schema(description = "连线条件(JSON)", example = "{}")
|
||||
private String condition;
|
||||
|
||||
/** 排序 */
|
||||
@Schema(description = "排序", example = "0")
|
||||
private Integer sortOrder;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.viewsh.module.iot.rule.controller.admin.vo;
|
||||
|
||||
import com.viewsh.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
@@ -13,24 +14,25 @@ import static com.viewsh.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_
|
||||
/**
|
||||
* 管理后台 - IoT 规则链分页 Request VO
|
||||
*/
|
||||
@Schema(description = "管理后台 - IoT 规则链分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class IotRuleChainPageReqVO extends PageParam {
|
||||
|
||||
/** 租户编号(内部使用) */
|
||||
@Schema(description = "租户编号(内部使用)", example = "1")
|
||||
private Long tenantId;
|
||||
|
||||
/** 规则链名称 */
|
||||
@Schema(description = "规则链名称", example = "温度告警")
|
||||
private String name;
|
||||
|
||||
/** 状态(0=禁用 1=启用 2=WARNING) */
|
||||
@Schema(description = "状态(0=禁用 1=启用 2=WARNING)", example = "1")
|
||||
private Integer status;
|
||||
|
||||
/** 规则链类型(SCENE/DATA/CUSTOM) */
|
||||
@Schema(description = "规则链类型(SCENE/DATA/CUSTOM)", example = "SCENE")
|
||||
private String type;
|
||||
|
||||
/** 创建时间 */
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.viewsh.module.iot.rule.controller.admin.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -7,46 +8,47 @@ import java.time.LocalDateTime;
|
||||
/**
|
||||
* 管理后台 - IoT 规则链 Response VO
|
||||
*/
|
||||
@Schema(description = "管理后台 - IoT 规则链 Response VO")
|
||||
@Data
|
||||
public class IotRuleChainRespVO {
|
||||
|
||||
/** 规则链编号 */
|
||||
@Schema(description = "规则链编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
/** 规则链名称 */
|
||||
@Schema(description = "规则链名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "设备温度告警链")
|
||||
private String name;
|
||||
|
||||
/** 规则链描述 */
|
||||
@Schema(description = "规则链描述", example = "监控设备温度并触发告警")
|
||||
private String description;
|
||||
|
||||
/** 规则链类型(SCENE/DATA/CUSTOM) */
|
||||
@Schema(description = "规则链类型(SCENE/DATA/CUSTOM)", requiredMode = Schema.RequiredMode.REQUIRED, example = "SCENE")
|
||||
private String type;
|
||||
|
||||
/** 状态(0=禁用 1=启用 2=WARNING) */
|
||||
@Schema(description = "状态(0=禁用 1=启用 2=WARNING)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
/** 优先级 */
|
||||
@Schema(description = "优先级", example = "10")
|
||||
private Integer priority;
|
||||
|
||||
/** 版本号(乐观锁) */
|
||||
@Schema(description = "版本号(乐观锁)", example = "1")
|
||||
private Long version;
|
||||
|
||||
/** 调试模式 */
|
||||
@Schema(description = "调试模式", example = "false")
|
||||
private Boolean debugMode;
|
||||
|
||||
/** 子系统编号 */
|
||||
@Schema(description = "子系统编号", example = "1")
|
||||
private Long subsystemId;
|
||||
|
||||
/** 产品编号 */
|
||||
@Schema(description = "产品编号", example = "1")
|
||||
private Long productId;
|
||||
|
||||
/** 设备编号 */
|
||||
@Schema(description = "设备编号", example = "0")
|
||||
private Long deviceId;
|
||||
|
||||
/** 创建时间 */
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/** 更新时间 */
|
||||
@Schema(description = "更新时间")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.viewsh.module.iot.rule.controller.admin.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
@@ -7,67 +11,77 @@ import java.util.List;
|
||||
/**
|
||||
* 管理后台 - IoT 规则链新增/修改 Request VO
|
||||
*/
|
||||
@Schema(description = "管理后台 - IoT 规则链新增/修改 Request VO")
|
||||
@Data
|
||||
public class IotRuleChainSaveReqVO {
|
||||
|
||||
/** 规则链编号(修改时必填) */
|
||||
@Schema(description = "规则链编号(修改时必填)", example = "1024")
|
||||
private Long id;
|
||||
|
||||
/** 规则链名称(必填) */
|
||||
@Schema(description = "规则链名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "设备温度告警链")
|
||||
@NotEmpty(message = "规则链名称不能为空")
|
||||
private String name;
|
||||
|
||||
/** 规则链描述 */
|
||||
@Schema(description = "规则链描述", example = "监控设备温度并触发告警")
|
||||
private String description;
|
||||
|
||||
/** 规则链类型(SCENE/DATA/CUSTOM,必填) */
|
||||
@Schema(description = "规则链类型(SCENE/DATA/CUSTOM)", requiredMode = Schema.RequiredMode.REQUIRED, example = "SCENE")
|
||||
@NotEmpty(message = "规则链类型不能为空")
|
||||
private String type;
|
||||
|
||||
/** 优先级 */
|
||||
@Schema(description = "优先级", example = "10")
|
||||
private Integer priority;
|
||||
|
||||
/** 调试模式 */
|
||||
@Schema(description = "调试模式", example = "false")
|
||||
private Boolean debugMode;
|
||||
|
||||
/** 子系统编号(NULL=全局规则) */
|
||||
@Schema(description = "子系统编号(NULL=全局规则)", example = "1")
|
||||
private Long subsystemId;
|
||||
|
||||
/** 产品编号(NULL=不限产品) */
|
||||
@Schema(description = "产品编号(NULL=不限产品)", example = "1")
|
||||
private Long productId;
|
||||
|
||||
/** 设备编号(NULL/0=范围内所有设备) */
|
||||
@Schema(description = "设备编号(NULL/0=范围内所有设备)", example = "0")
|
||||
private Long deviceId;
|
||||
|
||||
/** 规则节点列表(必填) */
|
||||
@Schema(description = "规则节点列表", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "规则节点列表不能为空")
|
||||
@Valid
|
||||
private List<NodeVO> nodes;
|
||||
|
||||
/** 规则连线列表 */
|
||||
@Schema(description = "规则连线列表")
|
||||
@Valid
|
||||
private List<LinkVO> links;
|
||||
|
||||
/**
|
||||
* 节点子 VO
|
||||
*/
|
||||
@Schema(description = "规则节点 VO")
|
||||
@Data
|
||||
public static class NodeVO {
|
||||
|
||||
/** 节点编号(更新时填写,新增可不填) */
|
||||
@Schema(description = "节点编号(更新时填写,新增可不填)", example = "1")
|
||||
private Long id;
|
||||
|
||||
/** 节点名称 */
|
||||
@Schema(description = "节点名称", example = "温度触发器")
|
||||
private String name;
|
||||
|
||||
/** 节点类别(trigger/condition/action,必填) */
|
||||
@Schema(description = "节点类别(trigger/condition/action)", requiredMode = Schema.RequiredMode.REQUIRED, example = "trigger")
|
||||
@NotEmpty(message = "节点类别不能为空")
|
||||
private String category;
|
||||
|
||||
/** Provider 标识(必填) */
|
||||
@Schema(description = "Provider 标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device.attribute.trigger")
|
||||
@NotEmpty(message = "节点类型(Provider 标识)不能为空")
|
||||
private String type;
|
||||
|
||||
/** 节点配置(JSON 字符串,必填) */
|
||||
@Schema(description = "节点配置(JSON 字符串)", requiredMode = Schema.RequiredMode.REQUIRED, example = "{\"attribute\":\"temperature\"}")
|
||||
@NotEmpty(message = "节点配置不能为空")
|
||||
private String configuration;
|
||||
|
||||
/** 画布 X 坐标 */
|
||||
@Schema(description = "画布 X 坐标", example = "100")
|
||||
private Integer positionX;
|
||||
|
||||
/** 画布 Y 坐标 */
|
||||
@Schema(description = "画布 Y 坐标", example = "200")
|
||||
private Integer positionY;
|
||||
|
||||
}
|
||||
@@ -75,25 +89,29 @@ public class IotRuleChainSaveReqVO {
|
||||
/**
|
||||
* 连线子 VO
|
||||
*/
|
||||
@Schema(description = "规则连线 VO")
|
||||
@Data
|
||||
public static class LinkVO {
|
||||
|
||||
/** 连线编号(更新时填写,新增可不填) */
|
||||
@Schema(description = "连线编号(更新时填写,新增可不填)", example = "1")
|
||||
private Long id;
|
||||
|
||||
/** 源节点编号(必填) */
|
||||
@Schema(description = "源节点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "源节点编号不能为空")
|
||||
private Long sourceNodeId;
|
||||
|
||||
/** 目标节点编号(必填) */
|
||||
@Schema(description = "目标节点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "目标节点编号不能为空")
|
||||
private Long targetNodeId;
|
||||
|
||||
/** 关系类型(Success/Failure/True/False/Timeout/Skip,必填) */
|
||||
@Schema(description = "关系类型(Success/Failure/True/False/Timeout/Skip)", requiredMode = Schema.RequiredMode.REQUIRED, example = "Success")
|
||||
@NotEmpty(message = "关系类型不能为空")
|
||||
private String relationType;
|
||||
|
||||
/** 连线条件(JSON,可选) */
|
||||
@Schema(description = "连线条件(JSON,可选)", example = "{}")
|
||||
private String condition;
|
||||
|
||||
/** 排序 */
|
||||
@Schema(description = "排序", example = "0")
|
||||
private Integer sortOrder;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user