Browse Source

提交开源任务材料

10.0
LAPTOP-SB56SG4Q\86185 3 years ago
parent
commit
b38969c326
  1. BIN
      JSD-6952-配置使用文档.docx
  2. 5
      README.md
  3. BIN
      jsd-6952-需求确认书v1.docx
  4. BIN
      lib/finekit-10.0.jar
  5. 28
      plugin.xml
  6. 158
      src/main/java/com/fr/plugin/mqh/dingtalksyn/bean/DataResponse.java
  7. 107
      src/main/java/com/fr/plugin/mqh/dingtalksyn/bean/DingTalkJobConstructor.java
  8. 107
      src/main/java/com/fr/plugin/mqh/dingtalksyn/config/DingSynConfig.java
  9. 77
      src/main/java/com/fr/plugin/mqh/dingtalksyn/helper/DingTalkScheduleHelper.java
  10. 34
      src/main/java/com/fr/plugin/mqh/dingtalksyn/job/DingTalkSyncMemberJob.java
  11. 65
      src/main/java/com/fr/plugin/mqh/dingtalksyn/kit/CustomRoleServiceKit.java
  12. 95
      src/main/java/com/fr/plugin/mqh/dingtalksyn/kit/DepartmentServiceKit.java
  13. 186
      src/main/java/com/fr/plugin/mqh/dingtalksyn/kit/UserServiceKit.java
  14. 49
      src/main/java/com/fr/plugin/mqh/dingtalksyn/provider/LifeCycleMonitorImpl.java
  15. 36
      src/main/java/com/fr/plugin/mqh/dingtalksyn/provider/LocaleFinder.java
  16. 198
      src/main/java/com/fr/plugin/mqh/dingtalksyn/request/GlobalRequestFilterBridge.java
  17. 179
      src/main/java/com/fr/plugin/mqh/dingtalksyn/user/DingTalkUserManager.java
  18. 150
      src/main/java/com/fr/plugin/mqh/dingtalksyn/utils/DingAPI.java
  19. 67
      src/main/java/com/fr/plugin/mqh/dingtalksyn/utils/DingTokenUtils.java
  20. 18
      src/main/resources/com/fr/plugin/mqh/dingtalksyn/locale/lang.properties
  21. 18
      src/main/resources/com/fr/plugin/mqh/dingtalksyn/locale/lang_zh_CN.properties
  22. 24
      src/main/resources/com/fr/plugin/mqh/dingtalksyn/web/codePage.html
  23. 1
      src/main/resources/com/fr/plugin/mqh/dingtalksyn/web/dingtalk.open.js

BIN
JSD-6952-配置使用文档.docx

Binary file not shown.

5
README.md

@ -1,3 +1,6 @@
# open-JSD-6952
JSD-6952 开源任务代码
JSD-6952 开源任务代码\
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\
仅作为开发者学习参考使用!禁止用于任何商业用途!\
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。

BIN
jsd-6952-需求确认书v1.docx

Binary file not shown.

BIN
lib/finekit-10.0.jar

Binary file not shown.

28
plugin.xml

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<id>com.fr.plugin.mqh.dingtalksyn.job</id>
<name><![CDATA[钉钉数据同步]]></name>
<active>yes</active>
<version>1.0</version>
<env-version>10.0</env-version>
<jartime>2018-07-31</jartime>
<vendor>mqh</vendor>
<description><![CDATA[钉钉数据同步]]></description>
<change-notes><![CDATA[
版本1.0主要功能:<br/>
1.用户信息全量同步<br/>
2.用户单点登陆功能<br/>
]]></change-notes>
<main-package>com.fr.plugin.mqh.dingtalksyn</main-package>
<prefer-packages>
<prefer-package>com.fanruan.api</prefer-package>
</prefer-packages>
<lifecycle-monitor class="com.fr.plugin.mqh.dingtalksyn.provider.LifeCycleMonitorImpl"/>
<extra-core>
<LocaleFinder class="com.fr.plugin.mqh.dingtalksyn.provider.LocaleFinder"/>
</extra-core>
<extra-decision>
<GlobalRequestFilterProvider class="com.fr.plugin.mqh.dingtalksyn.request.GlobalRequestFilterBridge"/>
</extra-decision>
<function-recorder class="com.fr.plugin.mqh.dingtalksyn.provider.LocaleFinder"/>
</plugin>

158
src/main/java/com/fr/plugin/mqh/dingtalksyn/bean/DataResponse.java

