Skip to content

Conversation

@eryajf
Copy link
Member

@eryajf eryajf commented Sep 2, 2025

  • 添加错误消息格式化并记录详细日志
  • 改进错误提示信息,包含部门名称等上下文

🐛 fix(feishu): 修复飞书部门同步的错误处理和日志记录

  • 添加错误消息格式化并记录详细日志
  • 改进错误提示信息,包含部门名称等上下文

🐛 fix(openldap): 修复OpenLDAP同步的错误处理和日志记录

  • 添加错误消息格式化并记录详细日志
  • 改进错误提示信息,包含用户和部门名称等上下文

🐛 fix(sql): 修复SQL同步的错误处理和日志记录

  • 添加错误消息格式化并记录详细日志
  • 改进错误提示信息,包含用户和分组名称等上下文

🐛 fix(wecom): 修复企业微信同步的错误处理和日志记录

  • 添加错误消息格式化并记录详细日志
  • 改进错误提示信息,包含用户和部门名称等上下文

🔧 chore(logic): 统一添加common包导入

  • 在所有逻辑文件中添加common包用于日志记录

📝 docs(logic): 添加详细的同步进度日志

  • 在部门同步成功时记录成功日志
  • 在用户同步时添加进度跟踪日志(当前序号/总数)
  • 在同步完成时统计并记录同步数量汇总信息

在提出此拉取请求时,我确认了以下几点(请复选框):

  • 我已阅读并理解贡献者指南
  • 我已检查没有与此请求重复的拉取请求。
  • 我已经考虑过,并确认这份呈件对其他人很有价值。
  • 我接受此提交可能不会被使用,并根据维护人员的意愿关闭拉取请求。

填写 PR 内容:

Summary by CodeRabbit

  • 新功能
    • 同步企业微信/飞书/钉钉/OpenLDAP/SQL→LDAP 时新增详细进度与完成摘要日志,包含逐用户/逐部门成功提示与统计
    • 离职用户处理增加逐条处理日志与最终汇总
  • 修复
    • 统一并强化错误提示与返回,在获取、转换、写入等关键步骤失败时提供可读信息并记录
  • 重构
    • 全面采用集中式日志记录,标准化错误信息格式,提升可观测性与排障效率

- 添加错误消息格式化并记录详细日志
- 改进错误提示信息,包含部门名称等上下文

🐛 fix(feishu): 修复飞书部门同步的错误处理和日志记录

- 添加错误消息格式化并记录详细日志
- 改进错误提示信息,包含部门名称等上下文

🐛 fix(openldap): 修复OpenLDAP同步的错误处理和日志记录

- 添加错误消息格式化并记录详细日志
- 改进错误提示信息,包含用户和部门名称等上下文

🐛 fix(sql): 修复SQL同步的错误处理和日志记录

- 添加错误消息格式化并记录详细日志
- 改进错误提示信息,包含用户和分组名称等上下文

🐛 fix(wecom): 修复企业微信同步的错误处理和日志记录

- 添加错误消息格式化并记录详细日志
- 改进错误提示信息,包含用户和部门名称等上下文

🔧 chore(logic): 统一添加common包导入

- 在所有逻辑文件中添加common包用于日志记录

📝 docs(logic): 添加详细的同步进度日志

- 在部门同步成功时记录成功日志
- 在用户同步时添加进度跟踪日志(当前序号/总数)
- 在同步完成时统计并记录同步数量汇总信息
@coderabbitai
Copy link

coderabbitai bot commented Sep 2, 2025

Walkthrough

对多处逻辑文件统一接入公共日志(public/common),改造错误处理与信息化日志。飞书与企业微信用户同步增加离职用户处理与进度/汇总日志。飞书的部门与用户同步函数签名改为返回通用的 data、rspError。其余平台(钉钉、OpenLDAP、SQL→LDAP)主要为错误包装与上下文日志增强。

Changes

