LAPTOP-SB56SG4Q\86185
3 years ago
18 changed files with 1142 additions and 1 deletions
Binary file not shown.
@ -1,3 +1,6 @@ |
|||||||
# open-JSD-8329 |
# open-JSD-8329 |
||||||
|
|
||||||
JSD-8329 开源任务材料 |
JSD-8329 开源任务材料\ |
||||||
|
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||||
|
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||||
|
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,24 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<plugin> |
||||||
|
<id>com.fr.plugin.dingtalksyn.job</id> |
||||||
|
<name><![CDATA[钉钉用户同步]]></name> |
||||||
|
<active>yes</active> |
||||||
|
<version>1.2.6</version> |
||||||
|
<env-version>10.0</env-version> |
||||||
|
<jartime>2018-07-31</jartime> |
||||||
|
<vendor>fr.open</vendor> |
||||||
|
<description><![CDATA[钉钉用户同步]]></description> |
||||||
|
<change-notes><![CDATA[钉钉用户同步<br/>]]></change-notes> |
||||||
|
<main-package>com.fr.plugin.dingtalksyn</main-package> |
||||||
|
<prefer-packages> |
||||||
|
<prefer-package>com.fanruan.api</prefer-package> |
||||||
|
</prefer-packages> |
||||||
|
<lifecycle-monitor class="com.fr.plugin.dingtalksyn.provider.LifeCycleMonitorImpl"/> |
||||||
|
<extra-core> |
||||||
|
<LocaleFinder class="com.fr.plugin.dingtalksyn.provider.LocaleFinder"/> |
||||||
|
</extra-core> |
||||||
|
<extra-decision> |
||||||
|
<GlobalRequestFilterProvider class="com.fr.plugin.dingtalksyn.request.GlobalRequestFilterBridge"/> |
||||||
|
</extra-decision> |
||||||
|
<function-recorder class="com.fr.plugin.dingtalksyn.provider.LocaleFinder"/> |
||||||
|
</plugin> |
@ -0,0 +1,107 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C), 2018-2021 |
||||||
|
* Project: starter |
||||||
|
* FileName: DingTalkJobConstructor |
||||||
|
* Author: Louis |
||||||
|
* Date: 2021/4/21 15:58 |
||||||
|
*/ |
||||||
|
package com.fr.plugin.dingtalksyn.bean; |
||||||
|
|
||||||
|
import com.fr.scheduler.job.FineScheduleJob; |
||||||
|
|
||||||
|
/** |
||||||
|
* <Function Description><br> |
||||||
|
* <DingTalkJobConstructor> |
||||||
|
* |
||||||
|
* @author fr.open |
||||||
|
* @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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,83 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C), 2018-2021 |
||||||
|
* Project: starter |
||||||
|
* FileName: OneAccessConfig |
||||||
|
* Author: Louis |
||||||
|
* Date: 2021/3/30 9:38 |
||||||
|
*/ |
||||||
|
package com.fr.plugin.dingtalksyn.config; |
||||||
|
|
||||||
|
import com.fr.config.*; |
||||||
|
import com.fr.config.holder.Conf; |
||||||
|
import com.fr.config.holder.factory.Holders; |
||||||
|
import com.fr.intelli.record.Focus; |
||||||
|
import com.fr.intelli.record.Original; |
||||||
|
|
||||||
|
import static com.fr.plugin.dingtalksyn.provider.LocaleFinder.PLUGIN_ID; |
||||||
|
|
||||||
|
/** |
||||||
|
* <Function Description><br> |
||||||
|
* <OneAccessConfig> |
||||||
|
* |
||||||
|
* @author fr.open |
||||||
|
* @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 String APP_KEY = "xxxx"; |
||||||
|
public static final String APP_SECRET = "xxxx"; |
||||||
|
public static final long ROOT_DEP_ID = 1; |
||||||
|
private static volatile DingSynConfig config = null; |
||||||
|
|
||||||
|
@Focus(id = PLUGIN_ID, text = "Plugin-dingtalksyn", source = Original.PLUGIN) |
||||||
|
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(APP_KEY); |
||||||
|
@Identifier(value = "appSecret", name = "Plugin-dingtalksyn_Config_appSecret", description = "Plugin-dingtalksyn_Config_appSecret_Description", status = Status.SHOW) |
||||||
|
private Conf<String> appSecret = Holders.simple(APP_SECRET); |
||||||
|
@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); |
||||||
|
|
||||||
|
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 long getRootDepId() { |
||||||
|
return rootDepId.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setRootDepId(long rootDepId) { |
||||||
|
this.rootDepId.set(rootDepId); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C), 2018-2021 |
||||||
|
* Project: starter |
||||||
|
* FileName: DingTalkScheduleHelper |
||||||
|
* Author: Louis |
||||||
|
* Date: 2021/4/21 15:52 |
||||||
|
*/ |
||||||
|
package com.fr.plugin.dingtalksyn.helper; |
||||||
|
|
||||||
|
import com.fr.plugin.dingtalksyn.bean.DingTalkJobConstructor; |
||||||
|
import com.fr.plugin.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 fr.open |
||||||
|
* @since 1.0.0 |
||||||
|
*/ |
||||||
|
public class DingTalkScheduleHelper { |
||||||
|
private static final String SECOND = "0"; |
||||||
|
private static final String CRON_EXPRESSION_EVERY_DAY = "%s %s %s ? * *"; |
||||||
|
private static final String CRON_EXPRESSION_EVERY_WEEK = "%s %s %s ? * %s"; |
||||||
|
public static final String DINGTALK_SCHEDULE_SYN_MEMBER_JOB_NAME = "MQH_DingTalkSynDepMemberJob"; |
||||||
|
public static final String DINGTALK_SCHEDULE_SYN_MEMBER_TRIGGER_NAME = "MQH_DingTalkSynDepMemberTrigger"; |
||||||
|
public static final String DINGTALK_SCHEDULE_SYN_MEMBER_GROUP = "MQH_DingTalkSynDepMemberGroup"; |
||||||
|
public static final String DINGTALK_SCHEDULE_SYN_MEMBER_TRIGGER_GROUP = "MQH_DingTalkSynDepMemberTriggerGroup"; |
||||||
|
|
||||||
|
private DingTalkScheduleHelper() { |
||||||
|
} |
||||||
|
|
||||||
|
public static DingTalkScheduleHelper getInstance() { |
||||||
|
return DingTalkScheduleHelper.HOLDER.INSTANCE; |
||||||
|
} |
||||||
|
|
||||||
|
// private String getSynMemberJobCron(DingTalkTimingTaskConfig var1) {
|
||||||
|
// int var2 = var1.getPeriod();
|
||||||
|
// String var3 = var1.getStartHour();
|
||||||
|
// String var4 = var1.getStartMinute();
|
||||||
|
// Week var5 = Week.getWeek(var1.getStartWeekDay());
|
||||||
|
// if (var2 == 0) {
|
||||||
|
// return String.format("%s %s %s ? * *", "0", var4, var3);
|
||||||
|
// } else {
|
||||||
|
// return var2 == 1 ? String.format("%s %s %s ? * %s", "0", var4, var3, var5) : "";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public void startSynMemberSchedule(DingTalkTimingTaskConfig var1) throws Exception {
|
||||||
|
// if (var1.isEnableAutoSync()) {
|
||||||
|
// String var2 = this.getSynMemberJobCron(var1);
|
||||||
|
// DingTalkJobConstructor var3 = (new DingTalkJobConstructor()).cron(var2).jobName("DingTalkSynDepMemberJob").jobGroup("DingTalkSynDepMemberGroup").triggerName("DingTalkSynDepMemberTrigger").triggerGroup("DingTalkSynDepMemberTriggerGroup").jobClazz(DingTalkSyncMemberJob.class);
|
||||||
|
// this.startSchedule(var3);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
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() { |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C), 2018-2021 |
||||||
|
* Project: starter |
||||||
|
* FileName: DingTalkSyncMemberJob |
||||||
|
* Author: Louis |
||||||
|
* Date: 2021/4/21 16:02 |
||||||
|
*/ |
||||||
|
package com.fr.plugin.dingtalksyn.job; |
||||||
|
|
||||||
|
import com.fanruan.api.log.LogKit; |
||||||
|
import com.fr.cluster.core.ClusterNode; |
||||||
|
import com.fr.plugin.dingtalksyn.user.DingTalkUserManager; |
||||||
|
import com.fr.scheduler.job.FineScheduleJob; |
||||||
|
import com.fr.third.v2.org.quartz.JobExecutionContext; |
||||||
|
|
||||||
|
/** |
||||||
|
* <Function Description><br> |
||||||
|
* <DingTalkSyncMemberJob> |
||||||
|
* |
||||||
|
* @author fr.open |
||||||
|
* @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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C), 2018-2021 |
||||||
|
* Project: starter |
||||||
|
* FileName: OneAccessLifeCycleMonitor |
||||||
|
* Author: Louis |
||||||
|
* Date: 2021/3/30 15:10 |
||||||
|
*/ |
||||||
|
package com.fr.plugin.dingtalksyn.provider; |
||||||
|
|
||||||
|
import com.fanruan.api.log.LogKit; |
||||||
|
import com.fr.plugin.context.PluginContext; |
||||||
|
import com.fr.plugin.dingtalksyn.helper.DingTalkScheduleHelper; |
||||||
|
import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; |
||||||
|
import com.fr.plugin.dingtalksyn.config.DingSynConfig; |
||||||
|
|
||||||
|
import static com.fr.plugin.dingtalksyn.helper.DingTalkScheduleHelper.DINGTALK_SCHEDULE_SYN_MEMBER_GROUP; |
||||||
|
import static com.fr.plugin.dingtalksyn.helper.DingTalkScheduleHelper.DINGTALK_SCHEDULE_SYN_MEMBER_JOB_NAME; |
||||||
|
|
||||||
|
/** |
||||||
|
* <Function Description><br> |
||||||
|
* <OneAccessLifeCycleMonitor> |
||||||
|
* |
||||||
|
* @author fr.open |
||||||
|
* @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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C), 2018-2020 |
||||||
|
* Project: starter |
||||||
|
* FileName: LocaleFinder |
||||||
|
* Author: Louis |
||||||
|
* Date: 2020/8/31 22:19 |
||||||
|
*/ |
||||||
|
package com.fr.plugin.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 fr.open |
||||||
|
* @since 1.0.0 |
||||||
|
*/ |
||||||
|
@EnableMetrics |
||||||
|
public class LocaleFinder extends AbstractLocaleFinder { |
||||||
|
public static final String PLUGIN_ID = "com.fr.plugin.dingtalksyn.job"; |
||||||
|
|
||||||
|
@Override |
||||||
|
@Focus(id = PLUGIN_ID, text = "Plugin-dingtalksyn", source = Original.PLUGIN) |
||||||
|
public String find() { |
||||||
|
return "com/fr/plugin/dingtalksyn/locale/lang"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int currentAPILevel() { |
||||||
|
return CURRENT_LEVEL; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C), 2018-2021 |
||||||
|
* Project: starter |
||||||
|
* FileName: DelegatingServletInputStream |
||||||
|
* Author: Louis |
||||||
|
* Date: 2021/7/16 9:21 |
||||||
|
*/ |
||||||
|
package com.fr.plugin.dingtalksyn.request; |
||||||
|
|
||||||
|
import javax.servlet.ReadListener; |
||||||
|
import javax.servlet.ServletInputStream; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
|
||||||
|
/** |
||||||
|
* <Function Description><br> |
||||||
|
* <DelegatingServletInputStream> |
||||||
|
* |
||||||
|
* @author fr.open |
||||||
|
* @since 1.0.0 |
||||||
|
*/ |
||||||
|
public class DelegatingServletInputStream extends ServletInputStream { |
||||||
|
private final InputStream sourceStream; |
||||||
|
|
||||||
|
public DelegatingServletInputStream(InputStream stream) { |
||||||
|
this.sourceStream = stream; |
||||||
|
} |
||||||
|
|
||||||
|
public final InputStream getSourceStream() { |
||||||
|
return this.sourceStream; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int read() throws IOException { |
||||||
|
return this.sourceStream.read(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void close() throws IOException { |
||||||
|
super.close(); |
||||||
|
this.sourceStream.close(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isFinished() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isReady() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setReadListener(ReadListener listener) { |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,78 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C), 2018-2021 |
||||||
|
* Project: starter |
||||||
|
* FileName: GlobalRequestFilterBridge |
||||||
|
* Author: Louis |
||||||
|
* Date: 2021/7/15 15:40 |
||||||
|
*/ |
||||||
|
package com.fr.plugin.dingtalksyn.request; |
||||||
|
|
||||||
|
import com.fanruan.api.log.LogKit; |
||||||
|
import com.fanruan.api.util.StringKit; |
||||||
|
import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; |
||||||
|
|
||||||
|
import javax.servlet.FilterChain; |
||||||
|
import javax.servlet.FilterConfig; |
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
|
||||||
|
/** |
||||||
|
* <Function Description><br> |
||||||
|
* <GlobalRequestFilterBridge> |
||||||
|
* |
||||||
|
* @author fr.open |
||||||
|
* @since 1.0.0 |
||||||
|
*/ |
||||||
|
public class GlobalRequestFilterBridge extends AbstractGlobalRequestFilterProvider { |
||||||
|
public static final String LOGIN_PATH = "/login"; |
||||||
|
|
||||||
|
/** |
||||||
|
* 过滤器名称 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public String filterName() { |
||||||
|
return "DingTalkSynFilter"; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 过滤规则 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public String[] urlPatterns() { |
||||||
|
return new String[]{"/decision/*"}; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 过滤器初始化 |
||||||
|
* |
||||||
|
* @param filterConfig |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void init(FilterConfig filterConfig) { |
||||||
|
super.init(filterConfig); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 过滤器处理 |
||||||
|
* |
||||||
|
* @param request |
||||||
|
* @param response |
||||||
|
* @param filterChain |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) { |
||||||
|
String pathInfo = (request.getPathInfo() != null) ? request.getPathInfo() : StringKit.EMPTY; |
||||||
|
if (StringKit.equals(LOGIN_PATH, pathInfo) && StringKit.equalsIgnoreCase(request.getMethod(), "POST")) { |
||||||
|
request = new ModifyBodyRequestWrapper(request); |
||||||
|
} |
||||||
|
try { |
||||||
|
filterChain.doFilter(request, response); |
||||||
|
} catch (Exception e) { |
||||||
|
LogKit.error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C), 2018-2021 |
||||||
|
* Project: starter |
||||||
|
* FileName: UserNameTransferRequest |
||||||
|
* Author: Louis |
||||||
|
* Date: 2021/7/16 9:20 |
||||||
|
*/ |
||||||
|
package com.fr.plugin.dingtalksyn.request; |
||||||
|
|
||||||
|
import com.fanruan.api.decision.user.UserKit; |
||||||
|
import com.fanruan.api.util.StringKit; |
||||||
|
import com.fr.decision.webservice.v10.user.UserService; |
||||||
|
import com.fr.general.IOUtils; |
||||||
|
import com.fr.json.JSONObject; |
||||||
|
|
||||||
|
import javax.servlet.ServletInputStream; |
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletRequestWrapper; |
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* <Function Description><br> |
||||||
|
* <UserNameTransferRequest> |
||||||
|
* |
||||||
|
* @author fr.open |
||||||
|
* @since 1.0.0 |
||||||
|
*/ |
||||||
|
public class ModifyBodyRequestWrapper extends HttpServletRequestWrapper { |
||||||
|
private byte[] data; |
||||||
|
private String bodyContent; |
||||||
|
|
||||||
|
public ModifyBodyRequestWrapper(HttpServletRequest request) { |
||||||
|
super(request); |
||||||
|
this.bodyContent = modifyRequestBody(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 如登陆输入手机号,则替换为用户名 |
||||||
|
* |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private String modifyRequestBody() { |
||||||
|
try { |
||||||
|
String orgContent = IOUtils.inputStream2String(this.getRequest().getInputStream()); |
||||||
|
JSONObject bodyJo = new JSONObject(orgContent); |
||||||
|
if (!bodyJo.has("username")) { |
||||||
|
return orgContent; |
||||||
|
} |
||||||
|
String username = bodyJo.getString("username"); |
||||||
|
if (StringKit.isBlank(username)) { |
||||||
|
return orgContent; |
||||||
|
} |
||||||
|
if (!UserKit.existUsername(username)) { |
||||||
|
List<String> usernameList = UserService.getInstance().getUserNamesFromMobile(username); |
||||||
|
if (!usernameList.isEmpty() && StringKit.isNotBlank(usernameList.get(0))) { |
||||||
|
bodyJo.put("username", usernameList.get(0)); |
||||||
|
} |
||||||
|
} |
||||||
|
return bodyJo.encode(); |
||||||
|
} catch (Exception e) { |
||||||
|
return StringKit.EMPTY; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ServletInputStream getInputStream() { |
||||||
|
try { |
||||||
|
return new DelegatingServletInputStream(new ByteArrayInputStream(this.bodyContent.getBytes())); |
||||||
|
} catch (Exception e) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public BufferedReader getReader() { |
||||||
|
return new BufferedReader(new InputStreamReader(new ByteArrayInputStream(this.bodyContent.getBytes()))); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,468 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C), 2018-2021 |
||||||
|
* Project: starter |
||||||
|
* FileName: DingTalkUserManager |
||||||
|
* Author: Louis |
||||||
|
* Date: 2021/4/21 16:18 |
||||||
|
*/ |
||||||
|
package com.fr.plugin.dingtalksyn.user; |
||||||
|
|
||||||
|
import com.dingtalk.api.DefaultDingTalkClient; |
||||||
|
import com.dingtalk.api.DingTalkClient; |
||||||
|
import com.dingtalk.api.request.*; |
||||||
|
import com.dingtalk.api.response.*; |
||||||
|
import com.fanruan.api.decision.user.UserKit; |
||||||
|
import com.fanruan.api.i18n.I18nKit; |
||||||
|
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.SoftRoleType; |
||||||
|
import com.fr.decision.authority.base.constant.type.operation.ManualOperationType; |
||||||
|
import com.fr.decision.authority.data.*; |
||||||
|
import com.fr.decision.authority.data.personnel.DepRole; |
||||||
|
import com.fr.decision.privilege.TransmissionTool; |
||||||
|
import com.fr.decision.record.OperateMessage; |
||||||
|
import com.fr.decision.webservice.bean.user.DepartmentPostBean; |
||||||
|
import com.fr.decision.webservice.bean.user.RoleBean; |
||||||
|
import com.fr.decision.webservice.bean.user.UserBean; |
||||||
|
import com.fr.decision.webservice.exception.general.DuplicatedNameException; |
||||||
|
import com.fr.decision.webservice.utils.ControllerFactory; |
||||||
|
import com.fr.decision.webservice.utils.UserSourceFactory; |
||||||
|
import com.fr.decision.webservice.utils.WebServiceUtils; |
||||||
|
import com.fr.decision.webservice.v10.user.CustomRoleService; |
||||||
|
import com.fr.decision.webservice.v10.user.DepartmentService; |
||||||
|
import com.fr.decision.webservice.v10.user.PositionService; |
||||||
|
import com.fr.decision.webservice.v10.user.UserService; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.intelli.record.MetricRegistry; |
||||||
|
import com.fr.plugin.dingtalksyn.config.DingSynConfig; |
||||||
|
import com.fr.stable.StableUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
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 com.taobao.api.ApiException; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* <Function Description><br> |
||||||
|
* <DingTalkUserManager> |
||||||
|
* |
||||||
|
* @author fr.open |
||||||
|
* @since 1.0.0 |
||||||
|
*/ |
||||||
|
public final class DingTalkUserManager { |
||||||
|
public static final String DECISION_DEP_ROOT = "decision-dep-root"; |
||||||
|
|
||||||
|
public static final String GETTOKEN = "https://oapi.dingtalk.com/gettoken"; |
||||||
|
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 USER_GET = "https://oapi.dingtalk.com/topapi/v2/user/get"; |
||||||
|
public static final String ROLE_LIST = "https://oapi.dingtalk.com/topapi/role/list"; |
||||||
|
|
||||||
|
private DingSynConfig config; |
||||||
|
private String accessToken; |
||||||
|
|
||||||
|
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.error("dingtalksyn-DingTalkUserManager-synDingTalkUsers-start"); |
||||||
|
this.accessToken = getToken(); |
||||||
|
// 同步用户角色
|
||||||
|
List<OapiRoleListResponse.OpenRoleGroup> oapiRoleGroupList = getOapiRoleList(); |
||||||
|
for (OapiRoleListResponse.OpenRoleGroup openRoleGroup : oapiRoleGroupList) { |
||||||
|
List<OapiRoleListResponse.OpenRole> openRoleList = openRoleGroup.getRoles(); |
||||||
|
for (OapiRoleListResponse.OpenRole openRole : openRoleList) { |
||||||
|
roleSynOperation(openRole); |
||||||
|
} |
||||||
|
} |
||||||
|
// 同步部门和用户信息
|
||||||
|
departmentSynLoop(this.config.getRootDepId()); |
||||||
|
LogKit.error("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, oapiDepartment.getDeptId()); |
||||||
|
} catch (Exception e) { |
||||||
|
LogKit.error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
// 操作子部门遍历
|
||||||
|
departmentSynLoop(oapiDepartment.getDeptId()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 角色的新增更新操作 |
||||||
|
* |
||||||
|
* @param openRole |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
private void roleSynOperation(OapiRoleListResponse.OpenRole openRole) throws Exception { |
||||||
|
RoleBean roleBean = CustomRoleService.getInstance().getCustomRole(String.valueOf(openRole.getId())); |
||||||
|
if (roleBean == null) { |
||||||
|
roleBean = new RoleBean(openRole.getName(), String.valueOf(openRole.getId()), openRole.getName(), ManualOperationType.KEY.toInteger()); |
||||||
|
addCustomRole(getAdminUserId(), roleBean); |
||||||
|
} else if(!StringKit.equals(roleBean.getText(), openRole.getName())) { |
||||||
|
roleBean.setText(openRole.getName()); |
||||||
|
roleBean.setDescription(openRole.getName()); |
||||||
|
CustomRoleService.getInstance().editCustomRole(roleBean.getId(), roleBean); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private 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); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 部门组织的新增更新操作 |
||||||
|
* |
||||||
|
* @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) { |
||||||
|
this.addDepartment(departmentId, parentId, depName); |
||||||
|
} else { |
||||||
|
this.editDepartment(department.getId(), depName, parentId); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private 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); |
||||||
|
} |
||||||
|
|
||||||
|
private 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)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 用户新增更新操作 |
||||||
|
* |
||||||
|
* @param userGetResponse |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
private void userSynOperation(OapiV2UserGetResponse.UserGetResponse userGetResponse, Long currentDepId) throws Exception { |
||||||
|
UserBean userBean; |
||||||
|
if (UserKit.existUsername(userGetResponse.getUserid())) { |
||||||
|
userBean = updateUserBean(userGetResponse, currentDepId); |
||||||
|
UserService.getInstance().editUser(userBean); |
||||||
|
addUserDepartment(userBean); |
||||||
|
} else { |
||||||
|
userBean = createUserBean(userGetResponse, currentDepId); |
||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 增加用户部门关联 |
||||||
|
* |
||||||
|
* @param userBean |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
private void addUserDepartment(UserBean userBean) throws Exception { |
||||||
|
if (StringUtils.isNotEmpty(userBean.getDepartmentPostId())) { |
||||||
|
User user = UserService.getInstance().getUserByUserName(userBean.getUsername()); |
||||||
|
DepRole depRole = WebServiceUtils.parseUniqueDepartmentPostId(userBean.getDepartmentPostId()); |
||||||
|
UserSourceFactory.getInstance().checkSource(user, AuthorityContext.getInstance().getDepartmentController().getById(depRole.getDepartmentId())); |
||||||
|
AuthorityContext.getInstance().getUserController().addUserToDepartmentAndPost(user.getId(), depRole.getDepartmentId(), depRole.getPostId()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private UserBean updateUserBean(OapiV2UserGetResponse.UserGetResponse userGetResponse, Long currentDepId) throws Exception { |
||||||
|
User user = UserService.getInstance().getUserByUserName(userGetResponse.getUserid()); |
||||||
|
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 (userGetResponse.getRoleList() != null && !userGetResponse.getRoleList().isEmpty()) { |
||||||
|
userBean.setRoleIds(oapiUserRoles2Ids(userGetResponse.getRoleList())); |
||||||
|
} |
||||||
|
if (currentDepId == null) { |
||||||
|
return userBean; |
||||||
|
} |
||||||
|
String departmentPostId = String.valueOf(currentDepId); |
||||||
|
if (StringKit.isBlank(departmentPostId) || StringKit.equals(departmentPostId, "null")) { |
||||||
|
return userBean; |
||||||
|
} |
||||||
|
// 职务处理
|
||||||
|
String positionId = positionSynOperation(userGetResponse, departmentPostId); |
||||||
|
if (StringKit.isNotBlank(positionId)) { |
||||||
|
departmentPostId = departmentPostId + "@@@" + positionId; |
||||||
|
} |
||||||
|
// 旧版本jar 20210119
|
||||||
|
userBean.setDepartmentPostId(departmentPostId); |
||||||
|
// 新版jar
|
||||||
|
// List<String> departmentPostIds = userGetResponse.getDepartment().stream().map(String::valueOf).collect(Collectors.toList());
|
||||||
|
// userBean.setDepartmentPostIds(departmentPostIds);
|
||||||
|
return userBean; |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
private UserBean createUserBean(OapiV2UserGetResponse.UserGetResponse userGetResponse, Long currentDepId) 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("123456")); |
||||||
|
if (userGetResponse.getRoleList() != null && !userGetResponse.getRoleList().isEmpty()) { |
||||||
|
userBean.setRoleIds(oapiUserRoles2Ids(userGetResponse.getRoleList())); |
||||||
|
} |
||||||
|
if (currentDepId == null) { |
||||||
|
return userBean; |
||||||
|
} |
||||||
|
String departmentPostId = String.valueOf(currentDepId); |
||||||
|
if (StringKit.isBlank(departmentPostId) || StringKit.equals(departmentPostId, "null")) { |
||||||
|
return userBean; |
||||||
|
} |
||||||
|
// 职务处理
|
||||||
|
String positionId = positionSynOperation(userGetResponse, departmentPostId); |
||||||
|
if (StringKit.isNotBlank(positionId)) { |
||||||
|
departmentPostId = departmentPostId + "@@@" + positionId; |
||||||
|
} |
||||||
|
// 旧版本jar 20210119
|
||||||
|
userBean.setDepartmentPostId(departmentPostId); |
||||||
|
// 新版本jar
|
||||||
|
// List<String> departmentPostIds = userGetResponse.getDepartment().stream().map(String::valueOf).collect(Collectors.toList());
|
||||||
|
// userBean.setDepartmentPostIds(departmentPostIds);
|
||||||
|
return userBean; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 职务同步操作 |
||||||
|
* |
||||||
|
* @param userGetResponse |
||||||
|
* @param departmentId |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
private String positionSynOperation(OapiV2UserGetResponse.UserGetResponse userGetResponse, String departmentId) throws Exception { |
||||||
|
String position = StringKit.isNotBlank(userGetResponse.getTitle()) ? userGetResponse.getTitle() : "职员"; |
||||||
|
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.error("dingtalksyn-DingTalkUserManager-positionSynOperation-addPostToDepartmentFailed-position:{}, departmentId:{}, userID:{}, userName:{}", |
||||||
|
positionId + position, departmentId, userGetResponse.getUserid(), userGetResponse.getName()); |
||||||
|
LogKit.error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
return positionId; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取管理员id |
||||||
|
* |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
private 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"; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据userid获取用户详情 |
||||||
|
* |
||||||
|
* @param userId |
||||||
|
* @return |
||||||
|
* @throws ApiException |
||||||
|
*/ |
||||||
|
private 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, this.accessToken); |
||||||
|
return rsp.getResult(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取部门用户userid列表 |
||||||
|
* |
||||||
|
* @param deptId |
||||||
|
* @return |
||||||
|
* @throws ApiException |
||||||
|
*/ |
||||||
|
private 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, this.accessToken); |
||||||
|
return rsp.getResult().getUseridList(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取部门列表 |
||||||
|
* |
||||||
|
* @return |
||||||
|
* @throws ApiException |
||||||
|
*/ |
||||||
|
private 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, this.accessToken); |
||||||
|
return rsp.getResult(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取角色列表 |
||||||
|
* |
||||||
|
* @return |
||||||
|
* @throws ApiException |
||||||
|
*/ |
||||||
|
private 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, this.accessToken); |
||||||
|
return rsp.getResult().getList(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取企业内部应用的access_token |
||||||
|
* |
||||||
|
* @return |
||||||
|
* @throws ApiException |
||||||
|
*/ |
||||||
|
private String getToken() throws ApiException { |
||||||
|
DingTalkClient client = new DefaultDingTalkClient(GETTOKEN); |
||||||
|
OapiGettokenRequest request = new OapiGettokenRequest(); |
||||||
|
request.setAppkey(this.config.getAppKey()); |
||||||
|
request.setAppsecret(this.config.getAppSecret()); |
||||||
|
request.setHttpMethod("GET"); |
||||||
|
OapiGettokenResponse response = client.execute(request); |
||||||
|
return response.getAccessToken(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
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_rootDepId=Root Department ID |
||||||
|
Plugin-dingtalksyn_Config_rootDepId_Description=Root Department ID |
@ -0,0 +1,10 @@ |
|||||||
|
Plugin-dingtalksyn=\u9489\u9489\u7528\u6237\u540C\u6B65\u63D2\u4EF6 |
||||||
|
Plugin-dingtalksyn_Group=\u9489\u9489\u7528\u6237\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_rootDepId=\u6839\u90E8\u95E8ID |
||||||
|
Plugin-dingtalksyn_Config_rootDepId_Description=\u6839\u90E8\u95E8ID |
Loading…
Reference in new issue