Browse Source

插件上架,初始提交代码

master
Jianye.Wang 2 years ago
parent
commit
f360f93cdd
  1. 9
      README.md
  2. 41
      plugin.xml
  3. 23
      src/main/java/com/fr/plugin/decision/integration/ControllerBridgeImpl.java
  4. 24
      src/main/java/com/fr/plugin/decision/integration/LifecycleMonitorImpl.java
  5. 54
      src/main/java/com/fr/plugin/decision/integration/bean/TplInfoBean.java
  6. 25
      src/main/java/com/fr/plugin/decision/integration/bean/user/NamedBean.java
  7. 45
      src/main/java/com/fr/plugin/decision/integration/bean/user/UserInfoBean.java
  8. 273
      src/main/java/com/fr/plugin/decision/integration/config/IntegrateConf.java
  9. 50
      src/main/java/com/fr/plugin/decision/integration/config/strategy/CreateDepartmentStrategy.java
  10. 37
      src/main/java/com/fr/plugin/decision/integration/config/strategy/CreatePwdStrategy.java
  11. 38
      src/main/java/com/fr/plugin/decision/integration/config/strategy/user/CreateUserStrategy.java
  12. 53
      src/main/java/com/fr/plugin/decision/integration/config/strategy/user/impl/ContainDepRoleStrategy.java
  13. 15
      src/main/java/com/fr/plugin/decision/integration/config/strategy/user/impl/OnlyUserStrategy.java
  14. 224
      src/main/java/com/fr/plugin/decision/integration/controller/IntegratedController.java
  15. 7
      src/main/java/com/fr/plugin/decision/integration/exception/JwtKeyNullException.java
  16. 14
      src/main/java/com/fr/plugin/decision/integration/exception/JwtSubjectFormatException.java
  17. 14
      src/main/java/com/fr/plugin/decision/integration/exception/ThirdAuthException.java
  18. 7
      src/main/java/com/fr/plugin/decision/integration/exception/TokenDecodeExpiredException.java
  19. 14
      src/main/java/com/fr/plugin/decision/integration/exception/TokenNullException.java
  20. 57
      src/main/java/com/fr/plugin/decision/integration/filter/RemoteFilter.java
  21. 78
      src/main/java/com/fr/plugin/decision/integration/filter/RequestSsoFilter.java
  22. 62
      src/main/java/com/fr/plugin/decision/integration/filter/TplParaCheckFilter.java
  23. 27
      src/main/java/com/fr/plugin/decision/integration/resource/PluginConfigWebResourceImpl.java
  24. 43
      src/main/java/com/fr/plugin/decision/integration/resource/WebStartWebResourceImpl.java
  25. 254
      src/main/java/com/fr/plugin/decision/integration/service/IntegrateAuthService.java
  26. 98
      src/main/java/com/fr/plugin/decision/integration/service/IntegrateCustomService.java
  27. 68
      src/main/java/com/fr/plugin/decision/integration/utils/AESUtils.java
  28. 90
      src/main/java/com/fr/plugin/decision/integration/utils/CommonUtils.java
  29. 18
      src/main/java/com/fr/plugin/decision/integration/utils/Constants.java
  30. 96
      src/main/java/com/fr/plugin/decision/integration/utils/LogUtils.java
  31. 417
      src/main/java/com/fr/plugin/decision/integration/utils/UserUtils.java
  32. 42
      src/main/resources/com/fr/plugin/decision/integration/web/js/button_group.item.js
  33. 17
      src/main/resources/com/fr/plugin/decision/integration/web/js/constant.js
  34. 44
      src/main/resources/com/fr/plugin/decision/integration/web/js/model.pane.js
  35. 510
      src/main/resources/com/fr/plugin/decision/integration/web/js/pane.js
  36. 35
      src/main/resources/com/fr/plugin/decision/integration/web/js/plugin.js
  37. 263
      src/main/resources/com/fr/plugin/decision/integration/web/js/protocolcheck.js
  38. 26
      src/main/resources/com/fr/plugin/decision/integration/web/js/web_start.js

9
README.md

