
OpenProject 12.2.5 发布详解LDAP 组同步缺陷修复与未同步成员排查实践【免费下载链接】openprojectOpenProject is the leading open source project management software for product, project and portfolio management. A powerful Jira alternative with agile planning, issue tracking, roadmaps, Gantt charts, time tracking, collaboration features, and more. Available on premises or in the cloud. ⭐ Star us on GitHub项目地址: https://gitcode.com/GitHub_Trending/op/openprojectOpenProject 12.2.5 是 2022 年 10 月 4 日发布的补丁版本核心任务是修复 LDAP 组同步链路中的两处缺陷其中最值得关注的是同一同步批次中新增用户会导致已在 LDAP 中被移除的用户无法从 OpenProject 组中正确删除。本文以该版本发布说明为骨架结合 ldap_groups 模块的源码实现完整讲解缺陷成因、官方提供的ldap_groups:print_unsynced_members排查命令以及同步机制背后的原理帮助管理员准确评估影响面并完成升级与数据核对。版本概览版本号OpenProject 12.2.5发布日期2022-10-04版本类型补丁版本bugfix release官方在该版本中明确建议所有用户升级到最新版本升级方式包括打包安装的sudo openproject run系列命令与 Docker 部署的重建容器流程。本版本不包含新增功能全部变更聚焦于缺陷修复其中 LDAP 组同步相关的两个修复项构成了本次发布的主体。核心缺陷LDAP 组同步批次内的成员误删与残留缺陷现象发布说明中描述的缺陷链路如下管理员通过 LDAP 组同步功能将 LDAP 目录中的用户同步到 OpenProject 的内置用户组Group在同一个同步步骤中既有 LDAP 组内新增用户又存在被 LDAP 移除的用户此时本应从 OpenProject 组中删除的“被移除用户”没有按预期被清除最终导致这些用户在 LDAP 中已经不存在却仍然保留在 OpenProject 组内。从触发条件看该缺陷属于同步批次内的成员集合替换逻辑问题新增成员与移除成员在同一次update_memberships!调用中发生而移除判断依赖的成员快照被新增操作污染从而误判了哪些用户“仍然存在”。源码层面的成因分析在 ldap_groups 模块中同步的核心逻辑位于 synchronize_groups_service.rb。关键的update_memberships!方法第 86-96 行执行两阶段操作def update_memberships!(sync, users) # Remove group users no longer in ids no_longer_present ::LdapGroups::Membership.where(group_id: sync.id).where.not(user_id: users.select(:id)) remove_memberships!(no_longer_present, sync) # Add all current users from LDAP as members add_memberships!(users, sync) end第一阶段根据“当前 LDAP 成员集合”反查本地成员记录找出不再出现的用户并移除第二阶段再将 LDAP 中的当前成员全量加入。缺陷场景下同一步骤中新增用户会干扰成员快照的构建尤其是基于用户登录名映射时的大小写、重复记录处理使得remove_memberships!阶段拿到的“待移除列表”不完整被 LDAP 删除的用户因此漏删。模型层的增删实现位于 synchronized_group.rbadd_members!第 29-41 行在事务内通过Membership.insert_all批量写入同步成员关系并调用Groups::UpdateService将用户加入内部组remove_members!第 47-59 行在事务内先删除同步成员关系再从内部组移除用户任一步失败都会触发ActiveRecord::Rollback回滚。同步成员关系由 membership.rb 承载validates_uniqueness_of :user_id, scope: :group_id约束保证同一同步组内成员唯一这决定了同步必须依赖“全量比对、增量增删”的策略——也正是该缺陷暴露的位置。影响评估受影响的用户表现为在 LDAP 中已被移除但在 OpenProject 组中仍然存在该缺陷不会影响 LDAP 中仍然存在的用户也不会导致 LDAP 成员被误删由于系统无法判断这些残留用户是否本应保留例如管理员手动加入的成员12.2.5 未提供自动清理机制需要管理员借助诊断命令人工核对。官方排查命令ldap_groups:print_unsynced_members为帮助管理员发现上述残留用户12.2.5 引入了新的 rake 任务ldap_groups:print_unsynced_members其作用为遍历所有已同步的 LDAP 组打印出组内存在但并非源自 LDAP 同步的成员。打包安装Packaged installationsudo openproject run bundle exec rake ldap_groups:print_unsynced_membersDocker 安装docker exec -it web container ID bash -c bundle exec rake ldap_groups:print_unsynced_members其中web container ID需要替换为 OpenProject Web 容器的实际 ID可通过docker ps查看。命令的源码实现该任务定义于 ldap_groups.rake 的第 38-54 行task print_unsynced_members: :environment do LdapGroups::SynchronizedGroup .includes(:group) .find_each do |sync| group sync.group unsynced_logins User .where(id: group.user_ids) .where.not(id: sync.users.select(:user_id)) .pluck(:login) if unsynced_logins.any? puts In group #{group}, #{unsynced_logins.count} user(s) exist that are not synced from LDAP: puts unsynced_logins.join(, ) end end end核心比对逻辑清晰可读通过LdapGroups::SynchronizedGroup.includes(:group).find_each遍历所有同步组find_each分批加载避免内存暴涨对每个同步组取出内部组全部用户 IDgroup.user_ids与同步成员 IDsync.users.select(:user_id)用where.not求差集得到“在组内但不在同步记录中”的用户打印组名、残留用户数量与登录名列表逗号分隔。输出解读若所有同步组状态健康命令不输出任何组信息仅静默完成若存在残留输出格式为In group 组名, 数量 user(s) exist that are not synced from LDAP: login1, login2, ...管理员应逐一核对输出的登录名确认这些用户是否属于 LDAP 中已删除、但 OpenProject 侧未清理的情况再决定手动从组中移除。使用注意事项只读诊断该任务仅打印信息不会修改任何数据可安全在生产环境重复执行依赖环境需要应用数据库可访问且 Rails 环境正常加载task ... :environment会引导 Rails 启动适用范围仅覆盖已配置同步的组即存在LdapGroups::SynchronizedGroup记录的组手动创建的普通 OpenProject 组不在此列手动清理确认无误后可在 OpenProject 管理界面中从对应组移除这些用户或根据实际需要将其恢复为同步成员。同步机制的完整链路源码级为理解该缺陷的影响范围有必要梳理 ldap_groups 模块的同步全貌。顶层入口为 synchronization_service.rb执行顺序如下SynchronizationService.synchronize!以系统用户User.system.run_given身份执行同步保证权限一致遍历所有 LDAP 认证源LdapAuthSource.find_each对每个认证源先通过SynchronizeFilterService依据同步过滤器SynchronizedFilter发现/创建目录中的组再调用SynchronizeGroupsService逐个组同步成员即缺陷所在的synchronize_members链路任一环节异常均记录Rails.logger.error不中断其他组的同步。成员发现支持两种模式见 synchronize_groups_service.rb 第 101-109 行反向查找reverse lookup默认模式按memberOf组DN过滤 LDAP 用户适用于 Active Directory 与启用 memberof overlay 的 OpenLDAP正向查找forward lookup直接从组条目读取member_lookup_attribute如member、uniqueMember指向的 DN 列表再逐个解析适配groupOfNames/groupOfUniqueNames等模式。成员落库后同步关系LdapGroups::Membership与 OpenProject 内部用户组Group通过 synchronized_group.rb 的add_members!/remove_members!保持联动事务保证两处状态的一致性。本次修复的其他问题#41256LDAP 中移除的用户未从 OpenProject 组删除即上述核心缺陷。修复后同一同步批次内新增成员不再影响被移除成员的判定LDAP 中删除的用户能够正确地在 OpenProject 组中被同步移除。验证依据可在模块测试中查找例如 spec/services/synchronization_spec.rb 覆盖了同步服务的成员增删行为。#43892向组添加用户时自动补全显示已有用户该缺陷属于组管理界面的成员自动补全autocompleter问题在向用户组添加成员时候选列表中错误地显示了当前组已有的用户。修复后自动补全会正确排除已是组成员的对象避免管理员重复添加与界面误导。升级建议与操作清单升级版本将 OpenProject 升级至 12.2.5打包安装执行系统更新Docker 部署拉取最新镜像并重建容器运行诊断按部署方式执行ldap_groups:print_unsynced_members采集残留用户清单核对数据将输出与 LDAP 目录比对确认残留用户是否已在 LDAP 中被删除手动清理对确认应删除的成员在 OpenProject 管理界面的对应组中手动移除回归验证升级后再次触发一次 LDAP 组同步管理界面操作或执行bundle exec rake ldap_groups:synchronize确认新同步周期不再产生残留。总结OpenProject 12.2.5 是一次聚焦 LDAP 组同步正确性的补丁发布。对运维与管理员而言理解缺陷成因同步批次内成员集合替换与掌握ldap_groups:print_unsynced_members诊断命令是在升级前后准确评估数据一致性的关键。结合 ldap_groups 模块源码ldap_groups.rake、synchronize_groups_service.rb、synchronized_group.rb可以确认该版本未自动清理历史残留数据而是提供了安全、只读的排查手段把最终处置决策留给管理员这是兼顾正确性与数据安全的设计取舍。【免费下载链接】openprojectOpenProject is the leading open source project management software for product, project and portfolio management. A powerful Jira alternative with agile planning, issue tracking, roadmaps, Gantt charts, time tracking, collaboration features, and more. Available on premises or in the cloud. ⭐ Star us on GitHub项目地址: https://gitcode.com/GitHub_Trending/op/openproject创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考