Cohort / File(s) Summary
钉钉同步日志增强
logic/dingtalk_logic.go
统一错误信息格式与 common.Log 打点;完善部门/用户同步成功与失败日志;创建部门处增加错误判断与处理。
飞书同步与签名变更
logic/feishu_logic.go
引入 common.Log;统一 errMsg 构造与包装返回;部门同步完成日志;用户同步改为索引遍历并记录逐条成功;新增离职用户处理(获取、LDAP 删除、MySQL 状态更新、计数与汇总);函数签名改为返回 (data interface{}, rspError interface{})
OpenLDAP 同步日志增强
logic/openldap_logic.go
接入 common.Log;部门/用户同步各阶段增加上下文错误日志与完成日志;逐用户进度日志;对子部门递归与写入失败进行上下文包装。
SQL→LDAP 登录同步可观测性
logic/sqlToLdap_login.go
接入 common.Log;断言失败显式日志与 ReqAssertErr;用户/组查询、写入、状态更新与群组成员同步增加上下文错误与成功日志;保留管理员 DN 跳过逻辑并加强失败日志。
企业微信同步日志与离职处理
logic/wecom_logic.go
引入 common.Log;部门与用户同步统一错误包装;用户写入逐条成功日志;新增离职用户处理流程与 processedCount 统计,最终汇总日志;返回错误类型保持不变(Operation/MySql/Ldap)。

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Admin as 调度/调用方
  participant FeiShu as 飞书API
  participant Sync as SyncFeiShuUsers
  participant LDAP as LDAP
  participant MySQL as MySQL

  Admin->>Sync: 触发用户同步
  Sync->>FeiShu: GetAllUsers()
  FeiShu-->>Sync: 用户列表 or 错误
  alt 获取失败
    Sync-->>Admin: 返回包装后的错误并记录日志
  else 获取成功
    loop 遍历在职用户
      Sync->>Sync: ConvertUserData(单用户)
      alt 转换失败
        Sync-->>Admin: 返回包装后的错误并记录日志
      else
        Sync->>LDAP: 写入/更新用户
        alt 写入失败
          Sync-->>Admin: 返回包装后的错误并记录日志
        else
          Sync->>Sync: 记录单用户成功进度
        end
      end
    end
    Sync->>MySQL: 查询离职用户ID列表
    alt 查询失败
      Sync-->>Admin: 返回包装后的错误并记录日志
    else
      loop 遍历离职用户
        Sync->>MySQL: 查询用户记录
        alt 查询失败
          Sync-->>Admin: 返回MySQL错误并记录日志
        else
          Sync->>LDAP: 删除用户
          alt 删除失败
            Sync-->>Admin: 返回LDAP错误并记录日志
          else
            Sync->>MySQL: 更新用户状态为离职
            alt 更新失败
              Sync-->>Admin: 返回MySQL错误并记录日志
            else
              Sync->>Sync: processedCount++
            end
          end
        end
      end
      Sync->>Sync: 输出最终汇总日志
      Sync-->>Admin: 返回成功结果
    end
  end
Loading
sequenceDiagram
  autonumber
  actor Admin as 调度/调用方
  participant Src as 来源平台(API)
  participant DeptSync as 部门同步逻辑(addDepts)
  participant Log as common.Log

  Admin->>DeptSync: 触发部门同步
  DeptSync->>Src: 获取部门列表
  Src-->>DeptSync: 列表 or 错误
  alt 失败
    DeptSync->>Log: Errorf(获取失败)
    DeptSync-->>Admin: 返回包装错误
  else 成功
    DeptSync->>DeptSync: 转换为树结构
    alt 转换失败
      DeptSync->>Log: Errorf(转换失败)
      DeptSync-->>Admin: 返回包装错误
    else
      loop 递归创建部门
        DeptSync->>DeptSync: 创建部门
        alt 创建失败
          DeptSync->>Log: Errorf(包含部门名)
          DeptSync-->>Admin: 返回包装错误
        end
      end
      DeptSync->>Log: Infof(同步完成)
      DeptSync-->>Admin: 返回成功
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

我把日志胡萝卜排成行,
错误与进度,一口一口尝——
飞书与企微,离职也不慌;
LDAP 点头,SQL 递清香。
同步告成,耳朵竖得长,(=^‥^=)
月下轻跳,代码更明朗。

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat_print

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@eryajf eryajf merged commit 223e64c into main Sep 2, 2025
6 of 7 checks passed
@eryajf eryajf deleted the feat_print branch September 2, 2025 14:01
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (19)
logic/dingtalk_logic.go (4)

