Jianye.Wang
2 years ago
38 changed files with 3211 additions and 1 deletions
@ -1,3 +1,10 @@ |
|||||||
# com.fr.plugin.decision.integration |
# 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 |
@ -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> |
@ -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]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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) { |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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 { |
||||||
|
|
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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!"); |
||||||
|
} |
||||||
|
} |
@ -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!"); |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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!"); |
||||||
|
} |
||||||
|
} |
@ -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!"); |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
} |
||||||
|
} |
@ -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"); |
||||||
|
} |
||||||
|
} |
@ -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"); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
@ -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) {} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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())); |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -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; |
||||||
|
|
||||||
|
} |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -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); |
||||||
|
})(); |
@ -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: "部门名称拼接构建部门树" |
||||||
|
}]); |
||||||
|
})(); |
@ -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); |
||||||
|
})(); |
@ -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); |
||||||
|
})(); |
@ -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"); |
||||||
|
})(); |
@ -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) |
||||||
|
}); |
@ -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…
Reference in new issue