@ -0,0 +1,158 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: DataResponse
* Author: Louis
* Date: 2021/3/19 11:46
*/
package com.fr.plugin.mqh.dingtalksyn.bean;
import com.fanruan.api.util.StringKit;
import com.fr.decision.webservice.Response;
import com.fr.third.fasterxml.jackson.annotation.JsonInclude;
import com.fr.third.fasterxml.jackson.annotation.JsonProperty;
import java.util.Map;
/**
* <Function Description><br>
* <DataResponse>
*
* @author Louis
* @since 1.0.0
*/
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
public class DataResponse extends Response {
private static final long serialVersionUID = -6470353731188369521L;
@JsonProperty("msg_signature")
private String msgSignature;
private String timeStamp;
private String nonce;
private String encrypt;
private String code;
private String message;
public DataResponse() {
}
private static DataResponse create() {
return new DataResponse();
}
/**
* 相应success结果
*
* @return
*/
public static DataResponse success(Map<String, String> successMap) {
return create().msgSignature(successMap.get("msg_signature"))
.timeStamp(successMap.get("timeStamp"))
.nonce(successMap.get("nonce"))
.encrypt(successMap.get("encrypt"));
}
/**
* 操作结果
*
* @param data
* @return
*/
public static DataResponse operation(String data) {
return create().code("200").message("success").data(data);
}
/**
* 报错结果
*
* @param code
* @param message
* @return
*/
public static DataResponse error(String code, String message) {
return create().code(code).message(message).data(StringKit.EMPTY);
}
public DataResponse msgSignature(String msgSignature) {
this.msgSignature = msgSignature;
return this;
}
public DataResponse timeStamp(String timeStamp) {
this.timeStamp = timeStamp;
return this;
}
public DataResponse nonce(String nonce) {
this.nonce = nonce;
return this;
}
public DataResponse encrypt(String encrypt) {
this.encrypt = encrypt;
return this;
}
public DataResponse code(String code) {
this.code = code;
return this;
}
public DataResponse message(String message) {
this.message = message;
return this;
}
public DataResponse data(Object data) {
this.setData(data);
return this;
}
public String getMsgSignature() {
return msgSignature;
}
public void setMsgSignature(String msgSignature) {
this.msgSignature = msgSignature;
}
public String getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
public String getNonce() {
return nonce;
}
public void setNonce(String nonce) {
this.nonce = nonce;
}
public String getEncrypt() {
return encrypt;
}
public void setEncrypt(String encrypt) {
this.encrypt = encrypt;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

107
src/main/java/com/fr/plugin/mqh/dingtalksyn/bean/DingTalkJobConstructor.java

@ -0,0 +1,107 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: DingTalkJobConstructor
* Author: Louis
* Date: 2021/4/21 15:58
*/
package com.fr.plugin.mqh.dingtalksyn.bean;
import com.fr.scheduler.job.FineScheduleJob;
/**
* <Function Description><br>
* <DingTalkJobConstructor>
*
* @author Louis
* @since 1.0.0
*/
public class DingTalkJobConstructor {
private String cron;
private String jobName;
private String jobGroup;
private String triggerName;
private String triggerGroup;
private Class<? extends FineScheduleJob> jobClazz;
public DingTalkJobConstructor() {
}
public DingTalkJobConstructor cron(String var1) {
this.setCron(var1);
return this;
}
public String getCron() {
return this.cron;
}
public void setCron(String var1) {
this.cron = var1;
}
public DingTalkJobConstructor jobName(String var1) {
this.setJobName(var1);
return this;
}
public String getJobName() {
return this.jobName;
}
public void setJobName(String var1) {
this.jobName = var1;
}
public DingTalkJobConstructor jobGroup(String var1) {
this.setJobGroup(var1);
return this;
}
public String getJobGroup() {
return this.jobGroup;
}
public void setJobGroup(String var1) {
this.jobGroup = var1;
}
public DingTalkJobConstructor triggerName(String var1) {
this.setTriggerName(var1);
return this;
}
public String getTriggerName() {
return this.triggerName;
}
public void setTriggerName(String var1) {
this.triggerName = var1;
}
public DingTalkJobConstructor triggerGroup(String var1) {
this.setTriggerGroup(var1);
return this;
}
public String getTriggerGroup() {
return this.triggerGroup;
}
public void setTriggerGroup(String var1) {
this.triggerGroup = var1;
}
public DingTalkJobConstructor jobClazz(Class<? extends FineScheduleJob> var1) {
this.setJobClazz(var1);
return this;
}
public Class<? extends FineScheduleJob> getJobClazz() {
return this.jobClazz;
}
public void setJobClazz(Class<? extends FineScheduleJob> var1) {
this.jobClazz = var1;
}
}

107
src/main/java/com/fr/plugin/mqh/dingtalksyn/config/DingSynConfig.java

@ -0,0 +1,107 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: DingSynConfig
* Author: Louis
* Date: 2021/3/30 9:38
*/
package com.fr.plugin.mqh.dingtalksyn.config;
import com.fanruan.api.util.StringKit;
import com.fr.config.*;
import com.fr.config.holder.Conf;
import com.fr.config.holder.factory.Holders;
/**
* <Function Description><br>
* <DingSynConfig>
*
* @author Louis
* @since 1.0.0
*/
@Visualization(category = "Plugin-dingtalksyn_Group")
public class DingSynConfig extends DefaultConfiguration {
// 每天中午十二点触发
public static final String CRON_CONDITION = "0 0 12 * * ?";
public static final long ROOT_DEP_ID = 1;
private static volatile DingSynConfig config = null;
public static DingSynConfig getInstance() {
if (config == null) {
config = ConfigContext.getConfigInstance(DingSynConfig.class);
}
return config;
}
@Identifier(value = "cronCondition", name = "Plugin-dingtalksyn_Config_CronCondition", description = "Plugin-dingtalksyn_Config_CronCondition_Description", status = Status.SHOW)
private Conf<String> cronCondition = Holders.simple(CRON_CONDITION);
@Identifier(value = "appKey", name = "Plugin-dingtalksyn_Config_appKey", description = "Plugin-dingtalksyn_Config_appKey_Description", status = Status.SHOW)
private Conf<String> appKey = Holders.simple(StringKit.EMPTY);
@Identifier(value = "appSecret", name = "Plugin-dingtalksyn_Config_appSecret", description = "Plugin-dingtalksyn_Config_appSecret_Description", status = Status.SHOW)
private Conf<String> appSecret = Holders.simple(StringKit.EMPTY);
@Identifier(value = "corpId", name = "Plugin-dingtalksyn_Config_corpId", description = "Plugin-dingtalksyn_Config_corpId_Description", status = Status.SHOW)
private Conf<String> corpId = Holders.simple(StringKit.EMPTY);
@Identifier(value = "rootDepId", name = "Plugin-dingtalksyn_Config_rootDepId", description = "Plugin-dingtalksyn_Config_rootDepId_Description", status = Status.SHOW)
private Conf<Long> rootDepId = Holders.simple(ROOT_DEP_ID);
// @Identifier(value = "token", name = "Plugin-dingtalksyn_Config_Token", description = "Plugin-dingtalksyn_Config_Token_Description", status = Status.SHOW)
// private Conf<String> token = Holders.simple(StringKit.EMPTY);
// @Identifier(value = "aesKey", name = "Plugin-dingtalksyn_Config_AesKey", description = "Plugin-dingtalksyn_Config_AesKey_Description", status = Status.SHOW)
// private Conf<String> aesKey = Holders.simple(StringKit.EMPTY);
public String getCronCondition() {
return cronCondition.get();
}
public void setCronCondition(String cronCondition) {
this.cronCondition.set(cronCondition);
}
public String getAppKey() {
return appKey.get();
}
public void setAppKey(String appKey) {
this.appKey.set(appKey);
}
public String getAppSecret() {
return appSecret.get();
}
public void setAppSecret(String appSecret) {
this.appSecret.set(appSecret);
}
public String getCorpId() {
return corpId.get();
}
public void setCorpId(String corpId) {
this.corpId.set(corpId);
}
public long getRootDepId() {
return rootDepId.get();
}
public void setRootDepId(long rootDepId) {
this.rootDepId.set(rootDepId);
}
// public String getToken() {
// return token.get();
// }
//
// public void setToken(String token) {
// this.token.set(token);
// }
//
// public String getAesKey() {
// return aesKey.get();
// }
//
// public void setAesKey(String aesKey) {
// this.aesKey.set(aesKey);
// }
}

77
src/main/java/com/fr/plugin/mqh/dingtalksyn/helper/DingTalkScheduleHelper.java

@ -0,0 +1,77 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: DingTalkScheduleHelper
* Author: Louis
* Date: 2021/4/21 15:52
*/
package com.fr.plugin.mqh.dingtalksyn.helper;
import com.fr.plugin.mqh.dingtalksyn.bean.DingTalkJobConstructor;
import com.fr.plugin.mqh.dingtalksyn.job.DingTalkSyncMemberJob;
import com.fr.scheduler.ScheduleJobManager;
import com.fr.third.v2.org.quartz.CronScheduleBuilder;
import com.fr.third.v2.org.quartz.TriggerBuilder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TimeZone;
/**
* <Function Description><br>
* <DingTalkScheduleHelper>
*
* @author Louis
* @since 1.0.0
*/
public class DingTalkScheduleHelper {
public static final String DINGTALK_SCHEDULE_SYN_MEMBER_JOB_NAME = "MqhDingTalkSynDepMemberJob";
public static final String DINGTALK_SCHEDULE_SYN_MEMBER_TRIGGER_NAME = "MqhDingTalkSynDepMemberTrigger";
public static final String DINGTALK_SCHEDULE_SYN_MEMBER_GROUP = "MqhDingTalkSynDepMemberGroup";
public static final String DINGTALK_SCHEDULE_SYN_MEMBER_TRIGGER_GROUP = "MqhDingTalkSynDepMemberTriggerGroup";
private DingTalkScheduleHelper() {
}
public static DingTalkScheduleHelper getInstance() {
return DingTalkScheduleHelper.HOLDER.INSTANCE;
}
public void startSynMemberSchedule(String cronCondition) throws Exception {
DingTalkJobConstructor jobConstructor = (new DingTalkJobConstructor())
.cron(cronCondition).jobName(DINGTALK_SCHEDULE_SYN_MEMBER_JOB_NAME)
.jobGroup(DINGTALK_SCHEDULE_SYN_MEMBER_GROUP).triggerName(DINGTALK_SCHEDULE_SYN_MEMBER_TRIGGER_NAME)
.triggerGroup(DINGTALK_SCHEDULE_SYN_MEMBER_TRIGGER_GROUP).jobClazz(DingTalkSyncMemberJob.class);
this.startSchedule(jobConstructor);
}
public void startSchedule(DingTalkJobConstructor var1) throws Exception {
if (var1 != null) {
String var2 = var1.getCron();
String var3 = var1.getTriggerName();
String var4 = var1.getTriggerGroup();
String var5 = var1.getJobName();
String var6 = var1.getJobGroup();
Class var7 = var1.getJobClazz();
TriggerBuilder var8 = TriggerBuilder.newTrigger();
var8.withIdentity(var3, var4);
var8.withSchedule(CronScheduleBuilder.cronSchedule(var2).withMisfireHandlingInstructionFireAndProceed().inTimeZone(TimeZone.getTimeZone(TimeZone.getDefault().getID()))).startNow();
var8.forJob(var5, var6);
ArrayList var9 = new ArrayList();
var9.add(var8.build());
ScheduleJobManager.getInstance().removeJob(var5, var6);
ScheduleJobManager.getInstance().addJob(var5, var6, "jobDescription", var7, var9, new HashMap());
}
}
public void stopSchedule(String var1, String var2) {
ScheduleJobManager.getInstance().removeJob(var1, var2);
}
public static class HOLDER {
private static final DingTalkScheduleHelper INSTANCE = new DingTalkScheduleHelper();
public HOLDER() {
}
}
}

34
src/main/java/com/fr/plugin/mqh/dingtalksyn/job/DingTalkSyncMemberJob.java

@ -0,0 +1,34 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: DingTalkSyncMemberJob
* Author: Louis
* Date: 2021/4/21 16:02
*/
package com.fr.plugin.mqh.dingtalksyn.job;
import com.fanruan.api.log.LogKit;
import com.fr.cluster.core.ClusterNode;
import com.fr.plugin.mqh.dingtalksyn.user.DingTalkUserManager;
import com.fr.scheduler.job.FineScheduleJob;
import com.fr.third.v2.org.quartz.JobExecutionContext;
/**
* <Function Description><br>
* <DingTalkSyncMemberJob>
*
* @author Louis
* @since 1.0.0
*/
public class DingTalkSyncMemberJob extends FineScheduleJob {
public DingTalkSyncMemberJob() {
}
public void run(JobExecutionContext jobExecutionContext, ClusterNode clusterNode) {
try {
DingTalkUserManager.getInstance().synDingTalkUsers();
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
}
}
}

65
src/main/java/com/fr/plugin/mqh/dingtalksyn/kit/CustomRoleServiceKit.java

@ -0,0 +1,65 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: CustomRoleServiceKit
* Author: Louis
* Date: 2021/5/14 10:31
*/
package com.fr.plugin.mqh.dingtalksyn.kit;
import com.fr.decision.authority.AuthorityContext;
import com.fr.decision.authority.base.constant.SoftRoleType;
import com.fr.decision.authority.base.constant.type.operation.ManualOperationType;
import com.fr.decision.authority.data.CustomRole;
import com.fr.decision.record.OperateMessage;
import com.fr.decision.webservice.bean.user.RoleBean;
import com.fr.decision.webservice.exception.general.DuplicatedNameException;
import com.fr.decision.webservice.utils.ControllerFactory;
import com.fr.decision.webservice.v10.user.CustomRoleService;
import com.fr.intelli.record.MetricRegistry;
import com.fr.stable.query.QueryFactory;
import com.fr.stable.query.condition.QueryCondition;
import com.fr.stable.query.restriction.Restriction;
import com.fr.stable.query.restriction.RestrictionFactory;
/**
* <Function Description><br>
* <CustomRoleServiceKit>
*
* @author Louis
* @since 1.0.0
*/
public class CustomRoleServiceKit extends CustomRoleService {
private static volatile CustomRoleServiceKit customRoleServiceKit = null;
public CustomRoleServiceKit() {
}
public static CustomRoleServiceKit getInstance() {
if (customRoleServiceKit == null) {
customRoleServiceKit = new CustomRoleServiceKit();
}
return customRoleServiceKit;
}
public void addCustomRole(String username, RoleBean roleBean) throws Exception {
this.checkDuplicatedCustomRole(roleBean.getText());
CustomRole customRole = (new CustomRole()).id(roleBean.getId()).name(roleBean.getText()).description(roleBean.getDescription()).creationType(ManualOperationType.KEY).lastOperationType(ManualOperationType.KEY).enable(true);
ControllerFactory.getInstance().getCustomRoleController(username).addCustomRole(username, customRole);
this.deleteSoftData(customRole.getName());
MetricRegistry.getMetric().submit(OperateMessage.build("Dec-Module-User_Manager", "Dec-Role", roleBean.getText(), "Dec-Log_Add"));
}
private void checkDuplicatedCustomRole(String roleName) throws Exception {
QueryCondition queryCondition = QueryFactory.create().addRestriction(RestrictionFactory.eq("name", roleName));
CustomRole customRole = (CustomRole) AuthorityContext.getInstance().getCustomRoleController().findOne(queryCondition);
if (customRole != null) {
throw new DuplicatedNameException();
}
}
private void deleteSoftData(String roleName) throws Exception {
QueryCondition queryCondition = QueryFactory.create().addRestriction(RestrictionFactory.and(new Restriction[]{RestrictionFactory.eq("deletedName", roleName), RestrictionFactory.eq("type", SoftRoleType.CUSTOM)}));
AuthorityContext.getInstance().getSoftDataController().remove(queryCondition);
}
}

95
src/main/java/com/fr/plugin/mqh/dingtalksyn/kit/DepartmentServiceKit.java

@ -0,0 +1,95 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: DepartmentServiceKit
* Author: Louis
* Date: 2021/5/14 9:38
*/
package com.fr.plugin.mqh.dingtalksyn.kit;
import com.fanruan.api.i18n.I18nKit;
import com.fanruan.api.util.StringKit;
import com.fr.decision.authority.AuthorityContext;
import com.fr.decision.authority.base.constant.type.operation.ManualOperationType;
import com.fr.decision.authority.data.Department;
import com.fr.decision.record.OperateMessage;
import com.fr.decision.webservice.exception.general.DuplicatedNameException;
import com.fr.decision.webservice.v10.user.DepartmentService;
import com.fr.general.ComparatorUtils;
import com.fr.intelli.record.MetricRegistry;
import com.fr.stable.StableUtils;
import com.fr.stable.query.QueryFactory;
import com.fr.stable.query.condition.QueryCondition;
import com.fr.stable.query.restriction.Restriction;
import com.fr.stable.query.restriction.RestrictionFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* <Function Description><br>
* <DepartmentServiceKit>
*
* @author Louis
* @since 1.0.0
*/
public class DepartmentServiceKit extends DepartmentService {
public static final String DECISION_DEP_ROOT = "decision-dep-root";
private static volatile DepartmentServiceKit departmentServiceKit = null;
public DepartmentServiceKit() {
}
public static DepartmentServiceKit getInstance() {
if (departmentServiceKit == null) {
departmentServiceKit = new DepartmentServiceKit();
}
return departmentServiceKit;
}
public void addDepartment(String id, String pId, String depName) throws Exception {
if (StringKit.equals(pId, DECISION_DEP_ROOT)) {
pId = null;
}
this.checkDuplicatedDepartmentName(pId, depName);
Department department = (new Department()).id(id).name(depName).parentId(pId).creationType(ManualOperationType.KEY).lastOperationType(ManualOperationType.KEY).enable(true);
AuthorityContext.getInstance().getDepartmentController().add(department);
MetricRegistry.getMetric().submit(OperateMessage.build("Dec-Module-User_Manager", "Dec-Department", this.getDepartmentFullPath(pId, depName, "/"), "Dec-Log_Add"));
}
private void checkDuplicatedDepartmentName(String parentId, String depName) throws Exception {
QueryCondition condition = QueryFactory.create().addRestriction(RestrictionFactory.and(new Restriction[]{RestrictionFactory.eq("name", depName), RestrictionFactory.eq("parentId", parentId)}));
Department sameNameDep = AuthorityContext.getInstance().getDepartmentController().findOne(condition);
if (sameNameDep != null) {
throw new DuplicatedNameException();
}
}
private String getDepartmentFullPath(String pId, String depName, String splitter) throws Exception {
List<String> paths = new ArrayList<>();
paths.add(depName);
while (!ComparatorUtils.equals(pId, DECISION_DEP_ROOT) && pId != null) {
Department parentDepartment = AuthorityContext.getInstance().getDepartmentController().getById(pId);
paths.add(parentDepartment.getName());
pId = parentDepartment.getParentId();
}
Collections.reverse(paths);
return StableUtils.join(paths.toArray(new String[0]), splitter);
}
public void editDepartment(String departmentId, String depName, String pId) throws Exception {
if (StringKit.equals(pId, DECISION_DEP_ROOT)) {
pId = null;
}
Department department = AuthorityContext.getInstance().getDepartmentController().getById(departmentId);
String departmentFullPath = DepartmentService.getInstance().getDepartmentFullPath(departmentId);
if (!ComparatorUtils.equals(department.getName(), depName)) {
this.checkDuplicatedDepartmentName(department.getParentId(), depName);
department.setName(depName);
department.setParentId(pId);
AuthorityContext.getInstance().getDepartmentController().update(department);
}
MetricRegistry.getMetric().submit(OperateMessage.build("Dec-Module-User_Manager", "Dec-Department", DepartmentService.getInstance().getDepartmentFullPath(departmentId), "Dec-Log_Update", I18nKit.getLocText("Fine-Dec_Department") + ":" + departmentFullPath));
}
}

186
src/main/java/com/fr/plugin/mqh/dingtalksyn/kit/UserServiceKit.java

@ -0,0 +1,186 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: UserServiceKit
* Author: Louis
* Date: 2021/5/14 8:28
*/
package com.fr.plugin.mqh.dingtalksyn.kit;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.util.StringKit;
import com.fr.decision.authority.AuthorityContext;
import com.fr.decision.authority.data.Post;
import com.fr.decision.authority.data.User;
import com.fr.decision.authority.data.personnel.DepRole;
import com.fr.decision.privilege.TransmissionTool;
import com.fr.decision.webservice.bean.user.DepartmentPostBean;
import com.fr.decision.webservice.bean.user.UserBean;
import com.fr.decision.webservice.utils.UserSourceFactory;
import com.fr.decision.webservice.utils.WebServiceUtils;
import com.fr.decision.webservice.v10.user.PositionService;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.stable.StringUtils;
import com.fr.stable.collections.CollectionUtils;
import com.fr.stable.query.QueryFactory;
import com.fr.stable.query.restriction.RestrictionFactory;
import java.util.ArrayList;
import java.util.List;
/**
* <Function Description><br>
* <UserServiceKit>
*
* @author Louis
* @since 1.0.0
*/
public class UserServiceKit extends UserService {
private static volatile UserServiceKit userServiceKit = null;
public UserServiceKit() {
}
public static UserServiceKit getInstance() {
if (userServiceKit == null) {
userServiceKit = new UserServiceKit();
}
return userServiceKit;
}
public UserBean createUserBean(OapiV2UserGetResponse.UserGetResponse userGetResponse) throws Exception {
UserBean userBean = new UserBean();
userBean.setUsername(userGetResponse.getUserid());
userBean.setRealName(userGetResponse.getName());
userBean.setEmail(userGetResponse.getEmail());
userBean.setMobile(userGetResponse.getMobile());
userBean.setPassword(TransmissionTool.defaultEncrypt(userGetResponse.getUserid() + "123456"));
if (!CollectionUtils.isEmpty(userGetResponse.getRoleList())) {
userBean.setRoleIds(oapiUserRoles2Ids(userGetResponse.getRoleList()));
}
if (!CollectionUtils.isEmpty(userGetResponse.getDeptIdList())) {
List<String> departmentPostIds = createDepartmentPostIds(userGetResponse.getDeptIdList(), userGetResponse.getTitle());
userBean.setDepartmentPostIds(departmentPostIds);
}
return userBean;
}
/**
* 钉钉部门list转为部门职务组合list
*
* @param deptIdList
* @param title
* @return
* @throws Exception
*/
private List<String> createDepartmentPostIds(List<Long> deptIdList, String title) throws Exception {
List<String> departmentPostIds = new ArrayList<>();
String departmentPostId;
for (long currentDepId : deptIdList) {
departmentPostId = String.valueOf(currentDepId);
if (StringKit.isBlank(departmentPostId) || StringKit.equals(departmentPostId, "null")) {
continue;
}
// 职务处理
String positionId = positionSynOperation(title, departmentPostId);
if (StringKit.isNotBlank(positionId)) {
departmentPostId = departmentPostId + "@@@" + positionId;
}
departmentPostIds.add(departmentPostId);
}
return departmentPostIds;
}
/**
* 职务同步操作
*
* @param title
* @return
* @throws Exception
*/
private String positionSynOperation(String title, String departmentId) throws Exception {
String position = StringKit.isNotBlank(title) ? title : "职员";
Post post = AuthorityContext.getInstance().getPostController().findOne(QueryFactory.create().addRestriction(RestrictionFactory.eq("name", position)));
String positionId;
if (post == null) {
positionId = PositionService.getInstance().addPosition(position, position);
} else {
positionId = post.getId();
}
List<DepartmentPostBean> departmentPostBeanList = PositionService.getInstance().getPositionsUnderParentDepartment(getAdminUserId(), departmentId, position);
if (departmentPostBeanList == null || departmentPostBeanList.isEmpty()) {
try {
AuthorityContext.getInstance().getPostController().addPostToDepartment(positionId, departmentId);
} catch (Exception e) {
LogKit.info("dingtalksyn-UserServiceKit-positionSynOperation-addPostToDepartmentFailed-position:{}, departmentId:{}", positionId + position, departmentId);
LogKit.error(e.getMessage(), e);
}
}
return positionId;
}
/**
* 获取管理员id
*
* @return
* @throws Exception
*/
public String getAdminUserId() throws Exception {
List<String> adminUserIdList = UserService.getInstance().getAdminUserIdList();
if (adminUserIdList.isEmpty()) {
return "admin";
}
return StringKit.isNotBlank(adminUserIdList.get(0)) ? adminUserIdList.get(0) : "admin";
}
public UserBean updateUserBean(OapiV2UserGetResponse.UserGetResponse userGetResponse) throws Exception {
User user = UserService.getInstance().getUserByUserName(userGetResponse.getUserid());
if (user == null) {
return null;
}
UserBean userBean = new UserBean();
userBean.setId(user.getId());
userBean.setUsername(user.getUserName());
userBean.setRealName(userGetResponse.getName());
userBean.setEmail(userGetResponse.getEmail());
userBean.setMobile(userGetResponse.getMobile());
if (!CollectionUtils.isEmpty(userGetResponse.getRoleList())) {
userBean.setRoleIds(oapiUserRoles2Ids(userGetResponse.getRoleList()));
}
if (!CollectionUtils.isEmpty(userGetResponse.getDeptIdList())) {
List<String> departmentPostIds = createDepartmentPostIds(userGetResponse.getDeptIdList(), userGetResponse.getTitle());
userBean.setDepartmentPostIds(departmentPostIds);
}
return userBean;
}
/**
* 增加用户部门关联
*
* @param userBean
* @throws Exception
*/
public void addUserDepartment(UserBean userBean) throws Exception {
if (CollectionUtils.isEmpty(userBean.getDepartmentPostIds())) {
return;
}
for (String departmentPostId : userBean.getDepartmentPostIds()) {
if (StringUtils.isEmpty(departmentPostId)) {
continue;
}
User user = UserService.getInstance().getUserByUserName(userBean.getUsername());
DepRole depRole = WebServiceUtils.parseUniqueDepartmentPostId(departmentPostId);
UserSourceFactory.getInstance().checkSource(user, AuthorityContext.getInstance().getDepartmentController().getById(depRole.getDepartmentId()));
AuthorityContext.getInstance().getUserController().addUserToDepartmentAndPost(user.getId(), depRole.getDepartmentId(), depRole.getPostId());
}
}
private String[] oapiUserRoles2Ids(List<OapiV2UserGetResponse.UserRole> oapiUserRoleList) {
String[] roleIds = new String[oapiUserRoleList.size()];
for (int i = 0; i < oapiUserRoleList.size(); i++) {
roleIds[i] = String.valueOf(oapiUserRoleList.get(i).getId());
}
return roleIds;
}
}

49
src/main/java/com/fr/plugin/mqh/dingtalksyn/provider/LifeCycleMonitorImpl.java

@ -0,0 +1,49 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: LifeCycleMonitorImpl
* Author: Louis
* Date: 2021/3/30 15:10
*/
package com.fr.plugin.mqh.dingtalksyn.provider;
import com.fanruan.api.log.LogKit;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.mqh.dingtalksyn.helper.DingTalkScheduleHelper;
import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor;
import com.fr.plugin.mqh.dingtalksyn.config.DingSynConfig;
import static com.fr.plugin.mqh.dingtalksyn.helper.DingTalkScheduleHelper.DINGTALK_SCHEDULE_SYN_MEMBER_GROUP;
import static com.fr.plugin.mqh.dingtalksyn.helper.DingTalkScheduleHelper.DINGTALK_SCHEDULE_SYN_MEMBER_JOB_NAME;
/**
* <Function Description><br>
* <LifeCycleMonitorImpl>
*
* @author Louis
* @since 1.0.0
*/
public class LifeCycleMonitorImpl extends AbstractPluginLifecycleMonitor {
public LifeCycleMonitorImpl() {
}
@Override
public void afterRun(PluginContext pluginContext) {
DingSynConfig.getInstance();
this.reStartSchedule();
}
@Override
public void beforeStop(PluginContext pluginContext) {
DingTalkScheduleHelper.getInstance().stopSchedule(DINGTALK_SCHEDULE_SYN_MEMBER_JOB_NAME, DINGTALK_SCHEDULE_SYN_MEMBER_GROUP);
}
private void reStartSchedule() {
try {
String cronCondition = DingSynConfig.getInstance().getCronCondition();
DingTalkScheduleHelper.getInstance().startSynMemberSchedule(cronCondition);
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
}
}
}

36
src/main/java/com/fr/plugin/mqh/dingtalksyn/provider/LocaleFinder.java

@ -0,0 +1,36 @@
/*
* Copyright (C), 2018-2020
* Project: starter
* FileName: LocaleFinder
* Author: Louis
* Date: 2020/8/31 22:19
*/
package com.fr.plugin.mqh.dingtalksyn.provider;
import com.fr.intelli.record.Focus;
import com.fr.intelli.record.Original;
import com.fr.record.analyzer.EnableMetrics;
import com.fr.stable.fun.impl.AbstractLocaleFinder;
/**
* <Function Description><br>
* <LocaleFinder>
*
* @author Louis
* @since 1.0.0
*/
@EnableMetrics
public class LocaleFinder extends AbstractLocaleFinder {
public static final String PLUGIN_ID = "com.fr.plugin.mqh.dingtalksyn.job";
@Override
@Focus(id = PLUGIN_ID, text = "Plugin-dingtalksyn", source = Original.PLUGIN)
public String find() {
return "com/fr/plugin/mqh/dingtalksyn/locale/lang";
}
@Override
public int currentAPILevel() {
return CURRENT_LEVEL;
}
}

198
src/main/java/com/fr/plugin/mqh/dingtalksyn/request/GlobalRequestFilterBridge.java

@ -0,0 +1,198 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: GlobalRequestFilterBridge
* Author: Louis
* Date: 2021/3/30 22:09
*/
package com.fr.plugin.mqh.dingtalksyn.request;
import com.fanruan.api.decision.login.LoginKit;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.net.NetworkKit;
import com.fanruan.api.net.http.HttpKit;
import com.fanruan.api.util.IOKit;
import com.fanruan.api.util.StringKit;
import com.fr.base.TemplateUtils;
import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider;
import com.fr.decision.webservice.utils.DecisionServiceConstants;
import com.fr.json.JSONObject;
import com.fr.plugin.mqh.dingtalksyn.config.DingSynConfig;
import com.fr.web.utils.WebUtils;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import static com.fr.plugin.mqh.dingtalksyn.utils.DingAPI.GETTOKEN;
import static com.fr.plugin.mqh.dingtalksyn.utils.DingAPI.GET_USER_INFO;
/**
* <Function Description><br>
* <GlobalRequestFilterBridge>
*
* @author Louis
* @since 1.0.0
*/
public class GlobalRequestFilterBridge extends AbstractGlobalRequestFilterProvider {
public static final String TPL_PATH = "/com/fr/plugin/mqh/dingtalksyn/web/codePage.html";
public static final String DINGTALK_OPEN_JS = "/com/fr/plugin/mqh/dingtalksyn/web/dingtalk.open.js";
public static final String CODE = "code";
public static final String DING_TALK_LOGIN = "dt";
private DingSynConfig config;
/**
* 过滤器名称
*
* @return
*/
@Override
public String filterName() {
return "DingTalkSynFilter";
}
/**
* 过滤规则
*
* @return
*/
@Override
public String[] urlPatterns() {
return new String[]{"/decision/*"};
}
/**
* 过滤器初始化
*
* @param filterConfig
*/
@Override
public void init(FilterConfig filterConfig) {
this.config = DingSynConfig.getInstance();
super.init(filterConfig);
}
/**
* 过滤器处理
*
* @param request
* @param response
* @param filterChain
*/
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
try {
if (operation(request, response)) {
filterChain.doFilter(request, response);
}
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
}
}
/**
* 用户验证登陆操作
*
* @param req
* @param res
* @throws Exception
*/
private boolean operation(HttpServletRequest req, HttpServletResponse res) throws Exception {
String pathInfo = (req.getPathInfo() != null) ? req.getPathInfo() : StringKit.EMPTY;
if (StringKit.equals(DINGTALK_OPEN_JS, pathInfo)) {
WebUtils.printAsString(res, IOKit.readResourceAsString(DINGTALK_OPEN_JS));
return false;
}
//DingTalk登陆参数
String dt = NetworkKit.getHTTPRequestParameter(req, DING_TALK_LOGIN);
if (StringKit.isBlank(dt)) {
return true;
}
String code = NetworkKit.getHTTPRequestParameter(req, CODE);
LogKit.info("dingtalksyn-GlobalRequestFilterBridge-operation-code:{}", code);
if (StringKit.isEmpty(code)) {
loginPage(req, res);
return false;
}
String accessToken = getAccessToken(code);
String username = getUsername(code, accessToken);
LogKit.info("dingtalksyn-GlobalRequestFilterBridge-operation-username:{}", username);
if (StringKit.isEmpty(username)) {
return true;
}
String tokenFR = LoginKit.login(req, res, username);
req.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, tokenFR);
return true;
}
/**
* 钉钉获取code页面
*
* @param req
* @param res
* @return
* @throws Exception
*/
private void loginPage(HttpServletRequest req, HttpServletResponse res) throws Exception {
Map<String, String> parameterMap = new HashMap<>();
parameterMap.put("corpId", this.config.getCorpId());
parameterMap.put("openJs", WebUtils.createServletURL(req) + DINGTALK_OPEN_JS);
parameterMap.put("remoteServletURL", getRemoteServletURL(WebUtils.getOriginalURL(req)));
String codePage = TemplateUtils.renderTemplate(TPL_PATH, parameterMap);
WebUtils.printAsString(res, codePage);
}
/**
* 处理请求url加入code参数
*
* @param url
* @return
*/
private String getRemoteServletURL(String url) {
if (url.contains("?")) {
return url + "&" + CODE + "=";
}
return url + "?" + CODE + "=";
}
/**
* 获取access_token
*
* @param code
* @return
* @throws Exception
*/
private String getAccessToken(String code) throws Exception {
Map<String, String> tokenParams = new HashMap<>();
tokenParams.put("appkey", this.config.getAppKey());
tokenParams.put("appsecret", this.config.getAppSecret());
tokenParams.put("code", code);
LogKit.info("dingtalksyn-GlobalRequestFilterBridge-getAccessToken-params:{}", tokenParams);
String res = HttpKit.get(GETTOKEN, tokenParams);
LogKit.info("dingtalksyn-GlobalRequestFilterBridge-getAccessToken-res:{}", res);
if (StringKit.isEmpty(res)) {
return StringKit.EMPTY;
}
return new JSONObject(res).getString("access_token");
}
/**
* 通过凭证获得username
*
* @param code
* @param accessToken
* @return
*/
private String getUsername(String code, String accessToken) throws Exception {
Map<String, String> userInfoParams = new HashMap<>();
userInfoParams.put("access_token", accessToken);
userInfoParams.put("code", code);
String userRes = HttpKit.get(GET_USER_INFO, userInfoParams);
LogKit.info("dingtalksyn-GlobalRequestFilterBridge-getUsername-userRes:{}", userRes);
return new JSONObject(userRes).getString("userid");
}
}

