|
|
@@ -0,0 +1,203 @@
|
|
|
+package com.malk.service.dingtalk.impl;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.malk.server.common.McException;
|
|
|
+import com.malk.service.dingtalk.DDClient_Role;
|
|
|
+import com.malk.utils.UtilHttp;
|
|
|
+import com.malk.utils.UtilMap;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class DDImplClient_Role implements DDClient_Role {
|
|
|
+
|
|
|
+ private static final String OAPI = "https://oapi.dingtalk.com";
|
|
|
+
|
|
|
+ /** 钉钉员工角色批量增/删接口单批用户上限(addrolesforemps 文档限 20) */
|
|
|
+ private static final int USER_BATCH_SIZE = 20;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 钉钉老接口响应直接平铺(无 result 嵌套):
|
|
|
+ * { "errcode":0, "errmsg":"ok", "deptVisibleScopes":[...], "userVisibleScopes":[...], "isHidden":false }
|
|
|
+ * 用 UtilHttp 拿原始字符串自解析,绕开 DDR.result 字段限制。
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Map getMicroAppVisibleScopes(String access_token, long agentId) {
|
|
|
+ Map param = UtilMap.map("access_token", access_token);
|
|
|
+ Map body = UtilMap.map("agentId", agentId);
|
|
|
+ String raw = post(OAPI + "/microapp/visible_scopes", param, body);
|
|
|
+ Map rsp = JSON.parseObject(raw, Map.class);
|
|
|
+ assertDingSuccess(rsp);
|
|
|
+ log.info("[钉钉] 应用可见范围查询成功, agentId={}, 部门数={}, 用户数={}",
|
|
|
+ agentId, collectionSize(rsp.get("deptVisibleScopes")), collectionSize(rsp.get("userVisibleScopes")));
|
|
|
+ return rsp;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String roleGroupCreate(String access_token, String name) {
|
|
|
+ Map param = UtilMap.map("access_token", access_token);
|
|
|
+ Map body = UtilMap.map("name", name);
|
|
|
+ String raw = post(OAPI + "/topapi/role/add_role_group", param, body);
|
|
|
+ Map rsp = JSON.parseObject(raw, Map.class);
|
|
|
+ assertDingSuccess(rsp);
|
|
|
+ Object groupId = rsp.get("groupId");
|
|
|
+ if (groupId == null && rsp.get("result") instanceof Map) {
|
|
|
+ groupId = ((Map) rsp.get("result")).get("groupId");
|
|
|
+ }
|
|
|
+ log.info("[钉钉] 创建角色组成功, groupId={}", groupId);
|
|
|
+ return groupId == null ? null : String.valueOf(groupId);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void assertDingSuccess(Map rsp) {
|
|
|
+ Object errcode = rsp.get("errcode");
|
|
|
+ if (errcode != null && !"0".equals(String.valueOf(errcode))) {
|
|
|
+ throw new McException("502", "dingtalk errcode=" + errcode + ", errmsg=" + rsp.get("errmsg"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String roleCreate(String access_token, String roleName, String groupId) {
|
|
|
+ Map param = UtilMap.map("access_token", access_token);
|
|
|
+ Map body = UtilMap.map("roleName, groupId", roleName, groupId);
|
|
|
+ String raw = post(OAPI + "/topapi/role/add_role", param, body);
|
|
|
+ Map rsp = JSON.parseObject(raw, Map.class);
|
|
|
+ assertDingSuccess(rsp);
|
|
|
+ Object roleId = rsp.get("roleId");
|
|
|
+ if (roleId == null && rsp.get("result") instanceof Map) {
|
|
|
+ roleId = ((Map) rsp.get("result")).get("roleId");
|
|
|
+ }
|
|
|
+ log.info("[钉钉] 创建角色成功, groupId={}, roleId={}", groupId, roleId);
|
|
|
+ return roleId == null ? null : String.valueOf(roleId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void roleAddUsers(String access_token, String roleId, Collection<String> userIds) {
|
|
|
+ callBatch(access_token, OAPI + "/topapi/role/addrolesforemps", roleId, userIds, "add");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void roleDeleteUsers(String access_token, String roleId, Collection<String> userIds) {
|
|
|
+ callBatch(access_token, OAPI + "/topapi/role/removerolesforemps", roleId, userIds, "remove");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void roleUpdate(String access_token, String roleId, String roleName) {
|
|
|
+ Map param = UtilMap.map("access_token", access_token);
|
|
|
+ Map body = UtilMap.map("roleId, roleName", roleId, roleName);
|
|
|
+ String raw = post(OAPI + "/topapi/role/update_role", param, body);
|
|
|
+ assertDingSuccess(JSON.parseObject(raw, Map.class));
|
|
|
+ log.info("[钉钉] 更新角色成功, roleId={}", roleId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void roleDelete(String access_token, String roleId) {
|
|
|
+ Map param = UtilMap.map("access_token", access_token);
|
|
|
+ Map body = UtilMap.map("role_id", roleId);
|
|
|
+ String raw = post(OAPI + "/topapi/role/deleterole", param, body);
|
|
|
+ assertDingSuccess(JSON.parseObject(raw, Map.class));
|
|
|
+ log.info("[钉钉] 删除角色成功, roleId={}", roleId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map roleList(String access_token, Map body_ext) {
|
|
|
+ Map param = UtilMap.map("access_token", access_token);
|
|
|
+ Map body = new java.util.HashMap();
|
|
|
+ if (body_ext != null) {
|
|
|
+ body.putAll(body_ext);
|
|
|
+ }
|
|
|
+ return resultMap(post(OAPI + "/topapi/role/list", param, body));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map roleGet(String access_token, String roleId) {
|
|
|
+ Map param = UtilMap.map("access_token", access_token);
|
|
|
+ Map body = UtilMap.map("roleId", roleId);
|
|
|
+ return resultMap(post(OAPI + "/topapi/role/getrole", param, body));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map roleListEmployees(String access_token, String roleId, long size, long offset) {
|
|
|
+ Map param = UtilMap.map("access_token", access_token);
|
|
|
+ Map body = UtilMap.map("role_id, size, offset", roleId, size, offset);
|
|
|
+ return resultMap(post(OAPI + "/topapi/role/simplelist", param, body));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void setMicroAppVisibleScopes(String access_token, long agentId,
|
|
|
+ List<Long> addDeptIds, List<String> addUserIds, List<String> addRoleIds,
|
|
|
+ List<Long> delDeptIds, List<String> delUserIds, List<String> delRoleIds) {
|
|
|
+ Map param = UtilMap.map("access_token", access_token);
|
|
|
+ Map body = new java.util.HashMap();
|
|
|
+ body.put("agentId", agentId);
|
|
|
+ body.put("isHidden", false);
|
|
|
+ if (addDeptIds != null && !addDeptIds.isEmpty())
|
|
|
+ body.put("addDeptIds", addDeptIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
|
|
|
+ if (addUserIds != null && !addUserIds.isEmpty())
|
|
|
+ body.put("addUserIds", String.join(",", addUserIds));
|
|
|
+ if (addRoleIds != null && !addRoleIds.isEmpty())
|
|
|
+ body.put("addRoleIds", String.join(",", addRoleIds));
|
|
|
+ if (delDeptIds != null && !delDeptIds.isEmpty())
|
|
|
+ body.put("delDeptIds", delDeptIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
|
|
|
+ if (delUserIds != null && !delUserIds.isEmpty())
|
|
|
+ body.put("delUserIds", String.join(",", delUserIds));
|
|
|
+ if (delRoleIds != null && !delRoleIds.isEmpty())
|
|
|
+ body.put("delRoleIds", String.join(",", delRoleIds));
|
|
|
+ String raw = post(OAPI + "/microapp/set_visible_scopes", param, body);
|
|
|
+ assertDingSuccess(JSON.parseObject(raw, Map.class));
|
|
|
+ log.info("[钉钉] 设置应用可见范围成功, agentId={}, addDept={}, addUser={}, addRole={}, delDept={}, delUser={}, delRole={}",
|
|
|
+ agentId, collectionSize(addDeptIds), collectionSize(addUserIds), collectionSize(addRoleIds),
|
|
|
+ collectionSize(delDeptIds), collectionSize(delUserIds), collectionSize(delRoleIds));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ public List<Map> listMicroApp(String access_token) {
|
|
|
+ Map param = UtilMap.map("access_token", access_token);
|
|
|
+ Map body = new java.util.HashMap();
|
|
|
+ String raw = post(OAPI + "/microapp/list", param, body);
|
|
|
+ Map rsp = JSON.parseObject(raw, Map.class);
|
|
|
+ assertDingSuccess(rsp);
|
|
|
+ Object app_list = rsp.get("app_list");
|
|
|
+ if (app_list == null) app_list = rsp.get("appList");
|
|
|
+ List<Map> apps = app_list instanceof List ? (List<Map>) app_list : new ArrayList<>();
|
|
|
+ log.info("[钉钉] 自建应用列表查询成功, 数量={}", apps.size());
|
|
|
+ return apps;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void callBatch(String access_token, String url, String roleId, Collection<String> userIds, String op) {
|
|
|
+ if (userIds == null || userIds.isEmpty()) return;
|
|
|
+ List<String> all = new ArrayList<>(userIds);
|
|
|
+ Map param = UtilMap.map("access_token", access_token);
|
|
|
+ for (int i = 0; i < all.size(); i += USER_BATCH_SIZE) {
|
|
|
+ List<String> batch = all.subList(i, Math.min(i + USER_BATCH_SIZE, all.size()));
|
|
|
+ String userIdsCsv = batch.stream().collect(Collectors.joining(","));
|
|
|
+ Map body = UtilMap.map("roleIds, userIds", roleId, userIdsCsv);
|
|
|
+ String raw = post(url, param, body);
|
|
|
+ assertDingSuccess(JSON.parseObject(raw, Map.class));
|
|
|
+ log.info("[钉钉] 角色成员{}成功, roleId={}, 批次={}/{}, 数量={}",
|
|
|
+ op, roleId, i / USER_BATCH_SIZE + 1,
|
|
|
+ (all.size() + USER_BATCH_SIZE - 1) / USER_BATCH_SIZE, batch.size());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected String post(String url, Map<String, Object> param, Map body) {
|
|
|
+ return UtilHttp.doPost(url, null, param, body);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Map resultMap(String raw) {
|
|
|
+ Map rsp = JSON.parseObject(raw, Map.class);
|
|
|
+ assertDingSuccess(rsp);
|
|
|
+ return rsp.get("result") instanceof Map ? (Map) rsp.get("result") : rsp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static int collectionSize(Object value) {
|
|
|
+ return value instanceof Collection ? ((Collection) value).size() : 0;
|
|
|
+ }
|
|
|
+}
|