25-28: 统一用%w保留原始错误链并简化日志/返回构造

当前先拼接 errMsg 再 fmt.Errorf 会丢失原始错误类型,后续排障不便。建议直接日志打印原始 err,返回时用 %w 进行包裹。

示例修正(同类位置一并套用):

- errMsg := fmt.Sprintf("获取钉钉部门列表失败:%s", err.Error())
- common.Log.Errorf("SyncDingTalkDepts: %s", errMsg)
- return nil, tools.NewOperationError(fmt.Errorf(errMsg))
+ common.Log.Errorf("SyncDingTalkDepts: 获取钉钉部门列表失败: %v", err)
+ return nil, tools.NewOperationError(fmt.Errorf("获取钉钉部门列表失败: %w", err))

同理可应用于“转换钉钉部门数据失败”等处。

Also applies to: 31-34


56-66: 修正文案笔误并补充统一前缀,便于检索

日志中的前缀含有笔误“DsyncDingTalkDepts…”。建议统一为“SyncDingTalkDepts: …”,并同样使用 %w 包裹返回错误。

- errMsg := fmt.Sprintf("DsyncDingTalkDepts添加部门[%s]失败: %s", dept.GroupName, err.Error())
- common.Log.Errorf("%s", errMsg)
- return tools.NewOperationError(fmt.Errorf(errMsg))
+ common.Log.Errorf("SyncDingTalkDepts: 添加部门[%s]失败: %v", dept.GroupName, err)
+ return tools.NewOperationError(fmt.Errorf("添加部门[%s]失败: %w", dept.GroupName, err))

- errMsg := fmt.Sprintf("DsyncDingTalkDepts添加子部门失败: %s", err.Error())
- common.Log.Errorf("%s", errMsg)
- return tools.NewOperationError(fmt.Errorf(errMsg))
+ common.Log.Errorf("SyncDingTalkDepts: 添加子部门失败: %v", err)
+ return tools.NewOperationError(fmt.Errorf("添加子部门失败: %w", err))

120-121: 考虑改为结构化日志,便于检索与聚合

当前使用 Infof 字符串插值,建议使用 SugaredLogger 的 Infow/Errorw,输出键值对,后续在日志平台更易筛选统计。

- common.Log.Infof("SyncDingTalkUsers: 成功同步用户[%s] (%d/%d)", staff.Username, i+1, len(staffs))
+ common.Log.Infow("SyncDingTalkUsers: 成功同步用户",
+   "username", staff.Username, "index", i+1, "total", len(staffs))

同理可应用于汇总日志与错误日志。

Also applies to: 171-171


132-135: 离职用户处理流程清晰,MySQL/LDAP 错误分型得当;建议保留错误链

整体流程与错误类型选择合理。为提升可观测性与溯源性,建议在这些 return 处同样用 %w 进行包裹(参考前述做法)。

Also applies to: 148-151, 155-158, 162-166, 167-171

logic/feishu_logic.go (4)

25-28: 用 %w 包裹错误,避免丢失原始错误链

同钉钉模块建议,移除中间 errMsg 变量,直接日志 + 包裹返回。

- errMsg := fmt.Sprintf("获取飞书部门列表失败:%s", err.Error())
- common.Log.Errorf("SyncFeiShuDepts: %s", errMsg)
- return nil, tools.NewOperationError(fmt.Errorf(errMsg))
+ common.Log.Errorf("SyncFeiShuDepts: 获取飞书部门列表失败: %v", err)
+ return nil, tools.NewOperationError(fmt.Errorf("获取飞书部门列表失败: %w", err))

同理用于“转换飞书部门数据失败”等位置。

Also applies to: 31-34


56-66: 修正文案笔误并统一前缀

“DsyncFeiShuDepts…”前缀存在笔误;建议统一为“SyncFeiShuDepts: …”,并用 %w 包裹错误。