179
src/main/java/com/fr/plugin/mqh/dingtalksyn/user/DingTalkUserManager.java

@ -0,0 +1,179 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: DingTalkUserManager
* Author: Louis
* Date: 2021/4/21 16:18
*/
package com.fr.plugin.mqh.dingtalksyn.user;
import com.dingtalk.api.response.OapiRoleListResponse;
import com.dingtalk.api.response.OapiV2DepartmentListsubResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.fanruan.api.decision.user.UserKit;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.util.StringKit;
import com.fr.decision.authority.AuthorityContext;
import com.fr.decision.authority.base.constant.type.operation.ManualOperationType;
import com.fr.decision.authority.data.Department;
import com.fr.decision.webservice.bean.user.RoleBean;
import com.fr.decision.webservice.bean.user.UserBean;
import com.fr.decision.webservice.v10.user.CustomRoleService;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.plugin.mqh.dingtalksyn.config.DingSynConfig;
import com.fr.plugin.mqh.dingtalksyn.kit.CustomRoleServiceKit;
import com.fr.plugin.mqh.dingtalksyn.kit.DepartmentServiceKit;
import com.fr.plugin.mqh.dingtalksyn.kit.UserServiceKit;
import com.taobao.api.ApiException;
import java.util.List;
import static com.fr.plugin.mqh.dingtalksyn.kit.DepartmentServiceKit.DECISION_DEP_ROOT;
import static com.fr.plugin.mqh.dingtalksyn.utils.DingAPI.*;
/**
* <Function Description><br>
* <DingTalkUserManager>
*
* @author Louis
* @since 1.0.0
*/
public final class DingTalkUserManager {
private DingSynConfig config;
public DingTalkUserManager() {
this.config = DingSynConfig.getInstance();
}
private static class HOLDER {
private static final DingTalkUserManager INSTANCE = new DingTalkUserManager();
}
public static DingTalkUserManager getInstance() {
return HOLDER.INSTANCE;
}
/**
* 同步更新的字段包括用户邮箱手机部门职位角色
* 用户唯一字段用户名更新时也是基于用户名
*
* @throws Exception
*/
public synchronized void synDingTalkUsers() throws Exception {
LogKit.info("dingtalksyn-DingTalkUserManager-synDingTalkUsers-start");
// 同步用户角色
List<OapiRoleListResponse.OpenRoleGroup> oapiRoleGroupList = getOapiRoleList();
for (OapiRoleListResponse.OpenRoleGroup openRoleGroup : oapiRoleGroupList) {
List<OapiRoleListResponse.OpenRole> openRoleList = openRoleGroup.getRoles();
for (OapiRoleListResponse.OpenRole openRole : openRoleList) {
roleSynOperation(openRoleGroup.getName(), openRole);
}
}
// 同步部门和用户信息
departmentSynLoop(this.config.getRootDepId());
LogKit.info("dingtalksyn-DingTalkUserManager-synDingTalkUsers-end");
}
/**
* 按部门遍历子部门并同步人员信息
*
* @param deptId
* @throws Exception
*/
private void departmentSynLoop(long deptId) throws ApiException {
List<OapiV2DepartmentListsubResponse.DeptBaseResponse> departmentList = getDepartmentList(deptId);
if (departmentList == null || departmentList.isEmpty()) {
return;
}
// 同步部门信息
for (OapiV2DepartmentListsubResponse.DeptBaseResponse oapiDepartment : departmentList) {
try {
departmentSynOperation(oapiDepartment);
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
}
// 同步当前部门的用户信息
List<String> deptMemberList = getDeptMember(oapiDepartment.getDeptId());
for (String userId : deptMemberList) {
try {
OapiV2UserGetResponse.UserGetResponse userGetResponse = getUserResponse(userId);
if (userGetResponse == null) {
continue;
}
userSynOperation(userGetResponse);
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
}
}
// 操作子部门遍历
departmentSynLoop(oapiDepartment.getDeptId());
}
}
/**
* 角色的新增更新操作
*
* @param openRole
* @throws Exception
*/
private void roleSynOperation(String groupName, OapiRoleListResponse.OpenRole openRole) throws Exception {
if (openRole == null) {
return;
}
RoleBean roleBean = CustomRoleService.getInstance().getCustomRole(String.valueOf(openRole.getId()));
String roleName = StringKit.isBlank(groupName) ? openRole.getName() : groupName + "-" + openRole.getName();
if (roleBean == null) {
roleBean = new RoleBean(roleName, String.valueOf(openRole.getId()), roleName, ManualOperationType.KEY.toInteger());
CustomRoleServiceKit.getInstance().addCustomRole(UserServiceKit.getInstance().getAdminUserId(), roleBean);
} else if(!StringKit.equals(roleBean.getText(), roleName)) {
roleBean.setText(roleName);
roleBean.setDescription(roleName);
CustomRoleService.getInstance().editCustomRole(roleBean.getId(), roleBean);
}
}
/**
* 部门组织的新增更新操作
*
* @param oapiDepartment
* @throws Exception
*/
private void departmentSynOperation(OapiV2DepartmentListsubResponse.DeptBaseResponse oapiDepartment) throws Exception {
String departmentId = String.valueOf(oapiDepartment.getDeptId());
String parentId = String.valueOf(oapiDepartment.getParentId());
if (StringKit.equals(parentId, String.valueOf(this.config.getRootDepId()))) { parentId = DECISION_DEP_ROOT; }
String depName = oapiDepartment.getName();
Department department = AuthorityContext.getInstance().getDepartmentController().getById(departmentId);
if (department == null) {
DepartmentServiceKit.getInstance().addDepartment(departmentId, parentId, depName);
} else {
DepartmentServiceKit.getInstance().editDepartment(department.getId(), depName, parentId);
}
}
/**
* 用户新增更新操作
*
* @param userGetResponse
* @throws Exception
*/
private void userSynOperation(OapiV2UserGetResponse.UserGetResponse userGetResponse) throws Exception {
UserBean userBean;
if (UserKit.existUsername(userGetResponse.getUserid())) {
userBean = UserServiceKit.getInstance().updateUserBean(userGetResponse);
if (userBean == null) {
return;
}
UserService.getInstance().editUser(userBean);
UserServiceKit.getInstance().addUserDepartment(userBean);
} else {
userBean = UserServiceKit.getInstance().createUserBean(userGetResponse);
try {
UserService.getInstance().addUser(userBean);
} catch (Exception e) {
LogKit.error("dingtalksyn-DingTalkUserManager-userSynOperation-Username:{}, RealName:{}, Mobile:{}, Email:{}",
userBean.getUsername(), userBean.getRealName(), userBean.getMobile(), userBean.getEmail());
LogKit.error(e.getMessage(), e);
}
}
}
}