@ -1,3 +1,10 @@
# com.fr.plugin.decision.integration
登录集成插件
登录集成插件
# 问题记录
Refused to execute script from ‘XXXX’ because its MIME type (‘text/html’) is not executable, and strict MIME type checking is enabled. 响应头中增加了X-Content-Type-Options:nosniff字段,导致跨域接口异常。
解决方案:响应头中新增 content-type: application/javascript; charset=utf-8 (https://www.freesion.com/article/64191377003/)
# 插件说明
https://www.showdoc.com.cn/1435897295186406/7012059782236943

41
plugin.xml

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plugin>
<id>com.fr.plugin.decision.integration</id>
<name><![CDATA[登录集成插件]]></name>
<active>yes</active>
<hidden>no</hidden>
<version>1.0.20</version>
<env-version>10.0~</env-version>
<jartime>2019-1-31</jartime>
<vendor>JianYe.Wang</vendor>
<description><![CDATA[登录集成插件]]></description>
<change-notes>
<![CDATA[
[2021-06-01]<br/>1.0.0:调整插件结构<br/>
[2021-06-08]<br/>1.0.1:优化插件配置项<br/>
[2021-07-07]<br/>1.0.2:跨域登录接口新增响应头content-type规避nosniff的限制<br/>
[2021-08-03]<br/>1.0.3:创建用户时部门为空<br/>
[2021-08-18]<br/>1.0.4:去除角色id的传递,统一通过角色名来匹配<br/>
[2021-08-24]<br/>1.0.5:角色添加逻辑异常修复<br/>
[2021-10-15]<br/>1.0.8:新增URL参数单点登录校验<br/>
[2021-11-15]<br/>1.0.12:去除管理员账号的权限处理<br/>
[2021-12-06]<br/>1.0.13/15:添加用户类型配置参数<br/>
[2021-12-10]<br/>1.0.14:移动端单点场景时重定向至携带fine_auth_token的地址<br/>
[2022-01-04]<br/>1.0.16:移动端跨域登录与RequestSsoFilter移动端重定向的冲突/部门创建支持名称拼接<br/>
[2022-02-22]<br/>1.0.17:将启动设计器按钮添加平台中/代码接口优化<br/>
[2022-03-23]<br/>1.0.18:新增接口,单点场景可直接访问固定地址打开URL来唤醒设计器;key默认值设置为uuid<br/>
[2022-04-01]<br/>1.0.19:调整WebResourceProvider接口;新增配置远程权限控制是否开启;调整用户平台类型添加逻辑<br/>
[2022-04-11]<br/>1.0.20:去除自定义登录页配置选项<br/>
]]>
</change-notes>
<function-recorder class="com.fr.plugin.decision.integration.ControllerBridgeImpl"/>
<lifecycle-monitor class="com.fr.plugin.decision.integration.LifecycleMonitorImpl"/>
<extra-decision>
<ControllerRegisterProvider class="com.fr.plugin.decision.integration.ControllerBridgeImpl"/>
<EmbedRequestFilterProvider class="com.fr.plugin.decision.integration.filter.RemoteFilter"/>
<EmbedRequestFilterProvider class="com.fr.plugin.decision.integration.filter.TplParaCheckFilter"/>
<EmbedRequestFilterProvider class="com.fr.plugin.decision.integration.filter.RequestSsoFilter"/>
<WebResourceProvider class="com.fr.plugin.decision.integration.resource.PluginConfigWebResourceImpl"/>
<WebResourceProvider class="com.fr.plugin.decision.integration.resource.WebStartWebResourceImpl"/>
</extra-decision>
</plugin>

23
src/main/java/com/fr/plugin/decision/integration/ControllerBridgeImpl.java

@ -0,0 +1,23 @@
package com.fr.plugin.decision.integration;
import com.fr.decision.fun.impl.AbstractControllerRegisterProvider;
import com.fr.plugin.context.PluginContexts;
import com.fr.plugin.decision.integration.controller.IntegratedController;
import com.fr.plugin.decision.integration.service.IntegrateAuthService;
import com.fr.plugin.transform.ExecuteFunctionRecord;
import com.fr.plugin.transform.FunctionRecorder;
import com.fr.stable.fun.Authorize;
@Authorize(callSignKey = "com.fr.plugin.decision.integration")
@FunctionRecorder
public class ControllerBridgeImpl extends AbstractControllerRegisterProvider {
@ExecuteFunctionRecord
@Override
public Class<?>[] getControllers() {
if (PluginContexts.currentContext().isAvailable()) {
return new Class[]{IntegratedController.class};
} else {
return new Class[0];
}
}
}

24
src/main/java/com/fr/plugin/decision/integration/LifecycleMonitorImpl.java

@ -0,0 +1,24 @@
package com.fr.plugin.decision.integration;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.decision.integration.config.IntegrateConf;
import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor;
/**
* @Author JianYe.Wang
* @Data 2022/2/22 15:54
* @Description TODO
* @Version 10.0
**/
public class LifecycleMonitorImpl extends AbstractPluginLifecycleMonitor {
@Override
public void afterRun(PluginContext pluginContext) {
IntegrateConf.getInstance();
}
@Override
public void beforeStop(PluginContext pluginContext) {
}
}

54
src/main/java/com/fr/plugin/decision/integration/bean/TplInfoBean.java

@ -0,0 +1,54 @@
package com.fr.plugin.decision.integration.bean;
import com.fr.decision.webservice.bean.BaseBean;
@Deprecated
public class TplInfoBean extends BaseBean {
private String menuId;
private String title;
private String url;
private String pmenuId;
public TplInfoBean() {
}
public TplInfoBean(String menuId, String title, String url, String pmenuId) {
this.menuId = menuId;
this.title = title;
this.url = url;
this.pmenuId = pmenuId;
}
public String getMenuId() {
return menuId;
}
public void setMenuId(String menuId) {
this.menuId = menuId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPmenuId() {
return pmenuId;
}
public void setPmenuId(String pmenuId) {
this.pmenuId = pmenuId;
}
}

25
src/main/java/com/fr/plugin/decision/integration/bean/user/NamedBean.java

@ -0,0 +1,25 @@
package com.fr.plugin.decision.integration.bean.user;
import com.fr.decision.webservice.bean.BaseBean;
public class NamedBean extends BaseBean {
private String name;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}

45
src/main/java/com/fr/plugin/decision/integration/bean/user/UserInfoBean.java

@ -0,0 +1,45 @@
package com.fr.plugin.decision.integration.bean.user;
import com.fr.decision.webservice.bean.BaseBean;
import java.util.List;
public class UserInfoBean extends BaseBean {
private String username;
private NamedBean department;
private List<String> roles;
private List<Integer> platformType;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public NamedBean getDepartment() {
return department;
}
public void setDepartment(NamedBean department) {
this.department = department;
}
public List<String> getRoles() {
return roles;
}
public void setRoles(List<String> roles) {
this.roles = roles;
}
public List<Integer> getPlatformType() {
return platformType;
}
public void setPlatformType(List<Integer> platformType) {
this.platformType = platformType;
}
}

273
src/main/java/com/fr/plugin/decision/integration/config/IntegrateConf.java

@ -0,0 +1,273 @@
package com.fr.plugin.decision.integration.config;
import com.fr.cert.token.Jwts;
import com.fr.cert.token.SignatureAlgorithm;
import com.fr.config.ConfigContext;
import com.fr.config.DefaultConfiguration;
import com.fr.config.Identifier;
import com.fr.config.holder.Conf;
import com.fr.config.holder.factory.Holders;
import com.fr.config.utils.ValueReader;
import com.fr.config.utils.ValueWriter;
import com.fr.decision.base.util.UUIDUtil;
import com.fr.json.JSONObject;
import com.fr.plugin.decision.integration.config.strategy.CreateDepartmentStrategy;
import com.fr.plugin.decision.integration.config.strategy.CreatePwdStrategy;
import com.fr.plugin.decision.integration.config.strategy.user.impl.ContainDepRoleStrategy;
import com.fr.plugin.decision.integration.config.strategy.user.impl.OnlyUserStrategy;
import com.fr.plugin.decision.integration.config.strategy.user.CreateUserStrategy;
import com.fr.plugin.decision.integration.utils.AESUtils;
import com.fr.plugin.decision.integration.utils.Constants;
import com.fr.stable.StringUtils;
import com.fr.third.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
@JsonIgnoreProperties({"id", "data", "classInfo", "nameSpace"})
public class IntegrateConf extends DefaultConfiguration {
private static volatile IntegrateConf configuration = null;
public static IntegrateConf getInstance() {
if (null == configuration) {
configuration = ConfigContext.getConfigInstance(IntegrateConf.class);
}
return configuration;
}
@Identifier("jwtKey")
private Conf<String> jwtKey = Holders.simple(UUIDUtil.generate());
@Identifier("createUserTurnOn")
private Conf<Boolean> createUserTurnOn = Holders.simple(false);
@Identifier("userStrategy")
private Conf<CreateUserStrategy> userStrategy = Holders.obj(new OnlyUserStrategy(), CreateUserStrategy.class);
@Identifier("paraCheckTurnOn")
private Conf<Boolean> paraCheckTurnOn = Holders.simple(false);
@Identifier("paraCheckUrl")
private Conf<String> paraCheckUrl = Holders.simple(StringUtils.EMPTY);
@Identifier("remoteTokenAuth")
private Conf<Boolean> remoteTokenAuth = Holders.simple(true);
@Identifier("aesEncryptSubject")
private Conf<Boolean> aesEncryptSubject = Holders.simple(false);
@Identifier("aesEncryptKey")
private Conf<String> aesEncryptKey = Holders.simple(StringUtils.EMPTY);
@Identifier("portalURLTurnOn")
private Conf<Boolean> portalURLTurnOn = Holders.simple(false);
@Identifier("portalURL")
private Conf<String> portalURL = Holders.simple(StringUtils.EMPTY);
@Identifier("crossDomain")
private Conf<Boolean> crossDomain = Holders.simple(false);
@Identifier("webStartDesigner")
private Conf<Boolean> webStartDesigner = Holders.simple(false);
@Identifier("downloadUrl32")
private Conf<String> downloadUrl32 = Holders.simple("");
@Identifier("downloadUrl64")
private Conf<String> downloadUrl64 = Holders.simple("");
@Identifier("decisionUrl")
private Conf<String> decisionUrl = Holders.simple(StringUtils.EMPTY);
@Identifier("remoteFolder")
private Conf<Boolean> remoteFolder = Holders.simple(false);
public String getJwtKey() {
return jwtKey.get();
}
public void setJwtKey(String jwtKey) {
this.jwtKey.set(jwtKey);
}
public Boolean getCreateUserTurnOn() {
return createUserTurnOn.get();
}
public void setCreateUserTurnOn(Boolean createUserTurnOn) {
this.createUserTurnOn.set(createUserTurnOn);
}
public CreateUserStrategy getUserStrategy() {
return userStrategy.get();
}
public void setUserStrategy(CreateUserStrategy userStrategy) {
this.userStrategy.set(userStrategy);
}
public Boolean getParaCheckTurnOn() {
return paraCheckTurnOn.get();
}
public void setParaCheckTurnOn(Boolean paraCheckTurnOn) {
this.paraCheckTurnOn.set(paraCheckTurnOn);
}
public String getParaCheckUrl() {
return paraCheckUrl.get();
}
public void setParaCheckUrl(String paraCheckUrl) {
this.paraCheckUrl.set(paraCheckUrl);
}
public Boolean getRemoteTokenAuth() {
return remoteTokenAuth.get();
}
public void setRemoteTokenAuth(Boolean remoteTokenAuth) {
this.remoteTokenAuth.set(remoteTokenAuth);
}
public Boolean getAesEncryptSubject() {
return aesEncryptSubject.get();
}
public void setAesEncryptSubject(Boolean aesEncryptSubject) {
this.aesEncryptSubject.set(aesEncryptSubject);
}
public String getAesEncryptKey() {
return aesEncryptKey.get();
}
public void setAesEncryptKey(String aesEncryptKey) {
this.aesEncryptKey.set(aesEncryptKey);
}
public Boolean getPortalURLTurnOn() {
return portalURLTurnOn.get();
}
public void setPortalURLTurnOn(Boolean portalURLTurnOn) {
this.portalURLTurnOn.set(portalURLTurnOn);
}
public String getPortalURL() {
return portalURL.get();
}
public void setPortalURL(String portalURL) {
this.portalURL.set(portalURL);
}
public Boolean getCrossDomain() {
return crossDomain.get();
}
public void setCrossDomain(Boolean crossDomain) {
this.crossDomain.set(crossDomain);
}
public Boolean getWebStartDesigner() {
return webStartDesigner.get();
}
public void setWebStartDesigner(Boolean webStartDesigner) {
this.webStartDesigner.set(webStartDesigner);
}
public String getDownloadUrl32() {
return downloadUrl32.get();
}
public void setDownloadUrl32(String downloadUrl32) {
this.downloadUrl32.set(downloadUrl32);
}
public String getDownloadUrl64() {
return downloadUrl64.get();
}
public void setDownloadUrl64(String downloadUrl64) {
this.downloadUrl64.set(downloadUrl64);
}
public String getDecisionUrl() {
return decisionUrl.get();
}
public void setDecisionUrl(String decisionUrl) {
this.decisionUrl.set(decisionUrl);
}
public Boolean getRemoteFolder() {
return remoteFolder.get();
}
public void setRemoteFolder(Boolean remoteFolder) {
this.remoteFolder.set(remoteFolder);
}
@Override
protected void initialize() {
ValueWriter.registerWriter(CreateDepartmentStrategy.class, new ValueWriter<CreateDepartmentStrategy>() {
@Override
public String writeObject(CreateDepartmentStrategy createDepEnum) {
return String.valueOf(createDepEnum.toInteger());
}
});
ValueReader.registerReader(CreateDepartmentStrategy.class, new ValueReader<CreateDepartmentStrategy>() {
public CreateDepartmentStrategy covert(String value) {
return CreateDepartmentStrategy.parse(Integer.parseInt(value));
}
});
ValueWriter.registerWriter(CreatePwdStrategy.class, new ValueWriter<CreatePwdStrategy>() {
@Override
public String writeObject(CreatePwdStrategy createDepEnum) {
return String.valueOf(createDepEnum.toInteger());
}
});
ValueReader.registerReader(CreatePwdStrategy.class, new ValueReader<CreatePwdStrategy>() {
public CreatePwdStrategy covert(String value) {
return CreatePwdStrategy.parse(Integer.parseInt(value));
}
});
}
public HashMap getWebStartedInfo(String username) throws Exception {
HashMap<String, String> info = new HashMap<>(3);
info.put("url", "fanruan://" + getDecisionUrl() + "?GWToken?" + getTokenByUserName(username));
info.put("download64", getDownloadUrl64());
info.put("download32", getDownloadUrl32());
return info;
}
public String getWebStartURL(String username, String path) throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("<script>window.open('")
.append("fanruan://").append(getDecisionUrl()).append("?GWToken?").append(getTokenByUserName(username))
.append(StringUtils.isEmpty(path)? "": ("?" + path))
.append("');(window.top==window)&&window.close();</script>");
return buffer.toString();
}
private String getTokenByUserName(String username) throws Exception {
String subject = username;
if (getUserStrategy() instanceof ContainDepRoleStrategy) {
subject = JSONObject.create().put("username", username).toString();
}
if (getAesEncryptSubject()) {
subject = Base64.getEncoder().encodeToString(AESUtils.aesEncryptToBytes(subject, getAesEncryptKey()));
}
Date date = new Date();
return Jwts.builder()
.setSubject(subject)
.setExpiration(new Date(date.getTime() + Constants.EXPIRED_TIME))
.signWith(SignatureAlgorithm.HS256, getJwtKey())
.compact();
}
}

50
src/main/java/com/fr/plugin/decision/integration/config/strategy/CreateDepartmentStrategy.java

@ -0,0 +1,50 @@
package com.fr.plugin.decision.integration.config.strategy;
import com.fr.general.ComparatorUtils;
import com.fr.third.fasterxml.jackson.annotation.JsonCreator;
import com.fr.third.fasterxml.jackson.annotation.JsonValue;
/**
* @Author JianYe.Wang
* @Data 10:14
* @Description TODO
* @Version 10.0
**/
/**
* "department": {
* "name": "beijing",
* "id": "02"
* }
*/
public enum CreateDepartmentStrategy {
/**
* 根据id长度 01 011 012
*/
DEP_ID_LENGTH(0),
/**
* 根据name拼接 中国|北京市|朝阳区
*/
DEP_NAME_GROUP(1);
private int type;
CreateDepartmentStrategy(int type) {
this.type = type;
}
@JsonValue
public int toInteger() {
return this.type;
}
@JsonCreator
public static CreateDepartmentStrategy parse(int value) {
for (CreateDepartmentStrategy type : CreateDepartmentStrategy.values()) {
if (ComparatorUtils.equals(value, type.toInteger())) {
return type;
}
}
return null;
}
}

37
src/main/java/com/fr/plugin/decision/integration/config/strategy/CreatePwdStrategy.java

@ -0,0 +1,37 @@
package com.fr.plugin.decision.integration.config.strategy;
import com.fr.general.ComparatorUtils;
import com.fr.third.fasterxml.jackson.annotation.JsonCreator;
import com.fr.third.fasterxml.jackson.annotation.JsonValue;
/**
* @Author JianYe.Wang
* @Data 21-06-07 10:07
* @Description TODO
* @Version 10.0
**/
public enum CreatePwdStrategy {
SAME_USER(0), RANDOM(1);
private int type;
CreatePwdStrategy(int type) {
this.type = type;
}
@JsonValue
public int toInteger() {
return this.type;
}
@JsonCreator
public static CreatePwdStrategy parse(int value) {
for (CreatePwdStrategy type : CreatePwdStrategy.values()) {
if (ComparatorUtils.equals(value, type.toInteger())) {
return type;
}
}
return null;
}
}

38
src/main/java/com/fr/plugin/decision/integration/config/strategy/user/CreateUserStrategy.java

@ -0,0 +1,38 @@
package com.fr.plugin.decision.integration.config.strategy.user;
import com.fr.config.Identifier;
import com.fr.config.holder.Conf;
import com.fr.config.holder.factory.Holders;
import com.fr.config.utils.UniqueKey;
import com.fr.plugin.decision.integration.config.strategy.CreatePwdStrategy;
import com.fr.plugin.decision.integration.config.strategy.user.impl.ContainDepRoleStrategy;
import com.fr.plugin.decision.integration.config.strategy.user.impl.OnlyUserStrategy;
import com.fr.third.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fr.third.fasterxml.jackson.annotation.JsonSubTypes;
import com.fr.third.fasterxml.jackson.annotation.JsonTypeInfo;
/**
* @Author JianYe.Wang
* @Data 21-6-7 10:01
* @Description TODO
* @Version 10.0
**/
@JsonIgnoreProperties({"id", "data", "classInfo", "nameSpace"})
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "userType")
@JsonSubTypes({
@JsonSubTypes.Type(value = OnlyUserStrategy.class, name = "onlyUser"),
@JsonSubTypes.Type(value = ContainDepRoleStrategy.class, name = "containDepRole")
})
public abstract class CreateUserStrategy extends UniqueKey {
@Identifier("pwdStrategy")
private Conf<CreatePwdStrategy> pwdStrategy = Holders.simple(CreatePwdStrategy.SAME_USER);
public CreatePwdStrategy getPwdStrategy() {
return pwdStrategy.get();
}
public void setPwdStrategy(CreatePwdStrategy pwdStrategy) {
this.pwdStrategy.set(pwdStrategy);
}
}

53
src/main/java/com/fr/plugin/decision/integration/config/strategy/user/impl/ContainDepRoleStrategy.java

@ -0,0 +1,53 @@
package com.fr.plugin.decision.integration.config.strategy.user.impl;
import com.fr.config.Identifier;
import com.fr.config.holder.Conf;
import com.fr.config.holder.factory.Holders;
import com.fr.plugin.decision.integration.config.strategy.CreateDepartmentStrategy;
import com.fr.plugin.decision.integration.config.strategy.user.CreateUserStrategy;
import com.fr.stable.StringUtils;
import com.fr.third.fasterxml.jackson.annotation.JsonTypeName;
/**
* @Author JianYe.Wang
* @Data 10:13
* @Description TODO
* @Version 10.0
**/
@JsonTypeName("containDepRole")
public class ContainDepRoleStrategy extends CreateUserStrategy {
@Identifier("depStrategy")
private Conf<CreateDepartmentStrategy> depStrategy = Holders.simple(CreateDepartmentStrategy.DEP_ID_LENGTH);
@Identifier("specialRootId")
private Conf<String> specialRootId = Holders.simple(StringUtils.EMPTY);
// 分隔符, CreateDepEnum.DEP_NAME_GROUP 会用到
@Identifier("separator")
private Conf<String> separator = Holders.simple(StringUtils.EMPTY);
public CreateDepartmentStrategy getDepStrategy() {
return depStrategy.get();
}
public void setDepStrategy(CreateDepartmentStrategy depStrategy) {
this.depStrategy.set(depStrategy);
}
public String getSpecialRootId() {
return specialRootId.get();
}
public void setSpecialRootId(String specialRootId) {
this.specialRootId.set(specialRootId);
}
public String getSeparator() {
return separator.get();
}
public void setSeparator(String separator) {
this.separator.set(separator);
}
}

15
src/main/java/com/fr/plugin/decision/integration/config/strategy/user/impl/OnlyUserStrategy.java

@ -0,0 +1,15 @@
package com.fr.plugin.decision.integration.config.strategy.user.impl;
import com.fr.plugin.decision.integration.config.strategy.user.CreateUserStrategy;
import com.fr.third.fasterxml.jackson.annotation.JsonTypeName;
/**
* @Author JianYe.Wang
* @Data 21-6-7 10:12
* @Description TODO
* @Version 10.0
**/
@JsonTypeName("onlyUser")
public class OnlyUserStrategy extends CreateUserStrategy {
}

224
src/main/java/com/fr/plugin/decision/integration/controller/IntegratedController.java