- errMsg := fmt.Sprintf("DsyncFeiShuDepts添加部门[%s]失败: %s", dept.GroupName, err.Error())
- common.Log.Errorf("%s", errMsg)
- return tools.NewOperationError(fmt.Errorf(errMsg))
+ common.Log.Errorf("SyncFeiShuDepts: 添加部门[%s]失败: %v", dept.GroupName, err)
+ return tools.NewOperationError(fmt.Errorf("添加部门[%s]失败: %w", dept.GroupName, err))

- errMsg := fmt.Sprintf("DsyncFeiShuDepts添加子部门失败: %s", err.Error())
- common.Log.Errorf("%s", errMsg)
- return tools.NewOperationError(fmt.Errorf(errMsg))
+ common.Log.Errorf("SyncFeiShuDepts: 添加子部门失败: %v", err)
+ return tools.NewOperationError(fmt.Errorf("添加子部门失败: %w", err))

113-122: 进度与汇总日志增加可观测性,改为结构化日志更佳

当前做法可用,建议按需升级为 Infow/Errorw 形式。

Also applies to: 165-166


125-131: 确认 unionID 规范一致,离职用户处理路径合理;可选:改用 %w 包裹错误

  • feishu.GetLeaveUserIds 已使用 lark.IDTypeUnionID 查询 unionID;BuildUserData 也按 flag_unionId 写入 SourceUnionId [已验证]
  • 可选:将 fmt.Errorf(errMsg) 改为 fmt.Errorf("获取飞书离职用户列表失败:%w", err) 以保留底层错误
logic/wecom_logic.go (4)

25-28: 错误链保留与返回包装建议(%w)

与其他模块保持一致,直接日志 + %w 包裹,减少信息损失。

- errMsg := fmt.Sprintf("获取企业微信部门列表失败:%s", err.Error())
- common.Log.Errorf("SyncWeComDepts: %s", errMsg)
- return nil, tools.NewOperationError(fmt.Errorf(errMsg))
+ common.Log.Errorf("SyncWeComDepts: 获取企业微信部门列表失败: %v", err)
+ return nil, tools.NewOperationError(fmt.Errorf("获取企业微信部门列表失败: %w", err))

Also applies to: 31-34


56-66: 修正文案笔误并统一日志前缀

“DsyncWeComDepts…”前缀有笔误;统一成“SyncWeComDepts: …”,并使用 %w 包裹返回。

- errMsg := fmt.Sprintf("DsyncWeComDepts添加部门[%s]失败: %s", dept.GroupName, err.Error())
- common.Log.Errorf("%s", errMsg)
- return tools.NewOperationError(fmt.Errorf(errMsg))
+ common.Log.Errorf("SyncWeComDepts: 添加部门[%s]失败: %v", dept.GroupName, err)
+ return tools.NewOperationError(fmt.Errorf("添加部门[%s]失败: %w", dept.GroupName, err))

- errMsg := fmt.Sprintf("DsyncWeComDepts添加子部门失败: %s", err.Error())
- common.Log.Errorf("%s", errMsg)
- return tools.NewOperationError(fmt.Errorf(errMsg))
+ common.Log.Errorf("SyncWeComDepts: 添加子部门失败: %v", err)
+ return tools.NewOperationError(fmt.Errorf("添加子部门失败: %w", err))

102-111: 用户列表获取/转换的错误处理与日志格式统一,建议引入 %w

与上文相同,建议保留错误链。


113-122: 进度与汇总日志补充到位

增加了逐条与最终汇总信息,便于观测。可按需演进为结构化日志。

Also applies to: 177-177

logic/sqlToLdap_login.go (5)

57-65: 可选:跳过 OU 容器,避免把用户加入 OU DN。

