完善钉钉组织用户同步逻辑

This commit is contained in:
wanggeng 2021-08-14 20:55:05 +08:00
parent f58421e170
commit 89d71da52b
13 changed files with 388 additions and 15 deletions

View File

@ -141,6 +141,12 @@
<artifactId>cloud-central-control</artifactId>
<version>1.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>3.1.0</version>
<scope>compile</scope>
</dependency>
<!-- 作为客户端使用 -->

View File

@ -0,0 +1,39 @@
package com.cm.serviceusercenter.controller.dingding.apis.user;
import com.cm.common.constants.ISystemConstant;
import com.cm.common.result.ErrorResult;
import com.cm.common.result.SuccessResult;
import com.cm.serviceusercenter.service.system.user.IDingDingUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName: DingDingUserController
* @Description: 钉钉用户管理
* @Author: wanggeng
* @Date: 2021/8/12 2:37 下午
* @Version: 1.0
*/
@Api(tags = ISystemConstant.API_TAGS_DINGDING_PREFIX + "登录")
@RestController
@RequestMapping(ISystemConstant.DINGDING_PREFIX + "/user")
public class DingDingUserController {
@Autowired
private IDingDingUserService dingDingUserService;
@ApiOperation(value = "同步钉钉通讯录", notes = "同步钉钉通讯录接口")
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PutMapping("update-sync-dingding")
public SuccessResult updateSyncDingDing() throws Exception {
dingDingUserService.updateSyncDingDing();
return new SuccessResult();
}
}

View File

@ -9,10 +9,8 @@ import com.cm.common.plugin.pojo.bos.user.UserDepartmentResourceBO;
import com.cm.serviceusercenter.pojo.dtos.*;
import com.cm.serviceusercenter.pojo.pos.UserAppDevicePO;
import com.cm.serviceusercenter.pojo.pos.UserPO;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -418,4 +416,13 @@ public interface IUserDao {
* @throws SearchException
*/
List<UserDepartmentResourceBO> listUserDepartmentResource(Map<String, Object> params) throws SearchException;
/**
* 部门用户详情
*
* @param params
* @return
* @throws SearchException
*/
DepartmentUserDTO getDepartmentUser(Map<String, Object> params) throws SearchException;
}

View File

@ -1,20 +1,20 @@
package com.cm.serviceusercenter.service.system.department;
import com.cm.common.plugin.pojo.bos.department.DepartmentResourceBO;
import com.cm.common.pojo.bos.DepartmentBO;
import com.cm.common.exception.RemoveException;
import com.cm.common.exception.SaveException;
import com.cm.common.exception.SearchException;
import com.cm.common.exception.UpdateException;
import com.cm.common.plugin.pojo.bos.department.DepartmentResourceBO;
import com.cm.common.pojo.ListPage;
import com.cm.common.pojo.bos.DepartmentBO;
import com.cm.common.pojo.dtos.ZTreeDTO;
import com.cm.common.pojo.dtos.department.DepartmentSortDTO;
import com.cm.common.result.SuccessResult;
import com.cm.common.result.SuccessResultData;
import com.cm.common.result.SuccessResultList;
import com.cm.common.result.UploadExcelResultDTO;
import com.cm.serviceusercenter.pojo.dtos.DepartmentAndUserListDTO;
import com.cm.serviceusercenter.pojo.dtos.DepartmentDTO;
import com.cm.common.result.UploadExcelResultDTO;
import com.cm.serviceusercenter.pojo.dtos.department.DepartmentSimpleDTO;
import com.cm.serviceusercenter.pojo.vos.DepartmentVO;
import com.cm.serviceusercenter.pojo.vos.department.MergeDepartmentInfoVO;
@ -388,4 +388,5 @@ public interface IDepartmentService {
* @return
*/
List<DepartmentSortDTO> listSort(Map<String, Object> params);
}

View File

@ -4,7 +4,10 @@ import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cm.common.constants.ISystemConstant;
import com.cm.common.exception.*;
import com.cm.common.exception.RemoveException;
import com.cm.common.exception.SaveException;
import com.cm.common.exception.SearchException;
import com.cm.common.exception.UpdateException;
import com.cm.common.plugin.excel.error.AbstractErrorExcelHandler;
import com.cm.common.plugin.pojo.bos.department.DepartmentResourceBO;
import com.cm.common.plugin.pojo.dtos.dataarea.DataAreaDTO;
@ -17,6 +20,7 @@ import com.cm.common.pojo.dtos.department.DepartmentSortDTO;
import com.cm.common.result.SuccessResult;
import com.cm.common.result.SuccessResultData;
import com.cm.common.result.SuccessResultList;
import com.cm.common.result.UploadExcelResultDTO;
import com.cm.common.utils.ArrayListUtil;
import com.cm.common.utils.HashMapUtil;
import com.cm.common.utils.UUIDUtil;
@ -28,7 +32,6 @@ import com.cm.serviceusercenter.listener.excel.department.DepartmentExcelListene
import com.cm.serviceusercenter.pojo.dtos.DepartmentAndUserListDTO;
import com.cm.serviceusercenter.pojo.dtos.DepartmentDTO;
import com.cm.serviceusercenter.pojo.dtos.DepartmentUserDTO;
import com.cm.common.result.UploadExcelResultDTO;
import com.cm.serviceusercenter.pojo.dtos.department.DepartmentSimpleDTO;
import com.cm.serviceusercenter.pojo.vos.DepartmentVO;
import com.cm.serviceusercenter.pojo.vos.department.MergeDepartmentInfoVO;

View File

