Merge branch 'dev' of github.com:dataease/dataease into dev

This commit is contained in:
taojinlong 2022-09-07 10:28:10 +08:00
commit 570156d5f6
10 changed files with 255 additions and 11 deletions

View File

@ -67,6 +67,14 @@ public interface AuthApi {
@PostMapping("/isOpenWecom") @PostMapping("/isOpenWecom")
boolean isOpenWecom(); boolean isOpenWecom();
@ApiOperation("是否开启钉钉")
@PostMapping("/isOpenDingtalk")
boolean isOpenDingtalk();
@ApiOperation("是否开启飞书")
@PostMapping("/isOpenFark")
boolean isOpenFark();
@ApiIgnore @ApiIgnore
@PostMapping("/isPluginLoaded") @PostMapping("/isPluginLoaded")
boolean isPluginLoaded(); boolean isPluginLoaded();

View File

@ -295,6 +295,24 @@ public class AuthServer implements AuthApi {
return authUserService.supportWecom(); return authUserService.supportWecom();
} }
@Override
public boolean isOpenDingtalk() {
Boolean licValid = PluginUtils.licValid();
if (!licValid)
return false;
return authUserService.supportDingtalk();
}
@Override
public boolean isOpenFark() {
Boolean licValid = PluginUtils.licValid();
if (!licValid)
return false;
return authUserService.supportFark();
}
@Override @Override
public boolean isPluginLoaded() { public boolean isPluginLoaded() {
Boolean licValid = PluginUtils.licValid(); Boolean licValid = PluginUtils.licValid();

View File

@ -34,6 +34,10 @@ public interface AuthUserService {
Boolean supportWecom(); Boolean supportWecom();
Boolean supportDingtalk();
Boolean supportFark();
Boolean pluginLoaded(); Boolean pluginLoaded();
void checkAdmin(String uname, String pwd); void checkAdmin(String uname, String pwd);

View File

@ -15,6 +15,7 @@ import io.dataease.plugins.common.service.PluginCommonService;
import io.dataease.plugins.config.SpringContextUtil; import io.dataease.plugins.config.SpringContextUtil;
import io.dataease.plugins.util.PluginUtils; import io.dataease.plugins.util.PluginUtils;
import io.dataease.plugins.xpack.cas.service.CasXpackService; import io.dataease.plugins.xpack.cas.service.CasXpackService;
import io.dataease.plugins.xpack.dingtalk.service.DingtalkXpackService;
import io.dataease.plugins.xpack.ldap.service.LdapXpackService; import io.dataease.plugins.xpack.ldap.service.LdapXpackService;
import io.dataease.plugins.xpack.oidc.service.OidcXpackService; import io.dataease.plugins.xpack.oidc.service.OidcXpackService;
@ -176,6 +177,20 @@ public class AuthUserServiceImpl implements AuthUserService {
return wecomXpackService.isOpen(); return wecomXpackService.isOpen();
} }
@Override
public Boolean supportDingtalk() {
Map<String, DingtalkXpackService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((DingtalkXpackService.class));
if (beansOfType.keySet().size() == 0) return false;
DingtalkXpackService dingtalkXpackService = SpringContextUtil.getBean(DingtalkXpackService.class);
if (ObjectUtils.isEmpty(dingtalkXpackService)) return false;
return dingtalkXpackService.isOpen();
}
@Override
public Boolean supportFark() {
return false;
}
@Override @Override
public Boolean pluginLoaded() { public Boolean pluginLoaded() {
Map<String, PluginCommonService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((PluginCommonService.class)); Map<String, PluginCommonService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((PluginCommonService.class));

View File

@ -83,7 +83,7 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap.put("/api/auth/isOpenOidc", ANON); filterChainDefinitionMap.put("/api/auth/isOpenOidc", ANON);
filterChainDefinitionMap.put("/api/auth/isOpenWecom", ANON); filterChainDefinitionMap.put("/api/auth/isOpenWecom", ANON);
filterChainDefinitionMap.put("/api/auth/isOpenDingtalk", ANON); filterChainDefinitionMap.put("/api/auth/isOpenDingtalk", ANON);
filterChainDefinitionMap.put("/api/auth/isOpenLark", ANON); filterChainDefinitionMap.put("/api/auth/isOpenFark", ANON);
filterChainDefinitionMap.put("/api/auth/getPublicKey", ANON); filterChainDefinitionMap.put("/api/auth/getPublicKey", ANON);
filterChainDefinitionMap.put("/api/pluginCommon/component/*", ANON); filterChainDefinitionMap.put("/api/pluginCommon/component/*", ANON);
filterChainDefinitionMap.put("/api/pluginCommon/staticInfo/**", ANON); filterChainDefinitionMap.put("/api/pluginCommon/staticInfo/**", ANON);
@ -92,6 +92,10 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap.put("/cas/callBack*", ANON); filterChainDefinitionMap.put("/cas/callBack*", ANON);
filterChainDefinitionMap.put("/plugin/wecom/callBack*", ANON); filterChainDefinitionMap.put("/plugin/wecom/callBack*", ANON);
filterChainDefinitionMap.put("/plugin/wecom/getQrParam", ANON); filterChainDefinitionMap.put("/plugin/wecom/getQrParam", ANON);
filterChainDefinitionMap.put("/plugin/dingtalk/callBack*", ANON);
filterChainDefinitionMap.put("/plugin/dingtalk/getQrParam", ANON);
filterChainDefinitionMap.put("/plugin/fark/callBack*", ANON);
filterChainDefinitionMap.put("/plugin/fark/getQrParam", ANON);
filterChainDefinitionMap.put("/cas/reset/**", ANON); filterChainDefinitionMap.put("/cas/reset/**", ANON);
filterChainDefinitionMap.put("/unauth", ANON); filterChainDefinitionMap.put("/unauth", ANON);

View File

@ -0,0 +1,130 @@
package io.dataease.plugins.server;
import io.dataease.auth.entity.SysUserEntity;
import io.dataease.auth.entity.TokenInfo;
import io.dataease.auth.service.AuthUserService;
import io.dataease.auth.util.JWTUtils;
import io.dataease.commons.constants.SysLogConstants;
import io.dataease.commons.exception.DEException;
import io.dataease.commons.utils.DeLogUtils;
import io.dataease.commons.utils.LogUtil;
import io.dataease.commons.utils.ServletUtils;
import io.dataease.plugins.config.SpringContextUtil;
import io.dataease.plugins.xpack.dingtalk.dto.response.DingQrResult;
import io.dataease.plugins.xpack.dingtalk.dto.response.DingUserEntity;
import io.dataease.plugins.xpack.dingtalk.dto.response.DingtalkInfo;
import io.dataease.plugins.xpack.dingtalk.service.DingtalkXpackService;
import io.dataease.plugins.xpack.display.dto.response.SysSettingDto;
import io.dataease.service.sys.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import springfox.documentation.annotations.ApiIgnore;
import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
@ApiIgnore
@RequestMapping("/plugin/dingtalk")
@Controller
public class XDingtalkServer {
@Resource
private AuthUserService authUserService;
@Resource
private SysUserService sysUserService;
@ResponseBody
@GetMapping("/info")
public DingtalkInfo getDingtalkInfo() {
DingtalkXpackService dingtalkXpackService = SpringContextUtil.getBean(DingtalkXpackService.class);
return dingtalkXpackService.info();
}
@ResponseBody
@RequiresPermissions("sysparam:read")
@PostMapping("/save")
public void save(@RequestBody List<SysSettingDto> settings) {
DingtalkXpackService dingtalkXpackService = SpringContextUtil.getBean(DingtalkXpackService.class);
dingtalkXpackService.save(settings);
}
@ResponseBody
@PostMapping("/testConn")
public void testConn(@RequestBody DingtalkInfo dingtalkInfo) {
DingtalkXpackService dingtalkXpackService = SpringContextUtil.getBean(DingtalkXpackService.class);
try {
dingtalkXpackService.testConn(dingtalkInfo);
}catch(Exception e) {
throw new RuntimeException(e);
}
}
@ResponseBody
@PostMapping("/getQrParam")
public DingQrResult getQrParam() {
DingtalkXpackService dingtalkXpackService = SpringContextUtil.getBean(DingtalkXpackService.class);
return dingtalkXpackService.getQrParam();
}
@GetMapping("/callBack")
public ModelAndView callBack(@RequestParam("code") String code, @RequestParam("state") String state) {
ModelAndView modelAndView = new ModelAndView("redirect:/");
HttpServletResponse response = ServletUtils.response();
DingtalkXpackService dingtalkXpackService = null;
try {
Map<String, DingtalkXpackService> beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((DingtalkXpackService.class));
if (beansOfType.keySet().size() == 0) {
DEException.throwException("缺少钉钉插件");
}
dingtalkXpackService = SpringContextUtil.getBean(DingtalkXpackService.class);
Boolean isOpen = dingtalkXpackService.isOpen();
if (!isOpen) {
DEException.throwException("未开启钉钉");
}
DingUserEntity dingUserEntity = dingtalkXpackService.userInfo(code);
String username = dingUserEntity.getUserid();
String unionid = dingUserEntity.getUnionid();
SysUserEntity sysUserEntity = authUserService.getUserBySub(unionid, 5);
if (null == sysUserEntity) {
String email = StringUtils.isNotBlank(dingUserEntity.getOrg_email()) ? dingUserEntity.getOrg_email() : StringUtils.isNotBlank(dingUserEntity.getEmail()) ? dingUserEntity.getEmail() : "demo@dingtalk.work";
sysUserService.validateExistUser(username, dingUserEntity.getName(), email);
sysUserService.saveDingtalkCUser(dingUserEntity, email);
sysUserEntity = authUserService.getUserBySub(unionid, 5);
}
TokenInfo tokenInfo = TokenInfo.builder().userId(sysUserEntity.getUserId()).username(sysUserEntity.getUsername()).build();
String realPwd = sysUserEntity.getPassword();
String token = JWTUtils.sign(tokenInfo, realPwd);
ServletUtils.setToken(token);
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.LOGIN, SysLogConstants.SOURCE_TYPE.USER, sysUserEntity.getUserId(), null, null, null);
Cookie cookie_token = new Cookie("Authorization", token);
cookie_token.setPath("/");
response.addCookie(cookie_token);
} catch (Exception e) {
String msg = e.getMessage();
if (null != e.getCause()) {
msg = e.getCause().getMessage();
}
try {
msg = URLEncoder.encode(msg, "UTF-8");
LogUtil.error(e);
Cookie cookie_error = new Cookie("DingtalkError", msg);
cookie_error.setPath("/");
return modelAndView;
} catch (UnsupportedEncodingException e1) {
e.printStackTrace();
}
}
return modelAndView;
}
}

View File

@ -19,6 +19,7 @@ import io.dataease.plugins.common.base.domain.*;
import io.dataease.plugins.common.base.mapper.SysUserMapper; import io.dataease.plugins.common.base.mapper.SysUserMapper;
import io.dataease.plugins.common.base.mapper.SysUsersRolesMapper; import io.dataease.plugins.common.base.mapper.SysUsersRolesMapper;
import io.dataease.plugins.common.entity.XpackLdapUserEntity; import io.dataease.plugins.common.entity.XpackLdapUserEntity;
import io.dataease.plugins.xpack.dingtalk.dto.response.DingUserEntity;
import io.dataease.plugins.xpack.oidc.dto.SSOUserInfo; import io.dataease.plugins.xpack.oidc.dto.SSOUserInfo;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
@ -146,13 +147,29 @@ public class SysUserService {
sysUser.setIsAdmin(false); sysUser.setIsAdmin(false);
sysUser.setSub(userId); sysUser.setSub(userId);
sysUserMapper.insert(sysUser); sysUserMapper.insert(sysUser);
SysUser dbUser = findOne(sysUser);
if (null != dbUser && null != dbUser.getUserId()) { }
// 默认角色是普通员工
List<Long> roleIds = new ArrayList<Long>(); @Transactional
roleIds.add(2L); public void saveDingtalkCUser(DingUserEntity dingUserEntity, String email) {
saveUserRoles( dbUser.getUserId(), roleIds); long now = System.currentTimeMillis();
} SysUser sysUser = new SysUser();
sysUser.setUsername(dingUserEntity.getUserid());
sysUser.setNickName(dingUserEntity.getName());
sysUser.setEmail(email);
sysUser.setPassword(CodingUtil.md5(DEFAULT_PWD));
sysUser.setCreateTime(now);
sysUser.setUpdateTime(now);
sysUser.setEnabled(1L);
sysUser.setLanguage("zh_CN");
sysUser.setFrom(5);
sysUser.setIsAdmin(false);
sysUser.setSub(dingUserEntity.getUnionid());
sysUser.setPhone(dingUserEntity.getMobile());
sysUserMapper.insert(sysUser);
} }
@Transactional @Transactional

View File

@ -107,6 +107,20 @@ export function wecomStatus() {
}) })
} }
export function dingtalkStatus() {
return request({
url: '/api/auth/isOpenDingtalk',
method: 'post'
})
}
export function farkStatus() {
return request({
url: '/api/auth/isOpenFark',
method: 'post'
})
}
export function pluginLoaded() { export function pluginLoaded() {
return request({ return request({
url: '/api/auth/isPluginLoaded', url: '/api/auth/isPluginLoaded',

View File

@ -58,7 +58,7 @@
</div> </div>
</el-form> </el-form>
<div v-show="codeShow" class="code"> <div v-show="codeShow" class="code">
<el-row> <el-row class="code-contaniner">
<plugin-com v-if="loginTypes.includes(4) && codeIndex === 4" ref="WecomQr" component-name="WecomQr" /> <plugin-com v-if="loginTypes.includes(4) && codeIndex === 4" ref="WecomQr" component-name="WecomQr" />
<plugin-com v-if="loginTypes.includes(5) && codeIndex === 5" ref="DingtalkQr" component-name="DingtalkQr" /> <plugin-com v-if="loginTypes.includes(5) && codeIndex === 5" ref="DingtalkQr" component-name="DingtalkQr" />
<plugin-com v-if="loginTypes.includes(6) && codeIndex === 6" ref="FarkQr" component-name="FarkQr" /> <plugin-com v-if="loginTypes.includes(6) && codeIndex === 6" ref="FarkQr" component-name="FarkQr" />
@ -89,7 +89,7 @@
<script> <script>
import { encrypt } from '@/utils/rsaEncrypt' import { encrypt } from '@/utils/rsaEncrypt'
import { ldapStatus, oidcStatus, getPublicKey, pluginLoaded, defaultLoginType, wecomStatus } from '@/api/user' import { ldapStatus, oidcStatus, getPublicKey, pluginLoaded, defaultLoginType, wecomStatus, dingtalkStatus, farkStatus } from '@/api/user'
import { getSysUI } from '@/utils/auth' import { getSysUI } from '@/utils/auth'
import { changeFavicon } from '@/utils/index' import { changeFavicon } from '@/utils/index'
import { initTheme } from '@/utils/ThemeUtil' import { initTheme } from '@/utils/ThemeUtil'
@ -178,9 +178,30 @@ export default {
wecomStatus().then(res => { wecomStatus().then(res => {
if (res.success && res.data) { if (res.success && res.data) {
this.loginTypes.push(4) this.loginTypes.push(4)
const arr = this.loginTypes.filter(item => item > 3)
this.codeIndex = arr && arr.length && Math.min(...arr) || this.codeIndex
} }
this.setDefaultType() this.setDefaultType()
}) })
dingtalkStatus().then(res => {
if (res.success && res.data) {
this.loginTypes.push(5)
const arr = this.loginTypes.filter(item => item > 3)
this.codeIndex = arr && arr.length && Math.min(...arr) || this.codeIndex
}
this.setDefaultType()
})
farkStatus().then(res => {
if (res.success && res.data) {
this.loginTypes.push(6)
const arr = this.loginTypes.filter(item => item > 3)
this.codeIndex = arr && arr.length && Math.min(...arr) || this.codeIndex
}
this.setDefaultType()
})
getPublicKey().then(res => { getPublicKey().then(res => {
if (res.success && res.data) { if (res.success && res.data) {
// //
@ -480,6 +501,9 @@ export default {
height: 150px; height: 150px;
padding: 10px; padding: 10px;
} }
.code-contaniner {
height: 410px;
}
} }
.login-third-item { .login-third-item {
display: inline-block; display: inline-block;

View File

@ -65,6 +65,12 @@
:label="$t('wecom.title')" :label="$t('wecom.title')"
name="eleven" name="eleven"
/> />
<el-tab-pane
v-if="isPluginLoaded"
:lazy="true"
:label="$t('dingtalk.title')"
name="twelve"
/>
</el-tabs> </el-tabs>
<div <div
class="tabs-container" class="tabs-container"
@ -97,6 +103,11 @@
ref="WecomSetting" ref="WecomSetting"
component-name="WecomSetting" component-name="WecomSetting"
/> />
<plugin-com
v-if="activeName === 'twelve'"
ref="DingtalkSetting"
component-name="DingtalkSetting"
/>
</div> </div>
</div> </div>
</div> </div>
@ -132,7 +143,6 @@ export default {
} }
}, },
computed: { computed: {
btnList() {}
}, },
beforeCreate() { beforeCreate() {
pluginLoaded().then((res) => { pluginLoaded().then((res) => {