@ -0,0 +1,224 @@
package com.fr.plugin.decision.integration.controller;
import com.fr.base.ServerConfig;
import com.fr.decision.authority.data.User;
import com.fr.decision.webservice.CrossDomainResponse;
import com.fr.decision.webservice.Response;
import com.fr.decision.webservice.annotation.LoginStatusChecker;
import com.fr.decision.webservice.v10.login.LoginService;
import com.fr.decision.webservice.v10.login.TokenResource;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.io.utils.ResourceIOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.decision.integration.config.IntegrateConf;
import com.fr.plugin.decision.integration.service.IntegrateAuthService;
import com.fr.plugin.decision.integration.service.IntegrateCustomService;
import com.fr.plugin.decision.integration.utils.CommonUtils;
import com.fr.plugin.decision.integration.utils.Constants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.third.fasterxml.jackson.databind.ObjectMapper;
import com.fr.third.springframework.stereotype.Controller;
import com.fr.third.springframework.web.bind.annotation.*;
import com.fr.web.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
@Controller
@RequestMapping({"/third/auth"})
@LoginStatusChecker(required = false)
public class IntegratedController {
private ObjectMapper mapper = new ObjectMapper();
/**
* 建议用于后台换取 fine_auth_token
* @param request
* @param response
* @param body 请求体
* @param third_token 请求参数
* @return fine_auth_token
* @throws Exception
*/
@RequestMapping("/login")
@ResponseBody
public Response loginByToken(HttpServletRequest request, HttpServletResponse response, @RequestBody(required = false) Map body, @RequestParam(required = false, value = Constants.TOKEN_NAME) String third_token) throws Exception {
String token = third_token;
if (StringUtils.isBlank(third_token)) {
token = (String) body.get(Constants.TOKEN_NAME);
}
String username = IntegrateAuthService.getInstance().getUserNameFromToken(token);
return Response.ok(LoginService.getInstance().login(request, response, username));
}
/**
* 用于前台跨域请求
* @param request
* @param response
* @param third_token
* @param callback
* @return
* @throws Exception
*/
@RequestMapping(
value = {"/cross/login"},
method = {RequestMethod.GET},
produces = "application/javascript; charset=utf-8"
)
@ResponseBody
public String crossLoginByToken(HttpServletRequest request,
HttpServletResponse response,
@RequestParam(Constants.TOKEN_NAME) String third_token,
@RequestParam(value = "callback", required = false, defaultValue = "callback") String callback
) throws Exception {
String username = IntegrateAuthService.getInstance().getUserNameFromToken(third_token);
return CrossDomainResponse.create().callbackFuncName(callback)
.parameter("accessToken", LoginService.getInstance().login(request, response, username))
.parameter("url", IntegrateCustomService.getInstance().generateDefaultHomePageUrl(request))
.parameter("status", "success")
.createCrossDomainResponse();
}
/**
* URL设计器启动需要用的接口
*/
/**
* 解析获取 token 对应的用户名
* @param third_token
* @return
*/
@RequestMapping(
value = {"/username"}
)
@ResponseBody
public String getUsernameFromToken(@RequestParam(Constants.TOKEN_NAME) String third_token) throws Exception {
return IntegrateAuthService.getInstance().getUserNameFromToken(third_token);
}
/**
* 获取用户对应的token用于web唤醒设计器传入token
*/
@RequestMapping(
value = {"/username/token"}
)
@ResponseBody
@LoginStatusChecker
public Response getThirdTokenByUsername(HttpServletRequest request) throws Exception {
String username = LoginService.getInstance().getCurrentUserNameFromRequest(request);
return Response.ok(IntegrateConf.getInstance().getWebStartedInfo(username));
}
/**
* 登录状态下
*/
@RequestMapping(
value = {"/designer/start"}
)
@ResponseBody
//@LoginStatusChecker(tokenResource = TokenResource.COOKIE)
public String openDesignerStartUrl(HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value = "path", required = false) String path) throws Exception {
String username = LoginService.getInstance().getCurrentUserNameFromRequestCookie(request);
if (StringUtils.isEmpty(username)) return StringUtils.EMPTY;
response.setContentType("text/html; charset=GB2312");
return IntegrateConf.getInstance().getWebStartURL(username, path);
}
/**
* 插件配置读取保存
*/
@RequestMapping(
value = {"/conf"},
method = RequestMethod.GET
)
@ResponseBody
@LoginStatusChecker
public Response getIntegrateConfig(HttpServletRequest request, HttpServletResponse response) throws Exception {
String userId = UserService.getInstance().getCurrentUserIdFromCookie(request);
if (UserService.getInstance().isAdmin(userId)) {
response.setContentType("application/json;charset=" + ServerConfig.getInstance().getServerCharset());
mapper.writeValue(response.getOutputStream(), IntegrateConf.getInstance());
}
return Response.error("getIntegrateConf", "仅管理员用户可见");
}
@RequestMapping(
value = {"/conf"},
method = RequestMethod.POST
)
@ResponseBody
@LoginStatusChecker
public Response updateIntegrateConfig(HttpServletRequest request) throws IOException {
IntegrateConf conf = mapper.readValue(request.getInputStream(), IntegrateConf.class);
IntegrateAuthService.getInstance().updateIntegrateConf(conf);
return Response.success();
}
/**
* 插件历史接口做兼容使用
*/
@RequestMapping(
value = {"/tpl/paste"}
)
@ResponseBody
@Deprecated
public Response pasteTemplate(@RequestParam(Constants.TOKEN_NAME) String third_token, @RequestParam("tplPath") String tplPath) throws Exception {
String username = IntegrateAuthService.getInstance().getUserNameFromToken(third_token);
if (StringUtils.isBlank(username))
return Response.error("pasteTemplate", "TOKEN解析异常");
if (StringUtils.isBlank(tplPath) || !ResourceIOUtils.exist(StableUtils.pathJoin("reportlets", tplPath)))
return Response.error("pasteTemplate", "模板文件不存在");
ResourceIOUtils.copy(
StableUtils.pathJoin("reportlets", tplPath),
StableUtils.pathJoin("reportlets", username, tplPath.substring(tplPath.lastIndexOf("/")))
);
return Response.success();
}
@RequestMapping(
value = {"/tpl/remote/list"}
)
@ResponseBody
@Deprecated
public Response getUserRemoteTplList(HttpServletRequest request, @RequestParam(Constants.TOKEN_NAME) String third_token) throws Exception {
String username = IntegrateAuthService.getInstance().getUserNameFromToken(third_token);
if (StringUtils.isBlank(username))
return Response.error("UserRemoteTplList", "TOKEN解析异常");
User user = UserService.getInstance().getUserByUserName(username);
return Response.ok(IntegrateCustomService.getInstance().getRemoteTplListByUserId(user.getId(), WebUtils.createServletURL(request)));
}
/**
* token 换取帆软token主要用于后台请求
*/
@RequestMapping({"/token"})
@ResponseBody
@Deprecated
public String tokenExchangeFineAuthToken(HttpServletRequest request, HttpServletResponse response, @RequestBody Map body) throws Exception {
String username = IntegrateAuthService.getInstance().getUserNameFromToken((String) body.get(Constants.TOKEN_NAME));
return LoginService.getInstance().login(request, response, username);
}
/**
* 处理下异常返回值统一格式返回
* @param ex
* @return
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public Response exceptionRespond(Exception ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
return CommonUtils.formatException(ex);
}
}

7
src/main/java/com/fr/plugin/decision/integration/exception/JwtKeyNullException.java

@ -0,0 +1,7 @@
package com.fr.plugin.decision.integration.exception;
public class JwtKeyNullException extends ThirdAuthException {
public JwtKeyNullException() {
super("The value of jwt key is null!");
}
}

14
src/main/java/com/fr/plugin/decision/integration/exception/JwtSubjectFormatException.java

@ -0,0 +1,14 @@
package com.fr.plugin.decision.integration.exception;
/**
* @Author JianYe.Wang
* @Data 2021/7/7 14:22
* @Description TODO
* @Version 10.0
**/
public class JwtSubjectFormatException extends ThirdAuthException {
public JwtSubjectFormatException() {
super("Jwt key subject format error!");
}
}

14
src/main/java/com/fr/plugin/decision/integration/exception/ThirdAuthException.java

@ -0,0 +1,14 @@
package com.fr.plugin.decision.integration.exception;
public class ThirdAuthException extends RuntimeException {
public static final String KEY = "FR decision integration exception: ";
public ThirdAuthException(String message) {
super(KEY + message);
}
public ThirdAuthException(String message, Throwable cause) {
super(KEY + message, cause);
}
}

7
src/main/java/com/fr/plugin/decision/integration/exception/TokenDecodeExpiredException.java

@ -0,0 +1,7 @@
package com.fr.plugin.decision.integration.exception;
public class TokenDecodeExpiredException extends ThirdAuthException {
public TokenDecodeExpiredException() {
super("Jwt token decode result is expired!");
}
}

14
src/main/java/com/fr/plugin/decision/integration/exception/TokenNullException.java

@ -0,0 +1,14 @@
package com.fr.plugin.decision.integration.exception;
/**
* @Author JianYe.Wang
* @Data 2021/11/1 9:41
* @Description TODO
* @Version 10.0
**/
public class TokenNullException extends ThirdAuthException {
public TokenNullException() {
super("Jwt token is null!");
}
}

57
src/main/java/com/fr/plugin/decision/integration/filter/RemoteFilter.java

@ -0,0 +1,57 @@
package com.fr.plugin.decision.integration.filter;
import com.fr.data.NetworkHelper;
import com.fr.decision.fun.impl.AbstractEmbedRequestFilterProvider;
import com.fr.decision.webservice.Response;
import com.fr.decision.webservice.v10.remote.RemoteDesignStatusService;
import com.fr.plugin.decision.integration.config.IntegrateConf;
import com.fr.plugin.decision.integration.service.IntegrateAuthService;
import com.fr.plugin.decision.integration.utils.LogUtils;
import com.fr.security.JwtUtils;
import com.fr.security.SecurityToolbox;
import com.fr.security.encryption.transmission.TransmissionEncryptors;
import com.fr.stable.StringUtils;
import com.fr.third.fasterxml.jackson.databind.ObjectMapper;
import com.fr.web.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 拦截设计器远程请求, 支持Token认证
*/
public class RemoteFilter extends AbstractEmbedRequestFilterProvider {
private static final String PATH_TOKEN = "/remote/design/token";
private static final String PATH_VERIFY = "/remote/design/verify";
@Override
public void filter(HttpServletRequest request, HttpServletResponse response) {
if (!IntegrateConf.getInstance().getRemoteTokenAuth()) return;
String username = NetworkHelper.getHTTPRequestParameter(request, "username");
String password;
if (request.getRequestURI().endsWith(PATH_TOKEN)) {
if (StringUtils.equalsIgnoreCase("get", request.getMethod())) {
password = NetworkHelper.getHTTPRequestParameter(request, "password");
} else {
password = SecurityToolbox.defaultDecrypt(NetworkHelper.getHTTPRequestParameter(request, "password"));
}
} else if (request.getRequestURI().endsWith(PATH_VERIFY)) {
password = TransmissionEncryptors.getInstance().decrypt(NetworkHelper.getHTTPRequestParameter(request, "password"));
} else {
return;
}
LogUtils.info("RemoteFilter token auth success: {}", username);
ObjectMapper mapper = new ObjectMapper();
try {
if (StringUtils.isNotBlank(IntegrateAuthService.getInstance().getUserNameFromToken(password))) {
String token = JwtUtils.createDefaultJWT(username);
RemoteDesignStatusService.loginStatusService().put(token, username, 1209600000);
WebUtils.printAsString(response, mapper.writeValueAsString(Response.ok(token)));
}
} catch (Exception e) {
LogUtils.error(e.getMessage(), e);
}
}
}

78
src/main/java/com/fr/plugin/decision/integration/filter/RequestSsoFilter.java