150
src/main/java/com/fr/plugin/mqh/dingtalksyn/utils/DingAPI.java

@ -0,0 +1,150 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: DingAPI
* Author: Louis
* Date: 2021/5/13 16:16
*/
package com.fr.plugin.mqh.dingtalksyn.utils;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.fr.plugin.mqh.dingtalksyn.config.DingSynConfig;
import com.taobao.api.ApiException;
import java.util.List;
/**
* <Function Description><br>
* <DingAPI>
*
* @author Louis
* @since 1.0.0
*/
public class DingAPI {
public static final int TOKEN_EXPIRE_TIME = 3600000;
/**
* 获取企业内部应用的access_token
*/
public static final String GETTOKEN = "https://oapi.dingtalk.com/gettoken";
/**
* 通过免登码获取用户信息
*/
public static final String GET_USER_INFO = "https://oapi.dingtalk.com/user/getuserinfo";
public static final String USER_GET = "https://oapi.dingtalk.com/topapi/v2/user/get";
public static final String DEPARTMENT_LIST = "https://oapi.dingtalk.com/topapi/v2/department/listsub";
public static final String GET_DEPT_MEMBER = "https://oapi.dingtalk.com/topapi/user/listid";
public static final String GET_DEPT = "https://oapi.dingtalk.com/topapi/v2/department/get";
public static final String ROLE_LIST = "https://oapi.dingtalk.com/topapi/role/list";
public static final String GETROLE = "https://oapi.dingtalk.com/topapi/role/getrole";
/**
* 根据deptId获取用户详情
*
* @param deptId
* @return
* @throws ApiException
*/
public static OapiV2DepartmentGetResponse.DeptGetResponse getDeptResponse(long deptId) throws ApiException {
DingTalkClient client = new DefaultDingTalkClient(GET_DEPT);
OapiV2DepartmentGetRequest req = new OapiV2DepartmentGetRequest();
req.setDeptId(deptId);
req.setLanguage("zh_CN");
OapiV2DepartmentGetResponse rsp = client.execute(req, DingTokenUtils.getAccessToken());
return rsp.getResult();
}
/**
* 获取部门用户userid列表
*
* @param deptId
* @return
* @throws ApiException
*/
public static List<String> getDeptMember(long deptId) throws ApiException {
DingTalkClient client = new DefaultDingTalkClient(GET_DEPT_MEMBER);
OapiUserListidRequest req = new OapiUserListidRequest();
req.setDeptId(deptId);
OapiUserListidResponse rsp = client.execute(req, DingTokenUtils.getAccessToken());
return rsp.getResult().getUseridList();
}
/**
* 获取部门列表
*
* @return
* @throws ApiException
*/
public static List<OapiV2DepartmentListsubResponse.DeptBaseResponse> getDepartmentList(long deptId) throws ApiException {
DingTalkClient client = new DefaultDingTalkClient(DEPARTMENT_LIST);
OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();
req.setDeptId(deptId);
req.setLanguage("zh_CN");
OapiV2DepartmentListsubResponse rsp = client.execute(req, DingTokenUtils.getAccessToken());
return rsp.getResult();
}
/**
* 根据roleId获取角色详情
*
* @param roleId
* @return
* @throws ApiException
*/
public static OapiRoleGetroleResponse.OpenRole getRoleResponse(long roleId) throws ApiException {
DingTalkClient client = new DefaultDingTalkClient(GETROLE);
OapiRoleGetroleRequest req = new OapiRoleGetroleRequest();
req.setRoleId(roleId);
OapiRoleGetroleResponse rsp = client.execute(req, DingTokenUtils.getAccessToken());
return rsp.getRole();
}
/**
* 获取角色列表
*
* @return
* @throws ApiException
*/
public static List<OapiRoleListResponse.OpenRoleGroup> getOapiRoleList() throws ApiException {
DingTalkClient client = new DefaultDingTalkClient(ROLE_LIST);
OapiRoleListRequest req = new OapiRoleListRequest();
req.setSize(200L);
req.setOffset(0L);
OapiRoleListResponse rsp = client.execute(req, DingTokenUtils.getAccessToken());
return rsp.getResult().getList();
}
/**
* 根据userid获取用户详情
*
* @param userId
* @return
* @throws ApiException
*/
public static OapiV2UserGetResponse.UserGetResponse getUserResponse(String userId) throws ApiException {
DingTalkClient client = new DefaultDingTalkClient(USER_GET);
OapiV2UserGetRequest req = new OapiV2UserGetRequest();
req.setUserid(userId);
req.setLanguage("zh_CN");
OapiV2UserGetResponse rsp = client.execute(req, DingTokenUtils.getAccessToken());
return rsp.getResult();
}
/**
* 获取企业内部应用的access_token
*
* @return
* @throws ApiException
*/
public static String getAccessToken() throws ApiException {
DingTalkClient client = new DefaultDingTalkClient(GETTOKEN);
OapiGettokenRequest request = new OapiGettokenRequest();
request.setAppkey(DingSynConfig.getInstance().getAppKey());
request.setAppsecret(DingSynConfig.getInstance().getAppSecret());
request.setHttpMethod("GET");
OapiGettokenResponse response = client.execute(request);
return response.getAccessToken();
}
}

