TBClientImpl.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. package com.malk.service.teambition.impl;
  2. import cn.hutool.core.util.ObjectUtil;
  3. import com.auth0.jwt.algorithms.Algorithm;
  4. import com.malk.server.common.McException;
  5. import com.malk.server.dingtalk.DDConf;
  6. import com.malk.server.teambition.TBConf;
  7. import com.malk.server.teambition.TBR;
  8. import com.malk.service.teambition.TBClient;
  9. import com.malk.utils.UtilHttp;
  10. import com.malk.utils.UtilMap;
  11. import com.malk.utils.UtilToken;
  12. import lombok.Synchronized;
  13. import lombok.extern.slf4j.Slf4j;
  14. import org.apache.commons.lang3.StringUtils;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Service;
  17. import java.util.Date;
  18. import java.util.HashMap;
  19. import java.util.List;
  20. import java.util.Map;
  21. @Slf4j
  22. @Service
  23. public class TBClientImpl implements TBClient {
  24. @Autowired
  25. private TBConf tbConf;
  26. private static final Long EXPIRES_IN = 2 * 3600 * 1000L;
  27. private static final String TOKEN_APP_ID = "_appId";
  28. // 获取访问授权
  29. @Synchronized
  30. private String getAccessToken() {
  31. String accessToken = UtilToken.get("invalid-token-teambition");
  32. if (StringUtils.isNotBlank(accessToken)) return accessToken;
  33. Algorithm algorithm = Algorithm.HMAC256(tbConf.getAppSecret());
  34. long timestamp = System.currentTimeMillis();
  35. Date issuedAt = new Date(timestamp);
  36. Date expiresAt = new Date(timestamp + EXPIRES_IN);
  37. accessToken = com.auth0.jwt.JWT.create()
  38. .withClaim(TOKEN_APP_ID, tbConf.getAppID())
  39. .withIssuedAt(issuedAt)
  40. .withExpiresAt(expiresAt)
  41. .sign(algorithm);
  42. log.info("响应token, {}", accessToken);
  43. // token失效自动重置: TB传递过期时间2h, 重复调用就会刷新
  44. UtilToken.put("invalid-token-teambition", accessToken, EXPIRES_IN);
  45. return accessToken;
  46. }
  47. // 初始化参数: 加载token
  48. private Map<String, String> initHeaderToken() {
  49. Map header = new HashMap();
  50. header.put("Authorization", getAccessToken());
  51. header.put("X-Tenant-Id", tbConf.getTenantId());
  52. header.put("X-Tenant-Type", TBConf.TENANT_TYPE);
  53. return header;
  54. }
  55. // 操作者ID: 若是查询, 以操作人视角作为权限
  56. private Map<String, String> initHeaderToken(String operatorId) {
  57. Map header = initHeaderToken();
  58. header.put("x-operator-id", operatorId);
  59. return header;
  60. }
  61. // 加载token, 老版本接口
  62. private Map<String, String> initHeaderToken_Bearer() {
  63. Map header = initHeaderToken();
  64. header.put("Authorization", "Bearer " + header.get("Authorization"));
  65. return header;
  66. }
  67. // // 操作者ID: 若是查询, 以操作人视角作为权限
  68. // private Map<String, String> initHeaderToken_Bearer(String operatorId) {
  69. // Map header = initHeaderToken_Bearer();
  70. // header.put("x-operator-id", operatorId);
  71. // return header;
  72. // }
  73. @Override
  74. public List<Map> templateSearch(String ptIds, String q) {
  75. Map param = new HashMap();
  76. param.put("ptIds", ptIds);
  77. param.put("q", q);
  78. param.put("organizationId", TBConf.TENANT_TYPE);
  79. TBR r = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project-template/search", initHeaderToken(), param, TBR.class);
  80. return (List<Map>) r.getResult();
  81. }
  82. @Override
  83. public Map projectCreate(String name, String operatorId) {
  84. Map param = new HashMap();
  85. param.put("organizationId", TBConf.TENANT_TYPE);
  86. Map body = new HashMap();
  87. body.put("name", name);
  88. TBR tbr = (TBR) UtilHttp.doPost(tbConf.getApiHost() + "/v3/project/create", initHeaderToken(operatorId), param, body, TBR.class);
  89. return (Map) tbr.getResult();
  90. }
  91. @Override
  92. public Map projectCreateWithTemplate(String name, String templateId, String operatorId) {
  93. Map param = new HashMap();
  94. param.put("organizationId", TBConf.TENANT_TYPE);
  95. Map body = new HashMap();
  96. body.put("name", name);
  97. body.put("templateId", templateId);
  98. TBR tbr = (TBR) UtilHttp.doPost(tbConf.getApiHost() + "/v3/project/create-from-template", initHeaderToken(operatorId), param, body, TBR.class);
  99. return (Map) tbr.getResult();
  100. }
  101. @Override
  102. public List<Map> projectDetail(String projectIds, String name, String sourceId) {
  103. Map param = UtilMap.map("projectIds, name", projectIds, name);
  104. UtilMap.putNotEmpty(param, "sourceId", sourceId);
  105. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/query", initHeaderToken(), param, TBR.class);
  106. return (List<Map>) tbr.getResult();
  107. }
  108. @Override
  109. public Map projectUpdate(String projectId, Map<String, String> data, String operatorId) {
  110. TBR tbr = (TBR) UtilHttp.doPut(tbConf.getApiHost() + "/v3/project/" + projectId, initHeaderToken(operatorId), data, TBR.class);
  111. return (Map) tbr.getResult();
  112. }
  113. @Override
  114. public Map updateProjectTag(String projectId, List<String> projectTagIds, String operatorId) {
  115. Map body = UtilMap.map("projectTagIds", projectTagIds);
  116. Map result = null;
  117. try {
  118. TBR tbr = (TBR) UtilHttp.doPut(tbConf.getApiHost() + "/v3/project/" + projectId + "/project-tag", initHeaderToken(operatorId), body, TBR.class);
  119. result = (Map) tbr.getResult();
  120. } catch (McException e) {
  121. // ppExt: 若修改分组相同, 不返回204, 会报错400, 已兼容
  122. if (!"400".equals(e.getCode())) {
  123. // 记录错误信息
  124. e.printStackTrace();
  125. }
  126. }
  127. return result;
  128. }
  129. @Deprecated
  130. @Override
  131. public List<Map> userSearch(String query) {
  132. Map param = UtilMap.map("orgId, query, pageSize", tbConf.getTenantId(), query, TBConf.PAGE_SIZE_LIMIT);
  133. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/org/member/search", initHeaderToken_Bearer(), param, TBR.class);
  134. return (List<Map>) tbr.getResult();
  135. }
  136. @Override
  137. public List<Map> idMapQuery(String tbId, String refer, String refId) {
  138. Map param = UtilMap.map("tbId, refer, refId", tbId, refer, refId);
  139. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/idmap/query", initHeaderToken_Bearer(), param, TBR.class);
  140. return (List<Map>) tbr.getResult();
  141. }
  142. @Autowired
  143. private DDConf ddConf;
  144. @Override
  145. public List<Map> idMapQuery(String userId, boolean isTbID) {
  146. Map param = UtilMap.map(" refer, refId", "dingTalk-user", ddConf.getCorpId());
  147. param.put(isTbID ? "tbId" : "extraUserId", userId);
  148. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/idmap/query", initHeaderToken_Bearer(), param, TBR.class);
  149. return (List<Map>) tbr.getResult();
  150. }
  151. @Override
  152. public Map updateUser(String operatorId, List<Map> members) {
  153. Map body = new HashMap();
  154. body.put("operatorId", operatorId);
  155. body.put("orgId", tbConf.getTenantId());
  156. body.put("members", members);
  157. TBR tbr = (TBR) UtilHttp.doPut(tbConf.getApiHost() + "/org/member/update", initHeaderToken_Bearer(), body, TBR.class);
  158. return (Map) tbr.getResult();
  159. }
  160. @Override
  161. public List<Map> createProjectMember(String projectId, List<String> userIds, String operatorId) {
  162. Map body = UtilMap.map("userIds", userIds);
  163. TBR tbr = (TBR) UtilHttp.doPost(tbConf.getApiHost() + "/v3/project/".concat(projectId).concat("/member/create-v2"), initHeaderToken(operatorId), body, TBR.class);
  164. return (List<Map>) tbr.getResult();
  165. }
  166. @Override
  167. public List<Map> updateProjectMember(List<String> userIds, List<String> roleIds, String projectId) {
  168. Map body = UtilMap.map("userIds", userIds);
  169. body.put("roleIds", roleIds); // 合并字段避免map拆分异常, todo 待优化 map 方法
  170. TBR tbr = (TBR) UtilHttp.doPost(tbConf.getApiHost() + "/v3/project/".concat(projectId).concat("/member/role/assign"), initHeaderToken(), body, TBR.class);
  171. return (List<Map>) tbr.getResult();
  172. }
  173. @Override
  174. public List<Map> queryProjectMember(String projectId, Map param) {
  175. param = UtilMap.put(param, "pageSize", TBConf.PAGE_SIZE_LIMIT);
  176. param.put("limit", TBConf.PAGE_SIZE_LIMIT);
  177. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/member", initHeaderToken(), param, TBR.class);
  178. return (List<Map>) tbr.getResult();
  179. }
  180. @Override
  181. public List<Map> queryProjectRoles(String projectId) {
  182. Map param = UtilMap.map("pageSize", TBConf.PAGE_SIZE_LIMIT);
  183. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/role", initHeaderToken(), param, TBR.class);
  184. return (List<Map>) tbr.getResult();
  185. }
  186. @Override
  187. public List<Map> queryTaskDetail(String taskId, String shortIds, String parentTaskId) {
  188. Map param = UtilMap.mapNotNull("taskId, shortIds, parentTaskId", taskId, shortIds, parentTaskId);
  189. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/task/query", initHeaderToken(), param, TBR.class);
  190. return (List<Map>) tbr.getResult();
  191. }
  192. @Override
  193. public List<Map> queryTaskGroupList(String projectId, Map param) {
  194. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/stage/search", initHeaderToken(), param, TBR.class);
  195. return (List<Map>) tbr.getResult();
  196. }
  197. @Override
  198. public List<Map> queryProjectTaskList(String projectId, Map param, QueryAll lambda) {
  199. param = UtilMap.put(param, "pageSize", TBConf.PAGE_SIZE_LIMIT);
  200. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/task/query", initHeaderToken(), param, TBR.class);
  201. List<Map> dataList = (List<Map>) tbr.getResult();
  202. if (ObjectUtil.isNotNull(lambda)) {
  203. boolean isAll = lambda.dataList(dataList);
  204. if (!isAll) {
  205. return dataList;
  206. }
  207. if (StringUtils.isNotBlank(tbr.getNextPageToken())) {
  208. param.put("pageToken", tbr.getNextPageToken());
  209. queryProjectTaskList(projectId, param, lambda);
  210. }
  211. }
  212. return dataList;
  213. }
  214. @Override
  215. public Map updateTaskDueDate(String taskId, String dueDate, String operatorId) {
  216. Map body = UtilMap.map("dueDate", dueDate);
  217. TBR tbr = (TBR) UtilHttp.doPut(tbConf.getApiHost() + "/v3/task/" + taskId + "/dueDate", initHeaderToken(operatorId), body, TBR.class);
  218. return (Map) tbr.getResult();
  219. }
  220. @Override
  221. public Map updateTaskExecutor(String taskId, String operatorId, String executorId, boolean disableActivity, boolean disableNotification) {
  222. Map body = UtilMap.map("executorId, disableActivity, disableNotification", executorId, disableActivity, disableNotification);
  223. TBR tbr = (TBR) UtilHttp.doPut(tbConf.getApiHost() + "/v3/task/" + taskId + "/executor", initHeaderToken(operatorId), body, TBR.class);
  224. return (Map) tbr.getResult();
  225. }
  226. @Override
  227. public Map updateTaskCustomField(String taskId, String operatorId, Map body) {
  228. TBR tbr = (TBR) UtilHttp.doPost(tbConf.getApiHost() + "/v3/task/" + taskId + "/customfield/update", initHeaderToken(operatorId), body, TBR.class);
  229. return (Map) tbr.getResult();
  230. }
  231. @Override
  232. public Map updateTaskFlowStatus(String taskId, String operatorId, String taskflowstatusId, String tfsUpdateNote) {
  233. Map body = UtilMap.map("taskflowstatusId, tfsUpdateNote", taskflowstatusId, tfsUpdateNote);
  234. TBR tbr = (TBR) UtilHttp.doPut(tbConf.getApiHost() + "/v3/task/" + taskId + "/taskflowstatus", initHeaderToken(operatorId), body, TBR.class);
  235. return (Map) tbr.getResult();
  236. }
  237. @Override
  238. public List<Map> queryProjectCustomField(String projectId, Map body) {
  239. body = UtilMap.put(body, "pageSize", TBConf.PAGE_SIZE_LIMIT);
  240. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/customfield/search", initHeaderToken(), body, TBR.class);
  241. return (List<Map>) tbr.getResult();
  242. }
  243. @Override
  244. public List<Map> queryProjectCustomFlowStatus(String projectId, Map body) {
  245. body = UtilMap.put(body, "pageSize", TBConf.PAGE_SIZE_LIMIT);
  246. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/taskflowstatus/search", initHeaderToken(), body, TBR.class);
  247. return (List<Map>) tbr.getResult();
  248. }
  249. @Override
  250. public List<Map> queryProjectCustomFlow(String projectId, Map body) {
  251. body = UtilMap.put(body, "pageSize", TBConf.PAGE_SIZE_LIMIT);
  252. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project/" + projectId + "/taskflow/search", initHeaderToken(), body, TBR.class);
  253. return (List<Map>) tbr.getResult();
  254. }
  255. @Override
  256. public List<Map> queryTaskDependency(String taskId, Map body) {
  257. body = UtilMap.put(body, "pageSize", TBConf.PAGE_SIZE_LIMIT);
  258. body.put("taskId", taskId);
  259. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "v3/task/dependency", initHeaderToken(), body, TBR.class);
  260. return (List<Map>) tbr.getResult();
  261. }
  262. @Override
  263. public Map removeTaskDependency(String dependencyId, String operatorId) {
  264. TBR tbr = (TBR) UtilHttp.doPost(tbConf.getApiHost() + "/v3/task/dependency/" + dependencyId + "/delete", initHeaderToken(operatorId), null, TBR.class);
  265. return (Map) tbr.getResult();
  266. }
  267. @Override
  268. public List<Map> queryGanttBaselineList(String projectId, Map body) {
  269. body = UtilMap.put(body, "pageSize", TBConf.PAGE_SIZE_LIMIT);
  270. body.put("projectId", projectId);
  271. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/gantt/baseline", initHeaderToken(), body, TBR.class);
  272. return (List<Map>) tbr.getResult();
  273. }
  274. @Override
  275. public List<Map> queryGanttBaselineTask(String baselineId, Map param, QueryAll lambda) {
  276. param = UtilMap.put(param, "pageSize", 10);
  277. param.put("baselineId", baselineId);
  278. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/gantt/baseline-task", initHeaderToken(), param, TBR.class);
  279. List<Map> dataList = (List<Map>) tbr.getResult();
  280. if (ObjectUtil.isNotNull(lambda)) {
  281. boolean isAll = lambda.dataList(dataList);
  282. if (!isAll) {
  283. return dataList;
  284. }
  285. if (StringUtils.isNotBlank(tbr.getNextPageToken())) {
  286. param.put("pageToken", tbr.getNextPageToken());
  287. queryGanttBaselineTask(baselineId, param, lambda);
  288. }
  289. }
  290. return dataList;
  291. }
  292. @Override
  293. public List<Map> queryTagList(Map param) {
  294. param = UtilMap.put(param, "pageSize", TBConf.PAGE_SIZE_LIMIT);
  295. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project-tag/query", initHeaderToken(), param, TBR.class);
  296. return (List<Map>) tbr.getResult();
  297. }
  298. @Override
  299. public Map updateTag(String projectTagId, Map param) {
  300. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/project-tag/" + projectTagId, initHeaderToken(), param, TBR.class);
  301. return (Map) tbr.getResult();
  302. }
  303. @Override
  304. public List<Map> queryProgramList(String programIds) {
  305. Map param = UtilMap.map("programIds", programIds);
  306. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "/v3/program/query", initHeaderToken(), param, TBR.class);
  307. return (List<Map>) tbr.getResult();
  308. }
  309. @Override
  310. public List<Map> queryProgramList_all() {
  311. TBR tbr = (TBR) UtilHttp.doPost(tbConf.getApiHost() + "/v3/program/query", initHeaderToken(), null, null, TBR.class);
  312. return (List<Map>) tbr.getResult();
  313. }
  314. @Override
  315. public List<Map> upsertProgramProject(String programId, List<String> projectIds, String operatorId) {
  316. TBR tbr = (TBR) UtilHttp.doPost(tbConf.getApiHost() + "v3/program/" + programId + "/project/create", initHeaderToken(operatorId), UtilMap.map("projectIds", projectIds), TBR.class);
  317. return (List<Map>) tbr.getResult();
  318. }
  319. @Override
  320. public List<Map> queryProjectStatusField(String projectId) {
  321. TBR tbr = (TBR) UtilHttp.doGet(tbConf.getApiHost() + "v3/project/" + projectId + "/status/customfield/list", initHeaderToken(), null, TBR.class);
  322. return (List<Map>) tbr.getResult();
  323. }
  324. @Override
  325. public Map updateProjectStatusField(String projectId, String operatorId, Map body) {
  326. TBR tbr = (TBR) UtilHttp.doPost(tbConf.getApiHost() + "/v3/project/" + projectId + "/status/customfield/create", initHeaderToken(operatorId), body, TBR.class);
  327. return (Map) tbr.getResult();
  328. }
  329. }