link2fun преди 1 седмица
родител
ревизия
38ea7b7b60

+ 52 - 11
maxkey-synchronizers/maxkey-synchronizer-workweixin/src/main/java/org/dromara/maxkey/synchronizer/workweixin/WorkweixinOrganizationService.java

@@ -66,14 +66,19 @@ public class WorkweixinOrganizationService extends AbstractSynchronizerService i
             // 关键字段不能依赖映射关系,否则映射数据有问题会导致功能异常
             // 先拿出字段映射关系
             Map<String, String> fieldMap = getFieldMap(Long.parseLong(synchronizer.getId()));
+            // 从映射里面拿到企业微信Id映射后的本地组织的字段 用于判断本地的组织是否存在
+            String targetIdField = getLocalFieldMappingByWx(fieldMap, "id");
 
             for (WorkWeixinDepts deptWxCur : deptWxListAfterLevelSort) {
                 _logger.debug("sync workweixin dept : {} {} {}", deptWxCur.getId(), deptWxCur.getName(), deptWxCur.getParentid());
                 //root
                 if (deptWxCur.getId() == ROOT_DEPT_ID) {
                     // 当前根节点
-                    // 先查询本地根节点, 这里可能有问题, ROOT_ORG_ID的组织可能不存在(原本的被删除了), 这里先假设存在
                     Organizations rootOrganization = organizationsService.get(Organizations.ROOT_ORG_ID);
+                    if (rootOrganization == null) {
+                        _logger.error("根组织不存在(ID: {}), 无法同步企业微信根部门", Organizations.ROOT_ORG_ID);
+                        throw new RuntimeException("根组织不存在, 同步失败! 请先确保系统中存在根组织(ID: " + Organizations.ROOT_ORG_ID + ")");
+                    }
                     // 构建同步关系
                     SynchroRelated rootSynchroRelated = buildSynchroRelated(rootOrganization, deptWxCur);
                     // 更新同步关系
@@ -98,9 +103,8 @@ public class WorkweixinOrganizationService extends AbstractSynchronizerService i
                     // 这里需要修正一下层级关系, 防止因为映射关系错误导致的层级错乱
                     String deptWxParentId = String.valueOf(deptWxCur.getParentid());
                     // 进入到这个节点的应该都是有上级的, 现在只需要根据上级Id查询上级的组织档案
-                    String targetIdField = getLocalFieldMappingByWx(fieldMap, "id"); // 从映射里面拿到企业微信Id映射后的本地组织的字段
-                    Organizations parentOrg = organizationsService.findOne(targetIdField + "   = ? and instId = ? ",
-                            new Object[]{deptWxParentId, this.synchronizer.getInstId()}, new int[]{Types.VARCHAR, Types.VARCHAR});
+
+                    Organizations parentOrg = findOrganizationByField(targetIdField, deptWxParentId);
                     // 这里父级不应该为 null
                     if (parentOrg == null) {
                         throw new RuntimeException("无法找到上级组织, 同步失败! 企业微信父部门Id: " + deptWxParentId);
@@ -125,16 +129,16 @@ public class WorkweixinOrganizationService extends AbstractSynchronizerService i
                         synchroRelated = buildSynchroRelated(orgCurrent, deptWxCur);
                     } else {
                         // 部门曾经同步过, 但是不能保证没被删除过, 所以还需要判定一次
-                        Organizations currentOrg = organizationsService.findOne(targetIdField + "   = ? and instId = ? ",
-                                new Object[]{deptWxCur.getId(), this.synchronizer.getInstId()}, new int[]{Types.VARCHAR, Types.VARCHAR});
+                        Organizations currentOrg = findOrganizationByField(targetIdField, String.valueOf(deptWxCur.getId()));
                         if (currentOrg == null) {
                             // 当前部门已经被删除, 那就需要重新写入一次
                             orgCurrent.setId(synchroRelated.getObjectId());
                             organizationsService.insert(orgCurrent);
+                        } else {
+                            // 组织存在, 执行更新操作
+                            orgCurrent.setId(synchroRelated.getObjectId());
+                            organizationsService.update(orgCurrent);
                         }
-
-                        orgCurrent.setId(synchroRelated.getObjectId());
-                        organizationsService.update(orgCurrent);
                     }
 
                     synchroRelatedService.updateSynchroRelated(
@@ -143,7 +147,8 @@ public class WorkweixinOrganizationService extends AbstractSynchronizerService i
             }
 
         } catch (Exception e) {
-            e.printStackTrace();
+            _logger.error("同步企业微信组织失败", e);
+            throw new RuntimeException("同步企业微信组织失败: " + e.getMessage(), e);
         }
 
     }
@@ -210,7 +215,9 @@ public class WorkweixinOrganizationService extends AbstractSynchronizerService i
                 return orgProperty;
             }
         }
-        throw new RuntimeException("未找到企业微信字段映射后的本地字段");
+        throw new RuntimeException(String.format(
+                "未找到企业微信字段'%s'映射后的本地字段,请检查同步器(ID: %s)的字段映射配置",
+                expectField, this.synchronizer.getId()));
     }
 
     /**
@@ -265,6 +272,40 @@ public class WorkweixinOrganizationService extends AbstractSynchronizerService i
     }
 
     /**
+     * 验证字段名是否合法,防止SQL注入
+     *
+     * @param fieldName 字段名
+     * @throws IllegalArgumentException 如果字段名不合法
+     */
+    private void validateFieldName(String fieldName) {
+        if (fieldName == null || fieldName.trim().isEmpty()) {
+            throw new IllegalArgumentException("字段名不能为空");
+        }
+        // 只允许字母、数字、下划线,且必须以字母或下划线开头
+        if (!fieldName.matches("^[a-zA-Z_][a-zA-Z0-9_]*$")) {
+            throw new IllegalArgumentException("非法的字段名: " + fieldName + ", 字段名只能包含字母、数字和下划线,且必须以字母或下划线开头");
+        }
+    }
+
+    /**
+     * 根据指定字段查询组织
+     *
+     * @param fieldName  字段名
+     * @param fieldValue 字段值
+     * @return 查询到的组织,如果不存在返回null
+     */
+    private Organizations findOrganizationByField(String fieldName, String fieldValue) {
+        // 验证字段名防止SQL注入
+        validateFieldName(fieldName);
+
+        return organizationsService.findOne(
+                fieldName + " = ? AND instId = ?",
+                new Object[]{fieldValue, this.synchronizer.getInstId()},
+                new int[]{Types.VARCHAR, Types.VARCHAR}
+        );
+    }
+
+    /**
      * 对部门列表进行排序,确保父节点在前,子节点在后
      * 使用拓扑排序算法,按照层级顺序遍历部门树
      *