@ -0,0 +1,78 @@
package com.fr.plugin.decision.integration.filter;
import com.fr.decision.fun.impl.AbstractEmbedRequestFilterProvider;
import com.fr.decision.webservice.v10.login.LoginService;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.decision.integration.config.IntegrateConf;
import com.fr.plugin.decision.integration.service.IntegrateAuthService;
import com.fr.plugin.decision.integration.utils.CommonUtils;
import com.fr.stable.StringUtils;
import com.fr.web.utils.WebUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import static org.apache.catalina.filters.CorsFilter.*;
/**
* @Author JianYe.Wang
* @Data 2021/10/15 14:44
* @Description TODO
* @Version 10.0
**/
public class RequestSsoFilter extends AbstractEmbedRequestFilterProvider {
@Override
public void filter(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
// url 携带 token 单点
String token = WebUtils.getHTTPRequestParameter(request, "third_token");
if (StringUtils.isNotEmpty(token)) {
String userName = IntegrateAuthService.getInstance().getUserNameFromToken(token);
if (CommonUtils.isMobile(request) && !request.getRequestURI().endsWith("/third/auth/cross/login")) {
String frToken = doLoginFR(request, response, userName);
String originalURL = WebUtils.getOriginalURL(request).replaceAll("&?third_token=[^&]*", "");
response.sendRedirect(originalURL + "&fine_auth_token=" + frToken);
} else {
String curUserName = LoginService.getInstance().getCurrentUserNameFromRequestCookie(request);
if (!LoginService.getInstance().isLogged(request) || !StringUtils.equals(userName, curUserName)) {
doLoginFR(request, response, userName);
}
}
}
// 自定义登录页判断,/login 还保留
if (IntegrateConf.getInstance().getPortalURLTurnOn() && request.getRequestURI().endsWith(WebUtils.createServletURL(request)) && !LoginService.getInstance().isLogged(request)) {
response.sendRedirect(IntegrateConf.getInstance().getPortalURL());
return;
}
// 跨域判断
if (IntegrateConf.getInstance().getCrossDomain()) {
String origin = request.getHeader("Origin");
if (StringUtils.isNotEmpty(origin)) {
response.addHeader(RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, origin);
String headers = request.getHeader(REQUEST_HEADER_ACCESS_CONTROL_REQUEST_HEADERS);
if (StringUtils.isNotEmpty(headers))
response.addHeader(RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_HEADERS, headers);
response.addHeader(RESPONSE_HEADER_ACCESS_CONTROL_ALLOW_METHODS, "*");
response.addHeader(RESPONSE_HEADER_ACCESS_CONTROL_MAX_AGE, "3600");
}
/*if (request.getMethod().equals("OPTIONS")) {
response.setStatus(HttpServletResponse.SC_OK);
}*/
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private String doLoginFR(HttpServletRequest request, HttpServletResponse response, String username) throws Exception {
String frToken = LoginService.getInstance().login(request, response, username);
request.setAttribute("fine_auth_token", frToken);
return frToken;
}
}

62
src/main/java/com/fr/plugin/decision/integration/filter/TplParaCheckFilter.java

@ -0,0 +1,62 @@
package com.fr.plugin.decision.integration.filter;
import com.fr.decision.fun.impl.AbstractEmbedRequestFilterProvider;
import com.fr.decision.webservice.v10.login.LoginService;
import com.fr.general.http.HttpRequest;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONObject;
import com.fr.plugin.decision.integration.config.IntegrateConf;
import com.fr.plugin.decision.integration.utils.CommonUtils;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StringUtils;
import com.fr.third.fasterxml.jackson.databind.ObjectMapper;
import com.fr.third.org.apache.http.HttpEntity;
import com.fr.third.org.apache.http.entity.StringEntity;
import com.fr.web.utils.WebUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class TplParaCheckFilter extends AbstractEmbedRequestFilterProvider {
private String[] reportParameterNames = new String[]{"viewlet", "viewlets", "reportlet", "reportlets"};
@Override
public void filter(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (!needCheckParameter(request)) return;
HashMap<String, Object> requestMap = new HashMap<>();
for (String parameter : request.getParameterMap().keySet()) {
if (!ArrayUtils.contains(reportParameterNames, parameter))
requestMap.put(parameter, request.getParameter(parameter));
}
requestMap.put("userId", LoginService.getInstance().getCurrentUserNameFromRequestCookie(request));
try {
if (doCheckTplParameter(requestMap)) return;
} catch (Exception e) {
}
CommonUtils.showErrorPage(response, "请登录系统访问报表", "");
}
/**
* 请求是否需要校验预览参数
**/
private boolean needCheckParameter(HttpServletRequest request) {
return IntegrateConf.getInstance().getParaCheckTurnOn() &&
//LoginService.getInstance().isLogged(request) &&
StringUtils.isNotBlank(WebUtils.getReportTitleFromRequest(request));
}
private boolean doCheckTplParameter(Map requestMap) throws IOException {
HashMap headerMap = new HashMap();
headerMap.put("Content-Type", "application/json");
HttpEntity entity = new StringEntity(new ObjectMapper().writeValueAsString(requestMap), "utf-8");
String result = HttpToolbox.executeAndParse(HttpRequest.custom().url(IntegrateConf.getInstance().getParaCheckUrl()).post(entity).headers(headerMap).build());
return new JSONObject(result).getBoolean("data");
}
}

27
src/main/java/com/fr/plugin/decision/integration/resource/PluginConfigWebResourceImpl.java

@ -0,0 +1,27 @@
package com.fr.plugin.decision.integration.resource;
import com.fr.decision.fun.impl.AbstractWebResourceProvider;
import com.fr.decision.web.MainComponent;
import com.fr.plugin.decision.integration.config.IntegrateConf;
import com.fr.web.struct.Atom;
import com.fr.web.struct.Component;
import com.fr.web.struct.Filter;
import com.fr.web.struct.category.ScriptPath;
public class PluginConfigWebResourceImpl extends AbstractWebResourceProvider {
@Override
public Atom attach() {
return MainComponent.KEY;
}
@Override
public Atom client() {
return new Component() {
@Override
public ScriptPath script() {
return ScriptPath.build("com/fr/plugin/decision/integration/web/js/plugin.js");
}
};
}
}

43
src/main/java/com/fr/plugin/decision/integration/resource/WebStartWebResourceImpl.java

@ -0,0 +1,43 @@
package com.fr.plugin.decision.integration.resource;
import com.fr.decision.fun.impl.AbstractWebResourceProvider;
import com.fr.decision.web.MainComponent;
import com.fr.plugin.decision.integration.config.IntegrateConf;
import com.fr.web.struct.Atom;
import com.fr.web.struct.Component;
import com.fr.web.struct.Filter;
import com.fr.web.struct.category.ScriptPath;
/**
* @Author JianYe.Wang
* @Data 2022/4/1 15:22
* @Description TODO
* @Version 10.0
**/
public class WebStartWebResourceImpl extends AbstractWebResourceProvider {
@Override
public Atom attach() {
return MainComponent.KEY;
}
@Override
public Atom client() {
return new Component() {
@Override
public ScriptPath script() {
return ScriptPath.build("com/fr/plugin/decision/integration/web/js/web_start.js");
}
@Override
public Filter filter() {
return new Filter() {
@Override
public boolean accept() {
return IntegrateConf.getInstance().getWebStartDesigner();
}
};
}
};
}
}

254
src/main/java/com/fr/plugin/decision/integration/service/IntegrateAuthService.java

@ -0,0 +1,254 @@
package com.fr.plugin.decision.integration.service;
import com.fr.cert.token.Claims;
import com.fr.decision.base.util.UUIDUtil;
import com.fr.decision.privilege.TransmissionTool;
import com.fr.decision.webservice.bean.user.UserBean;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.io.utils.ResourceIOUtils;
import com.fr.plugin.decision.integration.config.strategy.CreatePwdStrategy;
import com.fr.plugin.decision.integration.bean.user.UserInfoBean;
import com.fr.plugin.decision.integration.config.IntegrateConf;
import com.fr.plugin.decision.integration.config.strategy.user.impl.OnlyUserStrategy;
import com.fr.plugin.decision.integration.exception.JwtKeyNullException;
import com.fr.plugin.decision.integration.exception.JwtSubjectFormatException;
import com.fr.plugin.decision.integration.exception.TokenDecodeExpiredException;
import com.fr.plugin.decision.integration.exception.TokenNullException;
import com.fr.plugin.decision.integration.utils.*;
import com.fr.report.ReportContext;
import com.fr.report.constant.RoleType;
import com.fr.report.data.RemoteDesignAuthority;
import com.fr.report.util.RemoteDesignAuthHelper;
import com.fr.report.util.RemoteUserInfo;
import com.fr.security.JwtUtils;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.third.fasterxml.jackson.databind.ObjectMapper;
import com.fr.transaction.Configurations;
import com.fr.transaction.WorkerAdaptor;
import com.fr.web.service.RemoteDesignAuthorityDataService;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
public class IntegrateAuthService {
private volatile static IntegrateAuthService service;
private static Properties properties = new Properties();
private IntegrateConf config = IntegrateConf.getInstance();
private ObjectMapper mapper = new ObjectMapper();
private IntegrateAuthService() {
}
public static IntegrateAuthService getInstance() {
if (service == null) {
synchronized (IntegrateAuthService.class) {
if (service == null) {
service = new IntegrateAuthService();
}
}
}
return service;
}
public String getUserNameFromToken(String thirdToken) throws Exception {
if (StringUtils.isEmpty(thirdToken)) {
throw new TokenNullException();
}
String userInfo = decodeJwtToken(thirdToken, loadJwtKey());
if (config.getAesEncryptSubject()) {
userInfo = AESUtils.aesDecryptByBytes(Base64.getDecoder().decode(userInfo), config.getAesEncryptKey());
}
return addOrUpdateUserInfo(userInfo);
}
private String loadJwtKey() {
String key = config.getJwtKey();
if (StringUtils.isBlank(key)) {
key = properties.getProperty("key");
}
if (StringUtils.isBlank(key)) {
throw new JwtKeyNullException();
}
return key;
}
private String decodeJwtToken(String thirdToken, String key) {
Claims claims = JwtUtils.parseJWT(thirdToken, key);
Date date = claims.getExpiration();
if (date != null && date.after(new Date())) {
return claims.getSubject();
}
throw new TokenDecodeExpiredException();
}
/**
* 校验更新/创建用户信息
*
* @param userInfoStr
* @return username
* @throws Exception
*/
private String addOrUpdateUserInfo(String userInfoStr) throws Exception {
// 未开启创建用户时,直接返回用户名不需要创建用户信息
if (!config.getCreateUserTurnOn()) {
if (CommonUtils.isJsonFormatStr(userInfoStr)) {
return mapper.readValue(userInfoStr, UserInfoBean.class).getUsername();
};
return userInfoStr;
}
// 仅用户名
if (config.getUserStrategy() instanceof OnlyUserStrategy) {
if (CommonUtils.isJsonFormatStr(userInfoStr)) {
throw new JwtSubjectFormatException();
}
// 用户不存在时基于用户名创建下用户
if (!UserUtils.existUsername(userInfoStr)) {
UserService.getInstance().addUser(buildBaseUserBean(userInfoStr));
checkAndCreateRemoteDesignAuth(userInfoStr);
}
return userInfoStr;
}
// 含部门职位
UserInfoBean userInfo = mapper.readValue(userInfoStr, UserInfoBean.class);
// 管理员账号不进行处理
if (UserUtils.isAdmin(userInfo.getUsername())) {
return userInfo.getUsername();
}
UserBean userBean;
if (!UserUtils.existUsername(userInfo.getUsername())) {
UserService.getInstance().addUser(buildBaseUserBean(userInfo.getUsername()));
}
userBean = UserService.getInstance().getUserAccount(userInfo.getUsername());
// 更新部门信息
if (null != userInfo.getDepartment()) {
userBean.setDepartmentPostIds(UserUtils.updateDepTreeAndPost(
userInfo.getDepartment().getName(),
userInfo.getDepartment().getId())
);
UserUtils.updateUserDepartmentPost(UserUtils.getAdminUserId(), userBean);
}
// 更新角色信息
if (null != userInfo.getRoles()) {
ArrayList<String> roles = new ArrayList<>();
for (String roleName : userInfo.getRoles()) {
roles.add(UserUtils.checkAndAddRole(roleName));
}
userBean.setRoleIds(roles.toArray(new String[0]));
UserService.getInstance().updateUserRoles(UserUtils.getAdminUserId(), userBean);
}
// 用户平台类型
if (null != userInfo.getPlatformType()) {
UserUtils.updateUserPlatformType(userBean, userInfo.getPlatformType());
}
// 更新远程设计权限和目录信息
checkAndCreateRemoteDesignAuth(userInfo.getUsername());
return userInfo.getUsername();
}
private UserBean buildBaseUserBean(String username) {
UserBean userBean = new UserBean(UUIDUtil.generate(), username, username, true);
String pwd;
if (config.getUserStrategy().getPwdStrategy() == CreatePwdStrategy.SAME_USER) {
pwd = username;
} else {
pwd = UserUtils.getRandomPassword(8);
}
userBean.setPassword(TransmissionTool.defaultEncrypt(pwd));
return userBean;
}
/**
* 校验如果用户没有自己同名模板跟目录文件夹的远程设计权限则新建添加一下
*
* @param username
*/
private void checkAndCreateRemoteDesignAuth(String username) throws Exception {
if (!config.getRemoteFolder()) return;
RemoteUserInfo remoteUserInfo = RemoteDesignAuthHelper.getUserInfo(username);
if (remoteUserInfo == null) {
return;
}
String userRemoteFileName = formatUsername(username);
List<RemoteDesignAuthority> remoteDesignAuthorities = RemoteDesignAuthorityDataService.getInstance().getAuthorities(remoteUserInfo.getUserID());
for (RemoteDesignAuthority remoteDesignAuthority : remoteDesignAuthorities) {
if (remoteDesignAuthority.getPathType() && StringUtils.equals(userRemoteFileName, remoteDesignAuthority.getPath())) {
return;
}
}
String path = StableUtils.pathJoin("reportlets", userRemoteFileName);
if (!ResourceIOUtils.isDirectoryExist(path)) {
ResourceIOUtils.createDirectory(path);
}
RemoteDesignAuthority authority = new RemoteDesignAuthority();
authority.userName(username).userId(remoteUserInfo.getUserID()).path(userRemoteFileName).pathType(true).roleType(RoleType.USER);
ReportContext.getInstance().getRemoteDesignAuthorityController().add(authority);
}
private String formatUsername(String username) {
return username.replaceAll("[\\\\/:*?\"<>|]", StringUtils.EMPTY);
}
public void updateIntegrateConf(IntegrateConf conf) {
Configurations.update(new WorkerAdaptor(IntegrateConf.class) {
@Override
public void run() {
IntegrateConf instance = IntegrateConf.getInstance();
instance.setDecisionUrl(conf.getDecisionUrl());
instance.setJwtKey(conf.getJwtKey());
instance.setRemoteTokenAuth(conf.getRemoteTokenAuth());
instance.setAesEncryptSubject(conf.getAesEncryptSubject());
instance.setAesEncryptKey(conf.getAesEncryptKey());
instance.setPortalURLTurnOn(conf.getPortalURLTurnOn());
instance.setPortalURL(conf.getPortalURL());
instance.setCrossDomain(conf.getCrossDomain());
instance.setRemoteFolder(conf.getRemoteFolder());
if (conf.getCreateUserTurnOn()) {
instance.setUserStrategy(conf.getUserStrategy());
instance.setCreateUserTurnOn(true);
} else {
instance.setCreateUserTurnOn(false);
}
if (conf.getParaCheckTurnOn()) {
instance.setParaCheckUrl(conf.getParaCheckUrl());
instance.setParaCheckTurnOn(true);
} else {
instance.setParaCheckTurnOn(false);
}
if (conf.getWebStartDesigner()) {
instance.setDownloadUrl32(conf.getDownloadUrl32());
instance.setDownloadUrl64(conf.getDownloadUrl64());
instance.setWebStartDesigner(true);
} else {
instance.setWebStartDesigner(false);
}
}
});
}
static {
// 历史参数获取方式,兼容使用
InputStream inputStream = ResourceIOUtils.read("/resources/third_auth.properties");
if (null != inputStream) {
try {
properties.load(inputStream);
} catch (IOException ignore) {}
}
}
}

98
src/main/java/com/fr/plugin/decision/integration/service/IntegrateCustomService.java

@ -0,0 +1,98 @@
package com.fr.plugin.decision.integration.service;
import com.fr.base.FRContext;
import com.fr.base.TemplateUtils;
import com.fr.data.NetworkHelper;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.file.filetree.FileNode;
import com.fr.file.filetree.FileNodes;
import com.fr.json.JSONException;
import com.fr.plugin.decision.integration.bean.TplInfoBean;
import com.fr.report.DesignAuthority;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import com.fr.workspace.server.authority.AuthorityOperator;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
@Deprecated
public class IntegrateCustomService {
private static final String FRM_PATH = "/view/form?viewlet=";
private static final String CPT_PATH = "/view/report?viewlet=";
private volatile static IntegrateCustomService service = null;
public IntegrateCustomService() {
}
public static IntegrateCustomService getInstance() {
if (service == null) {
synchronized (IntegrateAuthService.class) {
if (service == null) {
service = new IntegrateCustomService();
}
}
}
return service;
}
public String generateDefaultHomePageUrl(HttpServletRequest request) throws Exception {
String originalURL = NetworkHelper.getOriginalURL(request);
String requestURI = request.getRequestURI();
return TemplateUtils.render(originalURL.replace(requestURI, "${fineServletURL}"));
}
public ArrayList getRemoteTplListByUserId(String userId, String servletName) {
Workspace workspace = WorkContext.getCurrent();
FileNodes root = FRContext.getFileNodes();
ArrayList fileNodes = new ArrayList();
fileNodes.add(getNodeItem("reportlets", "", true, servletName));
if (UserService.getInstance().isAdmin(userId)) {
getFileNode(fileNodes, root, "reportlets", servletName);
} else {
DesignAuthority auth = (workspace.get(AuthorityOperator.class)).getAuthorities(userId)[0];
for (DesignAuthority.Item item : auth.getItems()) {
String path = item.getPath();
boolean type = item.getType();
fileNodes.add(getNodeItem("reportlets/" + path, "reportlets", type, servletName));
if (type) {
getFileNode(fileNodes, root, "reportlets/" + path, servletName);
}
}
}
return fileNodes;
}
private void getFileNode(ArrayList nodeItem, FileNodes root, String path, String servletName) throws JSONException {
FileNode[] fNodes = root.list(path, false);
for (int i = 0; i < fNodes.length; i++) {
FileNode fileNode = fNodes[i];
String fileNodePath = fileNode.getEnvPath();
nodeItem.add(getNodeItem(fileNodePath, path, fileNode.isDirectory(), servletName));
if (fileNode.isDirectory()) {
getFileNode(nodeItem, root, fileNodePath, servletName);
}
}
}
private TplInfoBean getNodeItem(String path, String pId, boolean isDirectory, String servletName) {
boolean isCpt = false;
String menuId;
if (path.contains(".cpt")) {
isCpt = true;
menuId = path.replace(".cpt", "");
} else {
menuId = path.replace(".frm", "");
}
if (!isDirectory) {
menuId = new StringBuffer().append(menuId).append("_f").toString();
}
path = path.replace("reportlets/", "");
String nodeName = menuId.replaceAll(pId + "/", "");
return new TplInfoBean(menuId, nodeName, isDirectory ? "" : isCpt ? servletName + CPT_PATH + path : servletName + FRM_PATH + path, pId);
}
}

68
src/main/java/com/fr/plugin/decision/integration/utils/AESUtils.java

@ -0,0 +1,68 @@
package com.fr.plugin.decision.integration.utils;
import com.fr.base.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* @Author JianYe.Wang
* @Data 2021/8/16 15:06
* @Description TODO
* @Version 10.0
**/
public class AESUtils {
private static final String AES_ECB_PKCS_5_PADDING = "AES/ECB/PKCS5Padding";
private static final String HMAC_SHA_256 = "HmacSHA256";
/**
* AES加密
*
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的byte[]
*/
public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Cipher cipher = Cipher.getInstance(AES_ECB_PKCS_5_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));
return cipher.doFinal(content.getBytes("utf-8"));
}
/**
* AES解密
*
* @param encryptBytes 待解密的byte[]
* @param decryptKey 解密密钥
* @return 解密后的String
*/
public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Cipher cipher = Cipher.getInstance(AES_ECB_PKCS_5_PADDING);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
byte[] decryptBytes = cipher.doFinal(encryptBytes);
return new String(decryptBytes, "utf-8");
}
/**
* HmacSHA256 签名
*
* @param content
* @param signKey
* @return base64 encode
* @throws Exception
*/
public static String hmacSHA256Sign(String content, String signKey) throws Exception {
Mac sha256Hmac = Mac.getInstance(HMAC_SHA_256);
SecretKeySpec secret_key = new SecretKeySpec(signKey.getBytes(), HMAC_SHA_256);
sha256Hmac.init(secret_key);
return Base64.encode(sha256Hmac.doFinal(content.getBytes()));
}
}