与 openldap_logic.AddUsers 的处理保持一致,减少无效 LDAP 调用与错误日志。

     for _, group := range groups {
-      //根据选择的部门,添加到部门内
+      // 跳过 OU 容器,仅向可承载成员的实体组添加
+      if strings.HasPrefix(strings.ToLower(group.GroupDN), "ou=") {
+        continue
+      }
+      // 根据选择的部门,添加到部门内
       err = ildap.Group.AddUserToGroup(group.GroupDN, user.UserDN)

需要在本文件 import strings。

import (
    "fmt"
+   "strings"
    ...
)

22-24: 日志补充上下文:打印请求实际类型。

便于快速定位断言失败原因。

- common.Log.Errorf("SyncSqlUsers: %s", errMsg)
+ common.Log.Errorf("SyncSqlUsers: %s, got type=%T", errMsg, req)

83-85: 日志补充上下文:打印请求实际类型。

同上,提升排障效率。

- common.Log.Errorf("SyncSqlGroups: %s", errMsg)
+ common.Log.Errorf("SyncSqlGroups: %s, got type=%T", errMsg, req)

104-130: 可选:分组同步也增加进度日志。

与用户同步一致,输出 (index/total) 更直观。

- for _, group := range groups {
+ for j, group := range groups {
    err = ildap.Group.Add(group)
    if err != nil {
      ...
    }
    ...
    err = isql.Group.ChangeSyncState(int(group.ID), 1)
    if err != nil {
      ...
    }
+   common.Log.Infof("SyncSqlGroups: 成功同步分组[%s] (%d/%d)", group.GroupName, j+1, len(groups))
 }

28-37: 可选:避免逐个 Exist 查询的 N+1 次 DB 访问。

一次性拉取并校验缺失 ID,友好提示所有缺失项,减少往返。

我可以提供一个基于 map 校验缺失 ID 的实现,是否需要我补一个小改动?

logic/openldap_logic.go (2)

57-60: 日志前缀/拼写错误(DsyncOpenLdapDepts)。

修正为一致的模块前缀,便于检索。

- errMsg := fmt.Sprintf("DsyncOpenLdapDepts添加部门[%s]失败: %s", dept.GroupName, err.Error())
+ errMsg := fmt.Sprintf("SyncOpenLdapDepts: 添加部门[%s]失败:%s", dept.GroupName, err.Error())
...
- errMsg := fmt.Sprintf("DsyncOpenLdapDepts添加子部门失败: %s", err.Error())
- common.Log.Errorf("%s", errMsg)
+ errMsg := fmt.Sprintf("SyncOpenLdapDepts: 添加子部门失败(父部门:%s):%s", dept.GroupName, err.Error())
+ common.Log.Errorf("%s", errMsg)

Also applies to: 64-67


133-136: 可选:角色查询失败更适合标记为 MySqlErr/OperationErr。

此处是从 DB 取角色失败,使用 ValidatorErr 语义不直观。

- return nil, tools.NewValidatorError(fmt.Errorf(errMsg))
+ return nil, tools.NewMySqlError(fmt.Errorf(errMsg))

或使用 tools.NewOperationError 也可。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 06b6c87 and 0293d38.

📒 Files selected for processing (5)
  • logic/dingtalk_logic.go (6 hunks)
  • logic/feishu_logic.go (5 hunks)
  • logic/openldap_logic.go (6 hunks)
  • logic/sqlToLdap_login.go (3 hunks)
  • logic/wecom_logic.go (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
logic/dingtalk_logic.go (5)
public/common/logger.go (1)
  • Log (17-17)
public/tools/http.go (3)
  • NewOperationError (55-57)
  • NewMySqlError (40-42)
  • NewLdapError (50-52)
logic/a_logic.go (4)
  • ConvertDeptData (305-314)
  • GroupListToTree (398-403)
  • ConvertUserData (317-333)
  • User (23-23)
model/user.go (1)
  • User (5-28)
service/isql/a_isql.go (1)
  • User (4-4)
logic/openldap_logic.go (3)
public/common/logger.go (1)
  • Log (17-17)
public/tools/http.go (3)
  • NewOperationError (55-57)
  • NewMySqlError (40-42)
  • NewValidatorError (45-47)
model/group.go (1)
  • Group (7-22)
logic/sqlToLdap_login.go (7)
public/common/logger.go (1)
  • Log (17-17)
logic/a_logic.go (3)
  • ReqAssertErr (20-20)
  • User (23-23)
  • Group (24-24)
model/user.go (1)
  • User (5-28)
public/tools/http.go (2)
  • NewMySqlError (40-42)
  • NewLdapError (50-52)
model/group.go (1)
  • Group (7-22)
public/tools/slice_cmp.go (1)
  • StringToSlice (89-100)
model/request/group_req.go (1)
  • SyncSqlGrooupsReq (116-118)
logic/feishu_logic.go (6)
public/common/logger.go (1)
  • Log (17-17)
public/tools/http.go (3)
  • NewOperationError (55-57)
  • NewMySqlError (40-42)
  • NewLdapError (50-52)
logic/a_logic.go (5)
  • ConvertDeptData (305-314)
  • FeiShu (30-30)
  • GroupListToTree (398-403)
  • ConvertUserData (317-333)
  • User (23-23)
public/client/feishu/feishu.go (1)
  • GetLeaveUserIds (217-230)
model/user.go (1)
  • User (5-28)
service/isql/a_isql.go (1)
  • User (4-4)
logic/wecom_logic.go (5)
public/common/logger.go (1)
  • Log (17-17)
public/tools/http.go (3)
  • NewOperationError (55-57)
  • NewMySqlError (40-42)
  • NewLdapError (50-52)
logic/a_logic.go (4)
  • ConvertDeptData (305-314)
  • GroupListToTree (398-403)
  • ConvertUserData (317-333)
  • User (23-23)
model/user.go (1)
  • User (5-28)
public/tools/type.go (1)
  • H (6-6)
🔇 Additional comments (4)
logic/dingtalk_logic.go (2)

101-104: 用户同步阶段的错误处理与进度日志一致性良好

获取与转换失败统一包装,且加入逐条进度日志,便于观测。

Also applies to: 107-110, 116-121


139-149: 无需修改:DingTalk SourceUserId 赋值与匹配规则一致
BuildUserData 中对 sourceUserId 使用 fmt.Sprintf("%s_%s", flag, …) 的写入方式,已与 SyncDingTalkUsers 中按 fmt.Sprintf("%s_%s", config.Conf.DingTalk.Flag, uid) 的匹配规则保持一致,无需调整。

logic/wecom_logic.go (1)

150-175: 确认 SourceUserId 前缀一致,无需修改
BuildUserData 已在 logic/a_logic.go:296 使用 fmt.Sprintf("%s_%s", flag, …) 为 SourceUserId 添加 WeCom.Flag 前缀,与 logic/wecom_logic.go 查询时的 “source_user_id” 完全一致。

logic/openldap_logic.go (1)

23-26: 整体 LGTM:错误包装与进度/汇总日志清晰一致。

  • 失败路径统一先记录上下文再返回 typed 错误。
  • 用户同步过程中的逐条与汇总日志完整。

Also applies to: 118-121, 162-166

Comment on lines +43 to 73
for i, user := range users {
err = ildap.User.Add(&user)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("SyncUser向LDAP同步用户失败:" + err.Error()))
errMsg := fmt.Sprintf("向LDAP同步用户[%s]失败:%s", user.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewLdapError(fmt.Errorf(errMsg))
}
// 获取用户将要添加的分组
groups, err := isql.Group.GetGroupByIds(tools.StringToSlice(user.DepartmentId, ","))
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("根据部门ID获取部门信息失败" + err.Error()))
errMsg := fmt.Sprintf("用户[%s]根据部门ID获取部门信息失败: %s", user.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
}
for _, group := range groups {
//根据选择的部门,添加到部门内
err = ildap.Group.AddUserToGroup(group.GroupDN, user.UserDN)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("向Ldap添加用户到分组关系失败:" + err.Error()))
errMsg := fmt.Sprintf("向Ldap添加用户[%s]到分组[%s]失败:%s", user.Username, group.GroupName, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
}
}
err = isql.User.ChangeSyncState(int(user.ID), 1)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("用户同步完毕之后更新状态失败:" + err.Error()))
errMsg := fmt.Sprintf("用户[%s]同步完毕之后更新状态失败:%s", user.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewLdapError(fmt.Errorf(errMsg))
}
common.Log.Infof("SyncSqlUsers: 成功同步用户[%s] (%d/%d)", user.Username, i+1, len(users))
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

