Ver Fonte

feat: 流程支持创建人隔离(商户隔离)

wuwenyi há 21 horas atrás
pai
commit
067f3e06b0

+ 12 - 2
src/main/java/com/qqflow/engine/domain/flow/mapper/ProcessDefinitionMapper.java

@@ -30,16 +30,26 @@ public interface ProcessDefinitionMapper extends BaseMapper<ProcessDefinition> {
         return this.selectOne(wrapper);
     }
 
-    default List<ProcessDefinition> selectEnabledList() {
+    /**
+     * 启用中的流程列表;ownerId 非空时只返回该创建人的流程(商户隔离)。
+     */
+    default List<ProcessDefinition> selectEnabledList(Long ownerId) {
         LambdaQueryWrapper<ProcessDefinition> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(ProcessDefinition::getStatus, 1);
+        if (ownerId != null) {
+            wrapper.eq(ProcessDefinition::getCreateBy, ownerId);
+        }
         return this.selectList(wrapper);
     }
 
-    default Integer selectMaxVersion(String processCode) {
+    /**
+     * 同创建人、同编码的最新版本号;商户之间编码命名空间互相独立。
+     */
+    default Integer selectMaxVersion(String processCode, Long ownerId) {
         LambdaQueryWrapper<ProcessDefinition> wrapper = new LambdaQueryWrapper<>();
         wrapper.select(ProcessDefinition::getVersion)
                 .eq(ProcessDefinition::getProcessCode, processCode)
+                .eq(ProcessDefinition::getCreateBy, ownerId)
                 .orderByDesc(ProcessDefinition::getVersion)
                 .last("limit 1");
         ProcessDefinition result = this.selectOne(wrapper);

+ 32 - 6
src/main/java/com/qqflow/engine/domain/flow/service/impl/ProcessDefinitionServiceImpl.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.qqflow.engine.common.PageResult;
 import com.qqflow.engine.common.exception.BusinessException;
+import com.qqflow.engine.common.util.SecurityUtils;
 import com.qqflow.engine.domain.flow.dto.ProcessDefinitionDTO;
 import com.qqflow.engine.domain.flow.enums.DefinitionStatus;
 import com.qqflow.engine.domain.flow.enums.ProcessStatus;
@@ -19,6 +20,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 @Service
@@ -32,8 +34,10 @@ public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
     @Transactional(rollbackFor = Exception.class)
     public Long saveDefinition(ProcessDefinition po) {
         // 检查是否已存在设计中的同编码流程(防止新建时编码冲突)
+        // 商户之间流程互相隔离,编码唯一性只在同创建人范围内校验
         LambdaQueryWrapper<ProcessDefinition> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(ProcessDefinition::getProcessCode, po.getProcessCode())
+                .eq(ProcessDefinition::getCreateBy, po.getCreateBy())
                 .eq(ProcessDefinition::getStatus, DefinitionStatus.DESIGNING.getCode())
                 .eq(ProcessDefinition::getDeleted, 0);
         Long existingCount = this.processDefinitionMapper.selectCount(wrapper);
@@ -51,6 +55,7 @@ public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
         if (existing == null) {
             throw new BusinessException("流程定义不存在");
         }
+        this.checkOwner(existing);
         // 只有 modelJson(流程设计)真正变化 + 非设计状态 才创建新版本
         // formSchema、元信息等变化直接更新
         boolean modelChanged = po.getModelJson() != null && !po.getModelJson().equals(existing.getModelJson());
@@ -82,7 +87,7 @@ public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
         newDef.setBizFieldName(po.getBizFieldName() != null ? po.getBizFieldName() : existing.getBizFieldName());
         newDef.setModelJson(po.getModelJson());
         newDef.setDescription(po.getDescription());
-        Integer maxVersion = this.processDefinitionMapper.selectMaxVersion(po.getProcessCode());
+        Integer maxVersion = this.processDefinitionMapper.selectMaxVersion(po.getProcessCode(), existing.getCreateBy());
         newDef.setVersion((maxVersion != null ? maxVersion : existing.getVersion()) + 1);
         newDef.setStatus(DefinitionStatus.DESIGNING.getCode());
         newDef.setCreateBy(existing.getCreateBy());
@@ -97,6 +102,7 @@ public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
         if (existing == null) {
             throw new BusinessException("流程定义不存在");
         }
+        this.checkOwner(existing);
         if (!DefinitionStatus.DESIGNING.getCode().equals(existing.getStatus())
                 && !DefinitionStatus.HISTORICAL.getCode().equals(existing.getStatus())) {
             throw new BusinessException("只有设计中或已停用的流程才能删除");
@@ -118,6 +124,7 @@ public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
     @Override
     public ProcessDefinitionDTO getById(Long id) {
         ProcessDefinition po = this.processDefinitionMapper.selectById(id);
+        this.checkOwner(po);
         return ProcessDefinitionDTO.of(po);
     }
 
@@ -125,6 +132,8 @@ public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
     public PageResult<ProcessDefinitionDTO> page(Integer pageNum, Integer pageSize, String processCode, String processName, Integer status) {
         Page<ProcessDefinition> page = new Page<>(pageNum, pageSize);
         LambdaQueryWrapper<ProcessDefinition> wrapper = new LambdaQueryWrapper<>();
+        // 流程定义按创建人(商户账号)隔离,只能看到自己创建的流程
+        wrapper.eq(ProcessDefinition::getCreateBy, SecurityUtils.getUserId());
         if (processCode != null && !processCode.isEmpty()) {
             wrapper.like(ProcessDefinition::getProcessCode, processCode);
         }
@@ -147,8 +156,9 @@ public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
     public void publish(Long id) {
         ProcessDefinition definition = this.processDefinitionMapper.selectById(id);
         this.validateDesigning(definition);
-        // 查询并停用当前启用的同编码流程
-        this.disableOldVersion(definition.getProcessCode());
+        this.checkOwner(definition);
+        // 查询并停用当前创建人的同编码流程
+        this.disableOldVersion(definition.getProcessCode(), definition.getCreateBy());
         this.enableDefinition(id);
     }
 
@@ -159,6 +169,7 @@ public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
         if (definition == null) {
             throw new BusinessException("流程定义不存在");
         }
+        this.checkOwner(definition);
         if (!DefinitionStatus.ENABLED.getCode().equals(definition.getStatus())) {
             throw new BusinessException("只有启用中的流程才能停用");
         }
@@ -175,16 +186,17 @@ public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
         if (definition == null) {
             throw new BusinessException("流程定义不存在");
         }
+        this.checkOwner(definition);
         if (!DefinitionStatus.HISTORICAL.getCode().equals(definition.getStatus())) {
             throw new BusinessException("只有已停用的流程才能启用");
         }
-        this.disableOldVersion(definition.getProcessCode());
+        this.disableOldVersion(definition.getProcessCode(), definition.getCreateBy());
         this.enableDefinition(id);
     }
 
     @Override
     public List<ProcessDefinitionDTO> listEnabled() {
-        List<ProcessDefinition> list = this.processDefinitionMapper.selectEnabledList();
+        List<ProcessDefinition> list = this.processDefinitionMapper.selectEnabledList(SecurityUtils.getUserId());
         return list.stream()
                 .map(ProcessDefinitionDTO::of)
                 .collect(Collectors.toList());
@@ -199,14 +211,28 @@ public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {
         }
     }
 
-    private void disableOldVersion(String processCode) {
+    private void disableOldVersion(String processCode, Long ownerId) {
         LambdaUpdateWrapper<ProcessDefinition> wrapper = new LambdaUpdateWrapper<>();
         wrapper.eq(ProcessDefinition::getProcessCode, processCode)
+                .eq(ProcessDefinition::getCreateBy, ownerId)
                 .eq(ProcessDefinition::getStatus, DefinitionStatus.ENABLED.getCode())
                 .set(ProcessDefinition::getStatus, DefinitionStatus.HISTORICAL.getCode());
         this.processDefinitionMapper.update(null, wrapper);
     }
 
+    /**
+     * 流程定义按创建人隔离:只能操作自己(本商户账号)创建的流程。
+     * <p>创建人取自流程发起时的登录账号,商户通过 iframe 使用各自的 qqflow 账号。</p>
+     */
+    private void checkOwner(ProcessDefinition definition) {
+        if (definition == null) {
+            return;
+        }
+        if (!Objects.equals(definition.getCreateBy(), SecurityUtils.getUserId())) {
+            throw new BusinessException("无权操作该流程");
+        }
+    }
+
     private void enableDefinition(Long id) {
         LambdaUpdateWrapper<ProcessDefinition> wrapper = new LambdaUpdateWrapper<>();
         wrapper.eq(ProcessDefinition::getId, id)