90
src/main/java/com/fr/plugin/decision/integration/utils/CommonUtils.java

@ -0,0 +1,90 @@
package com.fr.plugin.decision.integration.utils;
import com.fr.data.NetworkHelper;
import com.fr.decision.webservice.Response;
import com.fr.decision.webservice.utils.WebServiceUtils;
import com.fr.intelligence.IntelligenceException;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.web.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
public class CommonUtils {
public static boolean isJsonFormatStr(String str) {
if (StringUtils.isNotBlank(str)) {
str = str.trim();
try {
new JSONObject(str);
return true;
} catch (Exception e) {
}
}
return false;
}
public static void showErrorPage(HttpServletResponse response, String result, String solution) {
try {
PrintWriter printWriter = WebUtils.createPrintWriter(response);
Map<String, Object> map = new HashMap<>();
map.put("result", result);
map.put("solution", solution);
String page = WebServiceUtils.parseWebPageResourceSafe("com/fr/web/controller/decision/entrance/resources/unavailable.html", map);
printWriter.write(page);
printWriter.flush();
printWriter.close();
} catch (Exception e) {
LogUtils.error(e.getLocalizedMessage(), e);
}
}
public static boolean isMobile(HttpServletRequest req) {
String[] mobileArray = {"iPhone", "iPad", "android", "windows phone", "xiaomi"};
String userAgent = req.getHeader("user-agent");
// if (userAgent != null && userAgent.toUpperCase().contains("MOBILE")) {
// 华为PAD的chrome浏览器userAgent中不包含mobile
if (userAgent != null) {
for (String mobile : mobileArray) {
if (userAgent.toLowerCase().contains(mobile.toLowerCase())) {
return true;
}
}
}
//pc端企业微信
//if (userAgent.contains("wxwork")) return true;
FineLoggerFactory.getLogger().debug("isMobile userAgent:{} is:{}", userAgent, NetworkHelper.getDevice(req).isMobile());
return NetworkHelper.getDevice(req).isMobile();
}
public static Response formatException(Exception ex) {
String msg = ex.getMessage();
if (StringUtils.isBlank(msg)) {
msg = getStackTraceInfo(ex);
}
if (ex instanceof IntelligenceException) {
return Response.error(((IntelligenceException) ex).errorCode(), msg);
}
return Response.error("", msg);
}
//从异常中获取具体的堆栈信息
private static String getStackTraceInfo(Exception ex) {
StackTraceElement[] stackElements = ex.getStackTrace();
StringBuilder stringBuilder = new StringBuilder("\r\n");
if (stackElements != null) {
for (StackTraceElement stackElement : stackElements) {
stringBuilder.append(stackElement.getMethodName()).append("\r\n");
}
return stringBuilder.toString();
}
return ex.toString();
}
}

18
src/main/java/com/fr/plugin/decision/integration/utils/Constants.java

@ -0,0 +1,18 @@
package com.fr.plugin.decision.integration.utils;
/**
* @Author JianYe.Wang
* @Data 2021/12/3 14:05
* @Description TODO
* @Version 10.0
**/
public class Constants {
public static final int HOLD = -1;
// third token名称
public static final String TOKEN_NAME = "third_token";
// token的默认超期时间
public static final long EXPIRED_TIME = 1000 * 60 * 10;
}

96
src/main/java/com/fr/plugin/decision/integration/utils/LogUtils.java

@ -0,0 +1,96 @@
package com.fr.plugin.decision.integration.utils;
import com.fr.log.FineLoggerFactory;
import com.fr.log.FineLoggerProvider;
import com.fr.plugin.context.PluginContexts;
import com.fr.stable.StringUtils;
public final class LogUtils {
private static String LOG_PREFIX = "[平台集成] ";
private static final String PLUGIN_VERSION;
private static final FineLoggerProvider LOGGER = FineLoggerFactory.getLogger();
static {
// 判断 null
String version = PluginContexts.currentContext().getMarker().getVersion();
if (StringUtils.isNotBlank(version)) {
PLUGIN_VERSION = "[v" + version + "] ";
} else {
PLUGIN_VERSION = "[unknown version] ";
}
LOG_PREFIX = LOG_PREFIX + PLUGIN_VERSION;
}
public static void setPrefix(String prefix) {
if (prefix != null) {
LOG_PREFIX = prefix;
}
}
public static boolean isDebugEnabled() {
return LOGGER.isDebugEnabled();
}
public static void debug(String s) {
if (isDebugEnabled()) {
LOGGER.debug(LOG_PREFIX + s);
}
}
public static void debug(String s, Object... objects) {
if (isDebugEnabled()) {
LOGGER.debug(LOG_PREFIX + s, objects);
}
}
public static void debug(String s, Throwable throwable) {
if (isDebugEnabled()) {
LOGGER.debug(LOG_PREFIX + s, throwable);
}
}
public static boolean isInfoEnabled() {
return LOGGER.isInfoEnabled();
}
public static void info(String s) {
LOGGER.info(LOG_PREFIX + s);
}
public static void info(String s, Object... objects) {
LOGGER.info(LOG_PREFIX + s, objects);
}
public static void warn(String s) {
LOGGER.warn(LOG_PREFIX + s);
}
public static void warn(String s, Object... objects) {
LOGGER.warn(LOG_PREFIX + s, objects);
}
public static void warn(String s, Throwable throwable) {
LOGGER.warn(LOG_PREFIX + s, throwable);
}
public static void warn(Throwable throwable, String s, Object... objects) {
LOGGER.warn(throwable, LOG_PREFIX + s, objects);
}
public static void error(String s) {
LOGGER.error(LOG_PREFIX + s);
}
public static void error(String s, Object... objects) {
LOGGER.error(LOG_PREFIX + s, objects);
}
public static void error(String s, Throwable throwable) {
LOGGER.error(LOG_PREFIX + s, throwable);
}
public static void error(Throwable throwable, String s, Object... objects) {
LOGGER.error(throwable, LOG_PREFIX + s, objects);
}
}

417
src/main/java/com/fr/plugin/decision/integration/utils/UserUtils.java