避免对 range 变量取址导致潜在错误。

&user 取的是循环变量地址,若后续被异步保存或闭包捕获会出错;改为取切片元素地址更安全。

- for i, user := range users {
-   err = ildap.User.Add(&user)
+ for i := range users {
+   u := &users[i]
+   err = ildap.User.Add(u)
    if err != nil {
-     errMsg := fmt.Sprintf("向LDAP同步用户[%s]失败:%s", user.Username, err.Error())
+     errMsg := fmt.Sprintf("向LDAP同步用户[%s]失败:%s", u.Username, err.Error())
      common.Log.Errorf("SyncSqlUsers: %s", errMsg)
      return nil, tools.NewLdapError(fmt.Errorf(errMsg))
    }
    // 获取用户将要添加的分组
-   groups, err := isql.Group.GetGroupByIds(tools.StringToSlice(user.DepartmentId, ","))
+   groups, err := isql.Group.GetGroupByIds(tools.StringToSlice(u.DepartmentId, ","))
    if err != nil {
-     errMsg := fmt.Sprintf("用户[%s]根据部门ID获取部门信息失败: %s", user.Username, err.Error())
+     errMsg := fmt.Sprintf("用户[%s]根据部门ID获取部门信息失败: %s", u.Username, err.Error())
      common.Log.Errorf("SyncSqlUsers: %s", errMsg)
      return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
    }
    for _, group := range groups {
      //根据选择的部门,添加到部门内
-     err = ildap.Group.AddUserToGroup(group.GroupDN, user.UserDN)
+     err = ildap.Group.AddUserToGroup(group.GroupDN, u.UserDN)
      if err != nil {
-       errMsg := fmt.Sprintf("向Ldap添加用户[%s]到分组[%s]失败:%s", user.Username, group.GroupName, err.Error())
+       errMsg := fmt.Sprintf("向Ldap添加用户[%s]到分组[%s]失败:%s", u.Username, group.GroupName, err.Error())
        common.Log.Errorf("SyncSqlUsers: %s", errMsg)
        return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
      }
    }
-   err = isql.User.ChangeSyncState(int(user.ID), 1)
+   err = isql.User.ChangeSyncState(int(u.ID), 1)
    if err != nil {
-     errMsg := fmt.Sprintf("用户[%s]同步完毕之后更新状态失败:%s", user.Username, err.Error())
+     errMsg := fmt.Sprintf("用户[%s]同步完毕之后更新状态失败:%s", u.Username, err.Error())
      common.Log.Errorf("SyncSqlUsers: %s", errMsg)
      return nil, tools.NewLdapError(fmt.Errorf(errMsg))
    }
-   common.Log.Infof("SyncSqlUsers: 成功同步用户[%s] (%d/%d)", user.Username, i+1, len(users))
+   common.Log.Infof("SyncSqlUsers: 成功同步用户[%s] (%d/%d)", u.Username, i+1, len(users))
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for i, user := range users {
err = ildap.User.Add(&user)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("SyncUser向LDAP同步用户失败:" + err.Error()))
errMsg := fmt.Sprintf("向LDAP同步用户[%s]失败:%s", user.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewLdapError(fmt.Errorf(errMsg))
}
// 获取用户将要添加的分组
groups, err := isql.Group.GetGroupByIds(tools.StringToSlice(user.DepartmentId, ","))
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("根据部门ID获取部门信息失败" + err.Error()))
errMsg := fmt.Sprintf("用户[%s]根据部门ID获取部门信息失败: %s", user.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
}
for _, group := range groups {
//根据选择的部门,添加到部门内
err = ildap.Group.AddUserToGroup(group.GroupDN, user.UserDN)
if err != nil {
return nil, tools.NewMySqlError(fmt.Errorf("向Ldap添加用户到分组关系失败:" + err.Error()))
errMsg := fmt.Sprintf("向Ldap添加用户[%s]到分组[%s]失败:%s", user.Username, group.GroupName, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
}
}
err = isql.User.ChangeSyncState(int(user.ID), 1)
if err != nil {
return nil, tools.NewLdapError(fmt.Errorf("用户同步完毕之后更新状态失败:" + err.Error()))
errMsg := fmt.Sprintf("用户[%s]同步完毕之后更新状态失败:%s", user.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewLdapError(fmt.Errorf(errMsg))
}
common.Log.Infof("SyncSqlUsers: 成功同步用户[%s] (%d/%d)", user.Username, i+1, len(users))
}
for i := range users {
u := &users[i]
err = ildap.User.Add(u)
if err != nil {
errMsg := fmt.Sprintf("向LDAP同步用户[%s]失败:%s", u.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewLdapError(fmt.Errorf(errMsg))
}
// 获取用户将要添加的分组
groups, err := isql.Group.GetGroupByIds(tools.StringToSlice(u.DepartmentId, ","))
if err != nil {
errMsg := fmt.Sprintf("用户[%s]根据部门ID获取部门信息失败: %s", u.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
}
for _, group := range groups {
// 根据选择的部门,添加到部门内
err = ildap.Group.AddUserToGroup(group.GroupDN, u.UserDN)
if err != nil {
errMsg := fmt.Sprintf("向Ldap添加用户[%s]到分组[%s]失败:%s", u.Username, group.GroupName, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
}
}
err = isql.User.ChangeSyncState(int(u.ID), 1)
if err != nil {
errMsg := fmt.Sprintf("用户[%s]同步完毕之后更新状态失败:%s", u.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewLdapError(fmt.Errorf(errMsg))
}
common.Log.Infof("SyncSqlUsers: 成功同步用户[%s] (%d/%d)", u.Username, i+1, len(users))
}
🤖 Prompt for AI Agents
In logic/sqlToLdap_login.go around lines 43-73, the loop takes the address of
the range variable (&user) which can point to the same memory across iterations
and cause subtle bugs; change the loop to index into the slice and use a stable
pointer to the actual element (for example iterate with "for i := range users {
u := &users[i] }" and then replace uses of user or &user with u), ensuring all
subsequent calls (ildap.User.Add, isql calls, Group.AddUserToGroup,
ChangeSyncState, logging) reference the element pointer or its fields via u.

Comment on lines +61 to 64
errMsg := fmt.Sprintf("向Ldap添加用户[%s]到分组[%s]失败:%s", user.Username, group.GroupName, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

错误类型包装不当:LDAP 操作用 MySqlError。

将 LDAP 分组添加失败包装为 LdapErr,便于上层准确识别与分类处理。

-            return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
+            return nil, tools.NewLdapError(fmt.Errorf(errMsg))
🤖 Prompt for AI Agents
In logic/sqlToLdap_login.go around lines 61 to 64, the LDAP failure is being
wrapped as a MySqlError; change it to wrap as an LDAP error type so callers can
distinguish LDAP vs MySQL failures. Replace the tools.NewMySqlError(...) with
the appropriate LDAP error wrapper (e.g., tools.NewLdapErr or
tools.NewLdapError), passing the original error (or the formatted errMsg) into
that constructor; if the LDAP error wrapper doesn't exist, add a tools helper to
create a typed LdapErr that preserves the underlying error and message, then
return that instead.

Comment on lines +68 to 71
errMsg := fmt.Sprintf("用户[%s]同步完毕之后更新状态失败:%s", user.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewLdapError(fmt.Errorf(errMsg))
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

错误类型包装不当:DB 更新用 LdapError。

这里是 MySQL 更新状态失败,应包装为 MySqlErr。

-            return nil, tools.NewLdapError(fmt.Errorf(errMsg))
+            return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
errMsg := fmt.Sprintf("用户[%s]同步完毕之后更新状态失败:%s", user.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewLdapError(fmt.Errorf(errMsg))
}
errMsg := fmt.Sprintf("用户[%s]同步完毕之后更新状态失败:%s", user.Username, err.Error())
common.Log.Errorf("SyncSqlUsers: %s", errMsg)
return nil, tools.NewMySqlError(fmt.Errorf(errMsg))
}
🤖 Prompt for AI Agents
In logic/sqlToLdap_login.go around lines 68 to 71, the code wraps a MySQL update
failure in tools.NewLdapError; change the wrapper to the appropriate MySql error
constructor (e.g. tools.NewMySqlErr) and pass/wrap the original err (not just a
new formatted error string) so the returned error reflects a database failure
and preserves the original error details; keep the existing log but consider
logging the original err as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants