This commit is contained in:
MaxKey 2024-09-28 09:13:03 +08:00
commit 4484eb3d2c
41 changed files with 6172 additions and 87 deletions

View File

@ -0,0 +1,208 @@
package org.dromara.maxkey.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.dromara.mybatis.jpa.entity.JpaEntity;
import java.io.Serializable;
import java.util.Date;
/**
* @Description
* @Author Hunter
* @Date 2024-07-16
*/
@Entity
@Table(name = "SYNC_JOB_CONFIG_FIELD")
public class SyncJobConfigField extends JpaEntity implements Serializable {
private static final long serialVersionUID = 6784822536779144306L;
/**
*
* ID
*/
@Id
@Column
private Long id;
/**
* 同步任务ID
*/
@Column
private Long jobId;
/**
* 规则名
*/
@Column
private String name;
/**
* 类型
*/
@Column
private String objectType;
/**
* 目标字段
*/
@Column
private String targetField;
/**
* 目标字段描述
*/
@Column
private String targetFieldName;
/**
* 来源字段
*/
@Column
private String sourceField;
/**
* 来源字段描述
*/
@Column
private String sourceFieldName;
/**
* 描述
*/
@Column
private String description;
/**
* 创建人
*/
@Column
private Long createUser;
/**
* 创建时间
*/
@Column
private Date createTime;
/**
* 修改人
*/
@Column
private Long updateUser;
/**
* 修改时间
*/
@Column
private Date updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getJobId() {
return jobId;
}
public void setJobId(Long jobId) {
this.jobId = jobId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getObjectType() {
return objectType;
}
public void setObjectType(String objectType) {
this.objectType = objectType;
}
public String getTargetField() {
return targetField;
}
public void setTargetField(String targetField) {
this.targetField = targetField;
}
public String getTargetFieldName() {
return targetFieldName;
}
public void setTargetFieldName(String targetFieldName) {
this.targetFieldName = targetFieldName;
}
public String getSourceField() {
return sourceField;
}
public void setSourceField(String sourceField) {
this.sourceField = sourceField;
}
public String getSourceFieldName() {
return sourceFieldName;
}
public void setSourceFieldName(String sourceFieldName) {
this.sourceFieldName = sourceFieldName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Long getCreateUser() {
return createUser;
}
public void setCreateUser(Long createUser) {
this.createUser = createUser;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Long getUpdateUser() {
return updateUser;
}
public void setUpdateUser(Long updateUser) {
this.updateUser = updateUser;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}

View File

@ -0,0 +1,24 @@
package org.dromara.maxkey.persistence.mapper;
import org.apache.ibatis.annotations.Param;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.mybatis.jpa.IJpaMapper;
import java.util.List;
public interface SyncJobConfigFieldMapper extends IJpaMapper<SyncJobConfigField> {
/*@Select("SELECT * FROM sync_job_config_field WHERE job_id = #{jobId} AND object_type = #{objectType}")*/
public List<SyncJobConfigField> findByJobIdAndObjectType(@Param("jobId") Long jobId, @Param("objectType") String objectType);
public List<SyncJobConfigField> findByJobId(Long jobId);
void deleteFieldMapById(Long id);
void deleteFiledMapByjobId(Long jobId);
void deleteByJobIdAndObjectType(@Param("jobId") Long jobId, @Param("objectType") String objectType);
}

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace对应接口全类名-->
<!--
多行注释快捷键ctrl + shift + /
-->
<mapper namespace="org.dromara.maxkey.persistence.mapper.SyncJobConfigFieldMapper">
<!-- id要和方法名相同-->
<insert id="insertUser">
</insert>
<update id="updateUser">
</update>
<delete id="deleteUser">
</delete>
<delete id="deleteFieldMapById">
DELETE FROM sync_job_config_field s WHERE s.id = #{id}
</delete>
<delete id="deleteFiledMapByjobId">
DELETE FROM sync_job_config_field s WHERE s.job_id = #{jobId}
</delete>
<delete id="deleteByJobIdAndObjectType">
DELETE FROM sync_job_config_field WHERE job_id = #{jobId} AND object_type = #{objectType}
</delete>
<!--多对一映射-->
<!--
type:处理映射关系的实体类的类型常用的标签
id:处理主键和实体类中属性的映射关系
result: 处理普通字段和实体类中属性的映射关系
column: 设置映射关系中的字段名必须是sql查询出的某个字段
property: 设置映射关系中的属性的属性名,必须是处理的实体类类型中的属性名
-->
<!--
resultMap + association 处理多对一映射
association: 处理多对一的映射关系(处理实体类类型的属性)
property: 设置需要处理映射关系的属性的属性名
javaType:设置要处理的属性的类型
-->
<resultMap id="FieldMap" type="org.dromara.maxkey.entity.SyncJobConfigField">
<id column="id" property="id"></id>
<result column="jobid" property="jobId"></result>
<result column="name" property="name"></result>
<result column="objecttype" property="objectType"></result>
<result column="targetfield" property="targetField"></result>
<result column="targetfield_name" property="targetFieldName"></result>
<result column="sourcefield" property="sourceField"></result>
<result column="sourcefieldname" property="sourceFieldName"></result>
<result column="description" property="description"></result>
<result column="createuser" property="createUser"></result>
<result column="createtime" property="createTime"></result>
<result column="updateuser" property="updateUser"></result>
<result column="updatetime" property="updateTime"></result>
</resultMap>
<select id="findByJobIdAndObjectType" resultMap="FieldMap" parameterType="map">
SELECT * FROM sync_job_config_field WHERE jobid = #{jobId} AND objecttype = #{objectType}
</select>
<select id="findByJobId" resultMap="FieldMap" parameterType="map">
SELECT * FROM sync_job_config_field WHERE job_id = #{jobId}
</select>
<!-- &lt;!&ndash;
resultMap + 分步查询实现一对多映射
property: 设置需要处理映射关系的属性的属性名
select: 设置分步查询的sgl的唯一标识
column:将查询出的某个字段作为分步查询的sql的条件
&ndash;&gt;
<resultMap id="" type="">
<id column="" property=""></id>
<result column="" property=""></result>
<result column="" property=""></result>
<result column="" property=""></result>
<association property=""
select=""
column="">
</association>
</resultMap>
<select id="" resultMap="">
</select>
&lt;!&ndash;处理一对多映射&ndash;&gt;
&lt;!&ndash;
方法一resultMap + collection
&ndash;&gt;
<resultMap id="" type="">
<id column="" property=""></id>
<result column="" property=""></result>
<collection property="" ofType="">
<id column="" property=""></id>
<result column="" property=""></result>
<result column="" property=""></result>
<result column="" property=""></result>
</collection>
</resultMap>
<select id="" resultMap="">
</select>
&lt;!&ndash;
方法二collection分步查询
&ndash;&gt;
<resultMap id="" type="">
<id column="" property=""></id>
<result column="" property=""></result>
<collection property=""
select=""
column="">
</collection>
</resultMap>
<select id="" resultMap="">
</select>-->
</mapper>

View File

@ -17,8 +17,11 @@
package org.dromara.maxkey.synchronizer.activedirectory;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
@ -35,14 +38,23 @@ import org.dromara.maxkey.ldap.LdapUtils;
import org.dromara.maxkey.ldap.constants.OrganizationalUnit;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.getFieldValue;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.setFieldValue;
@Service
public class ActiveDirectoryOrganizationService extends AbstractSynchronizerService implements ISynchronizerService{
static final Logger _logger = LoggerFactory.getLogger(ActiveDirectoryOrganizationService.class);
@Autowired
private SyncJobConfigFieldService syncJobConfigFieldService;
private static final Integer ORG_TYPE = 2;
ActiveDirectoryUtils ldapUtils;
public void sync() {
@ -214,6 +226,65 @@ public class ActiveDirectoryOrganizationService extends AbstractSynchronizerSer
}
return null;
}
public Organizations buildOrgByFiledMap(HashMap<String,Attribute> attributeMap,String name,String nameInNamespace){
Organizations org = new Organizations();
Map<String, String> filedMap = getFiledMap(Long.parseLong(synchronizer.getId()));
String []namePaths = name.replaceAll(",OU=" , "/")
.replaceAll("OU=" , "/")
.replaceAll(",ou=" , "/")
.replaceAll("ou=" , "/")
.split("/");
String namePah= "/"+rootOrganization.getOrgName();
for(int i = namePaths.length -1 ; i >= 0 ; i --) {
namePah = namePah + "/" + namePaths[i];
}
namePah = namePah.substring(0, namePah.length() - 1);
org.setLdapDn(nameInNamespace);
org.setNamePath(namePah);
org.setId(org.generateId());
org.setLevel(namePaths.length);
org.setType("department");
org.setInstId(this.synchronizer.getInstId());
org.setStatus(ConstsStatus.ACTIVE);
for (Map.Entry<String, String> entry : filedMap.entrySet()) {
String orgProperty = entry.getKey();
String sourceProperty = entry.getValue();
try {
Object sourceValue = null;
if(attributeMap.keySet().contains(sourceProperty.toLowerCase())){
sourceValue = LdapUtils.getAttributeStringValue(sourceProperty, attributeMap);
}else{
sourceValue = getFieldValue(org, sourceProperty);
}
if (sourceValue != null) {
setFieldValue(org, orgProperty, sourceValue);
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | NamingException e) {
e.printStackTrace();
}
}
org.setOrgCode(org.getId());
return org;
}
public Map<String,String> getFiledMap(Long jobId){
Map<String,String> filedMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取用户属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == ORG_TYPE.intValue()){
filedMap.put(element.getTargetField(),element.getSourceField());
}
}
return filedMap;
}
@ -225,5 +296,11 @@ public class ActiveDirectoryOrganizationService extends AbstractSynchronizerSer
this.ldapUtils = ldapUtils;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
}

View File

@ -17,7 +17,10 @@
package org.dromara.maxkey.synchronizer.activedirectory;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
@ -36,14 +39,22 @@ import org.dromara.maxkey.ldap.LdapUtils;
import org.dromara.maxkey.ldap.constants.ActiveDirectoryUser;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.setFieldValue;
@Service
public class ActiveDirectoryUsersService extends AbstractSynchronizerService implements ISynchronizerService{
static final Logger _logger = LoggerFactory.getLogger(ActiveDirectoryUsersService.class);
final static Logger _logger = LoggerFactory.getLogger(ActiveDirectoryUsersService.class);
@Autowired
private SyncJobConfigFieldService syncJobConfigFieldService;
private static final Integer USER_TYPE = 1;
ActiveDirectoryUtils ldapUtils;
public void sync() {
@ -130,14 +141,15 @@ public class ActiveDirectoryUsersService extends AbstractSynchronizerService
namePah = namePah + "/" + namePaths[i];
}
//namePah = namePah.substring(0, namePah.length());
namePah = namePah.substring(0, namePah.length());
String deptNamePath= namePah.substring(0, namePah.lastIndexOf("/"));
_logger.info("deptNamePath " + deptNamePath);
Organizations deptOrg = orgsNamePathMap.get(deptNamePath);
if(deptOrg == null ) {
deptOrg = rootOrganization;
}
userInfo.setDepartment(deptOrg.getOrgName());
userInfo.setDepartmentId(deptOrg.getId());
try {
@ -185,7 +197,7 @@ public class ActiveDirectoryUsersService extends AbstractSynchronizerService
userInfo.setTimeZone("Asia/Shanghai");
userInfo.setStatus(ConstsStatus.ACTIVE);
userInfo.setInstId(this.synchronizer.getInstId());
HistorySynchronizer historySynchronizer =new HistorySynchronizer();
historySynchronizer.setId(historySynchronizer.generateId());
historySynchronizer.setSyncId(this.synchronizer.getId());
@ -203,6 +215,102 @@ public class ActiveDirectoryUsersService extends AbstractSynchronizerService
return userInfo;
}
public UserInfo buildUserInfoByFieldMap(HashMap<String,Attribute> attributeMap,String name,String nameInNamespace){
UserInfo userInfo = new UserInfo();
userInfo.setLdapDn(nameInNamespace);
userInfo.setId(userInfo.generateId());
String []namePaths = name.replaceAll(",OU=" , "/")
.replaceAll("OU=" , "/")
.replaceAll(",ou=" , "/")
.replaceAll("ou=" , "/")
.split("/");
String namePah= "/"+rootOrganization.getOrgName();
for(int i = namePaths.length -1 ; i >= 0 ; i --) {
namePah = namePah + "/" + namePaths[i];
}
namePah = namePah.substring(0, namePah.length());
String deptNamePath= namePah.substring(0, namePah.lastIndexOf("/"));
_logger.info("deptNamePath " + deptNamePath);
Organizations deptOrg = orgsNamePathMap.get(deptNamePath);
if(deptOrg == null ) {
deptOrg = rootOrganization;
}
Map<String, String> fieldMap = getFieldMap(Long.parseLong(synchronizer.getId()));
for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
String userInfoProperty = entry.getKey();
String sourceProperty = entry.getValue();
try {
if(sourceProperty.equals("orgName")){
userInfo.setDepartment(deptOrg.getOrgName());
continue;
}
if(sourceProperty.equals("id")){
userInfo.setDepartmentId(deptOrg.getId());
continue;
}
if(sourceProperty.equals("mobile")){
userInfo.setMobile(LdapUtils.getAttributeStringValue(sourceProperty, attributeMap).equals("")?
userInfo.getId():LdapUtils.getAttributeStringValue(sourceProperty,attributeMap));
continue;
}
// 获取源属性的值
Object sourceValue = LdapUtils.getAttributeStringValue(sourceProperty, attributeMap);
// 设置到 UserInfo 对象
if (sourceValue != null) {
setFieldValue(userInfo, userInfoProperty, sourceValue);
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
}
try {
userInfo.setLdapDn(nameInNamespace);
userInfo.setUserState("RESIDENT");
userInfo.setUserType("EMPLOYEE");
userInfo.setTimeZone("Asia/Shanghai");
userInfo.setStatus(ConstsStatus.ACTIVE);
userInfo.setInstId(this.synchronizer.getInstId());
HistorySynchronizer historySynchronizer =new HistorySynchronizer();
historySynchronizer.setId(historySynchronizer.generateId());
historySynchronizer.setSyncId(this.synchronizer.getId());
historySynchronizer.setSyncName(this.synchronizer.getName());
historySynchronizer.setObjectId(userInfo.getId());
historySynchronizer.setObjectName(userInfo.getUsername());
historySynchronizer.setObjectType(Organizations.class.getSimpleName());
historySynchronizer.setInstId(synchronizer.getInstId());
historySynchronizer.setResult("success");
this.historySynchronizerService.insert(historySynchronizer);
} catch (Exception e) {
e.printStackTrace();
}
return userInfo;
}
public Map<String,String> getFieldMap(Long jobId){
Map<String,String> fieldMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取用户属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == USER_TYPE.intValue()){
fieldMap.put(element.getTargetField(), element.getSourceField());
}
}
return fieldMap;
}
public ActiveDirectoryUtils getLdapUtils() {
return ldapUtils;
}
@ -210,5 +318,12 @@ public class ActiveDirectoryUsersService extends AbstractSynchronizerService
public void setLdapUtils(ActiveDirectoryUtils ldapUtils) {
this.ldapUtils = ldapUtils;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
}

View File

@ -17,6 +17,10 @@
package org.dromara.maxkey.synchronizer.dingtalk;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.LinkedBlockingQueue;
@ -25,8 +29,11 @@ import org.dromara.maxkey.entity.SynchroRelated;
import org.dromara.maxkey.entity.idm.Organizations;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
@ -37,9 +44,15 @@ import com.dingtalk.api.response.OapiV2DepartmentListsubResponse;
import com.dingtalk.api.response.OapiV2DepartmentListsubResponse.DeptBaseResponse;
import com.taobao.api.ApiException;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.*;
@Service
public class DingtalkOrganizationService extends AbstractSynchronizerService implements ISynchronizerService{
static final Logger _logger = LoggerFactory.getLogger(DingtalkOrganizationService.class);
final static Logger _logger = LoggerFactory.getLogger(DingtalkOrganizationService.class);
@Autowired
private SyncJobConfigFieldService syncJobConfigFieldService;
private static final Integer ORG_TYPE = 2;
static Long ROOT_DEPT_ID = 1L;
@ -55,7 +68,7 @@ public class DingtalkOrganizationService extends AbstractSynchronizerService im
OapiV2DepartmentGetResponse rootDeptRsp = requestDepartment(access_token,ROOT_DEPT_ID);
_logger.debug("root dept deptId {} , name {} , parentId {}"
,rootDeptRsp.getResult().getDeptId(),
rootDeptRsp.getResult().getName(),
rootDeptRsp.getResult().getName(),
rootDeptRsp.getResult().getParentId());
//root
SynchroRelated rootSynchroRelated = buildSynchroRelated(rootOrganization,
@ -81,8 +94,11 @@ public class DingtalkOrganizationService extends AbstractSynchronizerService im
SynchroRelated synchroRelated =
synchroRelatedService.findByOriginId(
this.synchronizer,dept.getDeptId() + "",Organizations.CLASS_TYPE );
Organizations organization = buildOrganization(dept);
//Parent
SynchroRelated synchroRelatedParent =
synchroRelatedService.findByOriginId(
this.synchronizer,dept.getParentId() + "",Organizations.CLASS_TYPE);
Organizations organization = buildOrgByFieldMap(dept,synchroRelatedParent);
if(synchroRelated == null) {
organization.setId(organization.generateId());
organizationsService.insert(organization);
@ -147,11 +163,8 @@ public class DingtalkOrganizationService extends AbstractSynchronizerService im
synchronizer.getInstId());
}
public Organizations buildOrganization(DeptBaseResponse dept) {
//Parent
SynchroRelated synchroRelatedParent =
synchroRelatedService.findByOriginId(
this.synchronizer,dept.getParentId() + "",Organizations.CLASS_TYPE);
public Organizations buildOrganization(DeptBaseResponse dept,SynchroRelated synchroRelatedParent) {
Organizations org = new Organizations();
org.setId(dept.getDeptId()+"");
org.setOrgCode(dept.getDeptId()+"");
@ -167,6 +180,51 @@ public class DingtalkOrganizationService extends AbstractSynchronizerService im
return org;
}
public Organizations buildOrgByFieldMap(DeptBaseResponse dept,SynchroRelated synchroRelatedParent){
Organizations org = new Organizations();
Map<String, String> fieldMap = getFieldMap(Long.parseLong(synchronizer.getId()));
for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
String orgProperty = entry.getKey();
String sourceProperty = entry.getValue();
try {
Object sourceValue = null;
if (hasField(DeptBaseResponse.class, sourceProperty)) {
sourceValue = getFieldValue(dept, sourceProperty);
}
else if (synchroRelatedParent != null && hasField(SynchroRelated.class, sourceProperty)) {
sourceValue = getFieldValue(synchroRelatedParent, sourceProperty);
}
if (sourceValue != null) {
setFieldValue(org, orgProperty, sourceValue);
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
org.setType("department");
org.setInstId(this.synchronizer.getInstId());
org.setStatus(ConstsStatus.ACTIVE);
org.setDescription("dingtalk");
return org;
}
public Map<String,String> getFieldMap(Long jobId){
Map<String,String> FieldMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取用户属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == ORG_TYPE.intValue()){
FieldMap.put(element.getTargetField(), element.getSourceField());
}
}
return FieldMap;
}
public String getAccess_token() {
@ -176,5 +234,13 @@ public class DingtalkOrganizationService extends AbstractSynchronizerService im
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
}

View File

@ -17,7 +17,10 @@
package org.dromara.maxkey.synchronizer.dingtalk;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.dromara.maxkey.constants.ConstsStatus;
@ -25,10 +28,13 @@ import org.dromara.maxkey.entity.SynchroRelated;
import org.dromara.maxkey.entity.idm.UserInfo;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
@ -36,11 +42,21 @@ import com.dingtalk.api.request.OapiV2UserListRequest;
import com.dingtalk.api.response.OapiV2UserListResponse;
import com.dingtalk.api.response.OapiV2UserListResponse.ListUserResponse;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.*;
@Service
public class DingtalkUsersService extends AbstractSynchronizerService implements ISynchronizerService{
static final Logger _logger = LoggerFactory.getLogger(DingtalkUsersService.class);
String access_token;
private static final Integer USER_TYPE = 1;
@Autowired
private SyncJobConfigFieldService syncJobConfigFieldService;
public void sync() {
_logger.info("Sync Dingtalk Users...");
@ -65,7 +81,7 @@ public class DingtalkUsersService extends AbstractSynchronizerService implement
for(ListUserResponse user :rsp.getResult().getList()) {
_logger.debug("name : {} , {} , {}", user.getName(),user.getLoginId(),user.getUserid());
UserInfo userInfo = buildUserInfo(user,relatedOrg);
UserInfo userInfo = buildUserInfoByFieldMap(user,relatedOrg);
_logger.trace("userInfo {}" , userInfo);
userInfo.setPassword(userInfo.getUsername() + UserInfo.DEFAULT_PASSWORD_SUFFIX);
userInfoService.saveOrUpdate(userInfo);
@ -96,7 +112,7 @@ public class DingtalkUsersService extends AbstractSynchronizerService implement
}
}
public UserInfo buildUserInfo(ListUserResponse user,SynchroRelated relatedOrg) {
UserInfo userInfo = new UserInfo();
@ -121,16 +137,88 @@ public class DingtalkUsersService extends AbstractSynchronizerService implement
}else {
userInfo.setStatus(ConstsStatus.INACTIVE);
}
userInfo.setInstId(this.synchronizer.getInstId());
//userInfo.setInstId(this.synchronizer.getInstId());
userInfo.setDescription("dingtalk "+user.getRemark());
return userInfo;
}
public UserInfo buildUserInfoByFieldMap(ListUserResponse user, SynchroRelated relatedOrg){
UserInfo userInfo = new UserInfo();
Map<String, String> fieldMap = getFieldMap(Long.parseLong(synchronizer.getId()));
for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
String userInfoProperty = entry.getKey();
String sourceProperty = entry.getValue();
try {
Object sourceValue = null;
if(sourceProperty.equals("email")){
userInfo.setEmail(StringUtils.isBlank(user.getEmail())? user.getUserid() +"@maxkey.top":user.getEmail());
continue;
}
if(sourceProperty.equals("active")){
userInfo.setStatus(user.getActive()?ConstsStatus.ACTIVE:ConstsStatus.INACTIVE);
continue;
}
if(sourceProperty.equals("remark")){
userInfo.setDescription("dingtalk "+user.getRemark());
continue;
}
if(sourceProperty.equals("hiredDate")){
userInfo.setEntryDate(new DateTime(user.getHiredDate()).toString(DateTimeFormat.forPattern("yyyy-MM-dd")));
continue;
}
if (hasField(OapiV2UserListResponse.ListUserResponse.class, sourceProperty)) {
sourceValue = getFieldValue(user, sourceProperty);
}
else if (hasField(SynchroRelated.class, sourceProperty)) {
sourceValue = getFieldValue(relatedOrg, sourceProperty);
}
if (sourceValue != null) {
setFieldValue(userInfo, userInfoProperty, sourceValue);
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
userInfo.setInstId(this.synchronizer.getInstId());
userInfo.setUserType("EMPLOYEE");
userInfo.setUserState("RESIDENT");
return userInfo;
}
public Map<String,String> getFieldMap(Long jobId){
Map<String,String> userFieldMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取用户属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == USER_TYPE.intValue()){
userFieldMap.put(element.getTargetField(), element.getSourceField());
}
}
return userFieldMap;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
}

View File

@ -17,7 +17,10 @@
package org.dromara.maxkey.synchronizer.feishu;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.LinkedBlockingQueue;
@ -26,20 +29,31 @@ import org.dromara.maxkey.entity.SynchroRelated;
import org.dromara.maxkey.entity.idm.Organizations;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.feishu.entity.FeishuDepts;
import org.dromara.maxkey.synchronizer.feishu.entity.FeishuDeptsResponse;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.dromara.maxkey.util.AuthorizationHeaderUtils;
import org.dromara.maxkey.util.JsonUtils;
import org.dromara.maxkey.web.HttpRequestAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.*;
@Service
public class FeishuOrganizationService extends AbstractSynchronizerService implements ISynchronizerService{
static final Logger _logger = LoggerFactory.getLogger(FeishuOrganizationService.class);
String access_token;
private static final Integer ORG_TYPE = 2;
@Autowired
private SyncJobConfigFieldService syncJobConfigFieldService;
static String DEPTS_URL = "https://open.feishu.cn/open-apis/contact/v3/departments/%s/children?page_size=50";
static String ROOT_DEPT_URL = "https://open.feishu.cn/open-apis/contact/v3/departments/%s";
@ -75,7 +89,11 @@ public class FeishuOrganizationService extends AbstractSynchronizerService imple
SynchroRelated synchroRelated =
synchroRelatedService.findByOriginId(
this.synchronizer,dept.getOpen_department_id(),Organizations.CLASS_TYPE );
Organizations organization = buildOrganization(dept);
//Parent
SynchroRelated synchroRelatedParent =
synchroRelatedService.findByOriginId(
this.synchronizer,dept.getParent_department_id(),Organizations.CLASS_TYPE);
Organizations organization = buildOrganizationByFieldMap(dept,synchroRelatedParent);
if(synchroRelated == null) {
organization.setId(organization.generateId());
organizationsService.insert(organization);
@ -138,11 +156,8 @@ public class FeishuOrganizationService extends AbstractSynchronizerService imple
synchronizer.getInstId());
}
public Organizations buildOrganization(FeishuDepts dept) {
//Parent
SynchroRelated synchroRelatedParent =
synchroRelatedService.findByOriginId(
this.synchronizer,dept.getParent_department_id(),Organizations.CLASS_TYPE);
public Organizations buildOrganization(FeishuDepts dept,SynchroRelated synchroRelatedParent) {
Organizations org = new Organizations();
org.setOrgCode(dept.getDepartment_id()+"");
@ -157,6 +172,59 @@ public class FeishuOrganizationService extends AbstractSynchronizerService imple
return org;
}
public Organizations buildOrganizationByFieldMap(FeishuDepts dept,SynchroRelated synchroRelatedParent){
Map<String, String> fieldMap = getFiledMap(Long.parseLong(synchronizer.getId()));
Organizations org = new Organizations();
for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
String orgProperty = entry.getKey();
String sourceProperty = entry.getValue();
try {
Object sourceValue = null;
if (hasField(dept.getClass(), sourceProperty)) {
sourceValue = getFieldValue(dept, sourceProperty);
}
else if (synchroRelatedParent != null && hasField(SynchroRelated.class, sourceProperty)) {
sourceValue = getFieldValue(synchroRelatedParent, sourceProperty);
}
if (sourceValue != null) {
setFieldValue(org, orgProperty, sourceValue);
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
// 额外处理特定逻辑:意味着这些属性不能出现在属性映射表中
try {
/*if (synchroRelatedParent != null) {
setFieldValue(org, "parentId", synchroRelatedParent.getObjectId());
setFieldValue(org, "parentName", synchroRelatedParent.getObjectName());
}*/
setFieldValue(org, "instId", this.synchronizer.getInstId());
setFieldValue(org, "status", ConstsStatus.ACTIVE);
setFieldValue(org, "description", "Feishu");
org.setType("department");
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return org;
}
public Map<String,String> getFiledMap(Long jobId){
//key是maxkey的属性value是其他应用的属性
Map<String,String> filedMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取组织属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == ORG_TYPE.intValue()){
filedMap.put(element.getTargetField(), element.getSourceField());
}
}
return filedMap;
}
public String getAccess_token() {
return access_token;
}
@ -165,4 +233,12 @@ public class FeishuOrganizationService extends AbstractSynchronizerService imple
this.access_token = access_token;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
}

View File

@ -17,28 +17,38 @@
package org.dromara.maxkey.synchronizer.feishu;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dromara.maxkey.constants.ConstsStatus;
import org.dromara.maxkey.entity.SynchroRelated;
import org.dromara.maxkey.entity.idm.UserInfo;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.feishu.entity.FeishuUsers;
import org.dromara.maxkey.synchronizer.feishu.entity.FeishuUsersResponse;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.dromara.maxkey.util.AuthorizationHeaderUtils;
import org.dromara.maxkey.util.JsonUtils;
import org.dromara.maxkey.web.HttpRequestAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.*;
@Service
public class FeishuUsersService extends AbstractSynchronizerService implements ISynchronizerService{
static final Logger _logger = LoggerFactory.getLogger(FeishuUsersService.class);
final static Logger _logger = LoggerFactory.getLogger(FeishuUsersService.class);
@Autowired
private SyncJobConfigFieldService syncJobConfigFieldService;
String access_token;
private static final Integer USER_TYPE = 1;
static String USERS_URL="https://open.feishu.cn/open-apis/contact/v3/users/find_by_department?department_id=%s&page_size=50";
@ -57,7 +67,7 @@ public class FeishuUsersService extends AbstractSynchronizerService implements I
_logger.trace("response : " + responseBody);
if(usersResponse.getCode() == 0 && usersResponse.getData().getItems() != null) {
for(FeishuUsers feiShuUser : usersResponse.getData().getItems()) {
UserInfo userInfo = buildUserInfo(feiShuUser,relatedOrg);
UserInfo userInfo = buildUserInfoByFieldMapper(feiShuUser,relatedOrg);
_logger.debug("userInfo : " + userInfo);
userInfo.setPassword(userInfo.getUsername() + UserInfo.DEFAULT_PASSWORD_SUFFIX);
userInfoService.saveOrUpdate(userInfo);
@ -89,6 +99,11 @@ public class FeishuUsersService extends AbstractSynchronizerService implements I
}
}
public void postSync(UserInfo userInfo) {
@ -124,7 +139,77 @@ public class FeishuUsersService extends AbstractSynchronizerService implements I
return userInfo;
}
public UserInfo buildUserInfoByFieldMapper(FeishuUsers user,SynchroRelated relatedOrg){
UserInfo userInfo = new UserInfo();
Map<String, String> fieldMap = this.getFiledMap(Long.parseLong(synchronizer.getId()));
for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
String userInfoProperty = entry.getKey();
String sourceProperty = entry.getValue();
try {
Object sourceValue = null;
if(sourceProperty.equals("status")){
if (user.getStatus().isIs_activated()) {
setFieldValue(userInfo, "status", ConstsStatus.ACTIVE);
} else {
setFieldValue(userInfo, "status", ConstsStatus.INACTIVE);
}
continue;
}
if (hasField(user.getClass(), sourceProperty)) {
sourceValue = getFieldValue(user, sourceProperty);
}
else if (hasField(SynchroRelated.class, sourceProperty)) {
sourceValue = getFieldValue(relatedOrg, sourceProperty);
}
if (sourceValue != null) {
setFieldValue(userInfo, userInfoProperty, sourceValue);
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
// 额外处理特定逻辑 意味着这些属性映射不能保存在数据库中
try {
if(userInfo.getUsername() == null){
userInfo.setUsername(user.getOpen_id());
}
setFieldValue(userInfo, "id", userInfo.generateId());
setFieldValue(userInfo, "instId", this.synchronizer.getInstId());
userInfo.setUserType("EMPLOYEE");
userInfo.setUserState("RESIDENT");
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return userInfo;
}
public Map<String,String> getFiledMap(Long jobId){
Map<String,String> fieldMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取用户属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == USER_TYPE.intValue()){
fieldMap.put(element.getTargetField(), element.getSourceField());
}
}
return fieldMap;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
}

View File

@ -25,9 +25,13 @@ import org.dromara.maxkey.entity.history.HistorySynchronizer;
import org.dromara.maxkey.entity.idm.Organizations;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.dromara.maxkey.synchronizer.utils.MyResultSet;
import org.dromara.maxkey.util.JdbcUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.Connection;
@ -35,11 +39,20 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.setFieldValue;
@Service
public class JdbcOrganizationService extends AbstractSynchronizerService implements ISynchronizerService {
static final Logger _logger = LoggerFactory.getLogger(JdbcOrganizationService.class);
static ArrayList<ColumnFieldMapper> mapperList = new ArrayList<>();
@Autowired
private SyncJobConfigFieldService syncJobConfigFieldService;
private static final Integer ORG_TYPE = 2;
@Override
public void sync() {
@ -74,6 +87,87 @@ public class JdbcOrganizationService extends AbstractSynchronizerService impleme
}
}
public Organizations buildOrgByFieldMap(ResultSet rs) throws SQLException{
Organizations org = new Organizations();
DbTableMetaData meta = JdbcUtils.getMetaData(rs);
Map<String, String> fieldMap = getFieldMap(Long.parseLong(synchronizer.getId()));
for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
String column = entry.getValue();
String field = entry.getKey();
Object value = rs.getObject(column);
if (value != null) {
try {
setFieldValue(org,field,value);
} catch (Exception e) {
_logger.error("setProperty {}", e);
}
}
}
org.setType("department");
org.setId(org.generateId());
org.setInstId(synchronizer.getInstId());
if (meta.getColumnsMap().containsKey("status")) {
org.setStatus(rs.getInt("status"));
} else {
org.setStatus(ConstsStatus.ACTIVE);
}
_logger.debug("Organization {}", org);
HistorySynchronizer historySynchronizer = new HistorySynchronizer();
historySynchronizer.setId(historySynchronizer.generateId());
historySynchronizer.setSyncId(synchronizer.getId());
historySynchronizer.setSyncName(synchronizer.getName());
historySynchronizer.setObjectId(org.getId());
historySynchronizer.setObjectName(org.getOrgName());
historySynchronizer.setObjectType(Organizations.class.getSimpleName());
historySynchronizer.setInstId(synchronizer.getInstId());
historySynchronizer.setResult("success");
historySynchronizerService.insert(historySynchronizer);
return org;
}
public Organizations buildOrgByFieldMapTemp(MyResultSet rs) throws SQLException{
Organizations org = new Organizations();
//DbTableMetaData meta = JdbcUtils.getMetaData(rs);
Map<String, String> fieldMap = getFieldMap(Long.parseLong(synchronizer.getId()));
for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
String column = entry.getValue();
String field = entry.getKey();
Object value = rs.getObject(column);
if (value != null) {
try {
setFieldValue(org,field,value);
} catch (Exception e) {
_logger.error("setProperty {}", e);
}
}
}
org.setId(org.generateId());
org.setInstId(synchronizer.getInstId());
if (rs.getColumnNames().contains("status")) {
org.setStatus(rs.getInt("status"));
} else {
org.setStatus(ConstsStatus.ACTIVE);
}
_logger.debug("Organization {}", org);
/*HistorySynchronizer historySynchronizer = new HistorySynchronizer();
historySynchronizer.setId(historySynchronizer.generateId());
historySynchronizer.setSyncId(synchronizer.getId());
historySynchronizer.setSyncName(synchronizer.getName());
historySynchronizer.setObjectId(org.getId());
historySynchronizer.setObjectName(org.getOrgName());
historySynchronizer.setObjectType(Organizations.class.getSimpleName());
historySynchronizer.setInstId(synchronizer.getInstId());
historySynchronizer.setResult("success");
historySynchronizerService.insert(historySynchronizer);*/
return org;
}
public Organizations buildOrganization(ResultSet rs) throws SQLException {
DbTableMetaData meta = JdbcUtils.getMetaData(rs);
@ -121,6 +215,72 @@ public class JdbcOrganizationService extends AbstractSynchronizerService impleme
}
public Organizations buildOrganizationTemp(MyResultSet rs) throws SQLException {
//DbTableMetaData meta = JdbcUtils.getMetaData(rs);
Organizations org = new Organizations();
for (ColumnFieldMapper mapper : mapperList) {
if (rs.getColumnNames().contains(mapper.getColumn())) {
Object value = null;
if (mapper.getType().equalsIgnoreCase("String")) {
value = rs.getString(mapper.getColumn());
} else {
value = rs.getInt(mapper.getColumn());
}
if (value != null) {
try {
PropertyUtils.setSimpleProperty(org, mapper.getField(), value);
} catch (Exception e) {
_logger.error("setSimpleProperty {}", e);
}
}
}
}
org.setId(org.generateId());
org.setInstId(synchronizer.getInstId());
if (rs.getColumnNames().contains("status")) {
org.setStatus(rs.getInt("status"));
} else {
org.setStatus(ConstsStatus.ACTIVE);
}
_logger.debug("Organization {}", org);
/*HistorySynchronizer historySynchronizer = new HistorySynchronizer();
historySynchronizer.setId(historySynchronizer.generateId());
historySynchronizer.setSyncId(synchronizer.getId());
historySynchronizer.setSyncName(synchronizer.getName());
historySynchronizer.setObjectId(org.getId());
historySynchronizer.setObjectName(org.getOrgName());
historySynchronizer.setObjectType(Organizations.class.getSimpleName());
historySynchronizer.setInstId(synchronizer.getInstId());
historySynchronizer.setResult("success");
historySynchronizerService.insert(historySynchronizer);*/
return org;
}
public Map<String,String> getFieldMap(Long jobId){
Map<String,String> filedMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取用户属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == ORG_TYPE.intValue()){
filedMap.put(element.getTargetField(), element.getSourceField());
}
}
return filedMap;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
static {
mapperList.add(new ColumnFieldMapper("id", "id", "String"));
@ -129,7 +289,7 @@ public class JdbcOrganizationService extends AbstractSynchronizerService impleme
mapperList.add(new ColumnFieldMapper("fullname", "fullName", "String"));
mapperList.add(new ColumnFieldMapper("parentid", "parentId", "String"));
mapperList.add(new ColumnFieldMapper("parentcode", "parentCode", "String"));
mapperList.add(new ColumnFieldMapper("parentname", "parentName", "String"));
mapperList.add(new ColumnFieldMapper(" ", "parentName", "String"));
mapperList.add(new ColumnFieldMapper("type", "type", "String"));
mapperList.add(new ColumnFieldMapper("codepath", "codePath", "String"));

View File

@ -25,21 +25,34 @@ import org.dromara.maxkey.entity.history.HistorySynchronizer;
import org.dromara.maxkey.entity.idm.UserInfo;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.dromara.maxkey.synchronizer.utils.MyResultSet;
import org.dromara.maxkey.util.JdbcUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.setFieldValue;
@Service
public class JdbcUsersService extends AbstractSynchronizerService implements ISynchronizerService {
static final Logger _logger = LoggerFactory.getLogger(JdbcUsersService.class);
final static Logger _logger = LoggerFactory.getLogger(JdbcUsersService.class);
@Autowired
public SyncJobConfigFieldService syncJobConfigFieldService;
private static final Integer USER_TYPE = 1;
static ArrayList<ColumnFieldMapper> mapperList = new ArrayList<>();
@Override
@ -93,6 +106,7 @@ public class JdbcUsersService extends AbstractSynchronizerService implements ISy
}
}
public UserInfo buildUserInfo(ResultSet rs) throws SQLException {
DbTableMetaData meta = JdbcUtils.getMetaData(rs);
UserInfo user = new UserInfo();
@ -153,6 +167,86 @@ public class JdbcUsersService extends AbstractSynchronizerService implements ISy
return user;
}
public UserInfo buildUserInfoByFieldMap(ResultSet rs) throws SQLException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
DbTableMetaData meta = JdbcUtils.getMetaData(rs);
UserInfo user = new UserInfo();
Map<String, String> fieldMap = getFieldMap(Long.parseLong(synchronizer.getId()));
for(Map.Entry<String,String> entry: fieldMap.entrySet()){
String column = entry.getValue();
String field = entry.getKey();
Object value = null;
if(meta.getColumnsMap().containsKey(column) && !field.equals("status") && !field.equals("password")){
value = rs.getObject(column);
if(value!=null){
setFieldValue(user,field,value);
}
}
}
user.setUserType("EMPLOYEE");
user.setUserState("RESIDENT");
//password的获取和user的其他属性相关如果在遍历过程中进行属性映射需要在password映射之前先完成其他属性的映射
if (meta.getColumnsMap().containsKey("status")) {
user.setStatus(rs.getInt("status"));
} else {
user.setStatus(ConstsStatus.ACTIVE);
}
user.setInstId(synchronizer.getInstId());
// password
if (meta.getColumnsMap().containsKey("password")) {
user.setPassword(rs.getString("password"));
} else {
String last4Char = "6666";
if (StringUtils.isNotBlank(user.getIdCardNo())) {
last4Char = user.getIdCardNo().substring(user.getIdCardNo().length() - 4);
} else if (StringUtils.isNotBlank(user.getMobile())) {
last4Char = user.getMobile().substring(user.getMobile().length() - 4);
} else if (StringUtils.isNotBlank(user.getEmployeeNumber())) {
last4Char = user.getEmployeeNumber().substring(user.getEmployeeNumber().length() - 4);
}
user.setPassword(user.getUsername() + "@M" + last4Char);
}
HistorySynchronizer historySynchronizer = new HistorySynchronizer();
historySynchronizer.setId(historySynchronizer.generateId());
historySynchronizer.setSyncId(synchronizer.getId());
historySynchronizer.setSyncName(synchronizer.getName());
historySynchronizer.setObjectId(user.getId());
historySynchronizer.setObjectName(user.getUsername());
historySynchronizer.setObjectType(UserInfo.class.getSimpleName());
historySynchronizer.setInstId(synchronizer.getInstId());
historySynchronizer.setResult("success");
historySynchronizerService.insert(historySynchronizer);
_logger.debug("User {} ", user);
return user;
}
public Map<String,String> getFieldMap(Long jobId){
Map<String,String> fieldMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取用户属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == USER_TYPE.intValue()){
fieldMap.put(element.getTargetField(), element.getSourceField());
}
}
return fieldMap;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
static {
mapperList.add(new ColumnFieldMapper("id", "id", "String"));
mapperList.add(new ColumnFieldMapper("username", "username", "String"));
@ -191,7 +285,7 @@ public class JdbcUsersService extends AbstractSynchronizerService implements ISy
mapperList.add(new ColumnFieldMapper("homestreetaddress", "homeStreetAddress", "String"));
mapperList.add(new ColumnFieldMapper("homeaddressformatted", "homeAddressFormatted", "String"));
mapperList.add(new ColumnFieldMapper("homeemail", "homeEmail", "String"));
mapperList.add(new ColumnFieldMapper("homephonenumber", "homePhonenumber", "String"));
mapperList.add(new ColumnFieldMapper("homephoneNumber", "homePhonenumber", "String"));
mapperList.add(new ColumnFieldMapper("homepostalcode", "homePostalCode", "String"));
mapperList.add(new ColumnFieldMapper("homefax", "homeFax", "String"));
//company
@ -207,8 +301,8 @@ public class JdbcUsersService extends AbstractSynchronizerService implements ISy
mapperList.add(new ColumnFieldMapper("manager", "manager", "String"));
mapperList.add(new ColumnFieldMapper("assistantid", "assistantId", "String"));
mapperList.add(new ColumnFieldMapper("assistant", "assistant", "String"));
mapperList.add(new ColumnFieldMapper("entrydate", "entrydate", "String"));
mapperList.add(new ColumnFieldMapper("quitdate", "quitdate", "String"));
mapperList.add(new ColumnFieldMapper("entryDate", "entrydate", "String"));
mapperList.add(new ColumnFieldMapper("quitDate", "quitdate", "String"));
mapperList.add(new ColumnFieldMapper("ldapdn", "ldapDn", "String"));
mapperList.add(new ColumnFieldMapper("description", "description", "String"));

View File

@ -17,8 +17,11 @@
package org.dromara.maxkey.synchronizer.ldap;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
@ -35,14 +38,23 @@ import org.dromara.maxkey.ldap.LdapUtils;
import org.dromara.maxkey.ldap.constants.OrganizationalUnit;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.getFieldValue;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.setFieldValue;
@Service
public class LdapOrganizationService extends AbstractSynchronizerService implements ISynchronizerService{
static final Logger _logger = LoggerFactory.getLogger(LdapOrganizationService.class);
final static Logger _logger = LoggerFactory.getLogger(LdapOrganizationService.class);
@Autowired
private SyncJobConfigFieldService syncJobConfigFieldService;
private static final Integer ORG_TYPE = 2;
LdapUtils ldapUtils;
public void sync() {
@ -212,6 +224,70 @@ public class LdapOrganizationService extends AbstractSynchronizerService implem
}
return null;
}
public Organizations buildOrgByFieldMap(HashMap<String,Attribute> attributeMap,String name,String nameInNamespace){
Organizations org = new Organizations();
String []namePaths = name.replaceAll(",OU=" , "/")
.replaceAll("OU=" , "/")
.replaceAll(",ou=" , "/")
.replaceAll("ou=" , "/")
.split("/");
String namePah= "/"+rootOrganization.getOrgName();
for(int i = namePaths.length -1 ; i >= 0 ; i --) {
namePah = namePah + "/" + namePaths[i];
}
namePah = namePah.substring(0, namePah.length() - 1);
org.setLdapDn(nameInNamespace);
org.setId(org.generateId());
org.setNamePath(namePah);
org.setLevel(namePaths.length);
org.setType("department");
Map<String, String> fieldMap = getFieldMap(Long.parseLong(synchronizer.getId()));
for(Map.Entry<String,String> entry:fieldMap.entrySet()){
String orgProperty = entry.getKey();
String sourceProperty = entry.getValue();
try {
String fieldValue = null;
if(!attributeMap.keySet().contains(sourceProperty.toLowerCase())){
fieldValue = (String) getFieldValue(org, sourceProperty);
}else {
fieldValue = LdapUtils.getAttributeStringValue(sourceProperty,attributeMap);
}
if(fieldValue!=null){
setFieldValue(org,orgProperty,fieldValue);
}
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (NamingException e) {
throw new RuntimeException(e);
}
org.setInstId(this.synchronizer.getInstId());
org.setStatus(ConstsStatus.ACTIVE);
}
return org;
}
public Map<String,String> getFieldMap(Long jobId){
Map<String,String> userFiledMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取用户属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == ORG_TYPE.intValue()){
userFiledMap.put(element.getTargetField(), element.getSourceField());
}
}
return userFiledMap;
}
public LdapUtils getLdapUtils() {
@ -221,6 +297,12 @@ public class LdapOrganizationService extends AbstractSynchronizerService implem
public void setLdapUtils(LdapUtils ldapUtils) {
this.ldapUtils = ldapUtils;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
}

View File

@ -17,7 +17,10 @@
package org.dromara.maxkey.synchronizer.ldap;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
@ -34,14 +37,23 @@ import org.dromara.maxkey.ldap.LdapUtils;
import org.dromara.maxkey.ldap.constants.InetOrgPerson;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.getFieldValue;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.setFieldValue;
@Service
public class LdapUsersService extends AbstractSynchronizerService implements ISynchronizerService{
static final Logger _logger = LoggerFactory.getLogger(LdapUsersService.class);
final static Logger _logger = LoggerFactory.getLogger(LdapUsersService.class);
@Autowired
public SyncJobConfigFieldService syncJobConfigFieldService;
private static final Integer USER_TYPE = 1;
LdapUtils ldapUtils;
public void sync() {
@ -121,10 +133,11 @@ public class LdapUsersService extends AbstractSynchronizerService implements IS
namePah = namePah + "/" + namePaths[i];
}
//namePah = namePah.substring(0, namePah.length());
namePah = namePah.substring(0, namePah.length());
String deptNamePath= namePah.substring(0, namePah.lastIndexOf("/"));
_logger.info("deptNamePath " + deptNamePath);
Organizations deptOrg = orgsNamePathMap.get(deptNamePath);
Organizations deptOrg = orgsNamePathMap.get(deptNamePath);
userInfo.setDepartment(deptOrg.getOrgName());
userInfo.setDepartmentId(deptOrg.getId());
@ -189,8 +202,8 @@ public class LdapUsersService extends AbstractSynchronizerService implements IS
userInfo.setTimeZone("Asia/Shanghai");
userInfo.setStatus(1);
userInfo.setInstId(this.synchronizer.getInstId());
HistorySynchronizer historySynchronizer =new HistorySynchronizer();
HistorySynchronizer historySynchronizer =new HistorySynchronizer();
historySynchronizer.setId(historySynchronizer.generateId());
historySynchronizer.setSyncId(this.synchronizer.getId());
historySynchronizer.setSyncName(this.synchronizer.getName());
@ -207,6 +220,123 @@ public class LdapUsersService extends AbstractSynchronizerService implements IS
return userInfo;
}
public UserInfo buildUserInfoByFieldMap(HashMap<String,Attribute> attributeMap,String name,String nameInNamespace){
UserInfo userInfo = new UserInfo();
Map<String, String> fieldMap = getFieldMap(Long.parseLong(synchronizer.getId()));
String []namePaths = name.replaceAll(",OU=" , "/")
.replaceAll("OU=" , "/")
.replaceAll(",ou=" , "/")
.replaceAll("ou=" , "/")
.split("/");
String namePah= "/"+rootOrganization.getOrgName();
for(int i = namePaths.length -1 ; i >= 0 ; i --) {
namePah = namePah + "/" + namePaths[i];
}
namePah = namePah.substring(0, namePah.length());
String deptNamePath= namePah.substring(0, namePah.lastIndexOf("/"));
_logger.info("deptNamePath " + deptNamePath);
Organizations deptOrg = orgsNamePathMap.get(deptNamePath);
userInfo.setLdapDn(nameInNamespace);
userInfo.setId(userInfo.generateId());
userInfo.setUserState("RESIDENT");
userInfo.setUserType("EMPLOYEE");
userInfo.setTimeZone("Asia/Shanghai");
userInfo.setStatus(1);
userInfo.setInstId(this.synchronizer.getInstId());
for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
String targetAttr = entry.getKey();
String sourceAttr = entry.getValue();
String value = null;
try {
if(!attributeMap.keySet().contains(sourceAttr.toLowerCase())){
value = (String) getFieldValue(deptOrg, sourceAttr);
if(value!=null){
setFieldValue(userInfo,targetAttr,value);
continue;
}
}
value = LdapUtils.getAttributeStringValue(sourceAttr,attributeMap);
if(targetAttr.equals("formattedName")){
userInfo.setFormattedName(LdapUtils.getAttributeStringValue(InetOrgPerson.SN,attributeMap)+
LdapUtils.getAttributeStringValue(InetOrgPerson.GIVENNAME,attributeMap));
continue;
}
//只配置 username uid 的映射关系
///只配置 windowsAccount uid 的映射关系
if (targetAttr.equals("username") || targetAttr.equals("windowsAccount")) {
if (sourceAttr.equals("uid") && StringUtils.isBlank(value)) {
value = LdapUtils.getAttributeStringValue(InetOrgPerson.CN,attributeMap);
}else{
value = LdapUtils.getAttributeStringValue(InetOrgPerson.UID,attributeMap);
}
//只配置 nickName initials 的映射关系
//只配置 nameZhShortSpell initials 的映射关系
} else if (targetAttr.equals("nickName") || targetAttr.equals("nameZhShortSpell")) {
if (sourceAttr.equals("initials") && StringUtils.isBlank(value)) {
value = LdapUtils.getAttributeStringValue(InetOrgPerson.SN,attributeMap) +
LdapUtils.getAttributeStringValue(InetOrgPerson.GIVENNAME,attributeMap);
}else{
value = LdapUtils.getAttributeStringValue(InetOrgPerson.INITIALS,attributeMap);
}
//只配置 displayName displayName 的映射关系
} else if (targetAttr.equals("displayName")) {
if (sourceAttr.equals("displayName") && StringUtils.isBlank(value)) {
value = LdapUtils.getAttributeStringValue(InetOrgPerson.SN,attributeMap) +
LdapUtils.getAttributeStringValue(InetOrgPerson.GIVENNAME,attributeMap);
}else {
value = LdapUtils.getAttributeStringValue(InetOrgPerson.DISPLAYNAME,attributeMap);
}
} else if (targetAttr.equals("mobile")) {
if (sourceAttr.equals("mobile") && StringUtils.isBlank(value)) {
value = (String) getFieldValue(userInfo,"id");
}else {
value = LdapUtils.getAttributeStringValue(InetOrgPerson.MOBILE,attributeMap);
}
}
setFieldValue(userInfo, targetAttr,value);
}catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
} catch (NamingException e) {
throw new RuntimeException(e);
}
}
HistorySynchronizer historySynchronizer =new HistorySynchronizer();
historySynchronizer.setId(historySynchronizer.generateId());
historySynchronizer.setSyncId(this.synchronizer.getId());
historySynchronizer.setSyncName(this.synchronizer.getName());
historySynchronizer.setObjectId(userInfo.getId());
historySynchronizer.setObjectName(userInfo.getUsername());
historySynchronizer.setObjectType(Organizations.class.getSimpleName());
historySynchronizer.setInstId(synchronizer.getInstId());
historySynchronizer.setResult("success");
this.historySynchronizerService.insert(historySynchronizer);
return userInfo;
}
public Map<String,String> getFieldMap(Long jobId){
Map<String,String> userFieldMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取用户属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == USER_TYPE.intValue()){
userFieldMap.put(element.getTargetField(), element.getSourceField());
}
}
return userFieldMap;
}
public LdapUtils getLdapUtils() {
return ldapUtils;
@ -215,5 +345,12 @@ public class LdapUsersService extends AbstractSynchronizerService implements IS
public void setLdapUtils(LdapUtils ldapUtils) {
this.ldapUtils = ldapUtils;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
}

View File

@ -22,20 +22,32 @@ import org.dromara.maxkey.entity.SynchroRelated;
import org.dromara.maxkey.entity.idm.Organizations;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.dromara.maxkey.synchronizer.workweixin.entity.WorkWeixinDepts;
import org.dromara.maxkey.synchronizer.workweixin.entity.WorkWeixinDeptsResponse;
import org.dromara.maxkey.util.JsonUtils;
import org.dromara.maxkey.web.HttpRequestAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.*;
@Service
public class WorkweixinOrganizationService extends AbstractSynchronizerService implements ISynchronizerService{
static final Logger _logger = LoggerFactory.getLogger(WorkweixinOrganizationService.class);
String access_token;
@Autowired
private SyncJobConfigFieldService syncJobConfigFieldService;
private static final Integer ORG_TYPE = 2;
static String DEPTS_URL="https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=%s";
static long ROOT_DEPT_ID = 1;
@ -58,8 +70,11 @@ public class WorkweixinOrganizationService extends AbstractSynchronizerService i
SynchroRelated synchroRelated =
synchroRelatedService.findByOriginId(
this.synchronizer,dept.getId() + "",Organizations.CLASS_TYPE );
Organizations organization = buildOrganization(dept);
//Parent
SynchroRelated synchroRelatedParent =
synchroRelatedService.findByOriginId(
this.synchronizer,dept.getParentid() + "",Organizations.CLASS_TYPE);
Organizations organization = buildOrgByFiledMap(dept,synchroRelatedParent);
if(synchroRelated == null) {
organization.setId(organization.generateId());
organizationsService.insert(organization);
@ -109,11 +124,8 @@ public class WorkweixinOrganizationService extends AbstractSynchronizerService i
return deptsResponse;
}
public Organizations buildOrganization(WorkWeixinDepts dept) {
//Parent
SynchroRelated synchroRelatedParent =
synchroRelatedService.findByOriginId(
this.synchronizer,dept.getParentid() + "",Organizations.CLASS_TYPE);
public Organizations buildOrganization(WorkWeixinDepts dept,SynchroRelated synchroRelatedParent) {
Organizations org = new Organizations();
org.setOrgName(dept.getName());
org.setOrgCode(dept.getId()+"");
@ -126,6 +138,57 @@ public class WorkweixinOrganizationService extends AbstractSynchronizerService i
return org;
}
public Organizations buildOrgByFiledMap(WorkWeixinDepts dept, SynchroRelated synchroRelatedParent){
Organizations org = new Organizations();
//fieldMap
Map<String, String> fieldMap = getFieldMap(Long.parseLong(synchronizer.getId()));
for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
String orgProperty = entry.getKey();
String sourceProperty = entry.getValue();
try {
Object sourceValue = null;
if (hasField(dept.getClass(), sourceProperty)) {
sourceValue = getFieldValue(dept, sourceProperty);
}
else if (synchroRelatedParent != null && hasField(SynchroRelated.class, sourceProperty)) {
sourceValue = getFieldValue(synchroRelatedParent, sourceProperty);
}
if (sourceValue != null) {
setFieldValue(org, orgProperty, sourceValue);
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
org.setInstId(this.synchronizer.getInstId());
org.setStatus(ConstsStatus.ACTIVE);
org.setDescription("WorkWeixin");
org.setType("department");
return org;
}
public Map<String,String> getFieldMap(Long jobId){
Map<String,String> filedMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取组织属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == ORG_TYPE.intValue()){
filedMap.put(element.getTargetField(), element.getSourceField());
}
}
return filedMap;
}
public String getAccess_token() {
return access_token;
}
@ -134,4 +197,11 @@ public class WorkweixinOrganizationService extends AbstractSynchronizerService i
this.access_token = access_token;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
}

View File

@ -17,25 +17,36 @@
package org.dromara.maxkey.synchronizer.workweixin;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dromara.maxkey.constants.ConstsStatus;
import org.dromara.maxkey.entity.SynchroRelated;
import org.dromara.maxkey.entity.idm.UserInfo;
import org.dromara.maxkey.synchronizer.AbstractSynchronizerService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.dromara.maxkey.synchronizer.workweixin.entity.WorkWeixinUsers;
import org.dromara.maxkey.synchronizer.workweixin.entity.WorkWeixinUsersResponse;
import org.dromara.maxkey.util.JsonUtils;
import org.dromara.maxkey.web.HttpRequestAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import static org.dromara.maxkey.synchronizer.utils.FieldUtil.*;
@Service
public class WorkweixinUsersService extends AbstractSynchronizerService implements ISynchronizerService{
static final Logger _logger = LoggerFactory.getLogger(WorkweixinUsersService.class);
final static Logger _logger = LoggerFactory.getLogger(WorkweixinUsersService.class);
@Autowired
public SyncJobConfigFieldService syncJobConfigFieldService;
private static final Integer USER_TYPE = 1;
String access_token;
static String USERS_URL="https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=%s&department_id=%s&fetch_child=0";
@ -53,7 +64,7 @@ public class WorkweixinUsersService extends AbstractSynchronizerService implemen
_logger.trace("response : " + responseBody);
for(WorkWeixinUsers user : usersResponse.getUserlist()) {
UserInfo userInfo = buildUserInfo(user);
UserInfo userInfo = buildUserInfoByFiledMap(user);
_logger.debug("userInfo : " + userInfo);
userInfo.setPassword(userInfo.getUsername() + UserInfo.DEFAULT_PASSWORD_SUFFIX);
userInfoService.saveOrUpdate(userInfo);
@ -113,7 +124,59 @@ public class WorkweixinUsersService extends AbstractSynchronizerService implemen
return userInfo;
}
public UserInfo buildUserInfoByFiledMap(WorkWeixinUsers user){
UserInfo userInfo = new UserInfo();
Map<String, String> fieldMap = getFieldMap(Long.parseLong(synchronizer.getId()));
for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
String userInfoProperty = entry.getKey();
String sourceProperty = entry.getValue();
try {
Object sourceValue = null;
if(sourceProperty.equals("status")){
userInfo.setStatus(user.getStatus() == 1?ConstsStatus.ACTIVE:ConstsStatus.INACTIVE);
continue;
}
if (hasField(user.getClass(), sourceProperty)) {
sourceValue = getFieldValue(user, sourceProperty);
}
if (sourceValue != null) {
setFieldValue(userInfo, userInfoProperty, sourceValue);
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
userInfo.setUserType("EMPLOYEE");
userInfo.setUserState("RESIDENT");
userInfo.setInstId(this.synchronizer.getInstId());
return userInfo;
}
public Map<String,String> getFieldMap(Long jobId){
Map<String,String> userFieldMap = new HashMap<>();
//根据job id查询属性映射表
List<SyncJobConfigField> syncJobConfigFieldList = syncJobConfigFieldService.findByJobId(jobId);
//获取用户属性映射
for(SyncJobConfigField element:syncJobConfigFieldList){
if(Integer.parseInt(element.getObjectType()) == USER_TYPE.intValue()){
userFieldMap.put(element.getTargetField(), element.getSourceField());
}
}
return userFieldMap;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public SyncJobConfigFieldService getSyncJobConfigFieldService() {
return syncJobConfigFieldService;
}
public void setSyncJobConfigFieldService(SyncJobConfigFieldService syncJobConfigFieldService) {
this.syncJobConfigFieldService = syncJobConfigFieldService;
}
}

View File

@ -0,0 +1,43 @@
package org.dromara.maxkey.synchronizer.service;
import org.dromara.maxkey.entity.SyncJobConfigField;
import org.dromara.maxkey.persistence.mapper.SyncJobConfigFieldMapper;
import org.dromara.mybatis.jpa.JpaService;
import org.springframework.stereotype.Service;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
@Service
public class SyncJobConfigFieldService extends JpaService<SyncJobConfigField> {
public SyncJobConfigFieldService() {
super(SyncJobConfigFieldMapper.class);
}
@Override
public SyncJobConfigFieldMapper getMapper() {
return (SyncJobConfigFieldMapper)super.getMapper();
}
public List<SyncJobConfigField> findByJobIdAndObjectType(Long jobId, String objectType) {
return getMapper().findByJobIdAndObjectType(jobId,objectType);
}
public void deleteFieldMapById(Long id){
ArrayList<String> ids = new ArrayList<>();
ids.add(String.valueOf(id));
super.deleteBatch(ids);
}
public List<SyncJobConfigField> findByJobId(Long jobId) {
List<SyncJobConfigField> list = find(" jobid = ?",
new Object[]{jobId},
new int[]{Types.BIGINT});
return list;
}
}

View File

@ -0,0 +1,108 @@
package org.dromara.maxkey.synchronizer.utils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class FieldUtil {
public static void setFieldValue(Object obj, String fieldName, Object value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<?> clazz = obj.getClass();
String setterMethodName = "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
String getterMethodName = "get" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
Method getterMethod = clazz.getMethod(getterMethodName);
Class<?> fieldType = getterMethod.getReturnType();
Object convertedValue = convertValueToFieldType(value, fieldType);
Method setterMethod = clazz.getMethod(setterMethodName, fieldType);
setterMethod.invoke(obj, convertedValue);
}
public static Object getFieldValue(Object obj, String fieldName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<?> clazz = obj.getClass();
String getterMethodName = "get" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
Method method = clazz.getMethod(getterMethodName);
return method.invoke(obj);
}
public static boolean hasField(Class<?> clazz, String fieldName) {
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {
if (field.getName().equals(fieldName)) {
return true;
}
}
return false;
}
public static Object convertValueToFieldType(Object value, Class<?> fieldType) {
if (fieldType.isInstance(value)) {
return value;
}
if (fieldType == Integer.class || fieldType == int.class) {
if (value instanceof Boolean) {
return (Boolean) value ? 1 : 0;
}
return Integer.parseInt(value.toString());
} else if (fieldType == Long.class || fieldType == long.class) {
return Long.parseLong(value.toString());
} else if (fieldType == Double.class || fieldType == double.class) {
return Double.parseDouble(value.toString());
} else if (fieldType == Boolean.class || fieldType == boolean.class) {
return "1".equals(value.toString()) || Boolean.parseBoolean(value.toString());
} else if (fieldType == String.class) {
return value.toString();
} else if (fieldType == DateTime.class) {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
DateTime dateTime;
if (value instanceof Long) {
dateTime = new DateTime((Long) value);
} else if (value instanceof String) {
dateTime = DateTime.parse((String) value);
}else {
dateTime = new DateTime(value);
}
return dateTime.toString(formatter);
}
throw new IllegalArgumentException("Unsupported field type: " + fieldType);
}
public static boolean areFieldsEqual(Object obj1, Object obj2) {
if (obj1 == null || obj2 == null) {
return false;
}
if (!obj1.getClass().equals(obj2.getClass())) {
return false;
}
Field[] fields = obj1.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
try {
Object value1 = field.get(obj1);
Object value2 = field.get(obj2);
if (value1 == null) {
if (value2 != null) {
return false;
}
} else if (!value1.equals(value2)) {
return false;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
return false;
}
}
return true;
}
}

View File

@ -100,4 +100,6 @@ public class RestOrganizationController {
_logger.debug("Organizations {}" , org);
return new Message<>(organizationsService.fetchPageResults(org));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -66,6 +66,7 @@
"ngx-cookie-service": "^13.2.0",
"ngx-tinymce": "^13.0.0",
"ngx-ueditor": "^13.0.0",
"npm": "^8.5.5",
"rxjs": "~7.5.0",
"screenfull": "^6.0.1",
"tslib": "^2.3.0",

View File

@ -0,0 +1,46 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { BaseEntity } from './BaseEntity';
export class JobConfigFeild extends BaseEntity {
jobId!: String;
name!: String;
objectType!: String;
targetField!: String;
sourceField!: String;
constructor() {
super();
}
override init(data: any): void {
Object.assign(this, data);
if (this.status == 1) {
this.switch_status = true;
}
}
override trans(): void {
if (this.switch_status) {
this.status = 1;
} else {
this.status = 0;
}
}
}

View File

@ -45,6 +45,10 @@ import { SocialsProviderEditerComponent } from './socials-provider/socials-provi
import { SocialsProviderComponent } from './socials-provider/socials-provider.component';
import { SynchronizerEditerComponent } from './synchronizers/synchronizer-editer/synchronizer-editer.component';
import { SynchronizersComponent } from './synchronizers/synchronizers.component';
import { SynchronizerConfigFieldComponent } from './synchronizers/synchronizer-config-field/synchronizer-config-field.component';
import {
SynchronizerConfigFieldEditComponent
} from "./synchronizers/synchronizer-config-field/editer/synchronizer-config-field-edit.component";
const routes: Routes = [
{
@ -115,7 +119,9 @@ const COMPONENTS = [PasswordPolicyComponent, EmailSendersComponent, LdapContextC
SelectAccountsStrategyComponent,
SelectAdaptersComponent,
ConnectorsComponent,
ConnectorEditerComponent
ConnectorEditerComponent,
SynchronizerConfigFieldComponent,
SynchronizerConfigFieldEditComponent
],
imports: [SharedModule, CommonModule, RouterModule.forChild(routes)],
exports: [RouterModule]

View File

@ -0,0 +1,41 @@
<div *nzModalTitle> {{ isEdit ? ('mxk.text.edit' | i18n) : ('mxk.text.add' | i18n) }} </div>
<div>
<form nz-form [formGroup]="formGroup" (ngSubmit)="onSubmit($event)" se-container="1">
<nz-form-item>
<nz-form-label [nzMd]="6" nzFor="sourceField">{{ 'mxk.job.mapping.sourceField' | i18n }}</nz-form-label>
<nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
<input [(ngModel)]="form.model.sourceField" [ngModelOptions]="{ standalone: true }" nz-input
name="sourceField" id="sourceField" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzMd]="6" nzFor="targetField">{{ 'mxk.job.mapping.targetField' | i18n }}</nz-form-label>
<nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
<input [(ngModel)]="form.model.targetField" [ngModelOptions]="{ standalone: true }" nz-input
name="targetField" id="targetField" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzMd]="6" nzFor="description">{{ 'mxk.job.mapping.description' | i18n }}</nz-form-label>
<nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
<input [(ngModel)]="form.model.description" [ngModelOptions]="{ standalone: true }" nz-input
name="description" id="description" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzMd]="6" nzFor="objectType">{{ 'mxk.job.mapping.objectType' | i18n }}</nz-form-label>
<nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
<nz-select [(ngModel)]="form.model.objectType" [ngModelOptions]="{ standalone: true }" name="objectType" id="objectType">
<nz-option nzValue="1" nzLabel="{{ 'mxk.menu.identities.users' | i18n }}"></nz-option>
<nz-option nzValue="2" nzLabel="{{ 'mxk.menu.identities.organizations' | i18n }}"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
</form>
</div>
<div *nzModalFooter>
<button nz-button nzType="default" (click)="onClose($event)">{{ 'mxk.text.close' | i18n }}</button>
<button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.submit' | i18n }}</button>
</div>

View File

@ -0,0 +1,92 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, ChangeDetectorRef, Input, OnInit, Inject } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { I18NService } from '@core';
import { _HttpClient, ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef } from 'ng-zorro-antd/modal';
import { JobConfigFeild } from '../../../../../entity/JobConfigFeild';
import { SynchronizersService } from '../../../../../service/synchronizers.service';
@Component({
selector: 'app-synchronizer-config-field-edit',
templateUrl: './synchronizer-config-field-edit.component.html',
styles: [
`
nz-form-item {
width: 100%;
}
`
],
})
export class SynchronizerConfigFieldEditComponent implements OnInit {
@Input() id?: String;
@Input() jobId?: String;
@Input() isEdit?: boolean;
form: {
submitting: boolean;
model: JobConfigFeild
} = {
submitting: false,
model: new JobConfigFeild(),
};
formGroup: FormGroup = new FormGroup({});
constructor(
private modalRef: NzModalRef,
private synchronizersService: SynchronizersService,
private fb: FormBuilder,
private msg: NzMessageService,
@Inject(ALAIN_I18N_TOKEN) private i18n: I18NService,
private cdr: ChangeDetectorRef
) {}
ngOnInit(): void {
this.get()
}
get(){
if (this.isEdit) {
this.synchronizersService.getField(`${this.id}`).subscribe(res => {
this.form.model.init(res.data);
this.cdr.detectChanges();
});
}
}
onClose(e: MouseEvent): void {
e.preventDefault();
this.modalRef.destroy({ refresh: false });
}
onSubmit(e: MouseEvent): void {
e.preventDefault();
this.form.submitting = true;
this.form.model.jobId = this.jobId +"";
(this.isEdit ? this.synchronizersService.mappingUpdate(this.form.model) : this.synchronizersService.mappingAdd(this.form.model)).subscribe(res => {
if (res.code == 0) {
this.msg.success(this.i18n.fanyi(this.isEdit ? 'mxk.alert.update.success' : 'mxk.alert.add.success'));
} else {
this.msg.error(this.i18n.fanyi(this.isEdit ? 'mxk.alert.update.error' : 'mxk.alert.add.error'));
}
this.form.submitting = false;
this.modalRef.destroy({ refresh: true });
this.cdr.detectChanges();
});
}
}

View File

@ -0,0 +1,41 @@
<div *nzModalTitle> {{ ('mxk.text.mapping' | i18n) }} </div>
<div>
<div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 8, lg: 24, xl: 48, xxl: 48 }">
<div nz-col [nzSpan]="24" class="table-list-toolbar">
<button nz-button type="button" [nzType]="'primary'" (click)="onAdd($event)">{{ 'mxk.text.add' | i18n }}</button>
</div>
<div nz-col nzMd="24" nzSm="24">
<nz-table [nzShowPagination]="false" [nzData]="form.rows">
<thead>
<tr>
<th nzAlign="center">{{ 'mxk.job.mapping.sourceField' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.job.mapping.targetField' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.job.mapping.description' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.job.mapping.objectType' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.text.action' | i18n }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of form.rows">
<td nzAlign="left">{{ data.sourceField }} </td>
<td nzAlign="left">{{ data.targetField }} </td>
<td nzAlign="left">{{ data.description }} </td>
<td nzAlign="center">
{{ data.objectType == '1' ? ('mxk.menu.identities.users' | i18n) : ('mxk.menu.identities.organizations' | i18n) }}
</td>
<td nzAlign="center">
<button nz-button type="button" (click)="onEdit($event, data.id)">{{ 'mxk.text.edit' | i18n }}</button>
<button nz-button type="button" nzDanger (click)="onDelete($event, data.id)">{{ 'mxk.text.delete' | i18n }}</button>
</td>
</tr>
</tbody>
</nz-table>
</div>
</div>
</div>
<div *nzModalFooter>
<button nz-button nzType="default" (click)="onClose($event)">{{ 'mxk.text.close' | i18n }}</button>
<button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.submit' | i18n }}</button>
</div>

View File

@ -0,0 +1,42 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SynchronizerConfigFieldComponent } from './synchronizer-config-field.component';
describe('SynchronizerConfigFieldComponent', () => {
let component: SynchronizerConfigFieldComponent;
let fixture: ComponentFixture<SynchronizerConfigFieldComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SynchronizerConfigFieldComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(SynchronizerConfigFieldComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,148 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {Component, ChangeDetectorRef, Input, OnInit, Inject, ViewContainerRef} from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { I18NService } from '@core';
import { _HttpClient, ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme';
import format from 'date-fns/format';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
import { JobConfigFeild } from '../../../../entity/JobConfigFeild';
import { SynchronizersService } from '../../../../service/synchronizers.service';
import {NzSafeAny} from "ng-zorro-antd/core/types";
import { SynchronizerConfigFieldEditComponent } from './editer/synchronizer-config-field-edit.component';
@Component({
selector: 'app-synchronizer-config-field',
templateUrl: './synchronizer-config-field.component.html',
styles: [
`
nz-form-item {
width: 100%;
}
`
],
styleUrls: ['./synchronizer-config-field.component.less']
})
export class SynchronizerConfigFieldComponent implements OnInit {
@Input() jobId?: String;
@Input() isEdit?: boolean;
form: {
submitting: boolean;
rows: NzSafeAny[]
} = {
submitting: false,
rows: []
};
formGroup: FormGroup = new FormGroup({});
constructor(
private modalRef: NzModalRef,
private modalService: NzModalService,
private synchronizersService: SynchronizersService,
private viewContainerRef: ViewContainerRef,
private fb: FormBuilder,
private msg: NzMessageService,
@Inject(ALAIN_I18N_TOKEN) private i18n: I18NService,
private cdr: ChangeDetectorRef
) {}
ngOnInit(): void {
this.fetch()
}
fetch(){
this.synchronizersService.getMapping(`${this.jobId}`).subscribe(res => {
this.form.rows = res.data
this.cdr.detectChanges();
});
}
onClose(e: MouseEvent): void {
e.preventDefault();
this.modalRef.destroy({ refresh: false });
}
onDelete(e: MouseEvent, deleteId: String): void {
e.preventDefault();
this.synchronizersService.deleteMapping(deleteId).subscribe(res => {
if (res.code == 0) {
this.msg.success(this.i18n.fanyi('mxk.alert.delete.success'));
this.fetch();
} else {
this.msg.error(this.i18n.fanyi('mxk.alert.delete.error'));
}
this.cdr.detectChanges();
});
}
onEdit(e: MouseEvent, id: String): void {
e.preventDefault();
const modal = this.modalService.create({
nzContent: SynchronizerConfigFieldEditComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
isEdit: true,
id: id,
jobId: this.jobId,
},
nzWidth: 1200,
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
modal.afterClose.subscribe(result => {
if (result.refresh) {
this.fetch();
}
});
}
onAdd(e: MouseEvent): void {
e.preventDefault();
const modal = this.modalService.create({
nzContent: SynchronizerConfigFieldEditComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
isEdit: false,
jobId: this.jobId,
},
nzWidth: 1200,
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
modal.afterClose.subscribe(result => {
if (result.refresh) {
this.fetch();
}
});
}
onSubmit(e: MouseEvent): void {
e.preventDefault();
this.form.submitting = true;
/* (this.isEdit ? this.synchronizersService.update(this.form.model) : this.synchronizersService.add(this.form.model)).subscribe(res => {
if (res.code == 0) {
this.msg.success(this.i18n.fanyi(this.isEdit ? 'mxk.alert.update.success' : 'mxk.alert.add.success'));
} else {
this.msg.error(this.i18n.fanyi(this.isEdit ? 'mxk.alert.update.error' : 'mxk.alert.add.error'));
}
this.form.submitting = false;
this.modalRef.destroy({ refresh: true });
this.cdr.detectChanges();
});*/
}
}

View File

@ -40,12 +40,12 @@
<tr>
<th [nzChecked]="query.checked" [nzIndeterminate]="query.indeterminate"
(nzCheckedChange)="onTableAllChecked($event)"></th>
<th nzAlign="center" style="display: none">Id</th>
<th nzAlign="center">{{ 'mxk.synchronizers.name' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.synchronizers.scheduler' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.text.status' | i18n }}</th>
<th nzAlign="center" class="table_cell_action_3">{{ 'mxk.text.action' | i18n }}</th>
</tr>
<th nzAlign="center" style="display: none">Id</th>
<th nzAlign="center">{{ 'mxk.synchronizers.name' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.synchronizers.scheduler' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.text.status' | i18n }}</th>
<th nzAlign="center" class="table_cell_action_5">{{ 'mxk.text.action' | i18n }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of query.results.rows">
@ -55,22 +55,25 @@
<span>{{ data.id }}</span>
</td>
<td nzAlign="left"> {{ data.name }}</td>
<td nzAlign="left"> {{ data.scheduler }}</td>
<td nzAlign="center"> <i *ngIf="data.status == 1" nz-icon nzType="check-circle" nzTheme="fill"
style="color: green"></i></td>
<td nzAlign="center" nzBreakWord="false">
<div nz-col>
<button nz-button type="button" (click)="onSynchr($event, data.id)">{{ 'mxk.text.synchr' | i18n }}</button>
<button nz-button type="button" (click)="onEdit($event, data.id)">{{ 'mxk.text.edit' | i18n }}</button>
<button nz-button type="button" nz-popconfirm
nzPopconfirmTitle="{{ 'mxk.text.delete.popconfirm.title' | i18n }}" nzPopconfirmPlacement="left"
[nzCancelText]="'mxk.text.delete.popconfirm.cancelText' | i18n"
[nzOkText]="'mxk.text.delete.popconfirm.okText' | i18n" (nzOnConfirm)="onDelete(data.id)" nzDanger>{{
'mxk.text.delete' | i18n }}</button>
</div>
</td>
</tr>
<td nzAlign="left"> {{ data.name }}</td>
<td nzAlign="left"> {{ data.scheduler }}</td>
<td nzAlign="center"> <i *ngIf="data.status == 1" nz-icon nzType="check-circle" nzTheme="fill"
style="color: green"></i></td>
<td nzAlign="center" nzBreakWord="false">
<div nz-col>
<button nz-button type="button" (click)="onSynchr($event, data.id)">{{ 'mxk.text.synchr'
| i18n }}</button>
<button nz-button type="button" (click)="onConfigFeild($event, data.id)">{{ 'mxk.text.mapping'
| i18n }}</button>
<button nz-button type="button" (click)="onEdit($event, data.id)">{{ 'mxk.text.edit' |
i18n }}</button>
<button nz-button type="button" (click)="onDelete(data.id)" nzDanger>{{ 'mxk.text.delete' | i18n
}}</button>
</div>
</td>
</tr>
</tbody>
</nz-table>
</nz-card>
</nz-card>

View File

@ -27,6 +27,7 @@ import { NzTableQueryParams } from 'ng-zorro-antd/table';
import { SynchronizersService } from '../../../service/synchronizers.service';
import { set2String } from '../../../shared/index';
import { SynchronizerEditerComponent } from './synchronizer-editer/synchronizer-editer.component';
import { SynchronizerConfigFieldComponent } from './synchronizer-config-field/synchronizer-config-field.component';
@Component({
selector: 'app-synchronizers',
templateUrl: './synchronizers.component.html',
@ -149,6 +150,7 @@ export class SynchronizersComponent implements OnInit {
});
}
onEdit(e: MouseEvent, editId: String): void {
e.preventDefault();
const modal = this.modalService.create({
@ -158,6 +160,26 @@ export class SynchronizersComponent implements OnInit {
isEdit: true,
id: editId
},
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
modal.afterClose.subscribe(result => {
if (result.refresh) {
this.fetch();
}
});
}
onConfigFeild(e: MouseEvent, jobId: String): void {
e.preventDefault();
const modal = this.modalService.create({
nzContent: SynchronizerConfigFieldComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
isEdit: true,
jobId: jobId
},
nzWidth: 1200,
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
@ -168,7 +190,8 @@ export class SynchronizersComponent implements OnInit {
});
}
onDelete(deleteId: String): void {
onDelete( deleteId: String): void {
this.synchronizersService.delete(deleteId).subscribe(res => {
if (res.code == 0) {
this.msg.success(this.i18n.fanyi('mxk.alert.delete.success'));

View File

@ -22,6 +22,7 @@ import { Observable } from 'rxjs';
import { Message } from '../entity/Message';
import { Synchronizers } from '../entity/Synchronizers';
import { BaseService } from './base.service';
import {JobConfigFeild} from "../entity/JobConfigFeild";
@Injectable({
providedIn: 'root'
@ -34,4 +35,24 @@ export class SynchronizersService extends BaseService<Synchronizers> {
synchr(synchrId: String): Observable<Message<Synchronizers>> {
return this.http.get<Message<Synchronizers>>(`${`${this.server.urls.base}/synchr`}?id=${synchrId}`);
}
getMapping(synchrId: String): Observable<Message<Synchronizers>> {
return this.http.get<Message<JobConfigFeild>>(`${`${this.server.urls.base}/mapping-list`}/${synchrId}`);
}
getField(id: String): Observable<Message<Synchronizers>> {
return this.http.get<Message<JobConfigFeild>>(`${`${this.server.urls.base}/mapping-get`}/${id}`);
}
mappingAdd(body: any): Observable<Message<JobConfigFeild>> {
return this.http.post<Message<JobConfigFeild>>(`${this.server.urls.base}/mapping-add`, body);
}
mappingUpdate(body: any): Observable<Message<JobConfigFeild>> {
return this.http.put<Message<JobConfigFeild>>(`${this.server.urls.base}/mapping-update`, body);
}
deleteMapping(id: String): Observable<Message<JobConfigFeild>> {
return this.http.get<Message<JobConfigFeild>>(`${`${this.server.urls.base}/mapping-delete`}/${id}`);
}
}

View File

@ -119,6 +119,10 @@ body {
margin-bottom: 2px !important;
}
.table_cell_action_5 {
width: 360px;
}
.table_cell_action_3 {
width: 240px;
}

View File

@ -943,5 +943,10 @@
"validation.title.required": "Please enter a title",
"validation.date.required": "Please select the start and end date",
"validation.goal.required": "Please enter a description of the goal",
"validation.standard.required": "Please enter a metric"
"validation.standard.required": "Please enter a metric",
"mxk.text.mapping": "Feild Mapping",
"mxk.job.mapping.targetField": "TargetField",
"mxk.job.mapping.sourceField": "SourceField",
"mxk.job.mapping.objectType": "ObjectType",
"mxk.job.mapping.description": "Description"
}

View File

@ -935,5 +935,12 @@
"validation.title.required": "请输入标题",
"validation.date.required": "请选择起止日期",
"validation.goal.required": "请输入目标描述",
"validation.standard.required": "请输入衡量标准"
"validation.standard.required": "请输入衡量标准",
"mxk.text.mapping": "属性映射",
"mxk.job.mapping.targetField": "目标字段",
"mxk.job.mapping.sourceField": "来源字段",
"mxk.job.mapping.objectType": "映射类型",
"mxk.job.mapping.description": "规则说明"
}

View File

@ -936,5 +936,10 @@
"validation.title.required": "請輸入標題",
"validation.date.required": "請選擇起止日期",
"validation.goal.required": "請輸入目標描述",
"validation.standard.required": "請輸入衡量標準"
"validation.standard.required": "請輸入衡量標準",
"mxk.text.mapping": "属性映射",
"mxk.job.mapping.targetField": "目标字段",
"mxk.job.mapping.sourceField": "来源字段",
"mxk.job.mapping.objectType": "映射类型",
"mxk.job.mapping.description": "规则说明"
}

View File

@ -103,9 +103,9 @@ maxkey.notices.visible =false
spring.datasource.type =com.alibaba.druid.pool.DruidDataSource
#mysql
spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver
spring.datasource.username =${DATABASE_USER:root}
spring.datasource.password =${DATABASE_PWD:maxkey}
spring.datasource.url =jdbc:mysql://${DATABASE_HOST:localhost}:${DATABASE_PORT:3306}/${DATABASE_NAME:maxkey}?autoReconnect=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username =root
spring.datasource.password =root
spring.datasource.url =jdbc:mysql://127.0.0.1:3306/maxkey?useSSL=false&serverTimezone=UTC
#highgo
#spring.datasource.driver-class-name=com.highgo.jdbc.Driver
#spring.datasource.username=highgo

View File

@ -25,6 +25,8 @@ import org.dromara.maxkey.persistence.repository.LoginHistoryRepository;
import org.dromara.maxkey.persistence.repository.LoginRepository;
import org.dromara.maxkey.persistence.repository.PasswordPolicyValidator;
import org.dromara.maxkey.persistence.service.UserInfoService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.synchronizer.ldap.LdapSynchronizerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
@ -69,4 +71,12 @@ public class MaxKeyMgtConfig {
return tfaOtpAuthn;
}
/*@Bean
public ISynchronizerService ldapSynchronizerService() {
LdapSynchronizerService ldapSynchronizerService = new LdapSynchronizerService();
ldapSynchronizerService.setId("LDAP_11122");
ldapSynchronizerService.syncOrg();
return ldapSynchronizerService;
}*/
}

View File

@ -20,6 +20,10 @@ package org.dromara.maxkey.web.config.contorller;
import org.apache.commons.lang3.StringUtils;
import org.dromara.maxkey.authn.annotation.CurrentUser;
import org.dromara.maxkey.crypto.password.PasswordReciprocal;
import org.dromara.maxkey.entity.*;
import org.dromara.maxkey.persistence.service.SynchronizersService;
import org.dromara.maxkey.synchronizer.ISynchronizerService;
import org.dromara.maxkey.synchronizer.service.SyncJobConfigFieldService;
import org.dromara.maxkey.entity.Connectors;
import org.dromara.maxkey.entity.Message;
import org.dromara.maxkey.entity.Synchronizers;
@ -30,10 +34,13 @@ import org.dromara.maxkey.util.StrUtils;
import org.dromara.maxkey.web.WebContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
@RestController
@ -44,6 +51,9 @@ public class SynchronizersController {
@Autowired
SynchronizersService synchronizersService;
@Autowired
SyncJobConfigFieldService syncJobConfigFieldService;
@RequestMapping(value = {"/fetch"}, produces = {MediaType.APPLICATION_JSON_VALUE})
@ResponseBody
public Message<?> fetch(Synchronizers synchronizers, @CurrentUser UserInfo currentUser) {
@ -126,4 +136,53 @@ public class SynchronizersController {
return new Message<Synchronizers>(Message.SUCCESS);
}
@RequestMapping(value = {"/mapping-list/{jobId}"}, produces = {MediaType.APPLICATION_JSON_VALUE})
@ResponseBody
public ResponseEntity<?> mapping(@PathVariable Long jobId) {
logger.debug("mapping {}", jobId);
List<SyncJobConfigField> syncJobConfigFields = syncJobConfigFieldService.findByJobId(jobId);
return new Message<>(syncJobConfigFields).buildResponse();
}
@RequestMapping(value = {"/mapping-get/{id}"}, produces = {MediaType.APPLICATION_JSON_VALUE})
@ResponseBody
public ResponseEntity<?> mappingGet(@PathVariable Long id) {
logger.debug("mapping get {}", id);
SyncJobConfigField syncJobConfigFields = syncJobConfigFieldService.get(String.valueOf(id));
return new Message<>(syncJobConfigFields).buildResponse();
}
@RequestMapping(value = {"/mapping-delete/{id}"}, produces = {MediaType.APPLICATION_JSON_VALUE})
@ResponseBody
public ResponseEntity<?> mappingDelete(@PathVariable Long id) {
logger.debug("mappingDelete {}", id);
syncJobConfigFieldService.deleteFieldMapById(id);
return new Message<SyncJobConfigField>(Message.SUCCESS).buildResponse();
}
@ResponseBody
@PostMapping(value = {"/mapping-add"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> mappingadd(@RequestBody SyncJobConfigField syncJobConfigField, @CurrentUser UserInfo currentUser) {
logger.debug("-mapping add : {}", syncJobConfigField);
syncJobConfigField.setCreateTime(new Date());
if (syncJobConfigFieldService.insert(syncJobConfigField)) {
return new Message<Synchronizers>(Message.SUCCESS).buildResponse();
} else {
return new Message<Synchronizers>(Message.FAIL).buildResponse();
}
}
@ResponseBody
@PutMapping(value = {"/mapping-update"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> mappingupdate(@RequestBody SyncJobConfigField syncJobConfigField, @CurrentUser UserInfo currentUser) {
logger.debug("-mapping update : {}", syncJobConfigField);
syncJobConfigField.setUpdateTime(new Date());
if (syncJobConfigFieldService.update(syncJobConfigField)) {
return new Message<Synchronizers>(Message.SUCCESS).buildResponse();
} else {
return new Message<Synchronizers>(Message.FAIL).buildResponse();
}
}
}

View File

@ -76,9 +76,9 @@ maxkey.login.jwt.issuer =${LOGIN_JWT_ISSUER:${maxkey.ser
spring.datasource.type =com.alibaba.druid.pool.DruidDataSource
#mysql
spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver
spring.datasource.username =${DATABASE_USER:root}
spring.datasource.password =${DATABASE_PWD:maxkey}
spring.datasource.url =jdbc:mysql://${DATABASE_HOST:localhost}:${DATABASE_PORT:3306}/${DATABASE_NAME:maxkey}?autoReconnect=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username =root
spring.datasource.password =root
spring.datasource.url =jdbc:mysql://localhost/maxkey?autoReconnect=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
#highgo
#spring.datasource.driver-class-name=com.highgo.jdbc.Driver
#spring.datasource.username=highgo

View File

@ -0,0 +1,255 @@
/*
Navicat Premium Data Transfer
Source Server : mysql80
Source Server Type : MySQL
Source Server Version : 80038
Source Host : localhost:3306
Source Schema : maxkey
Target Server Type : MySQL
Target Server Version : 80038
File Encoding : 65001
Date: 26/09/2024 10:36:51
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for sync_job_config_field
-- ----------------------------
DROP TABLE IF EXISTS `sync_job_config_field`;
CREATE TABLE `sync_job_config_field` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
`jobid` bigint NOT NULL DEFAULT 0 COMMENT '同步任务ID',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '规则名',
`objecttype` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '类型',
`targetfield` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '目标字段',
`targetfieldname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '目标字段描述',
`sourcefield` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '来源字段',
`sourcefieldname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '来源字段描述',
`description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '描述',
`createuser` bigint NULL DEFAULT 0 COMMENT '创建人',
`createtime` datetime NULL DEFAULT NULL COMMENT '创建时间',
`updateuser` bigint NULL DEFAULT 0 COMMENT '修改人',
`updatetime` datetime NULL DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_job_id`(`jobid` ASC) USING BTREE COMMENT '同步任务ID索引'
) ENGINE = InnoDB AUTO_INCREMENT = 214 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '同步任务字段映射表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sync_job_config_field
-- ----------------------------
INSERT INTO `sync_job_config_field` VALUES (1, 3, NULL, '1', 'username', NULL, 'userid', NULL, '钉钉用户', NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (2, 3, NULL, '1', 'nickName', NULL, 'name', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (3, 3, NULL, '1', 'displayName', NULL, 'name', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (4, 3, NULL, '1', 'formattedName', NULL, 'name', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (5, 3, NULL, '1', 'email', NULL, 'email', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (6, 3, NULL, '1', 'entryDate', NULL, 'hiredDate', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (7, 3, NULL, '1', 'mobile', NULL, 'mobile', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (8, 3, NULL, '1', 'departmentId', NULL, 'objectId', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (9, 3, NULL, '1', 'department', NULL, 'objectName', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (10, 3, NULL, '1', 'employeeNumber', NULL, 'jobNumber', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (11, 3, NULL, '1', 'jobTitle', NULL, 'title', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (12, 3, NULL, '1', 'workEmail', NULL, 'orgEmail', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (13, 3, NULL, '1', 'workPhoneNumber', NULL, 'telephone', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (14, 3, NULL, '1', 'workOfficeName', NULL, 'workPlace', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (15, 3, NULL, '1', 'status', NULL, 'active', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (16, 3, '', '1', 'description', '', 'remark', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (17, 3, NULL, '2', 'id', NULL, 'deptId', NULL, '钉钉组织', NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (18, 3, NULL, '2', 'orgCode', NULL, 'deptId', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (19, 3, NULL, '2', 'orgName', NULL, 'name', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (20, 3, NULL, '2', 'parentId', NULL, 'objectId', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (21, 3, NULL, '2', 'parentCode', NULL, 'parentId', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (22, 3, NULL, '2', 'parentName', NULL, 'objectName', NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `sync_job_config_field` VALUES (23, 6, '', '1', 'username', '', 'user_id', '', '飞书用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (24, 6, '', '1', 'nickName', '', 'nickname', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (25, 6, '', '1', 'displayName', '', 'name', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (26, 6, '', '1', 'mobile', '', 'mobile', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (27, 6, '', '1', 'email', '', 'email', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (28, 6, '', '1', 'gender', '', 'gender', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (29, 6, '', '1', 'employeeNumber', '', 'employee_no', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (30, 6, '', '1', 'workPhoneNumber', '', 'mobile', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (31, 6, '', '1', 'department', '', 'objectName', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (32, 6, '', '1', 'jobTitle', '', 'job_title', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (33, 6, '', '1', 'workAddressFormatted', '', 'work_station', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (34, 6, '', '1', 'status', '', 'status', '', '', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (35, 6, '', '2', 'orgCode', '', 'department_id', '', '飞书组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (36, 6, '', '2', 'orgName', '', 'name', '', '飞书组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (37, 6, '', '2', 'fullName', '', 'name', '', '飞书组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (38, 6, '', '2', 'parentId', '', 'objectId', '', '飞书组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (39, 6, '', '2', 'parentName', '', 'objectName', '', '飞书组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (40, 6, '', '2', 'sortIndex', '', 'order', '', '飞书组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (41, 4, '', '1', 'username', '', 'userid', '', '企业微信用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (42, 4, '', '1', 'nickName', '', 'alias', '', '企业微信用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (43, 4, '', '1', 'displayName', '', 'name', '', '企业微信用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (44, 4, '', '1', 'mobile', '', 'mobile', '', '企业微信用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (45, 4, '', '1', 'email', '', 'email', '', '企业微信用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (46, 4, '', '1', 'gender', '', 'gender', '', '企业微信用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (47, 4, '', '1', 'workPhoneNumber', '', 'telephone', '', '企业微信用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (48, 4, '', '1', 'departmentId', '', 'main_department', '', '企业微信用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (49, 4, '', '1', 'jobTitle', '', 'position', '', '企业微信用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (50, 4, '', '1', 'workAddressFormatted', '', 'address', '', '企业微信用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (51, 4, '', '2', 'orgName', '', 'name', '', '企业微信组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (52, 4, '', '2', 'orgCode', '', 'id', '', '企业微信组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (53, 4, '', '2', 'parentId', '', 'objectId', '', '企业微信组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (54, 4, '', '2', 'parentName', '', 'objectName', '', '企业微信组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (55, 4, '', '2', 'sortIndex', '', 'order', '', '企业微信组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (56, 2, '', '1', 'department', '', 'orgName', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (57, 2, '', '1', 'departmentId', '', 'id', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (58, 2, '', '1', 'formattedName', '', 'cn', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (59, 2, '', '1', 'username', '', 'sAMAccountname', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (60, 2, '', '1', 'windowsAccount', '', 'sAMAccountname', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (61, 2, '', '1', 'familyName', '', 'sn', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (62, 2, '', '1', 'givenName', '', 'givenName', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (63, 2, '', '1', 'nameZhShortSpell', '', 'initials', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (64, 2, '', '1', 'nickName', '', 'initials', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (65, 2, '', '1', 'displayName', '', 'displayName', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (66, 2, '', '1', 'description', '', 'description', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (67, 2, '', '1', 'workPhoneNumber', '', 'telephoneNumber', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (68, 2, '', '1', 'workOfficeName', '', 'physicalDeliveryOfficeName', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (69, 2, '', '1', 'workEmail', '', 'mail', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (70, 2, '', '1', 'webSite', '', 'wwwHomePage', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (71, 2, '', '1', 'workCountry', '', 'co', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (72, 2, '', '1', 'workRegion', '', 'st', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (73, 2, '', '1', 'workLocality', '', 'l', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (74, 2, '', '1', 'workStreetAddress', '', 'streetAddress', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (75, 2, '', '1', 'workPostalCode', '', 'postalCode', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (76, 2, '', '1', 'workAddressFormatted', '', 'postOfficeBox', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (77, 2, '', '1', 'mobile', '', 'mobile', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (78, 2, '', '1', 'homePhoneNumber', '', 'homePhone', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (79, 2, '', '1', 'workFax', '', 'facsimileTelephoneNumber', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (80, 2, '', '1', 'homeAddressFormatted', '', 'info', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (81, 2, '', '1', 'division', '', 'company', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (82, 2, '', '1', 'jobTitle', '', 'title', '', 'AD用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (83, 2, '', '2', 'orgCode', '', 'id', '', 'AD组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (84, 2, '', '2', 'orgName', '', 'ou', '', 'AD组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (85, 2, '', '2', 'fullName', '', 'orgName', '', 'AD组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (86, 2, '', '2', 'country', '', 'co', '', 'AD组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (87, 2, '', '2', 'region', '', 'st', '', 'AD组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (88, 2, '', '2', 'locality', '', 'l', '', 'AD组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (89, 2, '', '2', 'street', '', 'street', '', 'AD组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (90, 2, '', '2', 'postalCode', '', 'postalCode', '', 'AD组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (91, 2, '', '2', 'description', '', 'description', '', 'AD组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (92, 1, '', '1', 'department', '', 'orgName', '', 'LDAP用户', 0, NULL, 0, '2024-09-24 04:06:12');
INSERT INTO `sync_job_config_field` VALUES (93, 1, '', '1', 'departmentId', '', 'id', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (94, 1, '', '1', 'formattedName', '', 'givenName', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (95, 1, '', '1', 'username', '', 'uid', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (96, 1, '', '1', 'windowsAccount', '', 'uid', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (97, 1, '', '1', 'familyName', '', 'sn', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (98, 1, '', '1', 'givenName', '', 'givenName', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (99, 1, '', '1', 'nickName', '', 'initials', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (100, 1, '', '1', 'nameZhShortSpell', '', 'initials', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (101, 1, '', '1', 'displayName', '', 'displayName', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (102, 1, '', '1', 'employeeNumber', '', 'employeeNumber', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (103, 1, '', '1', 'jobTitle', '', 'title', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (104, 1, '', '1', 'workOfficeName', '', 'physicalDeliveryOfficeName', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (105, 1, '', '1', 'workEmail', '', 'mail', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (106, 1, '', '1', 'workRegion', '', 'st', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (107, 1, '', '1', 'workLocality', '', 'l', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (108, 1, '', '1', 'workStreetAddress', '', 'street', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (109, 1, '', '1', 'workPostalCode', '', 'postalCode', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (110, 1, '', '1', 'workAddressFormatted', '', 'postOfficeBox', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (111, 1, '', '1', 'workFax', '', 'facsimileTelephoneNumber', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (112, 1, '', '1', 'homePhoneNumber', '', 'homePhone', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (113, 1, '', '1', 'homeAddressFormatted', '', 'homePostalAddress', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (114, 1, '', '1', 'mobile', '', 'mobile', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (115, 1, '', '1', 'preferredLanguage', '', 'preferredLanguage', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (116, 1, '', '1', 'description', '', 'description', '', 'LDAP用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (117, 1, '', '2', 'orgCode', '', 'id', '', 'LDAP组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (118, 1, '', '2', 'orgName', '', 'ou', '', 'LDAP组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (119, 1, '', '2', 'fullName', '', 'orgName', '', 'LDAP组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (120, 1, '', '2', 'region', '', 'st', '', 'LDAP组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (121, 1, '', '2', 'locality', '', 'l', '', 'LDAP组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (122, 1, '', '2', 'street', '', 'street', '', 'LDAP组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (123, 1, '', '2', 'postalCode', '', 'postalCode', '', 'LDAP组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (124, 1, '', '2', 'address', '', 'postalAddress', '', 'LDAP组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (125, 1, '', '2', 'phone', '', 'telephoneNumber', '', 'LDAP组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (126, 1, '', '2', 'fax', '', 'facsimileTelephoneNumber', '', 'LDAP组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (127, 1, '', '2', 'description', '', 'description', '', 'LDAP组织', 0, NULL, 0, '2024-09-24 04:12:57');
INSERT INTO `sync_job_config_field` VALUES (128, 7, '', '1', 'id', '', 'id', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (129, 7, '', '1', 'username', '', 'username', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (130, 7, '', '1', 'picture', '', 'picture', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (131, 7, '', '1', 'displayName', '', 'displayname', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (132, 7, '', '1', 'nickName', '', 'nickname', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (133, 7, '', '1', 'mobile', '', 'mobile', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (134, 7, '', '1', 'email', '', 'email', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (135, 7, '', '1', 'birthDate', '', 'birthdate', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (136, 7, '', '1', 'userType', '', 'usertype', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (137, 7, '', '1', 'userState', '', 'userstate', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (138, 7, '', '1', 'windowsAccount', '', 'windowsaccount', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (139, 7, '', '1', 'givenName', '', 'givenname', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (140, 7, '', '1', 'middleName', '', 'middlename', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (141, 7, '', '1', 'married', '', 'married', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (142, 7, '', '1', 'gender', '', 'gender', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (143, 7, '', '1', 'idType', '', 'idtype', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (144, 7, '', '1', 'idCardNo', '', 'idcardno', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (145, 7, '', '1', 'webSite', '', 'website', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (146, 7, '', '1', 'startWorkDate', '', 'startworkdate', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (147, 7, '', '1', 'workCountry', '', 'workcountry', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (148, 7, '', '1', 'workRegion', '', 'workregion', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (149, 7, '', '1', 'workLocality', '', 'worklocality', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (150, 7, '', '1', 'workStreetAddress', '', 'workstreetaddress', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (151, 7, '', '1', 'workAddressFormatted', '', 'workaddressformatted', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (152, 7, '', '1', 'workEmail', '', 'workemail', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (153, 7, '', '1', 'workPhoneNumber', '', 'workphonenumber', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (154, 7, '', '1', 'workPostalCode', '', 'workpostalcode', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (155, 7, '', '1', 'workFax', '', 'workfax', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (156, 7, '', '1', 'workOfficeName', '', 'workofficename', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (157, 7, '', '1', 'homeCountry', '', 'homecountry', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (158, 7, '', '1', 'homeRegion', '', 'homeregion', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (159, 7, '', '1', 'homeLocality', '', 'homelocality', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (160, 7, '', '1', 'homeStreetAddress', '', 'homestreetaddress', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (161, 7, '', '1', 'homeAddressFormatted', '', 'homeaddressformatted', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (162, 7, '', '1', 'homeEmail', '', 'homeemail', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (163, 7, '', '1', 'homePhoneNumber', '', 'homephonenumber', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (164, 7, '', '1', 'homePostalCode', '', 'homepostalcode', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (165, 7, '', '1', 'homeFax', '', 'homefax', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (166, 7, '', '1', 'employeeNumber', '', 'employeenumber', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (167, 7, '', '1', 'costCenter', '', 'costcenter', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (168, 7, '', '1', 'organization', '', 'organization', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (169, 7, '', '1', 'division', '', 'division', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (170, 7, '', '1', 'departmentId', '', 'departmentid', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (171, 7, '', '1', 'department', '', 'department', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (172, 7, '', '1', 'jobTitle', '', 'jobtitle', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (173, 7, '', '1', 'jobLevel', '', 'joblevel', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (174, 7, '', '1', 'managerId', '', 'managerid', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (175, 7, '', '1', 'manager', '', 'manager', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (176, 7, '', '1', 'assistantId', '', 'assistantid', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (177, 7, '', '1', 'assistant', '', 'assistant', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (178, 7, '', '1', 'entryDate', '', 'entrydate', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (179, 7, '', '1', 'quitDate', '', 'quitdate', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (180, 7, '', '1', 'ldapDn', '', 'ldapdn', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (181, 7, '', '1', 'description', '', 'description', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (182, 7, '', '1', 'status', '', 'status', '', 'jdbc用户', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (183, 7, '', '2', 'id', '', 'id', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (184, 7, '', '2', 'orgCode', '', 'orgcode', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (185, 7, '', '2', 'orgName', '', 'orgname', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (186, 7, '', '2', 'fullName', '', 'fullname', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (187, 7, '', '2', 'parentId', '', 'parentid', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (188, 7, '', '2', 'parentCode', '', 'parentcode', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (189, 7, '', '2', 'type', '', 'type', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (190, 7, '', '2', 'codePath', '', 'codepath', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (191, 7, '', '2', 'namePath', '', 'namepath', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (192, 7, '', '2', 'level', '', 'level', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (193, 7, '', '2', 'hasChild', '', 'haschild', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (194, 7, '', '2', 'division', '', 'division', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (195, 7, '', '2', 'country', '', 'country', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (196, 7, '', '2', 'region', '', 'region', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (197, 7, '', '2', 'locality', '', 'locality', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (198, 7, '', '2', 'street', '', 'street', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (199, 7, '', '2', 'address', '', 'address', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (200, 7, '', '2', 'contact', '', 'contact', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (201, 7, '', '2', 'postalCode', '', 'postalcode', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (202, 7, '', '2', 'phone', '', 'phone', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (203, 7, '', '2', 'fax', '', 'fax', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (204, 7, '', '2', 'email', '', 'email', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (205, 7, '', '2', 'sortIndex', '', 'sortindex', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (206, 7, '', '2', 'ldapDn', '', 'ldapdn', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (207, 7, '', '2', 'description', '', 'description', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (208, 7, '', '2', 'status', '', 'status', '', 'jdbc组织', 0, NULL, 0, NULL);
INSERT INTO `sync_job_config_field` VALUES (209, 6, '', '1', 'departmentId', '', 'objectId', '', '飞书用户', 0, NULL, 0, NULL);
SET FOREIGN_KEY_CHECKS = 1;