@ -0,0 +1,417 @@
package com.fr.plugin.decision.integration.utils;
import com.finebi.cbb.utils.StringEscapeUtils;
import com.fr.decision.authority.AuthorityContext;
import com.fr.decision.authority.base.constant.type.operation.ManualOperationType;
import com.fr.decision.authority.controller.UserController;
import com.fr.decision.authority.data.*;
import com.fr.decision.authority.data.extra.user.type.PlatformUserKey;
import com.fr.decision.authority.data.extra.user.type.UserProductTypeKey;
import com.fr.decision.authority.data.personnel.DepRole;
import com.fr.decision.authority.entity.CustomRoleEntity;
import com.fr.decision.base.util.CollectionUtil;
import com.fr.decision.base.util.UUIDUtil;
import com.fr.decision.webservice.annotation.RoleCheckerType;
import com.fr.decision.webservice.bean.user.DepartmentPostBean;
import com.fr.decision.webservice.bean.user.UserBean;
import com.fr.decision.webservice.bean.user.UserUpdateBean;
import com.fr.decision.webservice.exception.user.AddUserProductTypeException;
import com.fr.decision.webservice.impl.user.type.UserProductType;
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.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.plugin.decision.integration.config.IntegrateConf;
import com.fr.plugin.decision.integration.config.strategy.user.impl.ContainDepRoleStrategy;
import com.fr.stable.ArrayUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.db.data.BaseDataRecord;
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.*;
public class UserUtils {
public static final String POST_DEFAULT_NAME = "职员";
public static final String DEP_ROOT_NAME = null;
public static boolean existUsername(String username) throws Exception {
return UserService.getInstance().getUserByUserName(username) != null;
}
public static String getAdminUserId() throws Exception {
return UserService.getInstance().getAdminUserIdList().get(0);
}
public static boolean isAdmin(String username) throws Exception {
return UserService.getInstance().getAdminUserNameList().contains(username);
}
public static List<String> updateDepTreeAndPost(String depName, String depId) throws Exception {
ArrayList<String> result = new ArrayList<>();
ContainDepRoleStrategy depStrategy = (ContainDepRoleStrategy) IntegrateConf.getInstance().getUserStrategy();
switch (depStrategy.getDepStrategy()) {
case DEP_ID_LENGTH:
generateDepByIdLength(depName, depId);
break;
case DEP_NAME_GROUP:
depId = generateDepByName(depName, depStrategy.getSeparator());
break;
}
String postId = generateDefaultPosition(depId);
result.add(WebServiceUtils.createUniquePostId(depId, postId));
return result;
}
/**
* 添加部门前先计算出最匹配的父节点添加完之后在更新父节点下子节点的父信息
*
* @param depName
* @param depId
* @return
* @throws Exception
*/
private static String generateDepByIdLength(String depName, String depId) throws Exception {
Department department = AuthorityContext.getInstance().getDepartmentController().getById(depId);
if (department == null) {
String depPId = getMostSimilarDepId(depId);
if (checkDuplicatedDepartmentName(depPId, depName)) {
depName = depName + "_" + depId;
}
addDepartment(depName, depId, depPId);
// 更新depPId下子节点的父信息
generateUnderParentDepartment(depPId, depId);
}
return depId;
}
/**
* 根据部门名称拼接来更新部门
*
* @param depNameGroup
* @return 部门id
*/
private static String generateDepByName(String depNameGroup, String separator) throws Exception {
String[] depArr = depNameGroup.split(StringEscapeUtils.escapeRegexSpecialWord(separator));
String pId = DEP_ROOT_NAME;
for (String depName : depArr) {
Department department = getDepartmentByNameAndPid(depName, pId);
if (department != null) {
pId = department.getId();
} else {
String depId = UUIDUtil.generate();
addDepartment(depName, depId, pId);
pId = depId;
}
}
return pId;
}
private static boolean existDepId(String depId) throws Exception {
return AuthorityContext.getInstance().getDepartmentController().getById(depId) != null;
}
private static Department getDepartmentByNameAndPid(String depName, String pId) throws Exception {
return AuthorityContext.getInstance().getDepartmentController().findOne(
QueryFactory.create().addRestriction(RestrictionFactory.eq(Department.COLUMN_NAME, depName))
.addRestriction(RestrictionFactory.eq(Department.COLUMN_PARENT_ID, pId))
);
}
private static boolean 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);
return sameNameDep != null;
}
/**
* 添加部门
*
* @param depName
* @param depId
* @param depPId
* @throws Exception
*/
private static void addDepartment(String depName, String depId, String depPId) throws Exception {
Department record = (new Department()).id(depId).name(depName).parentId(depPId).creationType(ManualOperationType.KEY).lastOperationType(ManualOperationType.KEY).enable(true);
AuthorityContext.getInstance().getDepartmentController().add(record);
}
private static void generateUnderParentDepartment(String depPId, String depId) throws Exception {
for (DepartmentPostBean departmentPostBean : DepartmentService.getInstance().getDepartmentsUnderParentDepartment(getAdminUserId(), depPId)) {
if (ComparatorUtils.equals(depId, departmentPostBean.getId())) continue;
String mostSimilarDepId = getMostSimilarDepId(departmentPostBean.getId());
if (!ComparatorUtils.equals(mostSimilarDepId, depPId)) {
Department record = AuthorityContext.getInstance().getDepartmentController().getById(departmentPostBean.getId());
record.setParentId(mostSimilarDepId);
AuthorityContext.getInstance().getDepartmentController().update(record);
}
}
}
private static List<Department> getAllDepartment() throws Exception {
return AuthorityContext.getInstance().getDepartmentController().find(QueryFactory.create());
}
/**
* 校验部门下是否有默认 POST_DEFAULT_NAME 职位
*
* @param departmentId
* @return POST_DEFAULT_NAME 职位的 id
* @throws Exception
*/
private static String generateDefaultPosition(String departmentId) throws Exception {
String adminId = UserService.getInstance().getAdminUserIdList().get(0);
Post[] posts = ControllerFactory.getInstance().getPostController(adminId).getPositionsUnderParentDepartment(adminId, departmentId, null);
for (Post post : posts) {
if (ComparatorUtils.equals(post.getName(), POST_DEFAULT_NAME)) {
return post.getId();
}
}
String positionId = getDefaultPostId();
AuthorityContext.getInstance().getPostController().addPostToDepartment(positionId, departmentId);
return positionId;
}
/**
* 校验是否有 POST_DEFAULT_NAME 职位没有的话新建个
*
* @return POST_DEFAULT_NAME 职位的 id
* @throws Exception
*/
private static String getDefaultPostId() throws Exception {
String adminId = UserService.getInstance().getAdminUserIdList().get(0);
Post[] posts = ControllerFactory.getInstance().getPostController(adminId).getPositions(adminId, null);
for (Post post : posts) {
if (ComparatorUtils.equals(post.getName(), POST_DEFAULT_NAME)) {
return post.getId();
}
}
return PositionService.getInstance().addPosition(POST_DEFAULT_NAME).getId();
}
/**
* 计算出与 depId 最相似的父节点
*
* @param depId
* @return
* @throws Exception
*/
private static String getMostSimilarDepId(String depId) throws Exception {
int similarLevel = 0;
String mostSimilarDepId = DEP_ROOT_NAME;
String specialDepRootId = ((ContainDepRoleStrategy) IntegrateConf.getInstance().getUserStrategy()).getSpecialRootId();
if (StringUtils.isNotBlank(specialDepRootId)) {
if (ComparatorUtils.equals(depId, specialDepRootId)) {
return mostSimilarDepId;
} else if (existDepId(specialDepRootId)) {
mostSimilarDepId = specialDepRootId;
}
}
for (Department department : getAllDepartment()) {
String currentDepId = department.getId();
// 部门id长度大于当前id长度的直接跳过,因为部门的树结构时根据id其实是否一致判断的
if (currentDepId.length() > depId.length() || ComparatorUtils.equals(currentDepId, depId)) continue;
int currentLevel = getDepIdSimilarityDegree(currentDepId, depId);
if (currentLevel > similarLevel) {
similarLevel = currentLevel;
mostSimilarDepId = department.getId();
}
}
return mostSimilarDepId;
}
private static int getDepIdSimilarityDegree(String depId1, String depId2) {
String shortId, longId;
if (depId1.length() > depId2.length()) {
shortId = depId2;
longId = depId1;
} else {
shortId = depId1;
longId = depId2;
}
if (longId.startsWith(shortId)) {
return shortId.length();
}
return 0;
}
public static String checkAndAddRole(String roleName) throws Exception {
CustomRole customRole = AuthorityContext.getInstance().getCustomRoleController().findOne(
QueryFactory.create().addRestriction(
RestrictionFactory.eq(CustomRoleEntity.COLUMN_NAME, roleName))
);
if (null != customRole) return customRole.getId();
String roleId = UUIDUtil.generate();
addRole(roleName, roleId);
return roleId;
}
public static void addRole(String roleName, String roleId) throws Exception {
String adminId = UserService.getInstance().getAdminUserIdList().get(0);
CustomRole record = (new CustomRole()).id(roleId).name(roleName);
ControllerFactory.getInstance().getCustomRoleController(adminId).addCustomRole(adminId, record);
}
/**
* 更新用户的部门信息
*
* @param currentUserId
* @param userBean
* @throws Exception
*/
public static void updateUserDepartmentPost(String currentUserId, UserBean userBean) throws Exception {
if (userBean.getDepartmentPostIds() != null) {
List<DepRole> newDepRoleList = new LinkedList();
Iterator depRoleIt = userBean.getDepartmentPostIds().iterator();
while (depRoleIt.hasNext()) {
String depPostId = (String) depRoleIt.next();
DepRole depRole = WebServiceUtils.parseUniqueDepartmentPostId(depPostId);
newDepRoleList.add(AuthorityContext.getInstance().getDepartmentController().getDepRole(depRole.getDepartmentId(), depRole.getPostId()));
}
List<DepRole> oldDepRoleList = AuthorityContext.getInstance().getDepartmentController().findDepRoleByUser(userBean.getId());
Map<String, DepRole> newIdDepRoleMap = CollectionUtil.convertToMap(newDepRoleList, BaseDataRecord::getId);
Map<String, DepRole> oldIdDepRoleMap = CollectionUtil.convertToMap(oldDepRoleList, BaseDataRecord::getId);
List<String> newDepRoleIdList = new LinkedList(newIdDepRoleMap.keySet());
List<String> oldDepRoleIdList = new LinkedList(oldIdDepRoleMap.keySet());
List<String> addDepRoleIdList = new LinkedList(newDepRoleIdList);
List<String> removeDepRoleIdList = new LinkedList(oldDepRoleIdList);
addDepRoleIdList.removeAll(oldDepRoleIdList);
removeDepRoleIdList.removeAll(newDepRoleIdList);
User targetUser = UserService.getInstance().getUserByUserId(userBean.getId());
Iterator addDepRoleIt = addDepRoleIdList.iterator();
String removeDepRoleId;
DepRole depRole;
while (addDepRoleIt.hasNext()) {
removeDepRoleId = (String) addDepRoleIt.next();
depRole = newIdDepRoleMap.get(removeDepRoleId);
if (RoleCheckerType.DEPARTMENT.checkAuthority(currentUserId, depRole.getDepartmentId())) {
Department department = AuthorityContext.getInstance().getDepartmentController().getById(depRole.getDepartmentId());
Post post = AuthorityContext.getInstance().getPostController().getById(depRole.getPostId());
UserSourceFactory.getInstance().checkSource(targetUser, department);
UserSourceFactory.getInstance().checkSource(targetUser, post);
AuthorityContext.getInstance().getUserController().addUserToDepartmentAndPost(targetUser.getId(), depRole.getDepartmentId(), depRole.getPostId());
}
}
addDepRoleIt = removeDepRoleIdList.iterator();
while (addDepRoleIt.hasNext()) {
removeDepRoleId = (String) addDepRoleIt.next();
depRole = oldIdDepRoleMap.get(removeDepRoleId);
if (RoleCheckerType.DEPARTMENT.checkAuthority(currentUserId, depRole.getDepartmentId())) {
AuthorityContext.getInstance().getUserController().removeUserFromDepartmentAndPost(targetUser.getId(), depRole.getDepartmentId(), depRole.getPostId());
}
}
}
}
/**
* 更新用户平台的类型
*
* @param userBean
* @param platformTypeList
* @throws Exception
*/
public static void updateUserPlatformType(UserBean userBean, List<Integer> platformTypeList) throws Exception {
UserController userController = AuthorityContext.getInstance().getUserController();
// 查询用户的平台用户类型
List<ExtraProperty> extraProperties = userController.findUserExtraProperty(QueryFactory.create().addRestriction(
RestrictionFactory.eq(ExtraProperty.COLUMN_RELEATED_ID, userBean.getId())
).addRestriction(
RestrictionFactory.startWith(ExtraProperty.COLUMN_NAME, UserProductTypeKey.KEY.getKey())
));
List<Integer> newIdList = new LinkedList(platformTypeList);
List<Integer> oldIdList = new LinkedList();
for (ExtraProperty property : extraProperties) {
UserProductTypeKey userProductTypeKey = (UserProductTypeKey) PlatformUserKey.fromKey(property.getName());
oldIdList.add(UserProductType.fromKey(userProductTypeKey).toInteger());
}
// 校验新的用户平台类型是否冲突
for (int i=0; i<platformTypeList.size(); i++) {
UserProductType leftType = UserProductType.fromInteger(platformTypeList.get(i));
for (int j=i+1; j<platformTypeList.size(); j++) {
UserProductType rightType = UserProductType.fromInteger(platformTypeList.get(j));
if (ArrayUtils.contains(leftType.excludeProductKeys(), rightType.transProductKey())) {
throw new IllegalArgumentException("add user platform type illegal " + platformTypeList);
}
}
}
LogUtils.debug("update user platform type, old type:{} new type:{}", oldIdList, newIdList);
List<Integer> addIdList = new LinkedList(newIdList);
List<Integer> removeIdList = new LinkedList(oldIdList);
addIdList.removeAll(oldIdList);
removeIdList.removeAll(newIdList);
// 删除用户原有平台类型
for (Integer i : removeIdList) {
userController.removeUserProductType(userBean.getId(), UserProductType.fromInteger(i).transProductKey());
}
// 添加新增部分的平台类型
out:
for (Integer platformType : addIdList) {
UserProductType userProductType = UserProductType.fromInteger(platformType);
if (!userProductType.isNoLimitEditOpen()) {
continue out;
}
if (userProductType.allowMax() > 0 && 1 > userProductType.leftRegisterTotal()) {
throw new AddUserProductTypeException();
}
userController.addUserProductType(userBean.getId(), userProductType.transProductKey());
}
}
/**
* 随机生成强密码
*
* @param len
* @return
*/
public static String getRandomPassword(int len) {
// 密码字典
char[] str = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '~', '!', '@', '#', '$', '%', '^', '-', '+'
};
StringBuffer pwd = null;
boolean flag = false;
while (!flag) {
int a = 0, b = 0, c = 0, d = 0;
pwd = new StringBuffer();
for (int i = 0; i < len; i++) {
int rand = (int) (Math.random() * str.length);
pwd.append(str[rand]);
if (rand < 26) {
a++;
} else if (rand < 52) {
b++;
} else if (rand < 62) {
c++;
} else {
d++;
}
}
flag = (a * b * c * d != 0);
}
return pwd.toString();
}
}

