You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

38 lines
3.7 KiB

# 钉钉组织同步端点与管理员角色配置接口
Label: wayfinder:task
Type: task
Status: resolved
Blocked by: 04
## Question
在 crm-auth 实现两个接口,为联调铺设真实用户/组织数据:
1. **钉钉组织同步端点**(如 `POST /api/system/sync/dingtalk`,超管权限):
- 引入 `com.github.tingyugetc520:dt-java:0.1.2` 依赖(用法结论见票据 04 的研究成果)
- 复用 application.yml 现有钉钉配置与企业级 access token 能力(`DingTalkAuthClient.getCorpAccessToken`)
- 拉取部门树 → `sys_dept`;拉取部门下用户 → `auth_user`(姓名/手机号/钉钉 userid 作 account/部门挂载)
- **部门负责人是钉钉字段**(dept_manager_userid),随部门存入,不映射为系统角色
- 幂等 upsert:重跑不重复,钉钉侧改名可更新
2. **管理员角色配置接口**:给指定用户分配/回收管理员类角色(部门负责人/销售角色仍由角色管理体系承载,此接口只解决「同步进来的用户如何拿到角色」)
验收:同步全量组织后,用户列表/部门树接口能查到真实数据,角色配置接口可给 2~3 个用户配上角色。
## Answer
两个接口均落在 crm-auth,测试全绿(`DtOrgSyncServiceImplTest` 3/3、`AuthUserServiceImplTest` 11/11,排除 crm-lead 既有失败后全量 EXIT=0)。
1. **钉钉组织同步** `POST /api/system/sync/dingtalk`(`@PreAuthorize("hasRole('ADMIN')")`,`SystemController`):
- `DtOrgSyncServiceImpl`:部门链路用 dt-java SDK(`DtDepartmentService.list(null, true)`),用户链路因 dt-java 0.1.2 发布版 `DtUser``isLeaderInDeparts` 改为 Hutool HTTP 直调 `/topapi/user/listbypage`(与 `DingTalkAuthClient` 同款手法,分页 100 + 100ms 限流);企业 token 共享 Redis key `crm:auth:dingtalk:corp-token`
- 幂等键:`sys_dept.dt_dept_id`(新增字段 + 唯一索引 `uk_dt_dept_id`)匹配部门;`crm_auth_user.account`=钉钉 userid 匹配用户;unionId 写 `crm_auth_identity` 保证扫码登录映射。
- BFS 排序保证父部门先落库;主/兼职部门拆分(首个出现部门为主部门,其余 `sys_user_dept` 全量替换);`isLeaderInDepts` 聚合反写 `sys_dept.leader_user_id`(负责人只是部门字段,不映射角色);离职用户置 `employment_status=resigned` 不动 enabled;AtomicBoolean 防并发重入。
- 返回 `DtSyncResultDTO` 统计(部门/用户增改数、负责人反写数);失败统一错误码 61017 `CODE_DINGTALK_SYNC_FAIL`
2. **管理员角色配置** `POST /api/system/users/admin-role`(`@PreAuthorize("hasRole('ADMIN')")`):
- `IAuthUserService.configureAdminRoles(userId, roleCodes, grant)`:增量授予/回收,只动目标角色行(授予幂等、回收无则忽略),不影响其他角色;`roleCodes` 缺省 `ROLE_ADMIN`(`AuthConstants.ROLE_CODE_ADMIN`)。
- 校验顺序:userId null → codes 空 → 用户存在 → 角色编码存在;DTO 为 `ConfigureAdminRoleDTO`(ADR-0017 风格)。
已知边界:crm-lead `LeadServiceImplTest` 3 个「省份不能为空」失败为既有 committed 问题(必填误校验),归票据 07 盘点范围;`syncOrg()` 整体包在单个 `@Transactional` 内(含 HTTP 拉取),大规模组织下事务较长,若联调遇连接池/超时问题再拆小事务。
**真实同步验证挂起(用户确认「先留着」)**:端点链路已实测跑通(本地 :8081 verify profile,调试 token 见 `tmp/dt-token.txt`),但钉钉侧返回 errcode=60011——应用 `dingikqv3al2koirnku7` 未开通 `qyapi_get_department_list`(部门读)与 `qyapi_get_member`(成员读)权限。权限就绪后直接重试 `POST /api/system/sync/dingtalk` 即可,无需改代码。