67
src/main/java/com/fr/plugin/mqh/dingtalksyn/utils/DingTokenUtils.java

@ -0,0 +1,67 @@
/*
* Copyright (C), 2018-2021
* Project: starter
* FileName: DingTokenUtils
* Author: Louis
* Date: 2021/5/14 14:23
*/
package com.fr.plugin.mqh.dingtalksyn.utils;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.util.StringKit;
import com.fr.plugin.mqh.dingtalksyn.config.DingSynConfig;
import com.fr.store.StateHubManager;
import com.fr.store.StateHubService;
import static com.fr.plugin.mqh.dingtalksyn.utils.DingAPI.TOKEN_EXPIRE_TIME;
/**
* <Function Description><br>
* <DingTokenUtils>
*
* @author Louis
* @since 1.0.0
*/
public class DingTokenUtils {
public static final String DINGTALKSYN_ACCESS_TOKEN = "dingtalksyn_access_token";
public static final String DINGTALKSYN_SUITE_TICKET = "dingtalksyn_suite_ticket";
private static final StateHubService tokenService = StateHubManager.applyForService(DINGTALKSYN_ACCESS_TOKEN);
private static final StateHubService ticketService = StateHubManager.applyForService(DINGTALKSYN_SUITE_TICKET);
public DingTokenUtils() {
}
/**
* 缓存钉钉端AccessToken
*
* @return
*/
public static String getAccessToken() {
String appKey = DingSynConfig.getInstance().getAppKey();
try {
if (StringKit.isBlank(tokenService.get(appKey))) {
tokenService.put(appKey, DingAPI.getAccessToken(), TOKEN_EXPIRE_TIME);
}
return tokenService.get(appKey);
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
return StringKit.EMPTY;
}
}
/**
* 缓存钉钉端SuiteTicket
*
* @return
*/
public static void setSuiteTicket(String suiteTicket) {
String appKey = DingSynConfig.getInstance().getAppKey();
try {
ticketService.put(appKey, suiteTicket, TOKEN_EXPIRE_TIME);
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
}
}
}