42
src/main/resources/com/fr/plugin/decision/integration/web/js/button_group.item.js

@ -0,0 +1,42 @@
!(function () {
var Item = BI.inherit(BI.Widget, {
props: {
value: "",
items: [],
changeAction: BI.emptyFn()
},
render: function () {
var self = this, o = this.options;
return {
type: "bi.button_group",
value: o.value + "",
layouts: [{
type: "bi.vertical_adapt"
}],
items: BI.createItems(o.items, {
type: "bi.single_select_radio_item",
height: 16,
logic: {
dynamic: true
},
cls: "bi-list-item-none"
}),
listeners: [{
eventName: BI.ButtonGroup.EVENT_CHANGE,
action: function (e) {
o.changeAction && o.changeAction(e);
}
}],
ref: function (_ref) {
self.group = _ref;
}
}
},
getValue: function () {
return this.group.getValue()[0];
}
});
BI.shortcut("dec.plugin.system.integration.group", Item);
})();

17
src/main/resources/com/fr/plugin/decision/integration/web/js/constant.js

@ -0,0 +1,17 @@
!(function () {
BI.constant("plugin.integration.userCreate", [{
value: "0", text: "仅用户名", userType: "onlyUser"
}, {
value: "1", text: "包含部门职位", userType: "containDepRole"
}]);
BI.constant("plugin.integration.pwd", [{
value: "0", text: "同用户名"
}, {
value: "1", text: "随机密码"
}]);
BI.constant("plugin.integration.dep", [{
value: "0", text: "部门ID长度构建部门树"
}, {
value: "1", text: "部门名称拼接构建部门树"
}]);
})();

44
src/main/resources/com/fr/plugin/decision/integration/web/js/model.pane.js

@ -0,0 +1,44 @@
!(function () {
var user_only = BI.Constants.getConstant("plugin.integration.userCreate")[0],
user_roledep = BI.Constants.getConstant("plugin.integration.userCreate")[1];
var Model = BI.inherit(Fix.Model, {
state: function () {
return {
config: {}
}
},
computed: {
userType: function () {
return this.model.config.userStrategy.userType === user_only.userType ? user_only.value : user_roledep.value;
}
},
actions: {
initData: function (cb) {
var self = this;
Dec.Utils.getPluginIntegrateConfig(function (res) {
if (!res.errorCode) {
self.model.config = res;
cb();
}
})
},
changeUserType: function (v) {
this.model.config.userStrategy.userType = (v === user_only.value ? user_only.userType : user_roledep.userType)
},
saveData: function (value) {
Dec.Utils.updatePluginIntegrateConfig(value, function (res) {
if (res.data === "success") {
BI.Msg.toast("保存成功!", {level: "success"})
} else {
BI.Msg.toast("保存失败!", {level: "error"})
}
})
}
}
});
BI.model("dec.plugin.system.integration.model", Model);
})();

510
src/main/resources/com/fr/plugin/decision/integration/web/js/pane.js

@ -0,0 +1,510 @@
!(function () {
var WIDGET_HEIGHT = 24;
var user_only = BI.Constants.getConstant("plugin.integration.userCreate")[0],
user_roledep = BI.Constants.getConstant("plugin.integration.userCreate")[1];
var dep_legnth = BI.Constants.getConstant("plugin.integration.dep")[0];
var Pane = BI.inherit(BI.Widget, {
props: {
baseCls: "dec-plugin-system-integration"
},
_store: function () {
return BI.Models.getModel("dec.plugin.system.integration.model");
},
beforeInit: function (cb) {
this.store.initData(cb);
},
render: function () {
var self = this;
var createUserInfoPane = {
type: "bi.vertical",
lgap: 10, bgap: 10,
ref: function (_ref) {
self.createUserInfoPane = _ref;
},
invisible: !self.model.config.createUserTurnOn,
items: [{
type: "bi.vertical_adapt",
height: 24,
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: "创建远程连接同名目录",
title: "创建远程连接同名目录",
width: 210
}, {
type: "dec.switch_button",
value: self.model.config.remoteFolder,
ref: function (_ref) {
self.remoteFolder = _ref;
}
}]
}, {
type: "bi.vertical_adapt",
height: WIDGET_HEIGHT,
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: "用户创建策略",
width: 210
}, {
type: "dec.plugin.system.integration.group",
value: self.model.userType,
items: BI.Constants.getConstant("plugin.integration.userCreate"),
changeAction: function (e) {
self.depStrategyPane.setVisible(e === user_roledep.value);
self.store.changeUserType(e);
},
ref: function (_ref) {
self.userCreate = _ref;
}
}]
}, {
type: "bi.vertical_adapt",
height: WIDGET_HEIGHT,
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: "密码策略",
width: 210
}, {
type: "dec.plugin.system.integration.group",
value: self.model.config.userStrategy.pwdStrategy,
items: BI.Constants.getConstant("plugin.integration.pwd"),
ref: function (_ref) {
self.pwd = _ref;
}
}]
}, {
type: "bi.vertical",
bgap: 10,
invisible: self.model.userType === user_only.value,
items: [{
type: "bi.vertical_adapt",
height: WIDGET_HEIGHT,
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: "创建部门策略",
width: 210
}, {
type: "dec.plugin.system.integration.group",
value: self.model.config.userStrategy.depStrategy || dep_legnth.value,
items: BI.Constants.getConstant("plugin.integration.dep"),
ref: function (_ref) {
self.dep = _ref;
},
changeAction: function (e) {
var depLen = e == 0;
self.specialRootId.setVisible(depLen);
self.separator.setVisible(!depLen);
},
}]
}, {
type: "dec.label.editor.item",
textWidth: 210,
invisible: BI.isKey(self.model.config.userStrategy.depStrategy) && self.model.config.userStrategy.depStrategy != 0,
cls: "dec-font-weight-bold",
text: "特殊根部门ID",
editorWidth: 180,
value: self.model.config.userStrategy.specialRootId,
ref: function (_ref) {
self.specialRootId = _ref
}
}, {
type: "dec.label.editor.item",
textWidth: 210,
invisible: self.model.config.userStrategy.depStrategy != 1,
cls: "dec-font-weight-bold",
text: "分隔符",
editorWidth: 180,
value: self.model.config.userStrategy.separator,
ref: function (_ref) {
self.separator = _ref
}
}],
ref: function (_ref) {
self.depStrategyPane = _ref;
}
}]
};
return {
type: "bi.vertical",
cls: "bi-card",
hgap: 10,
items: [{
type: "dec.card.vertical",
text: "配置项",
content: {
type: "bi.vertical",
vgap: 10,
items: [{
type: "dec.label.editor.item",
textWidth: 210,
cls: "dec-font-weight-bold",
text: "帆软平台地址",
title: "帆软平台地址",
watermark: "http(s)://ip:port/webroot/decision",
editorWidth: 300,
value: self.model.config.decisionUrl,
ref: function (_ref) {
self.decisionUrl = _ref
}
}, {
type: "dec.label.editor.item",
textWidth: 210,
cls: "dec-font-weight-bold",
text: "Jwt 密钥值",
editorWidth: 300,
value: self.model.config.jwtKey,
ref: function (_ref) {
self.jwtKey = _ref
}
}, {
type: "bi.vertical_adapt",
height: 24,
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: "认证完成创建用户",
title: "Jwt Token认证用户在平台中不存在时,自动在平台中创建用户信息",
width: 210
}, {
type: "dec.switch_button",
value: self.model.config.createUserTurnOn,
listeners: [{
eventName: "EVENT_CHANGE",
action: function () {
self.createUserInfoPane.setVisible(this.getValue());
}
}],
ref: function (_ref) {
self.createUserTurnOn = _ref;
}
}]
}, createUserInfoPane, {
type: "bi.vertical_adapt",
height: 24,
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: "模板预览参数校验",
width: 210
}, {
type: "dec.switch_button",
value: self.model.config.paraCheckTurnOn,
listeners: [{
eventName: "EVENT_CHANGE",
action: function () {
self.paraCheckPane.setVisible(this.getValue());
}
}],
ref: function (_ref) {
self.paraCheckTurnOn = _ref;
}
}]
}, {
type: "bi.vertical",
lgap: 10, bgap: 10,
invisible: !self.model.config.paraCheckTurnOn,
items: [{
type: "dec.label.editor.item",
textWidth: 210,
cls: "dec-font-weight-bold",
text: "校验地址",
title: "校验地址",
editorWidth: 180,
value: self.model.config.paraCheckUrl,
ref: function (_ref) {
self.paraCheckUrl = _ref
}
}],
ref: function (_ref) {
self.paraCheckPane = _ref
}
}, {
type: "bi.vertical_adapt",
height: 24,
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: "远程设计连接开启token校验",
width: 210
}, {
type: "dec.switch_button",
value: self.model.config.remoteTokenAuth,
ref: function (_ref) {
self.remoteTokenAuth = _ref;
}
}]
}, {
type: "bi.vertical_adapt",
height: 24,
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: "用户信息是否进行AES加密",
title: "Jwt Token中的 subject 字段是否使用 AES/ECB/PKCS5Padding 加密",
width: 210
}, {
type: "dec.switch_button",
value: self.model.config.aesEncryptSubject,
ref: function (_ref) {
self.aesEncryptSubjectButton = _ref;
},
listeners: [{
eventName: "EVENT_CHANGE",
action: function () {
self.aesEncryptKeyPane.setVisible(this.getValue());
}
}],
}]
}, {
type: "bi.vertical",
lgap: 10, bgap: 10,
invisible: !self.model.config.aesEncryptSubject,
items: [{
type: "dec.label.editor.item",
textWidth: 210,
cls: "dec-font-weight-bold",
text: "AES加密密钥(16位)",
title: "AES加密密钥",
editorWidth: 180,
value: self.model.config.aesEncryptKey,
ref: function (_ref) {
self.aesEncryptKeyEditor = _ref
}
}],
ref: function (_ref) {
self.aesEncryptKeyPane = _ref
}
}, /*{
type: "bi.vertical_adapt",
height: 24,
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: "自定义登录页",
title: "页面未登录时跳转至指定URL地址替代帆软登录页",
width: 210
}, {
type: "dec.switch_button",
value: self.model.config.portalURLTurnOn,
ref: function (_ref) {
self.portalURLTurnOnBtn = _ref;
},
listeners: [{
eventName: "EVENT_CHANGE",
action: function () {
self.portalURLPane.setVisible(this.getValue());
}
}],
}]
}, {
type: "bi.vertical",
lgap: 10, bgap: 10,
invisible: !self.model.config.portalURLTurnOn,
items: [{
type: "dec.label.editor.item",
textWidth: 210,
cls: "dec-font-weight-bold",
text: "地址",
title: "自定义登录页地址",
editorWidth: 180,
value: self.model.config.portalURL,
ref: function (_ref) {
self.portalURLEditor = _ref
}
}],
ref: function (_ref) {
self.portalURLPane = _ref
}
}, */{
type: "bi.vertical_adapt",
height: 24,
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: "跨域功能",
title: "开启后会在 response 中会添加允许的请求头",
width: 210
}, {
type: "dec.switch_button",
value: self.model.config.crossDomain,
ref: function (_ref) {
self.crossDomainBtn = _ref;
}
}]
}]
},
listeners: [{
eventName: "EVENT_CHANGE",
action: function () {
self.validate() && self.store.saveData(self.getValue());
}
}]
}, {
type: "bi.vertical_adapt",
height: 24,
items: [{
type: "bi.label",
textAlign: "left",
cls: "dec-font-weight-bold",
text: "显示唤醒设计器",
title: "平台首页地址显示唤醒设计器功能",
width: 210
}, {
type: "dec.switch_button",
value: self.model.config.webStartDesigner,
ref: function (_ref) {
self.webStartDesigner = _ref;
},
listeners: [{
eventName: "EVENT_CHANGE",
action: function () {
self.downloadURLPane.setVisible(this.getValue());
}
}],
}]
}, {
type: "bi.vertical",
lgap: 10, vgap: 10,
invisible: !self.model.config.webStartDesigner,
items: [{
type: "dec.label.editor.item",
textWidth: 210,
cls: "dec-font-weight-bold",
text: "64位设计器下载地址",
title: "64位设计器下载地址",
editorWidth: 500,
value: self.model.config.downloadUrl64,
ref: function (_ref) {
self.downloadUrl64 = _ref
}
}, {
type: "dec.label.editor.item",
textWidth: 210,
cls: "dec-font-weight-bold",
text: "32位设计器下载地址",
title: "32位设计器下载地址",
editorWidth: 500,
value: self.model.config.downloadUrl32,
ref: function (_ref) {
self.downloadUrl32 = _ref
}
}],
ref: function (_ref) {
self.downloadURLPane = _ref
}
}]
}
},
aesValidate: function () {
var editor = this.aesEncryptKeyEditor;
return editor.getValue().length == 16 ? true : (editor.showError("AES密钥长度需为16"), false);
},
validate: function () {
if (!BI.isKey(this.decisionUrl.getValue())) {
BI.Msg.toast("帆软平台地址不允许为空", {level: "error"});
return false;
}
if (this.aesEncryptSubjectButton.getValue()) {
return this.aesValidate();
}
if (this.webStartDesigner.getValue()) {
if (!BI.isKey(this.downloadUrl32.getValue())) {
BI.Msg.toast("32位下载地址不允许为空", {level: "error"});
return false;
}
if (!BI.isKey(this.downloadUrl64.getValue())) {
BI.Msg.toast("64位下载地址不允许为空", {level: "error"});
return false;
}
}
return true;
},
getValue: function () {
var self = this;
var value = {
decisionUrl: self.decisionUrl.getValue(),
jwtKey: self.jwtKey.getValue(),
remoteTokenAuth: self.remoteTokenAuth.getValue(),
aesEncryptSubject: self.aesEncryptSubjectButton.getValue(),
aesEncryptKey: self.aesEncryptKeyEditor.getValue(),
/*portalURLTurnOn: self.portalURLTurnOnBtn.getValue(),
portalURL: self.portalURLEditor.getValue(),*/
crossDomain: self.crossDomainBtn.getValue(),
remoteFolder: self.remoteFolder.getValue()
};
if (self.createUserTurnOn.getValue()) {
var userStrategy = {
pwdStrategy: self.pwd.getValue()
};
switch (self.userCreate.getValue()) {
case user_only.value:
BI.extend(userStrategy, {
userType: user_only.userType
});
break;
case user_roledep.value:
BI.extend(userStrategy, {
userType: user_roledep.userType,
depStrategy: self.dep.getValue(),
specialRootId: self.specialRootId.getValue(),
separator: self.separator.getValue()
});
break;
}
BI.extend(value, {
createUserTurnOn: true,
userStrategy: userStrategy
});
} else {
BI.extend(value, {
createUserTurnOn: false
})
}
if (self.paraCheckTurnOn.getValue()) {
BI.extend(value, {
paraCheckTurnOn: true,
paraCheckUrl: self.paraCheckUrl.getValue()
})
} else {
BI.extend(value, {
paraCheckTurnOn: false
})
}
var webStartDesigner = self.webStartDesigner.getValue();
value.webStartDesigner = webStartDesigner;
if (webStartDesigner) {
BI.extend(value, {
downloadUrl64: self.downloadUrl64.getValue(),
downloadUrl32: self.downloadUrl32.getValue(),
})
}
console.log(value);
return value;
}
});
BI.shortcut("dec.plugin.system.integration", Pane);
})();