@ -173,14 +173,14 @@ public class GroupServiceImpl extends BaseService implements IGroupService {
Map<String, Object> params = getHashMap(2);
params.put("groupId", groupId);
List<GroupUserDTO> groupUserDTOs = groupDao.listGroupUser(params);
if(groupUserDTOs.isEmpty()) {
if (groupUserDTOs.isEmpty()) {
return new ArrayList<>();
}
Set<String> userIdSet = new HashSet<>();
for(GroupUserDTO groupUserDTO : groupUserDTOs) {
for (GroupUserDTO groupUserDTO : groupUserDTOs) {
userIdSet.add(groupUserDTO.getUserId());
}
return userResourceService.listResourceByIds(new ArrayList<>());
return userResourceService.listResourceByIds(new ArrayList<>(userIdSet));
}
/**

View File

@ -0,0 +1,17 @@
package com.cm.serviceusercenter.service.system.user;
import com.taobao.api.ApiException;
/**
* @ClassName: IDingDingUserService
* @Description: 钉钉用户
* @Author: wanggeng
* @Date: 2021/8/12 2:49 下午
* @Version: 1.0
*/
public interface IDingDingUserService {
/**
* 同步钉钉通讯录不做删除只做新增
*/
void updateSyncDingDing() throws Exception;
}

View File

@ -90,6 +90,15 @@ public interface IUserService {
*/
SuccessResult saveUser(Map<String, Object> params) throws SaveException, SearchException;
/**
* 新增用户
*
* @param userVO
* @return
* @throws Exception
*/
String saveUserReturnId(UserVO userVO) throws Exception;
/**
* 用户新增(绑定组织)
*
@ -405,6 +414,7 @@ public interface IUserService {
/**
* 修改用户密码
*
* @param userId
* @param params
* @return
@ -705,6 +715,15 @@ public interface IUserService {
*/
void deleteDepartmentUserByDepartmentIdAndUserIds(String departmentId, String departmentName, List<String> userIds) throws SearchException;
/**
* 保存部门用户
*
* @param departmentId 部门ID
* @param userId 用户ID
*/
void saveDepartmentUser(String departmentId, String userId);
/**
* 新增部门用户ID通过部门ID部门名称
*
@ -881,6 +900,12 @@ public interface IUserService {
*/
List<UserDepartmentResourceBO> listUserDepartmentResourceByPositionIds(List<String> positionIds) throws SearchException;
/**
* 获取部门用户
*
* @param departmentId
* @param userId
* @return
*/
DepartmentUserDTO getDepartmentUser(String departmentId, String userId);
}

View File

@ -0,0 +1,212 @@
package com.cm.serviceusercenter.service.system.user.impl;
import com.cm.common.base.AbstractService;
import com.cm.common.dingding.pojo.pos.DingDingDepartmentPO;
import com.cm.common.dingding.pojo.pos.DingDingUserPO;
import com.cm.common.dingding.pojo.vos.DingDingDepartmentVO;
import com.cm.common.dingding.pojo.vos.DingDingUserVO;
import com.cm.common.dingding.service.IDingDingAppDepartmentService;
import com.cm.common.dingding.service.IDingDingAppUserService;
import com.cm.serviceusercenter.pojo.dtos.DepartmentUserDTO;
import com.cm.serviceusercenter.pojo.dtos.UserDTO;
import com.cm.serviceusercenter.pojo.dtos.department.DepartmentSimpleDTO;
import com.cm.serviceusercenter.pojo.vos.DepartmentVO;
import com.cm.serviceusercenter.pojo.vos.UserVO;
import com.cm.serviceusercenter.service.system.department.IDepartmentService;
import com.cm.serviceusercenter.service.system.user.IDingDingUserService;
import com.cm.serviceusercenter.service.system.user.IUserService;
import com.dingtalk.api.response.OapiV2DepartmentListsubResponse;
import com.dingtalk.api.response.OapiV2UserListResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @ClassName: DingDingUserServiceImpl
* @Description: 钉钉用户管理
* @Author: wanggeng
* @Date: 2021/8/12 2:49 下午
* @Version: 1.0
*/
@Service
public class DingDingUserServiceImpl extends AbstractService implements IDingDingUserService {
@Autowired
private IDingDingAppUserService dingDingAppUserService;
@Autowired
private IDingDingAppDepartmentService dingDingAppDepartmentService;
@Autowired
private IDepartmentService departmentService;
@Autowired
private IUserService userService;
@Override
public void updateSyncDingDing() throws Exception {
// 构建绑定的部门
LOG.debug("同步钉钉部门关系");
List<DingDingDepartmentVO> bindDingDingDepartmentVOs = new ArrayList<>();
// 添加根节点
DingDingDepartmentVO rootDingDingDepartmentVO = new DingDingDepartmentVO();
rootDingDingDepartmentVO.setDingdingDepartmentId(1L);
rootDingDingDepartmentVO.setDingdingDepartmentParentId(0L);
bindDingDingDepartmentVOs.add(rootDingDingDepartmentVO);
departmentSync(1L, "0", bindDingDingDepartmentVOs);
if (bindDingDingDepartmentVOs.isEmpty()) {
return;
}
// 保存部门绑定关系
for (DingDingDepartmentVO dingDingDepartmentVO : bindDingDingDepartmentVOs) {
if (dingDingDepartmentVO.getDingdingDepartmentId() == 1L) {
continue;
}
LOG.debug("保存部门:{}", dingDingDepartmentVO.getDepartmentName());
dingDingAppDepartmentService.save(dingDingDepartmentVO);
}
LOG.debug("同步钉钉用户");
Map<String, Object> params = getHashMap(0);
List<UserDTO> userDTOs = userService.listUsers(params);
List<DingDingUserVO> dingDingUserVOs = new ArrayList<>();
syncUser(bindDingDingDepartmentVOs, userDTOs, dingDingUserVOs);
if (dingDingUserVOs.isEmpty()) {
return;
}
// 绑定钉钉用户与系统用户关系
for (DingDingUserVO dingDingUserVO : dingDingUserVOs) {
LOG.debug("保存用户:{} - {}", dingDingUserVO.getMobile(), dingDingUserVO.getName());
dingDingAppUserService.save(dingDingUserVO);
LOG.debug("保存用户与部门关系");
String[] deptIdArray = dingDingUserVO.getDeptIdList().split(",");
for (String deptId : deptIdArray) {
for (DingDingDepartmentVO dingDingDepartmentVO : bindDingDingDepartmentVOs) {
if (StringUtils.isEmpty(dingDingDepartmentVO.getDepartmentId())) {
continue;
}
if (Long.valueOf(deptId).equals(dingDingDepartmentVO.getDingdingDepartmentId())) {
DepartmentUserDTO departmentUserDTO = userService.getDepartmentUser(dingDingDepartmentVO.getDepartmentId(), dingDingUserVO.getUserId());
if (departmentUserDTO != null) {
continue;
}
userService.saveDepartmentUser(dingDingDepartmentVO.getDepartmentId(), dingDingUserVO.getUserId());
}
}
}
}
}
/**
* 同步部门
*
* @param dingDingParentId
* @param departmentParentId
* @param bindDingDingDepartmentVOs
* @throws Exception
*/
public void departmentSync(Long dingDingParentId,
String departmentParentId,
List<DingDingDepartmentVO> bindDingDingDepartmentVOs) throws Exception {
List<OapiV2DepartmentListsubResponse.DeptBaseResponse> deptBaseResponses = dingDingAppDepartmentService.list(dingDingParentId);
if (deptBaseResponses == null || deptBaseResponses.isEmpty()) {
return;
}
List<DepartmentSimpleDTO> departmentSimpleDTOs = departmentService.listDepartmentSimpleByParentId(departmentParentId);
for (OapiV2DepartmentListsubResponse.DeptBaseResponse deptBaseResponse : deptBaseResponses) {
// 未绑定过
DingDingDepartmentPO dingDingDepartmentPO = dingDingAppDepartmentService.getPO(deptBaseResponse.getDeptId());
if (dingDingDepartmentPO != null) {
continue;
}
boolean isDepartmentExist = false;
DingDingDepartmentVO dingDingDepartmentVO = new DingDingDepartmentVO();
dingDingDepartmentVO.setDingdingDepartmentId(deptBaseResponse.getDeptId());
dingDingDepartmentVO.setDingdingDepartmentParentId(deptBaseResponse.getParentId());
dingDingDepartmentVO.setDepartmentName(deptBaseResponse.getName());
// 同步内容
for (DepartmentSimpleDTO departmentSimpleDTO : departmentSimpleDTOs) {
if (StringUtils.equals(deptBaseResponse.getName(), departmentSimpleDTO.getDepartmentName())) {
isDepartmentExist = true;
dingDingDepartmentVO.setDepartmentId(departmentSimpleDTO.getDepartmentId());
dingDingDepartmentVO.setDepartmentParentId(departmentSimpleDTO.getDepartmentParentId());
break;
}
}
if (!isDepartmentExist) {
DepartmentVO departmentVO = new DepartmentVO();
departmentVO.setDepartmentState(1);
departmentVO.setDepartmentType(1);
departmentVO.setDepartmentName(deptBaseResponse.getName());
departmentVO.setDepartmentSummary("钉钉同步");
departmentVO.setDepartmentParentId(departmentParentId);
String departmentId = departmentService.saveDepartmentReturnId(departmentVO);
// 填充信息
dingDingDepartmentVO.setDepartmentId(departmentId);
dingDingDepartmentVO.setDepartmentParentId(departmentParentId);
}
// 递归同步
departmentSync(deptBaseResponse.getDeptId(), dingDingDepartmentVO.getDepartmentId(), bindDingDingDepartmentVOs);
bindDingDingDepartmentVOs.add(dingDingDepartmentVO);
}
}
/**
* 同步用户
*
* @param bindDingDingDepartmentVOs
* @param userDTOs
* @param bindDingDingUserVOs
* @throws Exception
*/
private void syncUser(List<DingDingDepartmentVO> bindDingDingDepartmentVOs, List<UserDTO> userDTOs, List<DingDingUserVO> bindDingDingUserVOs) throws Exception {
// 部门用户
for (DingDingDepartmentVO dingDingDepartmentVO : bindDingDingDepartmentVOs) {
// 钉钉用户列表
List<OapiV2UserListResponse.ListUserResponse> userResponses = dingDingAppUserService.listByDeptId(dingDingDepartmentVO.getDingdingDepartmentId());
if (userResponses.isEmpty()) {
continue;
}
for (OapiV2UserListResponse.ListUserResponse userResponse : userResponses) {
DingDingUserPO dingDingUserPO = dingDingAppUserService.getPO(userResponse.getUserid());
if (dingDingUserPO != null) {
continue;
}
boolean isUserExist = false;
DingDingUserVO dingDingUserVO = new DingDingUserVO();
dingDingUserVO.setDingdingUserId(userResponse.getUserid());
dingDingUserVO.setUnionid(userResponse.getUnionid());
dingDingUserVO.setName(userResponse.getName());
dingDingUserVO.setMobile(userResponse.getMobile());
String deptIdListString = "";
for (Long deptId : userResponse.getDeptIdList()) {
if (!deptIdListString.isEmpty()) {
deptIdListString += ",";
}
deptIdListString += deptId;
}
dingDingUserVO.setDeptIdList(deptIdListString);
for (UserDTO userDTO : userDTOs) {
if (StringUtils.equals(userResponse.getMobile(), userDTO.getUserUsername())) {
isUserExist = true;
dingDingUserVO.setUserId(userDTO.getUserId());
break;
}
}
if (!isUserExist) {
UserVO userVO = new UserVO();
userVO.setUserName(userResponse.getName());
userVO.setUserUsername(userResponse.getMobile());
userVO.setUserState(0);
userVO.setUserType(2);
userVO.setUserPhone(userResponse.getMobile());
userVO.setUserEmail(userResponse.getEmail());
String userId = userService.saveUserReturnId(userVO);
dingDingUserVO.setUserId(userId);
}
bindDingDingUserVOs.add(dingDingUserVO);
}
}
}
}

View File

@ -113,6 +113,17 @@ public class UserServiceImpl extends BaseService implements IUserService {
return new SuccessResult();
}
@Override
public String saveUserReturnId(UserVO userVO) throws Exception {
String userId = UUIDUtil.getUUID();
userVO.setUserPassword(passwordEncoder.encode(DigestUtils.md5Hex(DigestUtils.md5Hex(DigestUtils.md5Hex(defaultPassword)))));
Map<String, Object> params = HashMapUtil.beanToMap(userVO);
params.put("userId", userId);
setSaveInfoByUserId(params, userId);
userDao.saveUser(params);
return userId;
}
@Override
public SuccessResult saveUserWithDepartment(String departmentId, UserVO userVO) throws Exception {
if (StringUtils.equals(ISystemConstant.TREE_ROOT_ID, departmentId)) {
@ -315,6 +326,15 @@ public class UserServiceImpl extends BaseService implements IUserService {
addUserDepartmentAdjustment(userIds, departmentId, adjustmentDepartmentName, USER_DEPARTMENT_TYPE_LEAVE);
}
@Override
public void saveDepartmentUser(String departmentId, String userId) {
Map<String, Object> params = getHashMap(2);
params.put("userId", userId);
params.put("departmentId", departmentId);
userDao.saveDepartmentUser(params);
}
@Override
public void saveDepartmentUserIdByDepartmentId(String departmentId, String departmentName, List<String> departmentUserIds) throws SaveException {
Map<String, Object> params = getHashMap(2);
@ -594,6 +614,13 @@ public class UserServiceImpl extends BaseService implements IUserService {
return userDepartmentResourceBOs;
}
@Override
public DepartmentUserDTO getDepartmentUser(String departmentId, String userId) {
Map<String, Object> params = getHashMap(4);
params.put("departmentId", departmentId);
params.put("userId", userId);
return userDao.getDepartmentUser(params);
}
/**
* 部门ID列表

View File

@ -1,6 +1,6 @@
server:
port: 8090
url: http://49.233.36.36:58090/usercenter
port: 7001
url: http://192.168.0.103:7001/usercenter
# ws: ws://192.168.0.103:7001/usercenter/ws
title: 统一用户管理平台
login-page-name: 统一用户管理平台
@ -29,7 +29,7 @@ spring:
datasource:
druid:
# url: jdbc:mysql://49.233.36.36:6688/db_cloud?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&autoReconnect=true&failOverReadOnly=false&useSSL=false&serverTimezone=UTC
url: jdbc:mysql://127.0.0.1:3306/db_cloud_v2_city?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&autoReconnect=true&failOverReadOnly=false&useSSL=false&serverTimezone=UTC
url: jdbc:mysql://192.168.0.151:3306/db_cloud_v2?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&autoReconnect=true&failOverReadOnly=false&useSSL=false&serverTimezone=UTC
db-type: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
# username: wanggeng

View File

@ -1742,4 +1742,17 @@
</if>
</select>
<!-- 部门用户详情 -->
<select id="getDepartmentUser" parameterType="map" resultMap="departmentUserDTO">
SELECT
department_id,
user_id
FROM
sys_department_user
WHERE
department_id = #{departmentId}
AND
user_id = #{userId}
</select>
</mapper>

View File

@ -33,6 +33,9 @@
<button type="button" class="layui-btn layui-btn-sm" id="uploadExcel">
<i class="fa fa-lg fa-cloud-upload"></i> 导入数据
</button>
<button type="button" class="layui-btn layui-btn-sm" id="syncDingDing">
<i class="fa fa-lg fa-refresh"></i> 同步钉钉
</button>
</div>
<table class="layui-hide" id="dataTable" lay-filter="dataTable"></table>
<!-- 表头按钮组 -->
@ -290,6 +293,26 @@
}
});
});
$(document).on('click', '#syncDingDing', function() {
top.dialog.msg('确定同步?', {
time: 0,
btn: [top.dataMessage.button.yes, top.dataMessage.button.no],
shade: 0.3,
yes: function (index) {
var loadLayerIndex;
top.restAjax.put(top.restAjax.path('dingding/user/update-sync-dingding', []), {}, null, function(code, data) {
top.dialog.msg('同步成功');
reloadTable();
}, function(code, data) {
top.dialog.msg(data.msg);
}, function() {
loadLayerIndex = top.dialog.msg('正在同步钉钉组织机构与用户...', {time: 3000});
}, function() {
top.dialog.close(loadLayerIndex);
});
}
});
});
// 事件 - 增删改
table.on('toolbar(dataTable)', function(obj) {
var layEvent = obj.event;