From 6da72042c5513b83f8e7df1647610733f01ef920 Mon Sep 17 00:00:00 2001 From: fit2cloud-chenyw Date: Tue, 6 Sep 2022 15:42:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E7=B3=BB=E7=BB=9F=E7=AE=A1=E7=90=86-?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=8F=82=E6=95=B0):=20=E9=92=89=E9=92=89?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/dataease/auth/api/AuthApi.java | 8 ++ .../io/dataease/auth/server/AuthServer.java | 18 +++ .../auth/service/AuthUserService.java | 4 + .../service/impl/AuthUserServiceImpl.java | 15 ++ .../auth/service/impl/ShiroServiceImpl.java | 6 +- .../plugins/server/XDingtalkServer.java | 130 ++++++++++++++++++ .../dataease/service/sys/SysUserService.java | 28 ++++ frontend/src/api/user.js | 14 ++ frontend/src/views/login/index.vue | 23 +++- frontend/src/views/system/SysParam/index.vue | 12 +- 10 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 backend/src/main/java/io/dataease/plugins/server/XDingtalkServer.java diff --git a/backend/src/main/java/io/dataease/auth/api/AuthApi.java b/backend/src/main/java/io/dataease/auth/api/AuthApi.java index 8bc3214d9c..c4d6230f8c 100644 --- a/backend/src/main/java/io/dataease/auth/api/AuthApi.java +++ b/backend/src/main/java/io/dataease/auth/api/AuthApi.java @@ -67,6 +67,14 @@ public interface AuthApi { @PostMapping("/isOpenWecom") boolean isOpenWecom(); + @ApiOperation("是否开启钉钉") + @PostMapping("/isOpenDingtalk") + boolean isOpenDingtalk(); + + @ApiOperation("是否开启飞书") + @PostMapping("/isOpenFark") + boolean isOpenFark(); + @ApiIgnore @PostMapping("/isPluginLoaded") boolean isPluginLoaded(); diff --git a/backend/src/main/java/io/dataease/auth/server/AuthServer.java b/backend/src/main/java/io/dataease/auth/server/AuthServer.java index 0a60ce4c71..bd7334851b 100644 --- a/backend/src/main/java/io/dataease/auth/server/AuthServer.java +++ b/backend/src/main/java/io/dataease/auth/server/AuthServer.java @@ -295,6 +295,24 @@ public class AuthServer implements AuthApi { 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 public boolean isPluginLoaded() { Boolean licValid = PluginUtils.licValid(); diff --git a/backend/src/main/java/io/dataease/auth/service/AuthUserService.java b/backend/src/main/java/io/dataease/auth/service/AuthUserService.java index ba237448ec..483bab6553 100644 --- a/backend/src/main/java/io/dataease/auth/service/AuthUserService.java +++ b/backend/src/main/java/io/dataease/auth/service/AuthUserService.java @@ -34,6 +34,10 @@ public interface AuthUserService { Boolean supportWecom(); + Boolean supportDingtalk(); + + Boolean supportFark(); + Boolean pluginLoaded(); void checkAdmin(String uname, String pwd); diff --git a/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java b/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java index f5376717d0..9fdb6c807c 100644 --- a/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java +++ b/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java @@ -15,6 +15,7 @@ import io.dataease.plugins.common.service.PluginCommonService; import io.dataease.plugins.config.SpringContextUtil; import io.dataease.plugins.util.PluginUtils; 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.oidc.service.OidcXpackService; @@ -176,6 +177,20 @@ public class AuthUserServiceImpl implements AuthUserService { return wecomXpackService.isOpen(); } + @Override + public Boolean supportDingtalk() { + Map 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 public Boolean pluginLoaded() { Map beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((PluginCommonService.class)); diff --git a/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java b/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java index e8d73a1119..5cf3f896ba 100644 --- a/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java +++ b/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java @@ -83,7 +83,7 @@ public class ShiroServiceImpl implements ShiroService { filterChainDefinitionMap.put("/api/auth/isOpenOidc", ANON); filterChainDefinitionMap.put("/api/auth/isOpenWecom", 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/pluginCommon/component/*", ANON); filterChainDefinitionMap.put("/api/pluginCommon/staticInfo/**", ANON); @@ -92,6 +92,10 @@ public class ShiroServiceImpl implements ShiroService { filterChainDefinitionMap.put("/cas/callBack*", ANON); filterChainDefinitionMap.put("/plugin/wecom/callBack*", 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("/unauth", ANON); diff --git a/backend/src/main/java/io/dataease/plugins/server/XDingtalkServer.java b/backend/src/main/java/io/dataease/plugins/server/XDingtalkServer.java new file mode 100644 index 0000000000..cc5603e1b0 --- /dev/null +++ b/backend/src/main/java/io/dataease/plugins/server/XDingtalkServer.java @@ -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 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 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; + } +} diff --git a/backend/src/main/java/io/dataease/service/sys/SysUserService.java b/backend/src/main/java/io/dataease/service/sys/SysUserService.java index ea994e15f9..a361c5b4b2 100644 --- a/backend/src/main/java/io/dataease/service/sys/SysUserService.java +++ b/backend/src/main/java/io/dataease/service/sys/SysUserService.java @@ -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.SysUsersRolesMapper; 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 org.apache.commons.collections4.CollectionUtils; @@ -155,6 +156,33 @@ public class SysUserService { } } + @Transactional + public void saveDingtalkCUser(DingUserEntity dingUserEntity, String email) { + 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); + SysUser dbUser = findOne(sysUser); + /*if (null != dbUser && null != dbUser.getUserId()) { + List roleIds = new ArrayList(); + roleIds.add(2L); + saveUserRoles( dbUser.getUserId(), roleIds); + }*/ + } + @Transactional public void saveCASUser(String name, String email) { long now = System.currentTimeMillis(); diff --git a/frontend/src/api/user.js b/frontend/src/api/user.js index e8f52e1a89..b8f1680b90 100644 --- a/frontend/src/api/user.js +++ b/frontend/src/api/user.js @@ -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() { return request({ url: '/api/auth/isPluginLoaded', diff --git a/frontend/src/views/login/index.vue b/frontend/src/views/login/index.vue index 8fd123d8f7..6835a93753 100644 --- a/frontend/src/views/login/index.vue +++ b/frontend/src/views/login/index.vue @@ -89,7 +89,7 @@