org.springframework.boot
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/ConnectController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/ConnectController.java
index 445268b61..ec9add850 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/ConnectController.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/ConnectController.java
@@ -1,8 +1,11 @@
package com.pig4cloud.pigx.admin.controller;
+import com.pig4cloud.pigx.admin.service.ConnectService;
import com.pig4cloud.pigx.common.core.util.R;
+import com.pig4cloud.pigx.common.security.annotation.Inner;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -13,19 +16,22 @@ import org.springframework.web.bind.annotation.RestController;
* @author lengleng
* @date 2022/4/22
*/
+@Inner(value = false)
@RestController
@RequiredArgsConstructor
@RequestMapping("/connect")
@Api(value = "connect", tags = "开放互联")
public class ConnectController {
+ private final ConnectService connectService;
+
/**
* 同步钉钉用户
* @return
*/
- @PostMapping("/sync/ding/user")
- public R syncUser() {
- return R.ok();
+ @PostMapping("/sync/ding/user/{deptId}")
+ public R syncUser(@PathVariable("deptId") Long deptId) {
+ return R.ok(connectService.syncDingUser(deptId));
}
/**
@@ -34,7 +40,7 @@ public class ConnectController {
*/
@PostMapping("/sync/ding/role")
public R syncRole() {
- return R.ok();
+ return R.ok(connectService.syncDingRole());
}
/**
@@ -43,7 +49,7 @@ public class ConnectController {
*/
@PostMapping("/sync/ding/dept")
public R syncDept() {
- return R.ok();
+ return R.ok(connectService.syncDingDept());
}
/**
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/ConnectService.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/ConnectService.java
index faedf2fb6..c0260fac0 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/ConnectService.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/ConnectService.java
@@ -3,9 +3,24 @@ package com.pig4cloud.pigx.admin.service;
/**
* @author lengleng
* @date 2022/4/22
- *
+ *
* 互联平台
*/
public interface ConnectService {
+ /**
+ * 同步钉钉角色
+ */
+ Boolean syncDingRole();
+
+ /**
+ * 同步钉钉部门
+ */
+ Boolean syncDingDept();
+
+ /**
+ * 同步钉钉用户
+ */
+ Boolean syncDingUser(Long deptId);
+
}
diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/ConnectServiceImpl.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/ConnectServiceImpl.java
index 1a8f54aba..2b8da301e 100644
--- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/ConnectServiceImpl.java
+++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/ConnectServiceImpl.java
@@ -1,25 +1,46 @@
package com.pig4cloud.pigx.admin.service.impl;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest;
import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse;
import com.aliyun.teaopenapi.models.Config;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiRoleListRequest;
+import com.dingtalk.api.request.OapiUserListidRequest;
+import com.dingtalk.api.request.OapiV2DepartmentListsubRequest;
+import com.dingtalk.api.request.OapiV2UserGetRequest;
+import com.dingtalk.api.response.OapiRoleListResponse;
+import com.dingtalk.api.response.OapiUserListidResponse;
+import com.dingtalk.api.response.OapiV2DepartmentListsubResponse;
+import com.dingtalk.api.response.OapiV2UserGetResponse;
+import com.pig4cloud.pigx.admin.api.entity.*;
import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper;
-import com.pig4cloud.pigx.admin.service.ConnectService;
+import com.pig4cloud.pigx.admin.service.*;
+import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
/**
* 互联平台实现
- *
+ *
* 钉钉: https://open-dev.dingtalk.com/apiExplorer
*
* @author lengleng
* @date 2022/4/22
*/
+@SuppressWarnings("unchecked")
@Slf4j
@Service
@RequiredArgsConstructor
@@ -27,6 +48,14 @@ public class ConnectServiceImpl implements ConnectService {
private final SysSocialDetailsMapper sysSocialDetailsMapper;
+ private final SysRoleService sysRoleService;
+
+ private final SysDeptService sysDeptService;
+
+ private final SysUserService sysUserService;
+
+ private final SysUserRoleService sysUserRoleService;
+
private String getDingAccessToken() {
SysSocialDetails dingTalk = sysSocialDetailsMapper
.selectOne(Wrappers.lambdaQuery().eq(SysSocialDetails::getType, "ding"));
@@ -54,4 +83,204 @@ public class ConnectServiceImpl implements ConnectService {
return new com.aliyun.dingtalkoauth2_1_0.Client(config);
}
+ /**
+ * 同步钉钉角色
+ *
+ * @see
+ */
+ @SneakyThrows
+ @Override
+ public Boolean syncDingRole() {
+ // 分页偏移量
+ long offset = 0L;
+ // 是否还有非同步的数据
+ boolean hasMore;
+ // 数据库中现有的角色
+ List roleList = sysRoleService.list(Wrappers.emptyWrapper());
+ // 钉钉同步过来的角色
+ List insertRole = new LinkedList<>();
+
+ do {
+ DingTalkClient client = new DefaultDingTalkClient(SecurityConstants.DING_OLD_ROLE_URL);
+ OapiRoleListRequest req = new OapiRoleListRequest();
+ // 分页查询,默认分页20条
+ req.setSize(2L);
+ req.setOffset(offset);
+ OapiRoleListResponse rsp = client.execute(req, getDingAccessToken());
+ offset += req.getSize();
+
+ JSONObject result = JSONUtil.parseObj(rsp.getBody());
+ JSONObject resultStr = result.getJSONObject("result");
+
+ hasMore = resultStr.get("hasMore", Boolean.class);
+ List list = resultStr.get("list", List.class);
+
+ if (CollectionUtils.isNotEmpty(list)) {
+ list.forEach(item -> {
+ List roles = (List) item.get("roles");
+ if (CollectionUtils.isNotEmpty(roles)) {
+ // 过滤出数据库不存在的角色
+ List sysRoles = roles.stream().filter(
+ role -> roleList.stream().noneMatch(db -> db.getRoleName().equals(role.get("name"))))
+ .map(role -> {
+ SysRole sysRole = new SysRole();
+ sysRole.setRoleId(Convert.toLong(role.get("id")));
+ sysRole.setRoleName(Convert.toStr(role.get("name")));
+ return sysRole;
+ }).collect(Collectors.toList());
+ insertRole.addAll(sysRoles);
+ }
+ });
+ }
+ }
+ while (hasMore);
+
+ // 保存到数据库中
+ return sysRoleService.saveBatch(insertRole);
+ }
+
+ /**
+ * 同步钉钉部门
+ *
+ * @see
+ */
+ @Override
+ public Boolean syncDingDept() {
+ OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();
+ req.setDeptId(1L);
+ req.setLanguage("zh_CN");
+
+ // 数据库中现有的部门
+ List deptList = sysDeptService.list(Wrappers.emptyWrapper());
+
+ // 查询根部门下的所有部门
+ List insertDept = queryChildDept(req, getDingAccessToken(), deptList);
+
+ // 去重
+ List syncDept = insertDept.stream().distinct().collect(Collectors.toList());
+
+ // 保存部门以及部门关系
+ if (CollectionUtils.isNotEmpty(syncDept)) {
+ syncDept.forEach(sysDeptService::saveDept);
+ }
+
+ return Boolean.TRUE;
+ }
+
+ /**
+ * 查询当前部门下的所有部门
+ */
+ @SneakyThrows
+ private List queryChildDept(OapiV2DepartmentListsubRequest req, String token, List deptList) {
+ List sysDepts = new LinkedList<>();
+
+ // 调用Api查询
+ DingTalkClient client = new DefaultDingTalkClient(SecurityConstants.DING_OLD_DEPT_URL);
+ OapiV2DepartmentListsubResponse rsp = client.execute(req, token);
+
+ JSONObject result = JSONUtil.parseObj(rsp.getBody());
+ List resultList = result.get("result", List.class);
+
+ if (CollectionUtils.isNotEmpty(resultList)) {
+ // 过滤出数据库存在的部门
+ List depts = resultList.stream()
+ .filter(dept -> deptList.stream().noneMatch(sysDept -> sysDept.getName().equals(dept.get("name"))))
+ .map(dept -> {
+ SysDept sysDept = new SysDept();
+ sysDept.setName(Convert.toStr(dept.get("name")));
+ sysDept.setDeptId(Convert.toLong(dept.get("dept_id")));
+ sysDept.setParentId(Convert.toLong(dept.get("parent_id")));
+ return sysDept;
+ }).collect(Collectors.toList());
+
+ // 递归查询下一级
+ if (CollectionUtils.isNotEmpty(depts)) {
+ sysDepts.addAll(depts);
+ depts.forEach(dept -> {
+ OapiV2DepartmentListsubRequest request = new OapiV2DepartmentListsubRequest();
+ request.setDeptId(dept.getDeptId());
+ request.setLanguage("zh_CN");
+ List childDept = queryChildDept(request, token, deptList);
+ sysDepts.addAll(childDept);
+ });
+ }
+ }
+
+ return sysDepts;
+ }
+
+ /**
+ * 同步部门下的钉钉用户
+ *
+ * @see
+ * @see
+ */
+ @SneakyThrows
+ @Override
+ public Boolean syncDingUser(Long deptId) {
+ // 数据库中现有用户
+ List users = sysUserService.list(Wrappers.emptyWrapper());
+
+ String token = getDingAccessToken();
+
+ // 查询部门下的用户id列表
+ DingTalkClient client = new DefaultDingTalkClient(SecurityConstants.DING_DEPT_USERIDS_URL);
+ OapiUserListidRequest req = new OapiUserListidRequest();
+ req.setDeptId(deptId);
+ OapiUserListidResponse rsp = client.execute(req, token);
+
+ JSONObject jsonObject = JSONUtil.parseObj(rsp.getBody());
+ JSONObject result = jsonObject.getJSONObject("result");
+ List useridList = result.get("userid_list", List.class);
+
+ // 查询用户详情
+ if (CollectionUtils.isNotEmpty(useridList)) {
+ for (String userid : useridList) {
+ DingTalkClient userClient = new DefaultDingTalkClient(SecurityConstants.DING_USER_INFO_URL);
+ OapiV2UserGetRequest userGetRequest = new OapiV2UserGetRequest();
+ userGetRequest.setUserid(userid);
+ OapiV2UserGetResponse userGetResponse = userClient.execute(userGetRequest, token);
+ JSONObject userResult = JSONUtil.parseObj(userGetResponse.getBody());
+ JSONObject userObj = JSONUtil.parseObj(userResult.get("result"));
+
+ boolean exist = users.stream().anyMatch(user -> user.getPhone().equals(userObj.getStr("mobile")));
+
+ if (!exist) {
+ // 用户部门信息
+ JSONArray deptOrders = userObj.getJSONArray("dept_order_list");
+ JSONObject deptInfo = (JSONObject) deptOrders.get(0);
+
+ // 用户信息
+ SysUser sysUser = new SysUser();
+ sysUser.setDeptId(Convert.toLong(deptInfo.get("dept_id")));
+ sysUser.setAvatar(userObj.getStr("avatar"));
+ sysUser.setUsername(userObj.getStr("name"));
+ sysUser.setPhone(userObj.getStr("mobile"));
+ sysUser.setNickname(userObj.getStr("nickname"));
+ sysUser.setEmail(userObj.getStr("email"));
+ sysUserService.save(sysUser);
+
+ // 用户角色信息
+ JSONArray roleList = userObj.getJSONArray("role_list");
+ if (roleList != null && roleList.size() > 0) {
+ JSONObject roleInfo = (JSONObject) roleList.get(0);
+ Long userRoleId = Convert.toLong(roleInfo.get("id"));
+ SysUserRole sysUserRole = new SysUserRole();
+ sysUserRole.setUserId(sysUser.getUserId());
+ sysUserRole.setRoleId(userRoleId);
+ sysUserRoleService.save(sysUserRole);
+ }
+ }
+
+ }
+
+ }
+
+ return Boolean.TRUE;
+ }
+
}
diff --git a/pom.xml b/pom.xml
index bf21ae7ce..033360534 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,6 +46,7 @@
1.2.7
3.6.4
1.3.40
+ 2.0.0
3.0.0
2.0.9
2.3