18
src/main/resources/com/fr/plugin/mqh/dingtalksyn/locale/lang.properties

@ -0,0 +1,18 @@
Plugin-dingtalksyn=DingTalk syn Plugin
Plugin-dingtalksyn_Group=DingTalk syn Plugin
Plugin-dingtalksyn_Config_CronCondition=Cron Condition
Plugin-dingtalksyn_Config_CronCondition_Description=Cron Condition
Plugin-dingtalksyn_Config_appKey=APPKEY
Plugin-dingtalksyn_Config_appKey_Description=APPKEY
Plugin-dingtalksyn_Config_appSecret=appSecret
Plugin-dingtalksyn_Config_appSecret_Description=appSecret
Plugin-dingtalksyn_Config_corpId=Corp Id
Plugin-dingtalksyn_Config_corpId_Description=Corp Id
Plugin-dingtalksyn_Config_rootDepId=Root Department ID
Plugin-dingtalksyn_Config_rootDepId_Description=Root Department ID
Plugin-dingtalksyn_Config_Token=Token
Plugin-dingtalksyn_Config_Token_Description=Token
Plugin-dingtalksyn_Config_AesKey=AesKey
Plugin-dingtalksyn_Config_AesKey_Description=AesKey
Plugin-dingtalksyn_Error_500=error
Plugin-dingtalksyn_Error_501=DingTalkSyn Plugin License Expired!

