-
-
Notifications
You must be signed in to change notification settings - Fork 305
🐛 fix(dingtalk): 修复钉钉部门同步的错误处理和日志记录 #403
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- 添加错误消息格式化并记录详细日志 - 改进错误提示信息,包含部门名称等上下文 🐛 fix(feishu): 修复飞书部门同步的错误处理和日志记录 - 添加错误消息格式化并记录详细日志 - 改进错误提示信息,包含部门名称等上下文 🐛 fix(openldap): 修复OpenLDAP同步的错误处理和日志记录 - 添加错误消息格式化并记录详细日志 - 改进错误提示信息,包含用户和部门名称等上下文 🐛 fix(sql): 修复SQL同步的错误处理和日志记录 - 添加错误消息格式化并记录详细日志 - 改进错误提示信息,包含用户和分组名称等上下文 🐛 fix(wecom): 修复企业微信同步的错误处理和日志记录 - 添加错误消息格式化并记录详细日志 - 改进错误提示信息,包含用户和部门名称等上下文 🔧 chore(logic): 统一添加common包导入 - 在所有逻辑文件中添加common包用于日志记录 📝 docs(logic): 添加详细的同步进度日志 - 在部门同步成功时记录成功日志 - 在用户同步时添加进度跟踪日志(当前序号/总数) - 在同步完成时统计并记录同步数量汇总信息
Walkthrough对多处逻辑文件统一接入公共日志(public/common),改造错误处理与信息化日志。飞书与企业微信用户同步增加离职用户处理与进度/汇总日志。飞书的部门与用户同步函数签名改为返回通用的 data、rspError。其余平台(钉钉、OpenLDAP、SQL→LDAP)主要为错误包装与上下文日志增强。 Changes
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
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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.
📒 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
| 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)) | ||
| } |
There was a problem hiding this comment.
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.
| 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.
| 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)) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
错误类型包装不当: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.
| errMsg := fmt.Sprintf("用户[%s]同步完毕之后更新状态失败:%s", user.Username, err.Error()) | ||
| common.Log.Errorf("SyncSqlUsers: %s", errMsg) | ||
| return nil, tools.NewLdapError(fmt.Errorf(errMsg)) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
错误类型包装不当: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.
| 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.
🐛 fix(feishu): 修复飞书部门同步的错误处理和日志记录
🐛 fix(openldap): 修复OpenLDAP同步的错误处理和日志记录
🐛 fix(sql): 修复SQL同步的错误处理和日志记录
🐛 fix(wecom): 修复企业微信同步的错误处理和日志记录
🔧 chore(logic): 统一添加common包导入
📝 docs(logic): 添加详细的同步进度日志
在提出此拉取请求时,我确认了以下几点(请复选框):
填写 PR 内容:
Summary by CodeRabbit