35
src/main/resources/com/fr/plugin/decision/integration/web/js/plugin.js

@ -0,0 +1,35 @@
!(function () {
BI.Plugin.config(function (type, options) {
}, function (type, object) {
object.element.attr("shortcut", object.options.type);
});
Dec.Utils = Dec.Utils || {};
BI.extend(Dec.Utils, {
getPluginIntegrateConfig: function (callback) {
Dec.reqGet("/third/auth/conf", "", callback);
},
updatePluginIntegrateConfig: function (val, callback) {
Dec.reqPost("/third/auth/conf", val, callback);
},
getWebStartInfo: function (callback) {
Dec.reqGet("/third/auth/username/token", "", callback);
}
});
BI.config("dec.constant.system.tabs", function (items) {
items.push({
value: "integration",
text: "登录集成",
cardType: "dec.plugin.system.integration"
});
return items;
});
var commonPath = Dec.fineServletURL + "/file?path=com/fr/plugin/decision/integration/web/js/";
BI.$import(commonPath + "constant.js");
BI.$import(commonPath + "button_group.item.js");
BI.$import(commonPath + "model.pane.js");
BI.$import(commonPath + "pane.js");
BI.$import(commonPath + "protocolcheck.js");
})();

263
src/main/resources/com/fr/plugin/decision/integration/web/js/protocolcheck.js

@ -0,0 +1,263 @@
(function (f) {
if (typeof exports === "object" && typeof module !== "undefined") {
module.exports = f()
} else if (typeof define === "function" && define.amd) {
define([], f)
} else {
var g;
if (typeof window !== "undefined") {
g = window
} else if (typeof global !== "undefined") {
g = global
} else if (typeof self !== "undefined") {
g = self
} else {
g = this
}
g.protocolCheck = f()
}
})(function () {
var define, module, exports;
return (function e(t, n, r) {
function s(o, u) {
if (!n[o]) {
if (!t[o]) {
var a = typeof require == "function" && require;
if (!u && a) return a(o, !0);
if (i) return i(o, !0);
var f = new Error("Cannot find module '" + o + "'");
throw f.code = "MODULE_NOT_FOUND", f
}
var l = n[o] = {exports: {}};
t[o][0].call(l.exports, function (e) {
var n = t[o][1][e];
return s(n ? n : e)
}, l, l.exports, e, t, n, r)
}
return n[o].exports
}
var i = typeof require == "function" && require;
for (var o = 0; o < r.length; o++) s(r[o]);
return s
})({
1: [function (require, module, exports) {
function _registerEvent(target, eventType, cb) {
if (target.addEventListener) {
target.addEventListener(eventType, cb);
return {
remove: function () {
target.removeEventListener(eventType, cb);
}
};
} else {
target.attachEvent(eventType, cb);
return {
remove: function () {
target.detachEvent(eventType, cb);
}
};
}
}
function _createHiddenIframe(target, uri) {
var iframe = document.createElement("iframe");
iframe.src = uri;
iframe.id = "hiddenIframe";
iframe.style.display = "none";
target.appendChild(iframe);
return iframe;
}
function openUriWithHiddenFrame(uri, failCb, successCb) {
var timeout = setTimeout(function () {
failCb();
handler.remove();
}, 1000);
var iframe = document.querySelector("#hiddenIframe");
if (!iframe) {
iframe = _createHiddenIframe(document.body, "about:blank");
}
var handler = _registerEvent(window, "blur", onBlur);
function onBlur() {
clearTimeout(timeout);
handler.remove();
successCb();
}
iframe.contentWindow.location.href = uri;
}
function openUriWithTimeoutHack(uri, failCb, successCb) {
var timeout = setTimeout(function () {
failCb();
handler.remove();
}, 1000);
//handle page running in an iframe (blur must be registered with top level window)
var target = window;
while (target != target.parent) {
target = target.parent;
}
var handler = _registerEvent(target, "blur", onBlur);
function onBlur() {
clearTimeout(timeout);
handler.remove();
successCb();
}
window.location = uri;
}
function openUriUsingFirefox(uri, failCb, successCb) {
var iframe = document.querySelector("#hiddenIframe");
if (!iframe) {
iframe = _createHiddenIframe(document.body, "about:blank");
}
try {
iframe.contentWindow.location.href = uri;
successCb();
} catch (e) {
if (e.name == "NS_ERROR_UNKNOWN_PROTOCOL") {
alert("Un Kown!")
failCb();
}
}
}
function openUriWithIE11UsingRegistry(uri, failCb, successCb) {
var shell = new ActiveXObject("WScript.shell");
try {
var reg = shell.RegRead("HKEY_CLASSES_ROOT\\glcloud\\URL Protocol");
if (reg) {
console.log(reg);
window.location.href = uri;
}
successCb();
} catch (e) {
failCb();
}
}
function openUriUsingIEInOlderWindows(uri, failCb, successCb) {
if (getInternetExplorerVersion() === 10) {
openUriUsingIE10InWindows7(uri, failCb, successCb);
} else if (getInternetExplorerVersion() === 9 || getInternetExplorerVersion() === 11) {
/*openUriWithHiddenFrame(uri, failCb, successCb);*/
openUriWithIE11UsingRegistry(uri, failCb, successCb);
} else {
openUriInNewWindowHack(uri, failCb, successCb);
}
}
function openUriUsingIE10InWindows7(uri, failCb, successCb) {
var timeout = setTimeout(failCb, 6000);
window.addEventListener("blur", function () {
clearTimeout(timeout);
successCb();
});
var iframe = document.querySelector("#hiddenIframe");
if (!iframe) {
iframe = _createHiddenIframe(document.body, "about:blank");
}
try {
iframe.contentWindow.location.href = uri;
} catch (e) {
failCb();
clearTimeout(timeout);
}
}
function openUriInNewWindowHack(uri, failCb, successCb) {
var myWindow = window.open('', '', 'width=0,height=0');
myWindow.document.write("<iframe src='" + uri + "'></iframe>");
setTimeout(function () {
try {
myWindow.location.href;
myWindow.setTimeout("window.close()", 1000);
successCb();
} catch (e) {
myWindow.close();
failCb();
}
}, 1000);
}
function openUriWithMsLaunchUri(uri, failCb, successCb) {
navigator.msLaunchUri(uri,
successCb,
failCb
);
}
function checkBrowser() {
var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
return {
isOpera: isOpera,
isFirefox: typeof InstallTrigger !== 'undefined',
isSafari: Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0,
isChrome: !!window.chrome && !isOpera,
isIE: /*@cc_on!@*/false || !!document.documentMode // At least IE6
}
}
function getInternetExplorerVersion() {
var rv = -1;
if (navigator.appName === "Microsoft Internet Explorer") {
var ua = navigator.userAgent;
var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
if (re.exec(ua) != null)
rv = parseFloat(RegExp.$1);
} else if (navigator.appName === "Netscape") {
var ua = navigator.userAgent;
var re = new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})");
if (re.exec(ua) != null) {
rv = parseFloat(RegExp.$1);
}
}
return rv;
}
module.exports = function (uri, failCb, successCb) {
function failCallback() {
failCb && failCb();
}
function successCallback() {
successCb && successCb();
}
if (navigator.msLaunchUri) { //for IE and Edge in Win 8 and Win 10
openUriWithMsLaunchUri(uri, failCb, successCb);
} else {
var browser = checkBrowser();
if (browser.isFirefox) {
openUriUsingFirefox(uri, failCallback, successCallback);
} else if (browser.isChrome) {
openUriWithTimeoutHack(uri, failCallback, successCallback);
} else if (browser.isIE) {
openUriUsingIEInOlderWindows(uri, failCallback, successCallback);
} else {
//not supported, implement please
}
}
}
}, {}]
}, {}, [1])(1)
});

26
src/main/resources/com/fr/plugin/decision/integration/web/js/web_start.js

@ -0,0 +1,26 @@
!(function () {
BI.config("dec.constant.header.items", function (items) {
return BI.concat([{
type: "bi.button",
text: "启动设计器",
ghost: true,
css: {color: "white"},
handler: function () {
Dec.Utils.getWebStartInfo(function (res) {
if (res.data) {
console.log(res);
window.protocolCheck(res.data.url, function () {
var agent = navigator.userAgent.toLowerCase();
var is64 = agent.indexOf("win64") >= 0 || agent.indexOf("wow64") >= 0 || agent.indexOf("x64") >= 0;
var downloadURL = is64 ? res.data.download64 : res.data.download32;
console.log(downloadURL);
window.open(downloadURL);
})
} else {
BI.Msg.toast(res.errorMsg, {level: "error"})
}
})
}
}], items);
});
})();
Loading…
Cancel
Save