18
src/main/resources/com/fr/plugin/mqh/dingtalksyn/locale/lang_zh_CN.properties

@ -0,0 +1,18 @@
Plugin-dingtalksyn=\u9489\u9489\u6570\u636E\u540C\u6B65\u63D2\u4EF6
Plugin-dingtalksyn_Group=\u9489\u9489\u6570\u636E\u540C\u6B65\u63D2\u4EF6
Plugin-dingtalksyn_Config_CronCondition=Cron\u8868\u8FBE\u5F0F
Plugin-dingtalksyn_Config_CronCondition_Description=Cron\u8868\u8FBE\u5F0F
Plugin-dingtalksyn_Config_appKey=\u5E94\u7528\u7CFB\u7EDF\u7684APPKEY
Plugin-dingtalksyn_Config_appKey_Description=\u5E94\u7528\u7CFB\u7EDF\u7684APPKEY
Plugin-dingtalksyn_Config_appSecret=\u5E94\u7528\u7CFB\u7EDF\u7684appSecret
Plugin-dingtalksyn_Config_appSecret_Description=\u5E94\u7528\u7CFB\u7EDF\u7684appSecret
Plugin-dingtalksyn_Config_corpId=Corp Id
Plugin-dingtalksyn_Config_corpId_Description=Corp Id
Plugin-dingtalksyn_Config_rootDepId=\u6839\u90E8\u95E8ID
Plugin-dingtalksyn_Config_rootDepId_Description=\u6839\u90E8\u95E8ID
Plugin-dingtalksyn_Config_Token=\u7B7E\u540DToken
Plugin-dingtalksyn_Config_Token_Description=\u7B7E\u540DToken
Plugin-dingtalksyn_Config_AesKey=\u52A0\u5BC6aes_key
Plugin-dingtalksyn_Config_AesKey_Description=\u52A0\u5BC6aes_key
Plugin-dingtalksyn_Error_500=error
Plugin-dingtalksyn_Error_501=DingTalkSyn\u63D2\u4EF6\u8BB8\u53EF\u5931\u6548!

24
src/main/resources/com/fr/plugin/mqh/dingtalksyn/web/codePage.html

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>DingTalk</title>
<script src="${openJs}"></script>
</head>
<body>
<script>
dd.ready(function () {
dd.runtime.permission.requestAuthCode({
corpId: "${corpId}",
onSuccess: function (result) {
window.open("${remoteServletURL}" + result.code);
},
onFail: function (err) {
}
});
});
</script>
</body>
</html>

1
src/main/resources/com/fr/plugin/mqh/dingtalksyn/web/dingtalk.open.js

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save