diff --git a/tashow-dependencies/pom.xml b/tashow-dependencies/pom.xml index ad6c26c..c2d1dfb 100644 --- a/tashow-dependencies/pom.xml +++ b/tashow-dependencies/pom.xml @@ -138,6 +138,11 @@ tashow-module-infra-api ${revision} + + com.tashow.cloud + tashow-module-user-api + ${revision} + com.tashow.cloud tashow-module-infra-biz diff --git a/tashow-module/pom.xml b/tashow-module/pom.xml index 24e63d2..a312e60 100644 --- a/tashow-module/pom.xml +++ b/tashow-module/pom.xml @@ -13,6 +13,8 @@ tashow-module-system tashow-module-infra + tashow-module-user + tashow-module-sso diff --git a/tashow-module/tashow-module-sso/pom.xml b/tashow-module/tashow-module-sso/pom.xml new file mode 100644 index 0000000..b694075 --- /dev/null +++ b/tashow-module/tashow-module-sso/pom.xml @@ -0,0 +1,24 @@ + + + + com.tashow.cloud + tashow-module + ${revision} + + 4.0.0 + + tashow-module-sso-api + tashow-module-sso-biz + + tashow-module-sso + pom + + ${project.artifactId} + + system 模块下,我们放通用业务,支撑上层的核心业务。 + 例如说:用户、部门、权限、数据字典等等 + + + diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-api/pom.xml b/tashow-module/tashow-module-sso/tashow-module-sso-api/pom.xml new file mode 100644 index 0000000..44a314d --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-api/pom.xml @@ -0,0 +1,48 @@ + + + + com.tashow.cloud + tashow-module-sso + ${revision} + + 4.0.0 + tashow-module-sso-api + jar + + ${project.artifactId} + + system 模块 API,暴露给其它模块调用 + + + + + com.tashow.cloud + tashow-common + + + + + org.springdoc + springdoc-openapi-starter-webmvc-api + provided + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + + org.springframework.cloud + spring-cloud-starter-openfeign + true + + + + + diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-api/src/main/java/com/tashow/cloud/TashowModuleSsoApiApplication.java b/tashow-module/tashow-module-sso/tashow-module-sso-api/src/main/java/com/tashow/cloud/TashowModuleSsoApiApplication.java new file mode 100644 index 0000000..28627af --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-api/src/main/java/com/tashow/cloud/TashowModuleSsoApiApplication.java @@ -0,0 +1,13 @@ +package com.tashow.cloud; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TashowModuleSsoApiApplication { + + public static void main(String[] args) { + SpringApplication.run(TashowModuleSsoApiApplication.class, args); + } + +} diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/pom.xml b/tashow-module/tashow-module-sso/tashow-module-sso-biz/pom.xml new file mode 100644 index 0000000..1e96a1e --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/pom.xml @@ -0,0 +1,208 @@ + + + + com.tashow.cloud + tashow-module-sso + ${revision} + + 4.0.0 + tashow-module-sso-biz + jar + + ${project.artifactId} + + system 模块下,我们放通用业务,支撑上层的核心业务。 + 例如说:用户、部门、权限、数据字典等等 + + + + + + com.tashow.cloud + tashow-framework-env + + + + + + + + com.tashow.cloud + tashow-data-permission + + + com.tashow.cloud + tashow-framework-tenant + + + + + com.tashow.cloud + tashow-framework-security + + + + + com.tashow.cloud + tashow-data-mybatis + + + + com.tashow.cloud + tashow-data-redis + + + + + com.tashow.cloud + tashow-framework-rpc + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + + + + + + + + + + + + + + org.springframework.boot + spring-boot-starter-mail + + + + + com.tashow.cloud + tashow-framework-monitor + + + + + com.xingyuv + spring-boot-starter-justauth + + + + com.xingyuv + spring-boot-starter-captcha-plus + + + + org.dromara.hutool + hutool-extra + + + + + + cn.dev33 + sa-token-reactor-spring-boot3-starter + 1.42.0 + + + + cn.dev33 + sa-token-spring-boot3-starter + 1.42.0 + + + + + cn.dev33 + sa-token-sso + 1.42.0 + + + + + cn.dev33 + sa-token-oauth2 + 1.42.0 + + + + + cn.dev33 + sa-token-redis-jackson + 1.42.0 + + + + com.dtflys.forest + forest-spring-boot-starter + 1.5.26 + + + + org.apache.commons + commons-pool2 + + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + + diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/TashowModuleSsoBizApplication.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/TashowModuleSsoBizApplication.java new file mode 100644 index 0000000..7a3db24 --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/TashowModuleSsoBizApplication.java @@ -0,0 +1,16 @@ +package com.tashow.cloud; + +import cn.dev33.satoken.oauth2.SaOAuth2Manager; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TashowModuleSsoBizApplication { + + public static void main(String[] args) { + SpringApplication.run(TashowModuleSsoBizApplication.class, args); + System.out.println("\nSa-Token-OAuth2 Server端启动成功,配置如下:"); + System.out.println(SaOAuth2Manager.getServerConfig()); + } + +} diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/config/MybatisPlusConfig.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/config/MybatisPlusConfig.java new file mode 100644 index 0000000..ad1e19d --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/config/MybatisPlusConfig.java @@ -0,0 +1,27 @@ +package com.tashow.cloud.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * MyBatis Plus配置类 + */ +@Configuration +@MapperScan("com.tashow.cloud.mapper") +public class MybatisPlusConfig { + + /** + * 配置分页插件 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 添加分页插件 + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } +} \ No newline at end of file diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/config/SsoSecurityConfig.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/config/SsoSecurityConfig.java new file mode 100644 index 0000000..e35d8fd --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/config/SsoSecurityConfig.java @@ -0,0 +1,21 @@ +package com.tashow.cloud.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +/** + * SSO模块安全配置类 + */ +@Configuration +public class SsoSecurityConfig { + + /** + * 配置密码编码器 + * 使用BCrypt强哈希算法 + */ + @Bean + public BCryptPasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} \ No newline at end of file diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/controller/SaOAuth2ServerController.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/controller/SaOAuth2ServerController.java new file mode 100644 index 0000000..04339ee --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/controller/SaOAuth2ServerController.java @@ -0,0 +1,378 @@ +package com.tashow.cloud.controller; + +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.oauth2.config.SaOAuth2ServerConfig; +import cn.dev33.satoken.oauth2.consts.GrantType; +import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel; +import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaFoxUtil; +import cn.dev33.satoken.util.SaResult; +import com.tashow.cloud.model.SystemUser; +import com.tashow.cloud.service.SystemUserService; +import jakarta.annotation.security.PermitAll; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import java.util.HashMap; +import java.util.Map; + +/** + * Sa-Token OAuth2 Server端 控制器 + */ +@RestController +public class SaOAuth2ServerController { + + @Autowired + private SystemUserService userService; + + // OAuth2-Server 端:处理所有 OAuth2 相关请求 + @RequestMapping("/oauth2/*") + @PermitAll + public Object request() { + System.out.println("------- 进入请求: " + SaHolder.getRequest().getUrl()); + return SaOAuth2ServerProcessor.instance.dister(); + } + + // Sa-Token OAuth2 定制化配置 + @Autowired + @PermitAll + public void configOAuth2Server(SaOAuth2ServerConfig oauth2Server) { + + // 添加 client 信息 + oauth2Server.addClient( + new SaClientModel() + .setClientId("1001") // client id + .setClientSecret("aaaa-bbbb-cccc-dddd-eeee") // client 秘钥 + .addAllowRedirectUris("*") // 所有允许授权的 url + .addContractScopes("openid", "userid", "userinfo") // 所有签约的权限 + .addAllowGrantTypes( // 所有允许的授权模式 + GrantType.authorization_code, // 授权码式 + GrantType.implicit, // 隐式式 + GrantType.refresh_token, // 刷新令牌 + GrantType.password, // 密码式 + GrantType.client_credentials // 客户端模式 + ) + ); + + // 可以添加更多 client 信息,只要保持 clientId 唯一就行了 + // oauth2Server.addClient(...) + + // 配置:未登录时返回的View + oauth2Server.notLoginView = () -> { + String msg = "当前会话在OAuth-Server端尚未登录,请先访问" + + "登录页面" + + "或 注册用户" + + ",进行登录之后,刷新页面开始授权"; + return msg; + }; + + // 配置:登录处理函数 + oauth2Server.doLoginHandle = (name, pwd) -> { + // 从数据库查询用户 + SystemUser user = userService.getUserByUsername(name); + + // 验证用户是否存在且密码是否正确 + if(user != null && userService.validatePassword(pwd, user.getPassword())) { + // 用户状态检查 + if(user.getStatus() != 0) { + return SaResult.error("账号已被禁用"); + } + + // 登录成功,记录用户IP + StpUtil.login(user.getId()); + + // 获取当前的HTTP请求对象 + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + String ip = "unknown"; + if (attributes != null) { + HttpServletRequest request = attributes.getRequest(); + ip = getClientIp(request); + } + + userService.updateLoginInfo(user.getId(), ip); + + return SaResult.ok(); + } + return SaResult.error("账号名或密码错误"); + }; + + // 配置:确认授权时返回的 view + oauth2Server.confirmView = (clientId, scopes) -> { + String scopeStr = SaFoxUtil.convertListToString(scopes); + String yesCode = + "fetch('/oauth2/doConfirm?client_id=" + clientId + "&scope=" + scopeStr + "', {method: 'POST'})" + + ".then(res => res.json())" + + ".then(res => location.reload())"; + String res = "

应用 " + clientId + " 请求授权:" + scopeStr + ",是否同意?

" + + "

" + + " " + + " " + + "

"; + return res; + }; + } + + /** + * 获取客户端真实IP地址 + */ + private String getClientIp(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Real-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + // 多个代理的情况,第一个IP为客户端真实IP + if (ip != null && ip.indexOf(",") > 0) { + ip = ip.substring(0, ip.indexOf(",")); + } + return ip; + } + + /** + * 登录页面接口 - 返回登录页面HTML + */ + @GetMapping("/oauth2/login-page") + @PermitAll + public Object loginPage() { + String html = "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " OAuth2登录\n" + + " \n" + + "\n" + + "\n" + + "
\n" + + "

用户登录

\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + "\n" + + ""; + return html; + } + + /** + * 登录接口 - 处理表单提交 + */ + @PostMapping("/oauth2/login") + @PermitAll + public Object login( + @RequestParam("username") String username, + @RequestParam("password") String password, + HttpServletRequest request) { + + // 查询用户 + SystemUser user = userService.getUserByUsername(username); + + // 验证用户 + if (user == null || !userService.validatePassword(password, user.getPassword())) { + return SaResult.error("账号或密码错误"); + } + + // 检查用户状态 + if (user.getStatus() != 0) { + return SaResult.error("账号已被禁用"); + } + + // 登录 + StpUtil.login(user.getId()); + + // 更新登录信息 + String ip = getClientIp(request); + userService.updateLoginInfo(user.getId(), ip); + + // 返回结果 + Map result = new HashMap<>(); + result.put("tokenValue", StpUtil.getTokenValue()); + result.put("tokenName", StpUtil.getTokenName()); + + return SaResult.data(result); + } + + /** + * 登录成功页面 - 当未指定回调地址时的默认页面 + */ + @GetMapping("/oauth2/login-success") + @PermitAll + public Object loginSuccess() { + String html = "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " 授权成功\n" + + " \n" + + "\n" + + "\n" + + "
\n" + + "

OAuth2授权成功

\n" + + "

您已成功登录并授权给应用

\n" + + "
\n" + + "

当前登录状态:已登录

\n" + + "

令牌信息已生成

\n" + + "
\n" + + " 关闭窗口\n" + + "
\n" + + "\n" + + ""; + return html; + } +} diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/controller/SsoServerController.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/controller/SsoServerController.java new file mode 100644 index 0000000..12453e5 --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/controller/SsoServerController.java @@ -0,0 +1,654 @@ +package com.tashow.cloud.controller; +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.sso.config.SaSsoServerConfig; +import cn.dev33.satoken.sso.processor.SaSsoServerProcessor; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaResult; +import com.dtflys.forest.Forest; +import com.tashow.cloud.model.SystemUser; +import com.tashow.cloud.service.SystemUserService; +import com.tashow.cloud.service.impl.SystemUserServiceImpl; +import jakarta.annotation.security.PermitAll; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Sa-Token-SSO Server端 Controller + */ +@RestController +public class SsoServerController { + + @Autowired + private SystemUserService userService; + + @Autowired + private SystemUserServiceImpl userServiceImpl; + + /** + * SSO-Server端:处理所有SSO相关请求 (下面的章节我们会详细列出开放的接口) + */ + @RequestMapping("/sso/*") + @PermitAll + public Object ssoRequest() { + return SaSsoServerProcessor.instance.dister(); + } + + /** + * 配置SSO相关参数 + */ + @Autowired + @PermitAll + private void configSso(SaSsoServerConfig ssoServer) { + // 配置:未登录时返回的View + ssoServer.notLoginView = () -> { + String msg = "当前会话在SSO-Server端尚未登录,请访问" + + "登录页面" + + "或 注册用户" + + ",登录成功后刷新页面开始授权"; + return msg; + }; + + // 配置:登录处理函数 + ssoServer.doLoginHandle = (name, pwd) -> { + // 从数据库查询用户 + SystemUser user = userService.getUserByUsername(name); + + // 验证用户是否存在且密码是否正确 + if(user != null && userService.validatePassword(pwd, user.getPassword())) { + // 用户状态检查 + if(user.getStatus() != 0) { + return SaResult.error("账号已被禁用"); + } + + // 登录成功,记录用户IP + StpUtil.login(user.getId()); + + // 获取当前的HTTP请求对象 + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + String ip = "unknown"; + if (attributes != null) { + HttpServletRequest request = attributes.getRequest(); + ip = getClientIp(request); + } + + userService.updateLoginInfo(user.getId(), ip); + + return SaResult.ok("登录成功!").setData(StpUtil.getTokenValue()); + } + + return SaResult.error("账号或密码错误"); + }; + + // 配置 Http 请求处理器 (在模式三的单点注销功能下用到,如不需要可以注释掉) + ssoServer.sendHttp = url -> { + try { + System.out.println("------ 发起请求:" + url); + String resStr = Forest.get(url).executeAsString(); + System.out.println("------ 请求结果:" + resStr); + return resStr; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + }; + } + + /** + * 获取客户端真实IP地址 + */ + private String getClientIp(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Real-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + // 多个代理的情况,第一个IP为客户端真实IP + if (ip != null && ip.indexOf(",") > 0) { + ip = ip.substring(0, ip.indexOf(",")); + } + return ip; + } + + /** + * 单点登录检查 - 自定义接口,方便前端调用 + */ + @GetMapping("/sso/checkLogin") + @PermitAll + public Object ssoCheckLogin() { + Map result = new HashMap<>(); + result.put("isLogin", StpUtil.isLogin()); + if (StpUtil.isLogin()) { + result.put("loginId", StpUtil.getLoginId()); + result.put("tokenValue", StpUtil.getTokenValue()); + } + return result; + } + + /** + * 登录页面接口 - 返回登录页面HTML + */ + @GetMapping("/sso/login-page") + @PermitAll + public Object loginPage() { + String html = "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " 单点登录\n" + + " \n" + + "\n" + + "\n" + + "
\n" + + "

用户登录

\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + " 没有账号?点击注册\n" + + "
\n" + + " \n" + + "\n" + + ""; + return html; + } + + /** + * 登录接口 - 前端表单登录请求 + */ + @PostMapping("/sso/login") + @PermitAll + public Object login( + @RequestParam("username") String username, + @RequestParam("password") String password, + HttpServletRequest request) { + + // 查询用户 + SystemUser user = userService.getUserByUsername(username); + + // 验证用户 + if (user == null || !userService.validatePassword(password, user.getPassword())) { + return SaResult.error("账号或密码错误"); + } + + // 检查用户状态 + if (user.getStatus() != 0) { + return SaResult.error("账号已被禁用"); + } + + // 登录 + StpUtil.login(user.getId()); + + // 更新登录信息 + String ip = getClientIp(request); + userService.updateLoginInfo(user.getId(), ip); + + // 返回结果 + Map result = new HashMap<>(); + result.put("tokenValue", StpUtil.getTokenValue()); + result.put("tokenName", StpUtil.getTokenName()); + + return SaResult.data(result); + } + + /** + * 注销登录 + */ + @GetMapping("/sso/logout") + @PermitAll + public Object logout() { + if (StpUtil.isLogin()) { + StpUtil.logout(); + return SaResult.ok("注销成功"); + } + return SaResult.error("当前会话未登录"); + } + + /** + * 查询用户信息 - 自定义接口,用于获取当前登录用户信息 + */ + @GetMapping("/sso/userinfo") + @PermitAll + public Object ssoUserInfo() { + if (!StpUtil.isLogin()) { + return SaResult.error("用户未登录"); + } + + Long userId = Long.valueOf(StpUtil.getLoginId().toString()); + SystemUser user = userService.getUserById(userId); + + if (user == null) { + return SaResult.error("用户不存在"); + } + + // 获取用户角色信息 + List roleCodes = userServiceImpl.getUserRoleCodes(userId); + List roleNames = userServiceImpl.getUserRoleNames(userId); + + Map userInfo = new HashMap<>(); + userInfo.put("id", user.getId()); + userInfo.put("username", user.getUsername()); + userInfo.put("nickname", user.getNickname()); + userInfo.put("email", user.getEmail()); + userInfo.put("mobile", user.getMobile()); + userInfo.put("avatar", user.getAvatar()); + userInfo.put("roleCodes", roleCodes); + userInfo.put("roleNames", roleNames); + + return SaResult.data(userInfo); + } + + /** + * 登录成功页面 - 当未指定回调地址时的默认页面 + */ + @GetMapping("/sso/login-success") + @PermitAll + public Object loginSuccess() { + String html = "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " 登录成功\n" + + " \n" + + "\n" + + "\n" + + "
\n" + + "

登录成功

\n" + + "

您已成功登录到单点登录系统

\n" + + "
\n" + + "

正在加载用户信息...

\n" + + "
\n" + + " 退出登录\n" + + "
\n" + + " \n" + + "\n" + + ""; + return html; + } + + /** + * 注册页面 - 返回注册页面HTML + */ + @GetMapping("/sso/register-page") + @PermitAll + public Object registerPage() { + String html = "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " 用户注册\n" + + " \n" + + "\n" + + "\n" + + "
\n" + + "

用户注册

\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + "
\n" + + " \n" + + "
\n" + + "
\n" + + "
\n" + + " 已有账号?点击登录\n" + + "
\n" + + " \n" + + "\n" + + ""; + return html; + } +} diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/framework/core/RedisCaptchaServiceImpl.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/framework/core/RedisCaptchaServiceImpl.java new file mode 100644 index 0000000..982721a --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/framework/core/RedisCaptchaServiceImpl.java @@ -0,0 +1,49 @@ +package com.tashow.cloud.framework.core; + +import com.xingyuv.captcha.service.CaptchaCacheService; +import lombok.Setter; +import org.springframework.data.redis.core.StringRedisTemplate; + +import java.util.concurrent.TimeUnit; + +/** + * 基于 Redis 实现验证码的存储 + * + * @author 星语 + */ +@Setter +public class RedisCaptchaServiceImpl implements CaptchaCacheService { + + private StringRedisTemplate stringRedisTemplate; + + @Override + public String type() { + return "redis"; + } + + @Override + public void set(String key, String value, long expiresInSeconds) { + stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS); + } + + @Override + public boolean exists(String key) { + return Boolean.TRUE.equals(stringRedisTemplate.hasKey(key)); + } + + @Override + public void delete(String key) { + stringRedisTemplate.delete(key); + } + + @Override + public String get(String key) { + return stringRedisTemplate.opsForValue().get(key); + } + + @Override + public Long increment(String key, long val) { + return stringRedisTemplate.opsForValue().increment(key,val); + } + +} diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/mapper/SystemUserMapper.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/mapper/SystemUserMapper.java new file mode 100644 index 0000000..deff44f --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/mapper/SystemUserMapper.java @@ -0,0 +1,46 @@ +package com.tashow.cloud.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.tashow.cloud.model.SystemUser; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import java.util.List; + +/** + * 系统用户Mapper接口 + */ +@Mapper +public interface SystemUserMapper extends BaseMapper { + + /** + * 获取用户角色ID列表 + * + * @param userId 用户ID + * @return 角色ID列表 + */ + @Select("SELECT role_id FROM system_user_role WHERE user_id = #{userId} AND deleted = 0") + List selectUserRoleIds(@Param("userId") Long userId); + + /** + * 获取用户角色名称列表 + * + * @param userId 用户ID + * @return 角色名称列表 + */ + @Select("SELECT r.name FROM system_role r " + + "JOIN system_user_role ur ON r.id = ur.role_id " + + "WHERE ur.user_id = #{userId} AND r.deleted = 0 AND ur.deleted = 0 AND r.status = 0") + List selectUserRoleNames(@Param("userId") Long userId); + + /** + * 获取用户角色编码列表 + * + * @param userId 用户ID + * @return 角色编码列表 + */ + @Select("SELECT r.code FROM system_role r " + + "JOIN system_user_role ur ON r.id = ur.role_id " + + "WHERE ur.user_id = #{userId} AND r.deleted = 0 AND ur.deleted = 0 AND r.status = 0") + List selectUserRoleCodes(@Param("userId") Long userId); +} \ No newline at end of file diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/model/SystemUser.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/model/SystemUser.java new file mode 100644 index 0000000..a3cbcac --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/model/SystemUser.java @@ -0,0 +1,110 @@ +package com.tashow.cloud.model; + +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 系统用户实体类 + */ +@Data +public class SystemUser { + /** + * 用户ID + */ + private Long id; + + /** + * 用户账号 + */ + private String username; + + /** + * 密码 + */ + private String password; + + /** + * 用户昵称 + */ + private String nickname; + + /** + * 备注 + */ + private String remark; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 岗位编号数组 + */ + private String postIds; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 手机号码 + */ + private String mobile; + + /** + * 用户性别 + */ + private Integer sex; + + /** + * 头像地址 + */ + private String avatar; + + /** + * 帐号状态(0正常 1停用) + */ + private Integer status; + + /** + * 最后登录IP + */ + private String loginIp; + + /** + * 最后登录时间 + */ + private LocalDateTime loginDate; + + /** + * 创建者 + */ + private String creator; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新者 + */ + private String updater; + + /** + * a更新时间 + */ + private LocalDateTime updateTime; + + /** + * 是否删除 + */ + private Boolean deleted; + + /** + * 租户编号 + */ + private Long tenantId; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/security/config/MyFilter.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/security/config/MyFilter.java new file mode 100644 index 0000000..6e174fd --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/security/config/MyFilter.java @@ -0,0 +1,48 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tashow.cloud.security.config; + +import cn.dev33.satoken.reactor.context.SaReactorSyncHolder; +import cn.dev33.satoken.stp.StpUtil; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; + +/** + * 自定义过滤器 + */ +@Component +public class MyFilter implements WebFilter { + + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + System.out.println("进入自定义过滤器"); + + try { + // 先 set 上下文,再调用 Sa-Token 同步 API,并在 finally 里清除上下文 + SaReactorSyncHolder.setContext(exchange); + System.out.println(StpUtil.isLogin()); + } + finally { + SaReactorSyncHolder.clearContext(); + } + + return chain.filter(exchange); + } + +} diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/security/config/SecurityConfiguration.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/security/config/SecurityConfiguration.java new file mode 100644 index 0000000..44f58a2 --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/security/config/SecurityConfiguration.java @@ -0,0 +1,41 @@ +package com.tashow.cloud.security.config; + +import com.tashow.cloud.security.security.config.AuthorizeRequestsCustomizer; +import com.tashow.cloud.systemapi.enums.ApiConstants; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; + +/** + * System 模块的 Security 配置 + */ +@Configuration(proxyBeanMethods = false, value = "systemSecurityConfiguration") +public class SecurityConfiguration { + + @Bean("systemAuthorizeRequestsCustomizer") + public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() { + return new AuthorizeRequestsCustomizer() { + + @Override + public void customize(AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry registry) { + // TODO 芋艿:这个每个项目都需要重复配置,得捉摸有没通用的方案 + // Swagger 接口文档 + registry.requestMatchers("/v3/api-docs/**").permitAll() + .requestMatchers("/webjars/**").permitAll() + .requestMatchers("/swagger-ui").permitAll() + .requestMatchers("/swagger-ui/**").permitAll() + ; + // Druid 监控 + registry.requestMatchers("/druid/**").permitAll(); + // Spring Boot Actuator 的安全配置 + registry.requestMatchers("/actuator").permitAll() + .requestMatchers("/actuator/**").permitAll(); + // RPC 服务的安全配置 + registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll(); + } + + }; + } + +} diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/service/SystemUserService.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/service/SystemUserService.java new file mode 100644 index 0000000..e48778b --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/service/SystemUserService.java @@ -0,0 +1,58 @@ +package com.tashow.cloud.service; + +import com.tashow.cloud.model.SystemUser; + +/** + * 系统用户服务接口 + */ +public interface SystemUserService { + + /** + * 根据用户名查询用户 + * + * @param username 用户名 + * @return 用户信息 + */ + SystemUser getUserByUsername(String username); + + /** + * 验证用户密码 + * + * @param rawPassword 原始密码 + * @param encodedPassword 编码后的密码 + * @return 是否匹配 + */ + boolean validatePassword(String rawPassword, String encodedPassword); + + /** + * 根据用户ID获取用户信息 + * + * @param userId 用户ID + * @return 用户信息 + */ + SystemUser getUserById(Long userId); + + /** + * 更新用户登录信息 + * + * @param userId 用户ID + * @param ip 登录IP + */ + void updateLoginInfo(Long userId, String ip); + + /** + * 注册新用户 + * + * @param user 用户信息 + * @return 是否注册成功 + */ + boolean registerUser(SystemUser user); + + /** + * 加密密码 + * + * @param rawPassword 原始密码 + * @return 加密后的密码 + */ + String encodePassword(String rawPassword); +} \ No newline at end of file diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/service/impl/SystemUserServiceImpl.java b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/service/impl/SystemUserServiceImpl.java new file mode 100644 index 0000000..8305f75 --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/java/com/tashow/cloud/service/impl/SystemUserServiceImpl.java @@ -0,0 +1,104 @@ +package com.tashow.cloud.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.tashow.cloud.mapper.SystemUserMapper; +import com.tashow.cloud.model.SystemUser; +import com.tashow.cloud.service.SystemUserService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 系统用户服务实现类 + */ +@Service +public class SystemUserServiceImpl extends ServiceImpl implements SystemUserService { + + private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + + @Override + public SystemUser getUserByUsername(String username) { + return getOne(new LambdaQueryWrapper() + .eq(SystemUser::getUsername, username) + .eq(SystemUser::getStatus, 0) + .eq(SystemUser::getDeleted, false)); + } + + @Override + public boolean validatePassword(String rawPassword, String encodedPassword) { + return passwordEncoder.matches(rawPassword, encodedPassword); + } + + @Override + public SystemUser getUserById(Long userId) { + return getById(userId); + } + + @Override + public void updateLoginInfo(Long userId, String ip) { + SystemUser user = new SystemUser(); + user.setId(userId); + user.setLoginIp(ip); + LocalDateTime now = LocalDateTime.now(); + user.setLoginDate(now); + user.setUpdateTime(now); + updateById(user); + } + + @Override + public boolean registerUser(SystemUser user) { + // 设置默认值 + LocalDateTime now = LocalDateTime.now(); + user.setCreateTime(now); + user.setUpdateTime(now); + user.setLoginDate(now); + user.setCreator("system"); + user.setUpdater("system"); + + if (user.getAvatar() == null || user.getAvatar().isEmpty()) { + user.setAvatar("https://sa-token.cc/logo.png"); // 设置默认头像 + } + + user.setTenantId(0L); // 默认租户ID + user.setDeleted(false); // 设置为未删除 + + return save(user); + } + + @Override + public String encodePassword(String rawPassword) { + return passwordEncoder.encode(rawPassword); + } + + /** + * 获取用户角色ID列表 + * + * @param userId 用户ID + * @return 角色ID列表 + */ + public List getUserRoleIds(Long userId) { + return baseMapper.selectUserRoleIds(userId); + } + + /** + * 获取用户角色名称列表 + * + * @param userId 用户ID + * @return 角色名称列表 + */ + public List getUserRoleNames(Long userId) { + return baseMapper.selectUserRoleNames(userId); + } + + /** + * 获取用户角色编码列表 + * + * @param userId 用户ID + * @return 角色编码列表 + */ + public List getUserRoleCodes(Long userId) { + return baseMapper.selectUserRoleCodes(userId); + } +} \ No newline at end of file diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/META-INF/services/com.xingyuv.captcha.service.CaptchaCacheService b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/META-INF/services/com.xingyuv.captcha.service.CaptchaCacheService new file mode 100644 index 0000000..93db95c --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/META-INF/services/com.xingyuv.captcha.service.CaptchaCacheService @@ -0,0 +1 @@ +com.tashow.cloud.framework.core.RedisCaptchaServiceImpl \ No newline at end of file diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/application-local.yaml b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/application-local.yaml new file mode 100644 index 0000000..ee65c20 --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/application-local.yaml @@ -0,0 +1,66 @@ +--- #################### 注册中心 + 配置中心相关配置 #################### + +spring: + cloud: + nacos: + server-addr: 43.139.42.137:8848 # Nacos 服务器地址 + username: nacos # Nacos 账号 + password: nacos # Nacos 密码 + discovery: # 【配置中心】配置项 + namespace: 5c8b8fe6-9a89-4ae3-975e-ef3bf560ff82 # 命名空间。这里使用 dev 开发环境 + group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP + metadata: + version: 1.0.0 # 服务实例的版本号,可用于灰度发布 + config: # 【注册中心】配置项 + namespace: 5c8b8fe6-9a89-4ae3-975e-ef3bf560ff82 # 命名空间。这里使用 dev 开发环境 + group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP + + + + # 数据源配置项 + autoconfigure: + exclude: + - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 + datasource: + druid: # Druid 【监控】相关的全局配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + allow: # 设置白名单,不填则允许所有访问 + url-pattern: /druid/* + login-username: # 控制台管理用户名和密码 + login-password: + filter: + stat: + enabled: true + log-slow-sql: true # 慢 SQL 记录 + slow-sql-millis: 100 + merge-sql: true + wall: + config: + multi-statement-allow: true + dynamic: # 多数据源配置 + druid: # Druid 【连接池】相关的全局配置 + initial-size: 1 # 初始连接数 + min-idle: 1 # 最小连接池数量 + max-active: 20 # 最大连接池数量 + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 + test-while-idle: true + test-on-borrow: false + test-on-return: false + primary: master + datasource: + master: + url: jdbc:mysql://43.139.42.137:8406/tashow-platform?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例 + username: tashow-platform + password: tashow123, +# slave: # 模拟从库,可根据自己需要修改 +# lazy: true # 开启懒加载,保证启动速度 +# url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true +# username: root +# password: 123456 diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/application.yaml b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/application.yaml new file mode 100644 index 0000000..77a4ec5 --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/application.yaml @@ -0,0 +1,236 @@ +server: + port: 48082 +spring: + application: + name: sso-server + profiles: + active: local + main: + allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。 + allow-bean-definition-overriding: true # 允许 Bean 覆盖,例如说 Feign 等会存在重复定义的服务 + config: + import: + - optional:classpath:application-${spring.profiles.active}.yaml # 加载【本地】配置 + - optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml # 加载【Nacos】的配置 + # Servlet 配置 + servlet: + # 文件上传相关配置项 + multipart: + max-file-size: 16MB # 单个文件大小 + max-request-size: 32MB # 设置总上传的文件大小 + # Jackson 配置项 + jackson: + serialization: + write-dates-as-timestamps: true # 设置 LocalDateTime 的格式,使用时间戳 + write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401 + write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 + fail-on-empty-beans: false # 允许序列化无属性的 Bean + # Cache 配置项 + cache: + type: REDIS + redis: + time-to-live: 1h # 设置过期时间为 1 小时 + + +logging: + file: + name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 + +--- #################### 接口文档配置 #################### + +springdoc: + api-docs: + enabled: true # 1. 是否开启 Swagger 接文档的元数据 + path: /v3/api-docs + swagger-ui: + enabled: true # 2.1 是否开启 Swagger 文档的官方 UI 界面 + path: /swagger-ui + default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 + +knife4j: + enable: true # 2.2 是否开启 Swagger 文档的 Knife4j UI 界面 + setting: + language: zh_cn + +# MyBatis Plus 的配置项 +mybatis-plus: + configuration: + map-underscore-to-camel-case: true #虽然默认为 true ,但是还是显示去指定下。 + global-config: + db-config: + id-type: NONE # "智能"模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。 + logic-delete-value: 1 # 逻辑已删除值(默认为 1) + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) + banner: false # 关闭控制台的 Banner 打印 + type-aliases-package: ${tashow.info.base-package}.dal.dataobject + encryptor: + password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 + +mybatis-plus-join: + banner: false # 关闭控制台的 Banner 打印 + +# Spring Data Redis 配置 +spring: + data: + redis: + repositories: + enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 + + + + +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + +--- #################### RPC 远程调用相关配置 #################### + +--- #################### 消息队列相关 #################### +spring: + # Kafka 配置项,对应 KafkaProperties 配置类 + kafka: + # Kafka Producer 配置项 + producer: + acks: 1 # 0-不应答。1-leader 应答。all-所有 leader 和 follower 应答。 + retries: 3 # 发送失败时,重试发送的次数 + value-serializer: org.springframework.kafka.support.serializer.JsonSerializer # 消息的 value 的序列化 + # Kafka Consumer 配置项 + consumer: + auto-offset-reset: earliest # 设置消费者分组最初的消费进度为 earliest 。可参考博客 https://blog.csdn.net/lishuangzhe7047/article/details/74530417 理解 + value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer + properties: + spring.json.trusted.packages: '*' + # Kafka Consumer Listener 监听器配置 + listener: + missing-topics-fatal: false # 消费监听接口监听的主题不存在时,默认会报错。所以通过设置为 false ,解决报错 + +--- #################### 定时任务相关配置 #################### + +xxl: + job: + executor: + appname: ${spring.application.name} # 执行器 AppName + logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径 + accessToken: default_token # 执行器通讯TOKEN + +--- #################### 验证码相关配置 #################### + +aj: + captcha: + jigsaw: classpath:images/jigsaw # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径 + pic-click: classpath:images/pic-click # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径 + cache-type: redis # 缓存 local/redis... + cache-number: 1000 # local 缓存的阈值,达到这个值,清除缓存 + timing-clear: 180 # local定时清除过期缓存(单位秒),设置为0代表不执行 + type: blockPuzzle # 验证码类型 default两种都实例化。 blockPuzzle 滑块拼图 clickWord 文字点选 + water-mark: 他秀 # 右下角水印文字(我的水印),可使用 https://tool.chinaz.com/tools/unicode.aspx 中文转 Unicode,Linux 可能需要转 unicode + interference-options: 0 # 滑动干扰项(0/1/2) + req-frequency-limit-enable: false # 接口请求次数一分钟限制是否开启 true|false + req-get-lock-limit: 5 # 验证失败5次,get接口锁定 + req-get-lock-seconds: 10 # 验证失败后,锁定时间间隔 + req-get-minute-limit: 30 # get 接口一分钟内请求数限制 + req-check-minute-limit: 60 # check 接口一分钟内请求数限制 + req-verify-minute-limit: 60 # verify 接口一分钟内请求数限制 + +--- #################### 芋道相关配置 #################### + +tashow: + info: + version: 1.0.0 + base-package: com.tashow.cloud.system + web: + admin-ui: + url: http://dashboard.yudao.iocoder.cn # Admin 管理后台 UI 的地址 + xss: + enable: false + exclude-urls: # 如下 url,仅仅是为了演示,去掉配置也没关系 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 + swagger: + title: 管理后台 + description: 提供管理员管理的所有功能 + version: ${tashow.info.version} + tenant: # 多租户相关配置项 + enable: true + ignore-urls: + - /admin-api/system/tenant/get-id-by-name # 基于名字获取租户,不许带租户编号 + - /admin-api/system/tenant/get-by-website # 基于域名获取租户,不许带租户编号 + - /admin-api/system/captcha/get-image # 获取图片验证码,和租户无关 + - /admin-api/system/captcha/get # 获取图片验证码,和租户无关 + - /admin-api/system/captcha/check # 校验图片验证码,和租户无关 + - /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号 + - /rpc-api/system/tenant/valid # 防止递归。避免调用 /rpc-api/system/tenant/valid 接口时,又去触发 /rpc-api/system/tenant/valid 去校验 + - /rpc-api/system/tenant/id-list # 获得租户列表的时候,无需传递租户编号 + - /rpc-api/system/oauth2/token/check # 访问令牌校验时,无需传递租户编号;主要解决上传文件的场景,前端不会传递 tenant-id! + ignore-tables: + - system_tenant + - system_tenant_package + - system_dict_data + - system_dict_type + - system_error_code + - system_menu + - system_sms_channel + - system_sms_template + - system_sms_log + - system_sensitive_word + - system_oauth2_client + - system_mail_account + - system_mail_template + - system_mail_log + - system_notify_template + ignore-caches: + - user_role_ids + - permission_menu_ids + - oauth_client + - notify_template + - mail_account + - mail_template + - sms_template + sms-code: # 短信验证码相关的配置项 + expire-times: 10m + send-frequency: 1m + send-maximum-quantity-per-day: 10 + begin-code: 9999 # 这里配置 9999 的原因是,测试方便。 + end-code: 9999 # 这里配置 9999 的原因是,测试方便。 + +debug: false + + +sa-token: + # ------- SSO-模式一相关配置 (非模式一不需要配置) + # cookie: + # 配置 Cookie 作用域 + # domain: stp.com + + # ------- SSO-模式二相关配置 + sso-server: + # Ticket有效期 (单位: 秒),默认五分钟 + ticket-timeout: 300 + # 所有允许的授权回调地址 + allow-url: "*" + home-route: "/sso/login-success" + # ------- SSO-模式三相关配置 (下面的配置在使用SSO模式三时打开) + # 是否打开模式三 + is-http: true + + # OAuth2相关配置 + oauth2: + is-code: true + is-implicit: true + is-password: true + is-client: true + is-refresh: true + # 授权码有效期 (单位: 秒) + code-timeout: 300 + # Access-Token有效期 (单位: 秒) + access-token-timeout: 7200 + # Refresh-Token有效期 (单位: 秒) + refresh-token-timeout: 604800 + # 客户端模式 Access-Token 有效期 (单位: 秒) + client-token-timeout: 7200 + # 登录后的默认跳转页面 + home-route: "/oauth2/login-success" + sign: + # API 接口调用秘钥 + secret-key: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor + # ---- 除了以上配置项,你还需要为 Sa-Token 配置http请求处理器(文档有步骤说明) + diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg1.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg1.png new file mode 100644 index 0000000..c481457 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg1.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg2.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg2.png new file mode 100644 index 0000000..bf8fb38 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg2.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg3.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg3.png new file mode 100644 index 0000000..f871d3d Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg3.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg4.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg4.png new file mode 100644 index 0000000..2e3d871 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg4.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg5.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg5.png new file mode 100644 index 0000000..fe383b7 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg5.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg6.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg6.png new file mode 100644 index 0000000..5024ceb Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg6.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg7.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg7.png new file mode 100644 index 0000000..efe76f8 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg7.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg8.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg8.png new file mode 100644 index 0000000..2727aa3 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg8.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg9.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg9.png new file mode 100644 index 0000000..4463aa2 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/original/bg9.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/1.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/1.png new file mode 100644 index 0000000..ef11324 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/1.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/10.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/10.png new file mode 100644 index 0000000..297e44c Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/10.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/11.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/11.png new file mode 100644 index 0000000..d9b1da8 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/11.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/12.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/12.png new file mode 100644 index 0000000..07e7313 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/12.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/13.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/13.png new file mode 100644 index 0000000..82c3dd9 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/13.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/14.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/14.png new file mode 100644 index 0000000..0b9a866 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/14.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/15.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/15.png new file mode 100644 index 0000000..86b0d1c Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/15.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/16.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/16.png new file mode 100644 index 0000000..e90a6e2 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/16.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/17.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/17.png new file mode 100644 index 0000000..a82cbc7 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/17.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/18.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/18.png new file mode 100644 index 0000000..d3f3cfd Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/18.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/19.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/19.png new file mode 100644 index 0000000..eb2855b Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/19.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/8.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/8.png new file mode 100644 index 0000000..3cb5ce1 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/8.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/9.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/9.png new file mode 100644 index 0000000..384d354 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/11/9.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/2.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/2.png new file mode 100644 index 0000000..baf3f06 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/2.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/3.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/3.png new file mode 100644 index 0000000..ccaf617 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/3.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/4.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/4.png new file mode 100644 index 0000000..7dab162 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/jigsaw/slidingBlock/4.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg1.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg1.png new file mode 100644 index 0000000..14e7345 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg1.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg10.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg10.png new file mode 100644 index 0000000..1ea1d6d Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg10.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg2.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg2.png new file mode 100644 index 0000000..0edb329 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg2.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg3.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg3.png new file mode 100644 index 0000000..9167996 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg3.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg4.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg4.png new file mode 100644 index 0000000..e8e8e6c Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg4.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg5.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg5.png new file mode 100644 index 0000000..66a3181 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg5.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg6.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg6.png new file mode 100644 index 0000000..9b0f5d8 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg6.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg7.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg7.png new file mode 100644 index 0000000..db41c74 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg7.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg8.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg8.png new file mode 100644 index 0000000..3496813 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg8.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg9.png b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg9.png new file mode 100644 index 0000000..4e7b477 Binary files /dev/null and b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/images/pic-click/bg9.png differ diff --git a/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/logback-spring.xml b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..16f0c0f --- /dev/null +++ b/tashow-module/tashow-module-sso/tashow-module-sso-biz/src/main/resources/logback-spring.xml @@ -0,0 +1,76 @@ + + + + + + + + + +       + + + ${PATTERN_DEFAULT} + + + + + + + + + + ${PATTERN_DEFAULT} + + + + ${LOG_FILE} + + + ${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz} + + ${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false} + + ${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB} + + ${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0} + + ${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30} + + + + + + 0 + + 256 + + + + + + + + ${PATTERN_DEFAULT} + + + + + + + + + + + + + + + + + + + + + + diff --git a/tashow-module/tashow-module-system/tashow-module-system-biz/src/main/resources/application.yaml b/tashow-module/tashow-module-system/tashow-module-system-biz/src/main/resources/application.yaml index 83cb5cd..0d0e5b5 100644 --- a/tashow-module/tashow-module-system/tashow-module-system-biz/src/main/resources/application.yaml +++ b/tashow-module/tashow-module-system/tashow-module-system-biz/src/main/resources/application.yaml @@ -2,7 +2,7 @@ server: port: 48081 spring: application: - name: system-server + name: user-server profiles: active: local main: diff --git a/tashow-module/tashow-module-user/pom.xml b/tashow-module/tashow-module-user/pom.xml new file mode 100644 index 0000000..cdfe634 --- /dev/null +++ b/tashow-module/tashow-module-user/pom.xml @@ -0,0 +1,24 @@ + + + + com.tashow.cloud + tashow-module + ${revision} + + 4.0.0 + + tashow-module-user-api + tashow-module-user-biz + + tashow-module-user + pom + + ${project.artifactId} + + system 模块下,我们放通用业务,支撑上层的核心业务。 + 例如说:用户、部门、权限、数据字典等等 + + + diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/HELP.md b/tashow-module/tashow-module-user/tashow-module-user-api/HELP.md new file mode 100644 index 0000000..b7509c2 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/HELP.md @@ -0,0 +1,10 @@ +# Getting Started + +### Reference Documentation + +For further reference, please consider the following sections: + +* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) +* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.6.13/maven-plugin/reference/html/) +* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.6.13/maven-plugin/reference/html/#build-image) + diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/pom.xml b/tashow-module/tashow-module-user/tashow-module-user-api/pom.xml new file mode 100644 index 0000000..d8e519d --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/pom.xml @@ -0,0 +1,54 @@ + + + + com.tashow.cloud + tashow-module-user + ${revision} + + 4.0.0 + tashow-module-user-api + jar + + ${project.artifactId} + + system 模块 API,暴露给其它模块调用 + + + + + com.tashow.cloud + tashow-common + + + + + org.springdoc + springdoc-openapi-starter-webmvc-api + provided + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + + org.springframework.cloud + spring-cloud-starter-openfeign + true + + + com.baomidou + mybatis-plus-annotation + 3.5.9 + compile + + + + + diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/convert/SystemRoleConvert.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/convert/SystemRoleConvert.java new file mode 100644 index 0000000..1755f20 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/convert/SystemRoleConvert.java @@ -0,0 +1,63 @@ +package com.tashow.cloud.convert; + +import com.tashow.cloud.model.SystemRole; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统角色对象转换器 + */ +@Mapper +public interface SystemRoleConvert { + + SystemRoleConvert INSTANCE = Mappers.getMapper(SystemRoleConvert.class); + + /** + * 将角色列表转换为角色ID列表 + * + * @param roles 角色列表 + * @return 角色ID列表 + */ + default List convertToRoleIds(List roles) { + if (roles == null || roles.isEmpty()) { + return Collections.emptyList(); + } + return roles.stream() + .map(SystemRole::getId) + .collect(Collectors.toList()); + } + + /** + * 将角色列表转换为角色名称列表 + * + * @param roles 角色列表 + * @return 角色名称列表 + */ + default List convertToRoleNames(List roles) { + if (roles == null || roles.isEmpty()) { + return Collections.emptyList(); + } + return roles.stream() + .map(SystemRole::getName) + .collect(Collectors.toList()); + } + + /** + * 将角色列表转换为角色编码列表 + * + * @param roles 角色列表 + * @return 角色编码列表 + */ + default List convertToRoleCodes(List roles) { + if (roles == null || roles.isEmpty()) { + return Collections.emptyList(); + } + return roles.stream() + .map(SystemRole::getCode) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemRole.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemRole.java new file mode 100644 index 0000000..7031edf --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemRole.java @@ -0,0 +1,92 @@ +package com.tashow.cloud.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 系统角色实体类 + */ +@Data +@TableName("system_role") +public class SystemRole { + /** + * 角色ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 角色名称 + */ + private String name; + + /** + * 角色权限字符串 + */ + private String code; + + /** + * 显示顺序 + */ + private Integer sort; + + /** + * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) + */ + private Integer dataScope; + + /** + * 数据范围(指定部门数组) + */ + private String dataScopeDeptIds; + + /** + * 角色状态(0正常 1停用) + */ + private Integer status; + + /** + * 角色类型 + */ + private Integer type; + + /** + * 备注 + */ + private String remark; + + /** + * 创建者 + */ + private String creator; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新者 + */ + private String updater; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 是否删除 + */ + @TableLogic + private Boolean deleted; + + /** + * 租户编号 + */ + private Long tenantId; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemRoleMenu.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemRoleMenu.java new file mode 100644 index 0000000..cabed2d --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemRoleMenu.java @@ -0,0 +1,62 @@ +package com.tashow.cloud.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 角色菜单关联实体类 + */ +@Data +@TableName("system_role_menu") +public class SystemRoleMenu { + /** + * 自增编号 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 角色ID + */ + private Long roleId; + + /** + * 菜单ID + */ + private Long menuId; + + /** + * 创建者 + */ + private String creator; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新者 + */ + private String updater; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 是否删除 + */ + @TableLogic + private Boolean deleted; + + /** + * 租户编号 + */ + private Long tenantId; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemUser.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemUser.java new file mode 100644 index 0000000..5e0914d --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemUser.java @@ -0,0 +1,118 @@ +package com.tashow.cloud.model; + + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 系统用户实体类 + */ +@Data +@TableName("system_users") +public class SystemUser { + /** + * 用户ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 用户账号 + */ + private String username; + + /** + * 密码 + */ + private String password; + + /** + * 用户昵称 + */ + private String nickname; + + /** + * 备注 + */ + private String remark; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 岗位编号数组 + */ + private String postIds; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 手机号码 + */ + private String mobile; + + /** + * 用户性别 + */ + private Integer sex; + + /** + * 头像地址 + */ + private String avatar; + + /** + * 帐号状态(0正常 1停用) + */ + private Integer status; + + /** + * 最后登录IP + */ + private String loginIp; + + /** + * 最后登录时间 + */ + private LocalDateTime loginDate; + + /** + * 创建者 + */ + private String creator; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新者 + */ + private String updater; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 是否删除 + */ + @TableLogic + private Boolean deleted; + + /** + * 租户编号 + */ + private Long tenantId; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemUserPost.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemUserPost.java new file mode 100644 index 0000000..68076af --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemUserPost.java @@ -0,0 +1,62 @@ +package com.tashow.cloud.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 用户岗位关联实体类 + */ +@Data +@TableName("system_user_post") +public class SystemUserPost { + /** + * 自增编号 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 岗位ID + */ + private Long postId; + + /** + * 创建者 + */ + private String creator; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新者 + */ + private String updater; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 是否删除 + */ + @TableLogic + private Boolean deleted; + + /** + * 租户编号 + */ + private Long tenantId; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemUserRole.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemUserRole.java new file mode 100644 index 0000000..f68d8df --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/SystemUserRole.java @@ -0,0 +1,62 @@ +package com.tashow.cloud.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import java.time.LocalDateTime; + +/** + * 用户角色关联实体类 + */ +@Data +@TableName("system_user_role") +public class SystemUserRole { + /** + * 自增编号 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 角色ID + */ + private Long roleId; + + /** + * 创建者 + */ + private String creator; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新者 + */ + private String updater; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 是否删除 + */ + @TableLogic + private Boolean deleted; + + /** + * 租户编号 + */ + private Long tenantId; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/dto/UserRegisterReqDTO.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/dto/UserRegisterReqDTO.java new file mode 100644 index 0000000..8b1076a --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/model/dto/UserRegisterReqDTO.java @@ -0,0 +1,59 @@ +package com.tashow.cloud.model.dto; + +import lombok.Data; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import java.io.Serializable; + +/** + * 用户注册请求DTO + */ +@Data +public class UserRegisterReqDTO implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 用户账号 + */ + @NotEmpty(message = "用户账号不能为空") + @Size(min = 4, max = 16, message = "账号长度为 4-16 位") + private String username; + + /** + * 密码 + */ + @NotEmpty(message = "密码不能为空") + @Size(min = 4, max = 16, message = "密码长度为 4-16 位") + private String password; + + /** + * 用户昵称 + */ + @Size(max = 30, message = "用户昵称长度不能超过30个字符") + private String nickname; + + /** + * 用户邮箱 + */ + @Email(message = "邮箱格式不正确") + @Size(max = 50, message = "邮箱长度不能超过50个字符") + private String email; + + /** + * 手机号码 + */ + @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号码格式不正确") + private String mobile; + + /** + * 用户性别 + */ + private Integer sex; + + /** + * 登录IP + */ + private String loginIp; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/service/SystemRoleService.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/service/SystemRoleService.java new file mode 100644 index 0000000..29257d8 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/service/SystemRoleService.java @@ -0,0 +1,92 @@ +package com.tashow.cloud.service; + +import com.tashow.cloud.model.SystemRole; +import java.util.List; + +/** + * 系统角色服务接口 + */ +public interface SystemRoleService { + + /** + * 创建角色 + * + * @param role 角色信息 + * @param menuIds 菜单ID列表 + * @return 是否创建成功 + */ + boolean createRole(SystemRole role, List menuIds); + + /** + * 更新角色 + * + * @param role 角色信息 + * @param menuIds 菜单ID列表 + * @return 是否更新成功 + */ + boolean updateRole(SystemRole role, List menuIds); + + /** + * 删除角色 + * + * @param roleId 角色ID + * @return 是否删除成功 + */ + boolean deleteRole(Long roleId); + + /** + * 获取角色信息 + * + * @param roleId 角色ID + * @return 角色信息 + */ + SystemRole getRoleById(Long roleId); + + /** + * 根据角色编码获取角色 + * + * @param code 角色编码 + * @return 角色信息 + */ + SystemRole getRoleByCode(String code); + + /** + * 获取所有角色列表 + * + * @return 角色列表 + */ + List getAllRoles(); + + /** + * 获取指定状态的角色列表 + * + * @param status 状态 + * @return 角色列表 + */ + List getRolesByStatus(Integer status); + + /** + * 获取角色的菜单ID列表 + * + * @param roleId 角色ID + * @return 菜单ID列表 + */ + List getRoleMenuIds(Long roleId); + + /** + * 根据用户ID获取角色列表 + * + * @param userId 用户ID + * @return 角色列表 + */ + List getRolesByUserId(Long userId); + + /** + * 更新角色状态 + * + * @param roleId 角色ID + * @param status 新状态 + * @return 是否更新成功 + */ + boolean updateRoleStatus(Long roleId, Integer status); +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/service/SystemUserService.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/service/SystemUserService.java new file mode 100644 index 0000000..f157b5a --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/service/SystemUserService.java @@ -0,0 +1,137 @@ +package com.tashow.cloud.service; + +import com.tashow.cloud.model.SystemUser; +import java.util.List; + +/** + * 系统用户服务接口 + */ +public interface SystemUserService { + + /** + * 根据用户名查询用户 + * + * @param username 用户名 + * @return 用户信息 + */ + SystemUser getUserByUsername(String username); + + /** + * 验证用户密码 + * + * @param rawPassword 原始密码 + * @param encodedPassword 编码后的密码 + * @return 是否匹配 + */ + boolean validatePassword(String rawPassword, String encodedPassword); + + /** + * 根据用户ID获取用户信息 + * + * @param userId 用户ID + * @return 用户信息 + */ + SystemUser getUserById(Long userId); + + /** + * 更新用户登录信息 + * + * @param userId 用户ID + * @param ip 登录IP + */ + void updateLoginInfo(Long userId, String ip); + + /** + * 注册新用户 + * + * @param user 用户信息 + * @return 是否注册成功 + */ + boolean registerUser(SystemUser user); + + /** + * 加密密码 + * + * @param rawPassword 原始密码 + * @return 加密后的密码 + */ + String encodePassword(String rawPassword); + + /** + * 创建用户 + * + * @param user 用户信息 + * @param roleIds 角色ID列表 + * @param postIds 岗位ID列表 + * @return 是否创建成功 + */ + boolean createUser(SystemUser user, List roleIds, List postIds); + + /** + * 更新用户 + * + * @param user 用户信息 + * @param roleIds 角色ID列表 + * @param postIds 岗位ID列表 + * @return 是否更新成功 + */ + boolean updateUser(SystemUser user, List roleIds, List postIds); + + /** + * 删除用户 + * + * @param userId 用户ID + * @return 是否删除成功 + */ + boolean deleteUser(Long userId); + + /** + * 重置用户密码 + * + * @param userId 用户ID + * @param newPassword 新密码 + * @return 是否重置成功 + */ + boolean resetUserPassword(Long userId, String newPassword); + + /** + * 更新用户状态 + * + * @param userId 用户ID + * @param status 新状态 + * @return 是否更新成功 + */ + boolean updateUserStatus(Long userId, Integer status); + + /** + * 获取用户角色ID列表 + * + * @param userId 用户ID + * @return 角色ID列表 + */ + List getUserRoleIds(Long userId); + + /** + * 获取用户角色名称列表 + * + * @param userId 用户ID + * @return 角色名称列表 + */ + List getUserRoleNames(Long userId); + + /** + * 获取用户角色编码列表 + * + * @param userId 用户ID + * @return 角色编码列表 + */ + List getUserRoleCodes(Long userId); + + /** + * 获取用户岗位ID列表 + * + * @param userId 用户ID + * @return 岗位ID列表 + */ + List getUserPostIds(Long userId); +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserCreateReqDTO.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserCreateReqDTO.java new file mode 100644 index 0000000..2d4b464 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserCreateReqDTO.java @@ -0,0 +1,66 @@ +package com.tashow.cloud.user.dto; + +import lombok.Data; +import java.util.List; + +/** + * 用户创建请求DTO + */ +@Data +public class UserCreateReqDTO { + + /** + * 用户账号 + */ + private String username; + + /** + * 用户密码 + */ + private String password; + + /** + * 用户昵称 + */ + private String nickname; + + /** + * 备注 + */ + private String remark; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 手机号码 + */ + private String mobile; + + /** + * 用户性别 + */ + private Integer sex; + + /** + * 头像地址 + */ + private String avatar; + + /** + * 角色ID列表 + */ + private List roleIds; + + /** + * 岗位ID列表 + */ + private List postIds; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserPageReqDTO.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserPageReqDTO.java new file mode 100644 index 0000000..6d89806 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserPageReqDTO.java @@ -0,0 +1,55 @@ +package com.tashow.cloud.user.dto; + +import lombok.Data; + +/** + * 用户分页查询请求DTO + */ +@Data +public class UserPageReqDTO { + + /** + * 当前页码 + */ + private Integer pageNum = 1; + + /** + * 每页条数 + */ + private Integer pageSize = 10; + + /** + * 用户账号 + */ + private String username; + + /** + * 用户昵称 + */ + private String nickname; + + /** + * 手机号码 + */ + private String mobile; + + /** + * 帐号状态(0正常 1停用) + */ + private Integer status; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 开始创建时间 + */ + private String beginCreateTime; + + /** + * 结束创建时间 + */ + private String endCreateTime; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserRegisterReqDTO.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserRegisterReqDTO.java new file mode 100644 index 0000000..61a229d --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserRegisterReqDTO.java @@ -0,0 +1,35 @@ +package com.tashow.cloud.user.dto; + +import lombok.Data; + +/** + * 用户注册请求DTO + */ +@Data +public class UserRegisterReqDTO { + + /** + * 用户账号 + */ + private String username; + + /** + * 用户密码 + */ + private String password; + + /** + * 用户昵称 + */ + private String nickname; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 手机号码 + */ + private String mobile; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserRespDTO.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserRespDTO.java new file mode 100644 index 0000000..7c81443 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserRespDTO.java @@ -0,0 +1,117 @@ +package com.tashow.cloud.user.dto; + +import lombok.Data; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 用户响应DTO + */ +@Data +public class UserRespDTO { + + /** + * 用户ID + */ + private Long id; + + /** + * 用户账号 + */ + private String username; + + /** + * 用户昵称 + */ + private String nickname; + + /** + * 备注 + */ + private String remark; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 手机号码 + */ + private String mobile; + + /** + * 用户性别 + */ + private Integer sex; + + /** + * 性别名称 + */ + private String sexName; + + /** + * 头像地址 + */ + private String avatar; + + /** + * 帐号状态(0正常 1停用) + */ + private Integer status; + + /** + * 状态名称 + */ + private String statusName; + + /** + * 最后登录IP + */ + private String loginIp; + + /** + * 最后登录时间 + */ + private LocalDateTime loginDate; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 角色ID列表 + */ + private List roleIds; + + /** + * 角色名称列表 + */ + private List roleNames; + + /** + * 角色编码列表 + */ + private List roleCodes; + + /** + * 岗位ID列表 + */ + private List postIds; + + /** + * 岗位名称列表 + */ + private List postNames; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserUpdateReqDTO.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserUpdateReqDTO.java new file mode 100644 index 0000000..d26f937 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/UserUpdateReqDTO.java @@ -0,0 +1,66 @@ +package com.tashow.cloud.user.dto; + +import lombok.Data; +import java.util.List; + +/** + * 用户更新请求DTO + */ +@Data +public class UserUpdateReqDTO { + + /** + * 用户ID + */ + private Long id; + + /** + * 用户昵称 + */ + private String nickname; + + /** + * 备注 + */ + private String remark; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 手机号码 + */ + private String mobile; + + /** + * 用户性别 + */ + private Integer sex; + + /** + * 头像地址 + */ + private String avatar; + + /** + * 帐号状态(0正常 1停用) + */ + private Integer status; + + /** + * 角色ID列表 + */ + private List roleIds; + + /** + * 岗位ID列表 + */ + private List postIds; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/package-info.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/package-info.java new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/dto/package-info.java @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/BaseEntity.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/BaseEntity.java new file mode 100644 index 0000000..a8fc1a2 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/BaseEntity.java @@ -0,0 +1,34 @@ +package com.tashow.cloud.user.model; + +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * 基础实体类,包含所有实体共有的字段 + */ +@Data +public class BaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 创建者 + */ + private String creator; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新者 + */ + private String updater; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/Role.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/Role.java new file mode 100644 index 0000000..8359041 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/Role.java @@ -0,0 +1,78 @@ +package com.tashow.cloud.user.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + * 角色信息实体 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Accessors(chain = true) +@TableName("system_role") +public class Role extends BaseEntity { + + /** + * 角色ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 角色名称 + */ + private String name; + + /** + * 角色权限字符串 + */ + private String code; + + /** + * 显示顺序 + */ + private Integer sort; + + /** + * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) + */ + private Integer dataScope; + + /** + * 数据范围(指定部门数组) + */ + private String dataScopeDeptIds; + + /** + * 角色状态(0正常 1停用) + */ + private Integer status; + + /** + * 角色类型 + */ + private Integer type; + + /** + * 备注 + */ + private String remark; + + /** + * 是否删除 + */ + @TableLogic + private Boolean deleted; + + /** + * 租户编号 + */ + private Long tenantId; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/RoleMenu.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/RoleMenu.java new file mode 100644 index 0000000..014caef --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/RoleMenu.java @@ -0,0 +1,48 @@ +package com.tashow.cloud.user.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + * 角色菜单关联实体 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Accessors(chain = true) +@TableName("system_role_menu") +public class RoleMenu extends BaseEntity { + + /** + * 自增编号 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 角色ID + */ + private Long roleId; + + /** + * 菜单ID + */ + private Long menuId; + + /** + * 是否删除 + */ + @TableLogic + private Boolean deleted; + + /** + * 租户编号 + */ + private Long tenantId; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/User.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/User.java new file mode 100644 index 0000000..716fe61 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/User.java @@ -0,0 +1,115 @@ +package com.tashow.cloud.user.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import java.util.List; + +/** + * 用户信息实体 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Accessors(chain = true) +@TableName("system_users") +public class User extends BaseEntity { + /** + * 用户ID + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 用户账号 + */ + private String username; + + /** + * 密码 + */ + private String password; + + /** + * 用户昵称 + */ + private String nickname; + + /** + * 备注 + */ + private String remark; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 岗位编号数组 + */ + private String postIds; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 手机号码 + */ + private String mobile; + + /** + * 用户性别 + * 0: 未知 + * 1: 男 + * 2: 女 + */ + private Integer sex; + + /** + * 头像地址 + */ + private String avatar; + + /** + * 帐号状态 + * 0: 正常 + * 1: 停用 + */ + private Integer status; + + /** + * 最后登录IP + */ + private String loginIp; + + /** + * 最后登录时间 + */ + private java.time.LocalDateTime loginDate; + + /** + * 是否删除 + */ + @TableLogic + private Boolean deleted; + + /** + * 租户编号 + */ + private Long tenantId; + + /** + * 角色列表 - 非数据库字段 + */ + @TableField(exist = false) + private List roles; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/UserPost.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/UserPost.java new file mode 100644 index 0000000..ea00e89 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/UserPost.java @@ -0,0 +1,48 @@ +package com.tashow.cloud.user.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + * 用户岗位关联实体 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Accessors(chain = true) +@TableName("system_user_post") +public class UserPost extends BaseEntity { + + /** + * 自增编号 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 岗位ID + */ + private Long postId; + + /** + * 是否删除 + */ + @TableLogic + private Boolean deleted; + + /** + * 租户编号 + */ + private Long tenantId; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/UserRole.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/UserRole.java new file mode 100644 index 0000000..d1fbd88 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/model/UserRole.java @@ -0,0 +1,48 @@ +package com.tashow.cloud.user.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; + +/** + * 用户角色关联实体 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Accessors(chain = true) +@TableName("system_user_role") +public class UserRole extends BaseEntity { + + /** + * 自增编号 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 角色ID + */ + private Long roleId; + + /** + * 是否删除 + */ + @TableLogic + private Boolean deleted; + + /** + * 租户编号 + */ + private Long tenantId; +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/service/RoleService.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/service/RoleService.java new file mode 100644 index 0000000..62d01ef --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/service/RoleService.java @@ -0,0 +1,89 @@ +package com.tashow.cloud.user.service; + +import com.tashow.cloud.user.model.Role; +import java.util.List; + +/** + * 角色服务接口 + */ +public interface RoleService { + + /** + * 创建角色 + * + * @param role 角色信息 + * @param menuIds 菜单ID列表 + * @return 角色ID + */ + Long createRole(Role role, List menuIds); + + /** + * 更新角色 + * + * @param role 角色信息 + * @param menuIds 菜单ID列表 + */ + void updateRole(Role role, List menuIds); + + /** + * 删除角色 + * + * @param roleId 角色ID + */ + void deleteRole(Long roleId); + + /** + * 获取角色信息 + * + * @param roleId 角色ID + * @return 角色信息 + */ + Role getRoleById(Long roleId); + + /** + * 根据角色编码获取角色 + * + * @param code 角色编码 + * @return 角色信息 + */ + Role getRoleByCode(String code); + + /** + * 获取所有角色列表 + * + * @return 角色列表 + */ + List getAllRoles(); + + /** + * 获取指定状态的角色列表 + * + * @param status 状态 + * @return 角色列表 + */ + List getRolesByStatus(Integer status); + + /** + * 获取角色的菜单ID列表 + * + * @param roleId 角色ID + * @return 菜单ID列表 + */ + List getRoleMenuIds(Long roleId); + + /** + * 根据用户ID获取角色列表 + * + * @param userId 用户ID + * @return 角色列表 + */ + List getRolesByUserId(Long userId); + + /** + * 更新角色状态 + * + * @param roleId 角色ID + * @param status 新状态 + */ + void updateRoleStatus(Long roleId, Integer status); +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/service/UserService.java b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/service/UserService.java new file mode 100644 index 0000000..84530c5 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-api/src/main/java/com/tashow/cloud/user/service/UserService.java @@ -0,0 +1,142 @@ +package com.tashow.cloud.user.service; + +import com.tashow.cloud.user.dto.UserCreateReqDTO; +import com.tashow.cloud.user.dto.UserPageReqDTO; +import com.tashow.cloud.user.dto.UserRegisterReqDTO; +import com.tashow.cloud.user.dto.UserRespDTO; +import com.tashow.cloud.user.dto.UserUpdateReqDTO; +import com.tashow.cloud.user.model.User; + +import java.util.List; + +/** + * 用户服务接口 + */ +public interface UserService { + + /** + * 创建用户 + * + * @param reqDTO 用户创建信息 + * @return 用户ID + */ + Long createUser(UserCreateReqDTO reqDTO); + + /** + * 更新用户 + * + * @param reqDTO 用户更新信息 + */ + void updateUser(UserUpdateReqDTO reqDTO); + + /** + * 删除用户 + * + * @param id 用户ID + */ + void deleteUser(Long id); + + /** + * 获取用户详情 + * + * @param id 用户ID + * @return 用户详情 + */ + UserRespDTO getUser(Long id); + + /** + * 获取用户详情 + * + * @param username 用户名 + * @return 用户详情 + */ + UserRespDTO getUserByUsername(String username); + + /** + * 获取用户分页列表 + * + * @param reqDTO 查询条件 + * @return 用户分页列表 + */ + List getUserPage(UserPageReqDTO reqDTO); + + /** + * 重置用户密码 + * + * @param id 用户ID + * @param password 新密码 + */ + void resetUserPassword(Long id, String password); + + /** + * 更新用户状态 + * + * @param id 用户ID + * @param status 新状态 + */ + void updateUserStatus(Long id, Integer status); + + /** + * 获取用户的角色ID列表 + * + * @param userId 用户ID + * @return 角色ID列表 + */ + List getUserRoleIds(Long userId); + + /** + * 获取用户的角色名称列表 + * + * @param userId 用户ID + * @return 角色名称列表 + */ + List getUserRoleNames(Long userId); + + /** + * 获取用户的角色编码列表 + * + * @param userId 用户ID + * @return 角色编码列表 + */ + List getUserRoleCodes(Long userId); + + /** + * 注册用户 + * + * @param reqDTO 注册信息 + * @return 用户ID + */ + Long registerUser(UserRegisterReqDTO reqDTO); + + /** + * 获取当前登录用户信息 + * + * @return 用户详情 + */ + UserRespDTO getCurrentUser(); + + /** + * 验证用户密码 + * + * @param rawPassword 原始密码 + * @param encodedPassword 编码后的密码 + * @return 是否匹配 + */ + boolean validatePassword(String rawPassword, String encodedPassword); + + /** + * 加密密码 + * + * @param rawPassword 原始密码 + * @return 加密后的密码 + */ + String encodePassword(String rawPassword); + + /** + * 更新用户登录信息 + * + * @param userId 用户ID + * @param ip 登录IP + */ + void updateLoginInfo(Long userId, String ip); +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/Dockerfile b/tashow-module/tashow-module-user/tashow-module-user-biz/Dockerfile new file mode 100644 index 0000000..7c18a64 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/Dockerfile @@ -0,0 +1,19 @@ +## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性 +## 感谢复旦核博士的建议!灰子哥,牛皮! +FROM eclipse-temurin:21-jre + +## 创建目录,并使用它作为工作目录 +RUN mkdir -p /yudao-module-user-biz +WORKDIR /yudao-module-user-biz +## 将后端项目的 Jar 文件,复制到镜像中 +COPY ./target/yudao-module-user-biz.jar app.jar + +## 设置 TZ 时区 +## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖 +ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms512m -Xmx512m" + +## 暴露后端项目的 48080 端口 +EXPOSE 48081 + +## 启动后端项目 +CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/HELP.md b/tashow-module/tashow-module-user/tashow-module-user-biz/HELP.md new file mode 100644 index 0000000..b7509c2 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/HELP.md @@ -0,0 +1,10 @@ +# Getting Started + +### Reference Documentation + +For further reference, please consider the following sections: + +* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) +* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.6.13/maven-plugin/reference/html/) +* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.6.13/maven-plugin/reference/html/#build-image) + diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/pom.xml b/tashow-module/tashow-module-user/tashow-module-user-biz/pom.xml new file mode 100644 index 0000000..f10391a --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/pom.xml @@ -0,0 +1,212 @@ + + + + com.tashow.cloud + tashow-module-user + ${revision} + + 4.0.0 + tashow-module-user-biz + jar + + ${project.artifactId} + + system 模块下,我们放通用业务,支撑上层的核心业务。 + 例如说:用户、部门、权限、数据字典等等 + + + + + + com.tashow.cloud + tashow-framework-env + + + + + + + + com.tashow.cloud + tashow-data-permission + + + com.tashow.cloud + tashow-framework-tenant + + + + + com.tashow.cloud + tashow-framework-security + + + + + com.tashow.cloud + tashow-data-mybatis + + + + com.tashow.cloud + tashow-data-redis + + + + + com.tashow.cloud + tashow-framework-rpc + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + + + + + + + + + + + + + + org.springframework.boot + spring-boot-starter-mail + + + + + com.tashow.cloud + tashow-framework-monitor + + + + + com.xingyuv + spring-boot-starter-justauth + + + + com.xingyuv + spring-boot-starter-captcha-plus + + + + org.dromara.hutool + hutool-extra + + + + + + cn.dev33 + sa-token-reactor-spring-boot3-starter + 1.42.0 + + + + cn.dev33 + sa-token-spring-boot3-starter + 1.42.0 + + + + + cn.dev33 + sa-token-sso + 1.42.0 + + + + + cn.dev33 + sa-token-oauth2 + 1.42.0 + + + + + cn.dev33 + sa-token-redis-jackson + 1.42.0 + + + + com.dtflys.forest + forest-spring-boot-starter + 1.5.26 + + + + org.apache.commons + commons-pool2 + + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + com.tashow.cloud + tashow-module-user-api + + + + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + + diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/TashowModuleUserBizApplication.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/TashowModuleUserBizApplication.java new file mode 100644 index 0000000..e809bc6 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/TashowModuleUserBizApplication.java @@ -0,0 +1,18 @@ +package com.tashow.cloud.tashowmoduleuserbiz; + +import cn.dev33.satoken.sso.SaSsoManager; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TashowModuleUserBizApplication { + + public static void main(String[] args) { + SpringApplication.run(TashowModuleUserBizApplication.class, args); + System.out.println(); + System.out.println("---------------------- Sa-Token SSO 统一认证中心启动成功 ----------------------"); + System.out.println("配置信息:" + SaSsoManager.getServerConfig()); + System.out.println(); + } + +} diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/config/MybatisPlusConfig.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/config/MybatisPlusConfig.java new file mode 100644 index 0000000..6a6598b --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/config/MybatisPlusConfig.java @@ -0,0 +1,27 @@ +package com.tashow.cloud.tashowmoduleuserbiz.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * MyBatis Plus配置类 + */ +@Configuration +@MapperScan("com.tashow.cloud.tashowmoduleuserbiz.mapper") +public class MybatisPlusConfig { + + /** + * 配置分页插件 + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 添加分页插件 + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/controller/RoleController.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/controller/RoleController.java new file mode 100644 index 0000000..4e24d9b --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/controller/RoleController.java @@ -0,0 +1,203 @@ +package com.tashow.cloud.tashowmoduleuserbiz.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaIgnore; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaResult; +import com.tashow.cloud.model.SystemRole; +import com.tashow.cloud.service.SystemRoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.stream.Collectors; + +/** + * 角色管理控制器 + */ +@RestController +@RequestMapping("/role") +public class RoleController { + + @Autowired + private SystemRoleService roleService; + + /** + * 创建角色 + */ + @PostMapping + @SaCheckPermission("system:role:create") + public SaResult createRole(@RequestBody Map params) { + try { + SystemRole role = new SystemRole(); + role.setName((String) params.get("name")); + role.setCode((String) params.get("code")); + role.setSort((Integer) params.get("sort")); + role.setStatus((Integer) params.get("status")); + role.setType((Integer) params.get("type")); + role.setRemark((String) params.get("remark")); + role.setDataScope((Integer) params.get("dataScope")); + role.setDataScopeDeptIds((String) params.get("dataScopeDeptIds")); + + // 设置创建者 + String username = StpUtil.getLoginIdAsString(); + role.setCreator(username); + role.setUpdater(username); + + @SuppressWarnings("unchecked") + List menuIds = (List) params.get("menuIds"); + + boolean success = roleService.createRole(role, menuIds); + + if (success) { + return SaResult.ok("角色创建成功").setData(role); + } else { + return SaResult.error("角色创建失败"); + } + } catch (Exception e) { + return SaResult.error("角色创建异常: " + e.getMessage()); + } + } + + /** + * 更新角色 + */ + @PutMapping("/{id}") + @SaCheckPermission("system:role:update") + public SaResult updateRole(@PathVariable("id") Long id, @RequestBody Map params) { + try { + SystemRole role = roleService.getRoleById(id); + if (role == null) { + return SaResult.error("角色不存在"); + } + + role.setName((String) params.get("name")); + role.setCode((String) params.get("code")); + role.setSort((Integer) params.get("sort")); + role.setStatus((Integer) params.get("status")); + role.setType((Integer) params.get("type")); + role.setRemark((String) params.get("remark")); + role.setDataScope((Integer) params.get("dataScope")); + role.setDataScopeDeptIds((String) params.get("dataScopeDeptIds")); + + // 设置更新者 + String username = StpUtil.getLoginIdAsString(); + role.setUpdater(username); + + @SuppressWarnings("unchecked") + List menuIds = (List) params.get("menuIds"); + + boolean success = roleService.updateRole(role, menuIds); + + if (success) { + return SaResult.ok("角色更新成功"); + } else { + return SaResult.error("角色更新失败"); + } + } catch (Exception e) { + return SaResult.error("角色更新异常: " + e.getMessage()); + } + } + + /** + * 删除角色 + */ + @DeleteMapping("/{id}") + @SaCheckPermission("system:role:delete") + public SaResult deleteRole(@PathVariable("id") Long id) { + try { + boolean success = roleService.deleteRole(id); + + if (success) { + return SaResult.ok("角色删除成功"); + } else { + return SaResult.error("角色删除失败"); + } + } catch (Exception e) { + return SaResult.error("角色删除异常: " + e.getMessage()); + } + } + + /** + * 获取角色详情 + */ + @GetMapping("/{id}") + @SaCheckPermission("system:role:query") + public SaResult getRoleDetail(@PathVariable("id") Long id) { + try { + SystemRole role = roleService.getRoleById(id); + if (role == null) { + return SaResult.error("角色不存在"); + } + + Map result = new HashMap<>(); + result.put("role", role); + + // 获取角色关联的菜单ID列表 + List menuIds = roleService.getRoleMenuIds(id); + result.put("menuIds", menuIds); + + return SaResult.ok().setData(result); + } catch (Exception e) { + return SaResult.error("获取角色详情异常: " + e.getMessage()); + } + } + + /** + * 获取角色列表 + */ + @GetMapping("/list") + @SaCheckPermission("system:role:query") + public SaResult getRoleList() { + try { + List roles = roleService.getAllRoles(); + return SaResult.ok().setData(roles); + } catch (Exception e) { + return SaResult.error("获取角色列表异常: " + e.getMessage()); + } + } + + /** + * 获取启用状态的角色列表(可用于下拉选择) + */ + @GetMapping("/options") + @SaIgnore + public SaResult getRoleOptions() { + try { + List roles = roleService.getRolesByStatus(0); // 0表示正常状态 + List> options = roles.stream() + .map(role -> { + Map option = new HashMap<>(); + option.put("value", role.getId()); + option.put("label", role.getName()); + option.put("code", role.getCode()); + return option; + }) + .collect(Collectors.toList()); + + return SaResult.ok().setData(options); + } catch (Exception e) { + return SaResult.error("获取角色选项异常: " + e.getMessage()); + } + } + + /** + * 更新角色状态 + */ + @PutMapping("/{id}/status") + @SaCheckPermission("system:role:update") + public SaResult updateRoleStatus(@PathVariable("id") Long id, @RequestParam("status") Integer status) { + try { + boolean success = roleService.updateRoleStatus(id, status); + + if (success) { + return SaResult.ok("角色状态更新成功"); + } else { + return SaResult.error("角色状态更新失败"); + } + } catch (Exception e) { + return SaResult.error("角色状态更新异常: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/controller/UserController.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/controller/UserController.java new file mode 100644 index 0000000..956fc60 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/controller/UserController.java @@ -0,0 +1,310 @@ +package com.tashow.cloud.tashowmoduleuserbiz.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaIgnore; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaResult; +import com.tashow.cloud.model.SystemUser; +import com.tashow.cloud.service.SystemUserService; +import com.tashow.cloud.model.dto.UserRegisterReqDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 用户管理控制器 + */ +@RestController +@RequestMapping("/user") +public class UserController { + + @Autowired + private SystemUserService userService; + + /** + * 用户注册 + */ + @SaIgnore + @PostMapping("/register") + public SaResult register(@Valid @RequestBody UserRegisterReqDTO reqDTO, HttpServletRequest request) { + + // 检查用户名是否已存在 + SystemUser existingUser = userService.getUserByUsername(reqDTO.getUsername()); + if (existingUser != null) { + return SaResult.error("用户名已被使用"); + } + + // 加密密码 + String encodedPassword = userService.encodePassword(reqDTO.getPassword()); + + // 创建用户 + SystemUser user = new SystemUser(); + user.setUsername(reqDTO.getUsername()); + user.setPassword(encodedPassword); + user.setNickname(reqDTO.getNickname()); + user.setEmail(reqDTO.getEmail()); + user.setMobile(reqDTO.getMobile()); + user.setSex(reqDTO.getSex()); + user.setStatus(0); // 正常状态 + + // 设置登录IP + String loginIp = reqDTO.getLoginIp(); + if (loginIp == null || loginIp.isEmpty()) { + loginIp = getClientIp(request); + } + user.setLoginIp(loginIp); + + // 注册用户 + boolean success = userService.registerUser(user); + + if (success) { + return SaResult.ok("注册成功"); + } else { + return SaResult.error("注册失败,请稍后重试"); + } + } + + /** + * 创建用户 + */ + @PostMapping + @SaCheckPermission("system:user:create") + public SaResult createUser(@RequestBody Map params) { + try { + SystemUser user = new SystemUser(); + user.setUsername((String) params.get("username")); + user.setPassword((String) params.get("password")); // 会在service中加密 + user.setNickname((String) params.get("nickname")); + user.setEmail((String) params.get("email")); + user.setMobile((String) params.get("mobile")); + user.setRemark((String) params.get("remark")); + user.setStatus((Integer) params.get("status")); + user.setSex((Integer) params.get("sex")); + user.setDeptId((Long) params.get("deptId")); + user.setAvatar((String) params.get("avatar")); + + // 设置创建者 + String username = StpUtil.getLoginIdAsString(); + user.setCreator(username); + user.setUpdater(username); + + @SuppressWarnings("unchecked") + List roleIds = (List) params.get("roleIds"); + + @SuppressWarnings("unchecked") + List postIds = (List) params.get("postIds"); + + boolean success = userService.createUser(user, roleIds, postIds); + + if (success) { + return SaResult.ok("用户创建成功").setData(user); + } else { + return SaResult.error("用户创建失败"); + } + } catch (Exception e) { + return SaResult.error("用户创建异常: " + e.getMessage()); + } + } + + /** + * 更新用户 + */ + @PutMapping("/{id}") + @SaCheckPermission("system:user:update") + public SaResult updateUser(@PathVariable("id") Long id, @RequestBody Map params) { + try { + SystemUser user = userService.getUserById(id); + if (user == null) { + return SaResult.error("用户不存在"); + } + + user.setNickname((String) params.get("nickname")); + user.setEmail((String) params.get("email")); + user.setMobile((String) params.get("mobile")); + user.setRemark((String) params.get("remark")); + user.setStatus((Integer) params.get("status")); + user.setSex((Integer) params.get("sex")); + user.setDeptId((Long) params.get("deptId")); + user.setAvatar((String) params.get("avatar")); + + // 设置更新者 + String username = StpUtil.getLoginIdAsString(); + user.setUpdater(username); + + @SuppressWarnings("unchecked") + List roleIds = (List) params.get("roleIds"); + + @SuppressWarnings("unchecked") + List postIds = (List) params.get("postIds"); + + boolean success = userService.updateUser(user, roleIds, postIds); + + if (success) { + return SaResult.ok("用户更新成功"); + } else { + return SaResult.error("用户更新失败"); + } + } catch (Exception e) { + return SaResult.error("用户更新异常: " + e.getMessage()); + } + } + + /** + * 删除用户 + */ + @DeleteMapping("/{id}") + @SaCheckPermission("system:user:delete") + public SaResult deleteUser(@PathVariable("id") Long id) { + try { + // 判断是否为当前登录用户 + Long loginId = StpUtil.getLoginIdAsLong(); + if (loginId.equals(id)) { + return SaResult.error("不能删除当前登录用户"); + } + + boolean success = userService.deleteUser(id); + + if (success) { + return SaResult.ok("用户删除成功"); + } else { + return SaResult.error("用户删除失败"); + } + } catch (Exception e) { + return SaResult.error("用户删除异常: " + e.getMessage()); + } + } + + /** + * 获取用户详情 + */ + @GetMapping("/{id}") + @SaCheckPermission("system:user:query") + public SaResult getUserDetail(@PathVariable("id") Long id) { + try { + SystemUser user = userService.getUserById(id); + if (user == null) { + return SaResult.error("用户不存在"); + } + + // 脱敏处理 + user.setPassword(null); + + Map result = new HashMap<>(); + result.put("user", user); + + // 获取用户角色ID列表 + List roleIds = userService.getUserRoleIds(id); + result.put("roleIds", roleIds); + + // 获取用户岗位ID列表 + List postIds = userService.getUserPostIds(id); + result.put("postIds", postIds); + + return SaResult.ok().setData(result); + } catch (Exception e) { + return SaResult.error("获取用户详情异常: " + e.getMessage()); + } + } + + /** + * 获取当前登录用户信息 + */ + @GetMapping("/info") + public SaResult getCurrentUserInfo() { + try { + Long userId = StpUtil.getLoginIdAsLong(); + SystemUser user = userService.getUserById(userId); + if (user == null) { + return SaResult.error("用户不存在"); + } + + // 脱敏处理 + user.setPassword(null); + + Map result = new HashMap<>(); + result.put("user", user); + + // 获取用户角色信息 + List roleCodes = userService.getUserRoleCodes(userId); + List roleNames = userService.getUserRoleNames(userId); + + result.put("roles", roleCodes); + result.put("roleNames", roleNames); + + return SaResult.ok().setData(result); + } catch (Exception e) { + return SaResult.error("获取当前用户信息异常: " + e.getMessage()); + } + } + + /** + * 重置用户密码 + */ + @PutMapping("/{id}/password") + @SaCheckPermission("system:user:update") + public SaResult resetPassword(@PathVariable("id") Long id, @RequestParam("newPassword") String newPassword) { + try { + boolean success = userService.resetUserPassword(id, newPassword); + + if (success) { + return SaResult.ok("密码重置成功"); + } else { + return SaResult.error("密码重置失败"); + } + } catch (Exception e) { + return SaResult.error("密码重置异常: " + e.getMessage()); + } + } + + /** + * 更新用户状态 + */ + @PutMapping("/{id}/status") + @SaCheckPermission("system:user:update") + public SaResult updateUserStatus(@PathVariable("id") Long id, @RequestParam("status") Integer status) { + try { + // 判断是否为当前登录用户 + Long loginId = StpUtil.getLoginIdAsLong(); + if (loginId.equals(id)) { + return SaResult.error("不能修改当前登录用户的状态"); + } + + boolean success = userService.updateUserStatus(id, status); + + if (success) { + return SaResult.ok("用户状态更新成功"); + } else { + return SaResult.error("用户状态更新失败"); + } + } catch (Exception e) { + return SaResult.error("用户状态更新异常: " + e.getMessage()); + } + } + + /** + * 获取客户端真实IP地址 + */ + private String getClientIp(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Real-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + // 多个代理的情况,第一个IP为客户端真实IP + if (ip != null && ip.indexOf(",") > 0) { + ip = ip.substring(0, ip.indexOf(",")); + } + return ip; + } +} diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemRoleMapper.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemRoleMapper.java new file mode 100644 index 0000000..5dfe115 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemRoleMapper.java @@ -0,0 +1,13 @@ +package com.tashow.cloud.tashowmoduleuserbiz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.tashow.cloud.model.SystemRole; +import org.apache.ibatis.annotations.Mapper; + +/** + * 系统角色Mapper接口 + */ +@Mapper +public interface SystemRoleMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemRoleMenuMapper.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemRoleMenuMapper.java new file mode 100644 index 0000000..9e12681 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemRoleMenuMapper.java @@ -0,0 +1,13 @@ +package com.tashow.cloud.tashowmoduleuserbiz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.tashow.cloud.model.SystemRoleMenu; +import org.apache.ibatis.annotations.Mapper; + +/** + * 角色菜单关联Mapper接口 + */ +@Mapper +public interface SystemRoleMenuMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemUserMapper.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemUserMapper.java new file mode 100644 index 0000000..69c0133 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemUserMapper.java @@ -0,0 +1,13 @@ +package com.tashow.cloud.tashowmoduleuserbiz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.tashow.cloud.model.SystemUser; +import org.apache.ibatis.annotations.Mapper; + +/** + * 系统用户Mapper接口 + */ +@Mapper +public interface SystemUserMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemUserPostMapper.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemUserPostMapper.java new file mode 100644 index 0000000..44f50f2 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemUserPostMapper.java @@ -0,0 +1,13 @@ +package com.tashow.cloud.tashowmoduleuserbiz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.tashow.cloud.model.SystemUserPost; +import org.apache.ibatis.annotations.Mapper; + +/** + * 用户岗位关联Mapper接口 + */ +@Mapper +public interface SystemUserPostMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemUserRoleMapper.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemUserRoleMapper.java new file mode 100644 index 0000000..b632d18 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/mapper/SystemUserRoleMapper.java @@ -0,0 +1,13 @@ +package com.tashow.cloud.tashowmoduleuserbiz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.tashow.cloud.model.SystemUserRole; +import org.apache.ibatis.annotations.Mapper; + +/** + * 用户角色关联Mapper接口 + */ +@Mapper +public interface SystemUserRoleMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/security/config/SaTokenConfigure.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/security/config/SaTokenConfigure.java new file mode 100644 index 0000000..269176f --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/security/config/SaTokenConfigure.java @@ -0,0 +1,44 @@ +package com.tashow.cloud.tashowmoduleuserbiz.security.config; + +import cn.dev33.satoken.interceptor.SaInterceptor; +import cn.dev33.satoken.router.SaRouter; +import cn.dev33.satoken.sso.SaSsoProcessor; +import cn.dev33.satoken.stp.StpUtil; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * Sa-Token 配置类 + */ +@Configuration +public class SaTokenConfigure implements WebMvcConfigurer { + + /** + * 注册Sa-Token拦截器,打开注解式鉴权功能 + */ + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册路由拦截器,自定义认证规则 + registry.addInterceptor(new SaInterceptor(handler -> { + // 登录认证 -- 排除登录接口外,其他接口需要登录才能访问 + SaRouter.match("/**") + .notMatch("/user/doLogin") + .notMatch("/sso/*") + .notMatch("/oauth2/*") + .check(r -> StpUtil.checkLogin()); + })).addPathPatterns("/**"); + } + + /** + * SSO-Client端:处理所有SSO相关请求 + * 配置此函数后,可在客户端端通过以下方式完成单点登录功能: + * http://{host}:{port}/sso/login —— Client端登录地址,接受参数:back=登录后的跳转地址 + * http://{host}:{port}/sso/logout —— Client端单点注销地址(isSlo=true时打开),接受参数:back=注销后的跳转地址 + * http://{host}:{port}/sso/logoutCall —— Client端单点注销回调地址(isSlo=true时打开),此接口为框架回调,开发者无需关心 + */ + public void ssoClientDister() { + // 处理SSO相关请求 + SaSsoProcessor.instance.clientDister(); + } +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/security/config/SecurityConfiguration.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/security/config/SecurityConfiguration.java index d23c094..099c65e 100644 --- a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/security/config/SecurityConfiguration.java +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/security/config/SecurityConfiguration.java @@ -24,7 +24,8 @@ public class SecurityConfiguration { registry.requestMatchers("/v3/api-docs/**").permitAll() .requestMatchers("/webjars/**").permitAll() .requestMatchers("/swagger-ui").permitAll() - .requestMatchers("/swagger-ui/**").permitAll(); + .requestMatchers("/swagger-ui/**").permitAll() + ; // Druid 监控 registry.requestMatchers("/druid/**").permitAll(); // Spring Boot Actuator 的安全配置 diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/service/impl/SystemRoleServiceImpl.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/service/impl/SystemRoleServiceImpl.java new file mode 100644 index 0000000..710fb5e --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/service/impl/SystemRoleServiceImpl.java @@ -0,0 +1,269 @@ +package com.tashow.cloud.tashowmoduleuserbiz.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.tashow.cloud.model.SystemRole; +import com.tashow.cloud.model.SystemRoleMenu; +import com.tashow.cloud.model.SystemUserRole; +import com.tashow.cloud.service.SystemRoleService; +import com.tashow.cloud.tashowmoduleuserbiz.mapper.SystemRoleMapper; +import com.tashow.cloud.tashowmoduleuserbiz.mapper.SystemRoleMenuMapper; +import com.tashow.cloud.tashowmoduleuserbiz.mapper.SystemUserRoleMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统角色服务实现类 + */ +@Service +public class SystemRoleServiceImpl extends ServiceImpl implements SystemRoleService { + + @Autowired + private SystemRoleMenuMapper roleMenuMapper; + + @Autowired + private SystemUserRoleMapper userRoleMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean createRole(SystemRole role, List menuIds) { + // 设置默认值 + LocalDateTime now = LocalDateTime.now(); + role.setCreateTime(now); + role.setUpdateTime(now); + role.setDeleted(false); + role.setTenantId(0L); // 默认租户ID + + // 保存角色 + boolean saved = save(role); + if (!saved) { + return false; + } + + // 保存角色菜单关联 + if (!CollectionUtils.isEmpty(menuIds)) { + batchInsertRoleMenus(role.getId(), menuIds, role.getCreator()); + } + + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateRole(SystemRole role, List menuIds) { + // 更新角色基本信息 + role.setUpdateTime(LocalDateTime.now()); + + // 更新角色 + boolean updated = updateById(role); + if (!updated) { + return false; + } + + // 更新角色菜单关联 + if (menuIds != null) { + // 先删除旧的关联 + deleteRoleMenusByRoleId(role.getId()); + + // 添加新的关联 + if (!menuIds.isEmpty()) { + batchInsertRoleMenus(role.getId(), menuIds, role.getUpdater()); + } + } + + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteRole(Long roleId) { + // 逻辑删除角色 + return removeById(roleId); + } + + @Override + public SystemRole getRoleById(Long roleId) { + return getById(roleId); + } + + @Override + public SystemRole getRoleByCode(String code) { + return getOne(new LambdaQueryWrapper() + .eq(SystemRole::getCode, code) + .eq(SystemRole::getStatus, 0) + .eq(SystemRole::getDeleted, false)); + } + + @Override + public List getAllRoles() { + return list(new LambdaQueryWrapper() + .eq(SystemRole::getDeleted, false) + .orderByAsc(SystemRole::getSort)); + } + + @Override + public List getRolesByStatus(Integer status) { + return list(new LambdaQueryWrapper() + .eq(SystemRole::getStatus, status) + .eq(SystemRole::getDeleted, false) + .orderByAsc(SystemRole::getSort)); + } + + /** + * 删除角色菜单关联(逻辑删除) + * + * @param roleId 角色ID + * @return 影响行数 + */ + public int deleteRoleMenus(Long roleId) { + // 创建更新条件 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(SystemRoleMenu::getRoleId, roleId) + .eq(SystemRoleMenu::getDeleted, false) + .set(SystemRoleMenu::getDeleted, true) + .set(SystemRoleMenu::getUpdateTime, LocalDateTime.now()); + + // 执行更新 + return roleMenuMapper.update(null, updateWrapper); + } + + /** + * 根据角色ID删除角色菜单关联(逻辑删除) + * + * @param roleId 角色ID + * @return 影响行数 + */ + public int deleteRoleMenusByRoleId(Long roleId) { + // 创建更新条件 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(SystemRoleMenu::getRoleId, roleId) + .eq(SystemRoleMenu::getDeleted, false) + .set(SystemRoleMenu::getDeleted, true) + .set(SystemRoleMenu::getUpdateTime, LocalDateTime.now()); + + // 执行更新 + return roleMenuMapper.update(null, updateWrapper); + } + + /** + * 批量插入角色菜单关联 + * + * @param roleId 角色ID + * @param menuIds 菜单ID列表 + * @param creator 创建者 + * @return 影响行数 + */ + public int batchInsertRoleMenus(Long roleId, List menuIds, String creator) { + if (CollectionUtils.isEmpty(menuIds)) { + return 0; + } + + LocalDateTime now = LocalDateTime.now(); + List roleMenus = new ArrayList<>(menuIds.size()); + + for (Long menuId : menuIds) { + SystemRoleMenu roleMenu = new SystemRoleMenu(); + roleMenu.setRoleId(roleId); + roleMenu.setMenuId(menuId); + roleMenu.setCreator(creator); + roleMenu.setUpdater(creator); + roleMenu.setCreateTime(now); + roleMenu.setUpdateTime(now); + roleMenu.setDeleted(false); + roleMenu.setTenantId(0L); + roleMenus.add(roleMenu); + } + + // 批量插入 + int count = 0; + for (SystemRoleMenu roleMenu : roleMenus) { + count += roleMenuMapper.insert(roleMenu); + } + + return count; + } + + @Override + public List getRoleMenuIds(Long roleId) { + // 使用LambdaQueryWrapper查询 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SystemRoleMenu::getRoleId, roleId) + .eq(SystemRoleMenu::getDeleted, false) + .select(SystemRoleMenu::getMenuId); + + // 执行查询并转换结果 + return roleMenuMapper.selectList(queryWrapper) + .stream() + .map(SystemRoleMenu::getMenuId) + .collect(Collectors.toList()); + } + + /** + * 根据角色ID列表获取菜单ID列表 + * + * @param roleIds 角色ID列表 + * @return 菜单ID列表 + */ + public List getMenuIdsByRoleIds(List roleIds) { + if (roleIds == null || roleIds.isEmpty()) { + return Collections.emptyList(); + } + + // 创建查询条件 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(SystemRoleMenu::getRoleId, roleIds) + .eq(SystemRoleMenu::getDeleted, false) + .select(SystemRoleMenu::getMenuId); + + // 执行查询并转换结果,确保唯一性 + return roleMenuMapper.selectList(queryWrapper) + .stream() + .map(SystemRoleMenu::getMenuId) + .distinct() + .collect(Collectors.toList()); + } + + @Override + public List getRolesByUserId(Long userId) { + // 先获取用户的角色ID列表 + LambdaQueryWrapper urQueryWrapper = new LambdaQueryWrapper<>(); + urQueryWrapper.eq(SystemUserRole::getUserId, userId) + .eq(SystemUserRole::getDeleted, false) + .select(SystemUserRole::getRoleId); + + List roleIds = userRoleMapper.selectList(urQueryWrapper) + .stream() + .map(SystemUserRole::getRoleId) + .collect(Collectors.toList()); + + if (roleIds.isEmpty()) { + return Collections.emptyList(); + } + + // 然后根据角色ID查询角色信息 + LambdaQueryWrapper rQueryWrapper = new LambdaQueryWrapper<>(); + rQueryWrapper.in(SystemRole::getId, roleIds) + .eq(SystemRole::getStatus, 0) + .eq(SystemRole::getDeleted, false); + + return baseMapper.selectList(rQueryWrapper); + } + + @Override + public boolean updateRoleStatus(Long roleId, Integer status) { + SystemRole role = new SystemRole(); + role.setId(roleId); + role.setStatus(status); + role.setUpdateTime(LocalDateTime.now()); + + return updateById(role); + } +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/service/impl/SystemUserServiceImpl.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/service/impl/SystemUserServiceImpl.java new file mode 100644 index 0000000..b653922 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/tashowmoduleuserbiz/service/impl/SystemUserServiceImpl.java @@ -0,0 +1,425 @@ +package com.tashow.cloud.tashowmoduleuserbiz.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.tashow.cloud.model.SystemRole; +import com.tashow.cloud.model.SystemUser; +import com.tashow.cloud.model.SystemUserRole; +import com.tashow.cloud.model.SystemUserPost; +import com.tashow.cloud.service.SystemUserService; +import com.tashow.cloud.tashowmoduleuserbiz.mapper.SystemUserMapper; +import com.tashow.cloud.tashowmoduleuserbiz.mapper.SystemUserRoleMapper; +import com.tashow.cloud.tashowmoduleuserbiz.mapper.SystemUserPostMapper; +import com.tashow.cloud.tashowmoduleuserbiz.mapper.SystemRoleMapper; +import com.tashow.cloud.convert.SystemRoleConvert; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 系统用户服务实现类 + * 基于MyBatis Plus的查询方式实现 + */ +@Service +public class SystemUserServiceImpl extends ServiceImpl implements SystemUserService { + + private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + + @Autowired + private SystemUserRoleMapper userRoleMapper; + + @Autowired + private SystemUserPostMapper userPostMapper; + + @Autowired + private SystemRoleMapper roleMapper; + + @Override + public SystemUser getUserByUsername(String username) { + return getOne(new LambdaQueryWrapper() + .eq(SystemUser::getUsername, username) + .eq(SystemUser::getStatus, 0) + .eq(SystemUser::getDeleted, false)); + } + + @Override + public boolean validatePassword(String rawPassword, String encodedPassword) { + return passwordEncoder.matches(rawPassword, encodedPassword); + } + + @Override + public SystemUser getUserById(Long userId) { + return getById(userId); + } + + @Override + public void updateLoginInfo(Long userId, String ip) { + SystemUser user = new SystemUser(); + user.setId(userId); + user.setLoginIp(ip); + LocalDateTime now = LocalDateTime.now(); + user.setLoginDate(now); + user.setUpdateTime(now); + updateById(user); + } + + @Override + public boolean registerUser(SystemUser user) { + // 设置默认值 + LocalDateTime now = LocalDateTime.now(); + user.setCreateTime(now); + user.setUpdateTime(now); + user.setLoginDate(now); + user.setCreator("system"); + user.setUpdater("system"); + + if (user.getAvatar() == null || user.getAvatar().isEmpty()) { + user.setAvatar("https://sa-token.cc/logo.png"); // 设置默认头像 + } + + user.setTenantId(0L); // 默认租户ID + user.setDeleted(false); // 设置为未删除 + + return save(user); + } + + @Override + public String encodePassword(String rawPassword) { + return passwordEncoder.encode(rawPassword); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean createUser(SystemUser user, List roleIds, List postIds) { + // 设置默认值 + LocalDateTime now = LocalDateTime.now(); + user.setCreateTime(now); + user.setUpdateTime(now); + user.setLoginDate(now); + + if (user.getAvatar() == null || user.getAvatar().isEmpty()) { + user.setAvatar("https://sa-token.cc/logo.png"); // 设置默认头像 + } + + user.setTenantId(0L); // 默认租户ID + user.setDeleted(false); // 设置为未删除 + + // 加密密码 + user.setPassword(encodePassword(user.getPassword())); + + // 保存用户 + boolean saved = save(user); + if (!saved) { + return false; + } + + // 保存用户角色关联 + if (!CollectionUtils.isEmpty(roleIds)) { + batchInsertUserRoles(user.getId(), roleIds, user.getCreator()); + } + + // 保存用户岗位关联 + if (!CollectionUtils.isEmpty(postIds)) { + batchInsertUserPosts(user.getId(), postIds, user.getCreator()); + } + + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateUser(SystemUser user, List roleIds, List postIds) { + // 更新用户基本信息 + user.setUpdateTime(LocalDateTime.now()); + + // 防止修改密码 + user.setPassword(null); + + // 更新用户 + boolean updated = updateById(user); + if (!updated) { + return false; + } + + // 更新用户角色关联 + if (roleIds != null) { + // 先删除旧的关联 + deleteUserRolesByUserId(user.getId()); + + // 添加新的关联 + if (!roleIds.isEmpty()) { + batchInsertUserRoles(user.getId(), roleIds, user.getUpdater()); + } + } + + // 更新用户岗位关联 + if (postIds != null) { + // 先删除旧的关联 + deleteUserPostsByUserId(user.getId()); + + // 添加新的关联 + if (!postIds.isEmpty()) { + batchInsertUserPosts(user.getId(), postIds, user.getUpdater()); + } + } + + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteUser(Long userId) { + // 逻辑删除用户 + return removeById(userId); + } + + @Override + public boolean resetUserPassword(Long userId, String newPassword) { + SystemUser user = new SystemUser(); + user.setId(userId); + user.setPassword(encodePassword(newPassword)); + user.setUpdateTime(LocalDateTime.now()); + + return updateById(user); + } + + @Override + public boolean updateUserStatus(Long userId, Integer status) { + SystemUser user = new SystemUser(); + user.setId(userId); + user.setStatus(status); + user.setUpdateTime(LocalDateTime.now()); + + return updateById(user); + } + + /** + * 删除用户角色关联(逻辑删除) + * + * @param userId 用户ID + * @return 影响行数 + */ + public int deleteUserRoles(Long userId) { + // 创建更新条件 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(SystemUserRole::getUserId, userId) + .eq(SystemUserRole::getDeleted, false) + .set(SystemUserRole::getDeleted, true) + .set(SystemUserRole::getUpdateTime, LocalDateTime.now()); + + // 执行更新 + return userRoleMapper.update(null, updateWrapper); + } + + /** + * + * 根据用户ID删除用户角色关联(逻辑删除) + * + * @param userId 用户ID + * @return 影响行数 + */ + public int deleteUserRolesByUserId(Long userId) { + // 创建更新条件 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(SystemUserRole::getUserId, userId) + .eq(SystemUserRole::getDeleted, false) + .set(SystemUserRole::getDeleted, true) + .set(SystemUserRole::getUpdateTime, LocalDateTime.now()); + + // 执行更新 + return userRoleMapper.update(null, updateWrapper); + } + + /** + * 根据用户ID删除用户岗位关联(逻辑删除) + * + * @param userId 用户ID + * @return 影响行数 + */ + public int deleteUserPostsByUserId(Long userId) { + // 创建更新条件 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(SystemUserPost::getUserId, userId) + .eq(SystemUserPost::getDeleted, false) + .set(SystemUserPost::getDeleted, true) + .set(SystemUserPost::getUpdateTime, LocalDateTime.now()); + + // 执行更新 + return userPostMapper.update(null, updateWrapper); + } + + /** + * 批量插入用户角色关联 + * + * @param userId 用户ID + * @param roleIds 角色ID列表 + * @param creator 创建者 + * @return 影响行数 + */ + public int batchInsertUserRoles(Long userId, List roleIds, String creator) { + if (CollectionUtils.isEmpty(roleIds)) { + return 0; + } + + LocalDateTime now = LocalDateTime.now(); + List userRoles = new ArrayList<>(roleIds.size()); + + for (Long roleId : roleIds) { + SystemUserRole userRole = new SystemUserRole(); + userRole.setUserId(userId); + userRole.setRoleId(roleId); + userRole.setCreator(creator); + userRole.setUpdater(creator); + userRole.setCreateTime(now); + userRole.setUpdateTime(now); + userRole.setDeleted(false); + userRole.setTenantId(0L); + userRoles.add(userRole); + } + + // 批量插入 + int count = 0; + for (SystemUserRole userRole : userRoles) { + count += userRoleMapper.insert(userRole); + } + + return count; + } + + /** + * 批量插入用户岗位关联 + * + * @param userId 用户ID + * @param postIds 岗位ID列表 + * @param creator 创建者 + * @return 影响行数 + */ + public int batchInsertUserPosts(Long userId, List postIds, String creator) { + if (CollectionUtils.isEmpty(postIds)) { + return 0; + } + + LocalDateTime now = LocalDateTime.now(); + List userPosts = new ArrayList<>(postIds.size()); + + for (Long postId : postIds) { + SystemUserPost userPost = new SystemUserPost(); + userPost.setUserId(userId); + userPost.setPostId(postId); + userPost.setCreator(creator); + userPost.setUpdater(creator); + userPost.setCreateTime(now); + userPost.setUpdateTime(now); + userPost.setDeleted(false); + userPost.setTenantId(0L); + userPosts.add(userPost); + } + + // 批量插入 + int count = 0; + for (SystemUserPost userPost : userPosts) { + count += userPostMapper.insert(userPost); + } + + return count; + } + + /** + * 删除用户岗位关联(逻辑删除) + * + * @param userId 用户ID + * @return 影响行数 + */ + public int deleteUserPosts(Long userId) { + // 创建更新条件 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(SystemUserPost::getUserId, userId) + .eq(SystemUserPost::getDeleted, false) + .set(SystemUserPost::getDeleted, true) + .set(SystemUserPost::getUpdateTime, LocalDateTime.now()); + + // 执行更新 + return userPostMapper.update(null, updateWrapper); + } + + @Override + public List getUserRoleIds(Long userId) { + // 使用LambdaQueryWrapper查询 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SystemUserRole::getUserId, userId) + .eq(SystemUserRole::getDeleted, false) + .select(SystemUserRole::getRoleId); + + return userRoleMapper.selectList(queryWrapper) + .stream() + .map(SystemUserRole::getRoleId) + .collect(Collectors.toList()); + } + + @Override + public List getUserRoleNames(Long userId) { + // 先获取用户角色 + List roles = getUserRoles(userId); + + // 提取角色名称 + return roles.stream() + .map(SystemRole::getName) + .collect(Collectors.toList()); + } + + @Override + public List getUserRoleCodes(Long userId) { + // 先获取用户角色 + List roles = getUserRoles(userId); + + // 提取角色编码 + return roles.stream() + .map(SystemRole::getCode) + .collect(Collectors.toList()); + } + + /** + * 获取用户角色列表 + * + * @param userId 用户ID + * @return 角色列表 + */ + private List getUserRoles(Long userId) { + // 先获取用户的角色ID列表 + List roleIds = getUserRoleIds(userId); + if (roleIds.isEmpty()) { + return Collections.emptyList(); + } + + // 查询这些角色的详细信息 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(SystemRole::getId, roleIds) + .eq(SystemRole::getStatus, 0) + .eq(SystemRole::getDeleted, false); + + return roleMapper.selectList(queryWrapper); + } + + @Override + public List getUserPostIds(Long userId) { + // 使用LambdaQueryWrapper查询 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SystemUserPost::getUserId, userId) + .eq(SystemUserPost::getDeleted, false) + .select(SystemUserPost::getPostId); + + // 执行查询并转换结果 + return userPostMapper.selectList(queryWrapper) + .stream() + .map(SystemUserPost::getPostId) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/user/convert/RoleConvert.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/user/convert/RoleConvert.java new file mode 100644 index 0000000..9eda50a --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/user/convert/RoleConvert.java @@ -0,0 +1,63 @@ +package com.tashow.cloud.user.convert; + +import com.tashow.cloud.user.model.Role; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 角色对象转换器 + */ +@Mapper +public interface RoleConvert { + + RoleConvert INSTANCE = Mappers.getMapper(RoleConvert.class); + + /** + * 将角色列表转换为角色ID列表 + * + * @param roles 角色列表 + * @return 角色ID列表 + */ + default List convertToRoleIds(List roles) { + if (roles == null || roles.isEmpty()) { + return Collections.emptyList(); + } + return roles.stream() + .map(Role::getId) + .collect(Collectors.toList()); + } + + /** + * 将角色列表转换为角色名称列表 + * + * @param roles 角色列表 + * @return 角色名称列表 + */ + default List convertToRoleNames(List roles) { + if (roles == null || roles.isEmpty()) { + return Collections.emptyList(); + } + return roles.stream() + .map(Role::getName) + .collect(Collectors.toList()); + } + + /** + * 将角色列表转换为角色编码列表 + * + * @param roles 角色列表 + * @return 角色编码列表 + */ + default List convertToRoleCodes(List roles) { + if (roles == null || roles.isEmpty()) { + return Collections.emptyList(); + } + return roles.stream() + .map(Role::getCode) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/user/convert/UserConvert.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/user/convert/UserConvert.java new file mode 100644 index 0000000..4d85357 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/user/convert/UserConvert.java @@ -0,0 +1,136 @@ +package com.tashow.cloud.user.convert; + +import com.tashow.cloud.user.dto.UserCreateReqDTO; +import com.tashow.cloud.user.dto.UserRegisterReqDTO; +import com.tashow.cloud.user.dto.UserRespDTO; +import com.tashow.cloud.user.dto.UserUpdateReqDTO; +import com.tashow.cloud.user.model.User; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 用户对象转换器 + */ +@Mapper +public interface UserConvert { + + UserConvert INSTANCE = Mappers.getMapper(UserConvert.class); + + /** + * 用户创建请求DTO转实体 + */ + @Mapping(target = "roles", ignore = true) + @Mapping(target = "createTime", ignore = true) + @Mapping(target = "updateTime", ignore = true) + @Mapping(target = "loginDate", ignore = true) + @Mapping(target = "deleted", ignore = true) + @Mapping(target = "loginIp", ignore = true) + @Mapping(target = "postIds", expression = "java(postIdsToString(bean.getPostIds()))") + User convert(UserCreateReqDTO bean); + + /** + * 用户更新请求DTO转实体 + */ + @Mapping(target = "roles", ignore = true) + @Mapping(target = "username", ignore = true) + @Mapping(target = "password", ignore = true) + @Mapping(target = "createTime", ignore = true) + @Mapping(target = "updateTime", ignore = true) + @Mapping(target = "loginDate", ignore = true) + @Mapping(target = "deleted", ignore = true) + @Mapping(target = "loginIp", ignore = true) + @Mapping(target = "postIds", expression = "java(postIdsToString(bean.getPostIds()))") + User convert(UserUpdateReqDTO bean); + + /** + * 用户注册请求DTO转实体 + */ + @Mapping(target = "roles", ignore = true) + @Mapping(target = "id", ignore = true) + @Mapping(target = "createTime", ignore = true) + @Mapping(target = "updateTime", ignore = true) + @Mapping(target = "loginDate", ignore = true) + @Mapping(target = "deleted", ignore = true) + @Mapping(target = "deptId", ignore = true) + @Mapping(target = "postIds", ignore = true) + @Mapping(target = "sex", ignore = true) + @Mapping(target = "creator", ignore = true) + @Mapping(target = "updater", ignore = true) + @Mapping(target = "tenantId", ignore = true) + @Mapping(target = "remark", ignore = true) + @Mapping(target = "status", constant = "0") + User convert(UserRegisterReqDTO bean); + + /** + * 用户实体转响应DTO + */ + @Mapping(target = "sexName", expression = "java(getSexName(bean.getSex()))") + @Mapping(target = "statusName", expression = "java(getStatusName(bean.getStatus()))") + @Mapping(target = "roleIds", ignore = true) + @Mapping(target = "roleNames", ignore = true) + @Mapping(target = "roleCodes", ignore = true) + @Mapping(target = "postIds", expression = "java(stringToPostIds(bean.getPostIds()))") + @Mapping(target = "postNames", ignore = true) + @Mapping(target = "deptName", ignore = true) + UserRespDTO convert(User bean); + + /** + * 用户实体列表转响应DTO列表 + */ + List convertList(List list); + + /** + * 岗位ID列表转字符串 + */ + default String postIdsToString(List postIds) { + if (postIds == null || postIds.isEmpty()) { + return null; + } + return postIds.stream() + .map(String::valueOf) + .collect(Collectors.joining(",")); + } + + /** + * 字符串转岗位ID列表 + */ + default List stringToPostIds(String postIds) { + if (postIds == null || postIds.isEmpty()) { + return java.util.Collections.emptyList(); + } + return java.util.Arrays.stream(postIds.split(",")) + .map(Long::valueOf) + .collect(Collectors.toList()); + } + + /** + * 获取性别名称 + */ + default String getSexName(Integer sex) { + if (sex == null) { + return null; + } + return switch (sex) { + case 1 -> "男"; + case 2 -> "女"; + default -> "未知"; + }; + } + + /** + * 获取状态名称 + */ + default String getStatusName(Integer status) { + if (status == null) { + return null; + } + return switch (status) { + case 0 -> "正常"; + case 1 -> "停用"; + default -> "未知"; + }; + } +} \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/user/package-info.java b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/user/package-info.java new file mode 100644 index 0000000..19372c4 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/java/com/tashow/cloud/user/package-info.java @@ -0,0 +1,13 @@ +/** + * 用户中心模块业务层实现 + * + *

此模块包含以下主要组件: + *

    + *
  • controller - 控制器层,负责接收和响应HTTP请求
  • + *
  • service - 服务实现层,实现业务逻辑
  • + *
  • mapper - 数据访问层,与数据库交互
  • + *
  • convert - 对象转换层,负责DTO和实体间的转换
  • + *
  • config - 配置类
  • + *
+ */ +package com.tashow.cloud.user; \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/META-INF/services/com.xingyuv.captcha.service.CaptchaCacheService b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/META-INF/services/com.xingyuv.captcha.service.CaptchaCacheService new file mode 100644 index 0000000..3a53b64 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/META-INF/services/com.xingyuv.captcha.service.CaptchaCacheService @@ -0,0 +1 @@ +com.tashow.cloud.tashowmoduleuserbiz.framework.core.RedisCaptchaServiceImpl \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/application-local.yaml b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/application-local.yaml new file mode 100644 index 0000000..ee65c20 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/application-local.yaml @@ -0,0 +1,66 @@ +--- #################### 注册中心 + 配置中心相关配置 #################### + +spring: + cloud: + nacos: + server-addr: 43.139.42.137:8848 # Nacos 服务器地址 + username: nacos # Nacos 账号 + password: nacos # Nacos 密码 + discovery: # 【配置中心】配置项 + namespace: 5c8b8fe6-9a89-4ae3-975e-ef3bf560ff82 # 命名空间。这里使用 dev 开发环境 + group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP + metadata: + version: 1.0.0 # 服务实例的版本号,可用于灰度发布 + config: # 【注册中心】配置项 + namespace: 5c8b8fe6-9a89-4ae3-975e-ef3bf560ff82 # 命名空间。这里使用 dev 开发环境 + group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP + + + + # 数据源配置项 + autoconfigure: + exclude: + - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 + datasource: + druid: # Druid 【监控】相关的全局配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + allow: # 设置白名单,不填则允许所有访问 + url-pattern: /druid/* + login-username: # 控制台管理用户名和密码 + login-password: + filter: + stat: + enabled: true + log-slow-sql: true # 慢 SQL 记录 + slow-sql-millis: 100 + merge-sql: true + wall: + config: + multi-statement-allow: true + dynamic: # 多数据源配置 + druid: # Druid 【连接池】相关的全局配置 + initial-size: 1 # 初始连接数 + min-idle: 1 # 最小连接池数量 + max-active: 20 # 最大连接池数量 + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 + test-while-idle: true + test-on-borrow: false + test-on-return: false + primary: master + datasource: + master: + url: jdbc:mysql://43.139.42.137:8406/tashow-platform?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例 + username: tashow-platform + password: tashow123, +# slave: # 模拟从库,可根据自己需要修改 +# lazy: true # 开启懒加载,保证启动速度 +# url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true +# username: root +# password: 123456 diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/application.yaml b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/application.yaml new file mode 100644 index 0000000..753b388 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/application.yaml @@ -0,0 +1,229 @@ +server: + port: 48082 +spring: + application: + name: user-server + profiles: + active: local + main: + allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。 + allow-bean-definition-overriding: true # 允许 Bean 覆盖,例如说 Feign 等会存在重复定义的服务 + config: + import: + - optional:classpath:application-${spring.profiles.active}.yaml # 加载【本地】配置 + - optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml # 加载【Nacos】的配置 + # Servlet 配置 + servlet: + # 文件上传相关配置项 + multipart: + max-file-size: 16MB # 单个文件大小 + max-request-size: 32MB # 设置总上传的文件大小 + # Jackson 配置项 + jackson: + serialization: + write-dates-as-timestamps: true # 设置 LocalDateTime 的格式,使用时间戳 + write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401 + write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 + fail-on-empty-beans: false # 允许序列化无属性的 Bean + # Cache 配置项 + cache: + type: REDIS + redis: + time-to-live: 1h # 设置过期时间为 1 小时 + + +logging: + file: + name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 + +--- #################### 接口文档配置 #################### + +springdoc: + api-docs: + enabled: true # 1. 是否开启 Swagger 接文档的元数据 + path: /v3/api-docs + swagger-ui: + enabled: true # 2.1 是否开启 Swagger 文档的官方 UI 界面 + path: /swagger-ui + default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 + +knife4j: + enable: true # 2.2 是否开启 Swagger 文档的 Knife4j UI 界面 + setting: + language: zh_cn + +# MyBatis Plus 的配置项 +mybatis-plus: + configuration: + map-underscore-to-camel-case: true #虽然默认为 true ,但是还是显示去指定下。 + global-config: + db-config: + id-type: NONE # "智能"模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。 + logic-delete-value: 1 # 逻辑已删除值(默认为 1) + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) + banner: false # 关闭控制台的 Banner 打印 + type-aliases-package: ${tashow.info.base-package}.dal.dataobject + encryptor: + password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 + +mybatis-plus-join: + banner: false # 关闭控制台的 Banner 打印 + +# Spring Data Redis 配置 +spring: + data: + redis: + repositories: + enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 + + + + +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + +--- #################### RPC 远程调用相关配置 #################### + +--- #################### 消息队列相关 #################### +spring: + # Kafka 配置项,对应 KafkaProperties 配置类 + kafka: + # Kafka Producer 配置项 + producer: + acks: 1 # 0-不应答。1-leader 应答。all-所有 leader 和 follower 应答。 + retries: 3 # 发送失败时,重试发送的次数 + value-serializer: org.springframework.kafka.support.serializer.JsonSerializer # 消息的 value 的序列化 + # Kafka Consumer 配置项 + consumer: + auto-offset-reset: earliest # 设置消费者分组最初的消费进度为 earliest 。可参考博客 https://blog.csdn.net/lishuangzhe7047/article/details/74530417 理解 + value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer + properties: + spring.json.trusted.packages: '*' + # Kafka Consumer Listener 监听器配置 + listener: + missing-topics-fatal: false # 消费监听接口监听的主题不存在时,默认会报错。所以通过设置为 false ,解决报错 + +--- #################### 定时任务相关配置 #################### + +xxl: + job: + executor: + appname: ${spring.application.name} # 执行器 AppName + logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径 + accessToken: default_token # 执行器通讯TOKEN + +--- #################### 验证码相关配置 #################### + +aj: + captcha: + jigsaw: classpath:images/jigsaw # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径 + pic-click: classpath:images/pic-click # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径 + cache-type: redis # 缓存 local/redis... + cache-number: 1000 # local 缓存的阈值,达到这个值,清除缓存 + timing-clear: 180 # local定时清除过期缓存(单位秒),设置为0代表不执行 + type: blockPuzzle # 验证码类型 default两种都实例化。 blockPuzzle 滑块拼图 clickWord 文字点选 + water-mark: 他秀 # 右下角水印文字(我的水印),可使用 https://tool.chinaz.com/tools/unicode.aspx 中文转 Unicode,Linux 可能需要转 unicode + interference-options: 0 # 滑动干扰项(0/1/2) + req-frequency-limit-enable: false # 接口请求次数一分钟限制是否开启 true|false + req-get-lock-limit: 5 # 验证失败5次,get接口锁定 + req-get-lock-seconds: 10 # 验证失败后,锁定时间间隔 + req-get-minute-limit: 30 # get 接口一分钟内请求数限制 + req-check-minute-limit: 60 # check 接口一分钟内请求数限制 + req-verify-minute-limit: 60 # verify 接口一分钟内请求数限制 + +--- #################### 芋道相关配置 #################### + +tashow: + info: + version: 1.0.0 + base-package: com.tashow.cloud.system + web: + admin-ui: + url: http://dashboard.yudao.iocoder.cn # Admin 管理后台 UI 的地址 + xss: + enable: false + exclude-urls: # 如下 url,仅仅是为了演示,去掉配置也没关系 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 + swagger: + title: 管理后台 + description: 提供管理员管理的所有功能 + version: ${tashow.info.version} + tenant: # 多租户相关配置项 + enable: true + ignore-urls: + - /admin-api/system/tenant/get-id-by-name # 基于名字获取租户,不许带租户编号 + - /admin-api/system/tenant/get-by-website # 基于域名获取租户,不许带租户编号 + - /admin-api/system/captcha/get-image # 获取图片验证码,和租户无关 + - /admin-api/system/captcha/get # 获取图片验证码,和租户无关 + - /admin-api/system/captcha/check # 校验图片验证码,和租户无关 + - /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号 + - /rpc-api/system/tenant/valid # 防止递归。避免调用 /rpc-api/system/tenant/valid 接口时,又去触发 /rpc-api/system/tenant/valid 去校验 + - /rpc-api/system/tenant/id-list # 获得租户列表的时候,无需传递租户编号 + - /rpc-api/system/oauth2/token/check # 访问令牌校验时,无需传递租户编号;主要解决上传文件的场景,前端不会传递 tenant-id! + ignore-tables: + - system_tenant + - system_tenant_package + - system_dict_data + - system_dict_type + - system_error_code + - system_menu + - system_sms_channel + - system_sms_template + - system_sms_log + - system_sensitive_word + - system_oauth2_client + - system_mail_account + - system_mail_template + - system_mail_log + - system_notify_template + ignore-caches: + - user_role_ids + - permission_menu_ids + - oauth_client + - notify_template + - mail_account + - mail_template + - sms_template + sms-code: # 短信验证码相关的配置项 + expire-times: 10m + send-frequency: 1m + send-maximum-quantity-per-day: 10 + begin-code: 9999 # 这里配置 9999 的原因是,测试方便。 + end-code: 9999 # 这里配置 9999 的原因是,测试方便。 + +debug: false + + +sa-token: + # token名称 + token-name: satoken + # token有效期 + timeout: 2592000 + # token临时有效期 + activity-timeout: -1 + # 是否允许同一账号并发登录 + is-concurrent: true + # 多人登录时,是否共用一个token + is-share: false + # token风格 + token-style: uuid + # 是否输出操作日志 + is-log: false + + # SSO-Client端相关配置 + sso: + # SSO-Server端 统一认证地址 + auth-url: http://localhost:48082/sso/auth + # 是否打开单点注销功能 + is-slo: true + # 单点登录查询ticket参数名称 + ticket-param-name: ticket + # 打开模式三(此值为true时需要配置下面所有参数) + is-http: true + # 请求秘钥 与SSO-Server端保持一致 + secretkey: kQwIOrYvnXmSDkwEiFngrKidMcdrgKor + # SSO-Server端 ticket校验地址 + check-ticket-url: http://localhost:48082/sso/checkTicket + # SSO-Server端 查询userinfo地址 + userinfo-url: http://localhost:48082/sso/userinfo \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg1.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg1.png new file mode 100644 index 0000000..c481457 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg1.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg2.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg2.png new file mode 100644 index 0000000..bf8fb38 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg2.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg3.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg3.png new file mode 100644 index 0000000..f871d3d Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg3.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg4.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg4.png new file mode 100644 index 0000000..2e3d871 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg4.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg5.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg5.png new file mode 100644 index 0000000..fe383b7 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg5.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg6.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg6.png new file mode 100644 index 0000000..5024ceb Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg6.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg7.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg7.png new file mode 100644 index 0000000..efe76f8 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg7.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg8.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg8.png new file mode 100644 index 0000000..2727aa3 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg8.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg9.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg9.png new file mode 100644 index 0000000..4463aa2 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/original/bg9.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/1.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/1.png new file mode 100644 index 0000000..ef11324 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/1.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/10.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/10.png new file mode 100644 index 0000000..297e44c Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/10.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/11.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/11.png new file mode 100644 index 0000000..d9b1da8 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/11.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/12.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/12.png new file mode 100644 index 0000000..07e7313 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/12.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/13.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/13.png new file mode 100644 index 0000000..82c3dd9 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/13.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/14.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/14.png new file mode 100644 index 0000000..0b9a866 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/14.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/15.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/15.png new file mode 100644 index 0000000..86b0d1c Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/15.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/16.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/16.png new file mode 100644 index 0000000..e90a6e2 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/16.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/17.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/17.png new file mode 100644 index 0000000..a82cbc7 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/17.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/18.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/18.png new file mode 100644 index 0000000..d3f3cfd Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/18.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/19.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/19.png new file mode 100644 index 0000000..eb2855b Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/19.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/8.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/8.png new file mode 100644 index 0000000..3cb5ce1 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/8.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/9.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/9.png new file mode 100644 index 0000000..384d354 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/11/9.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/2.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/2.png new file mode 100644 index 0000000..baf3f06 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/2.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/3.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/3.png new file mode 100644 index 0000000..ccaf617 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/3.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/4.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/4.png new file mode 100644 index 0000000..7dab162 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/jigsaw/slidingBlock/4.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg1.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg1.png new file mode 100644 index 0000000..14e7345 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg1.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg10.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg10.png new file mode 100644 index 0000000..1ea1d6d Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg10.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg2.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg2.png new file mode 100644 index 0000000..0edb329 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg2.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg3.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg3.png new file mode 100644 index 0000000..9167996 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg3.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg4.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg4.png new file mode 100644 index 0000000..e8e8e6c Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg4.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg5.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg5.png new file mode 100644 index 0000000..66a3181 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg5.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg6.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg6.png new file mode 100644 index 0000000..9b0f5d8 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg6.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg7.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg7.png new file mode 100644 index 0000000..db41c74 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg7.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg8.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg8.png new file mode 100644 index 0000000..3496813 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg8.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg9.png b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg9.png new file mode 100644 index 0000000..4e7b477 Binary files /dev/null and b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/images/pic-click/bg9.png differ diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/inde.html b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/inde.html new file mode 100644 index 0000000..566549b --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/inde.html @@ -0,0 +1,10 @@ + + + + + Title + + + + + \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/logback-spring.xml b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..16f0c0f --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/logback-spring.xml @@ -0,0 +1,76 @@ + + + + + + + + + +       + + + ${PATTERN_DEFAULT} + + + + + + + + + + ${PATTERN_DEFAULT} + + + + ${LOG_FILE} + + + ${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz} + + ${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false} + + ${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB} + + ${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0} + + ${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30} + + + + + + 0 + + 256 + + + + + + + + ${PATTERN_DEFAULT} + + + + + + + + + + + + + + + + + + + + + + diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/mapper/SystemRoleMenuMapper.xml b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/mapper/SystemRoleMenuMapper.xml new file mode 100644 index 0000000..24b0b0d --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/mapper/SystemRoleMenuMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + + + UPDATE system_role_menu + SET deleted = 1, + update_time = NOW() + WHERE role_id = #{roleId} + AND deleted = 0 + + + + INSERT INTO system_role_menu (role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id) + VALUES + + (#{roleId}, #{menuId}, #{creator}, NOW(), #{creator}, NOW(), 0, 0) + + + + \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/mapper/SystemUserPostMapper.xml b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/mapper/SystemUserPostMapper.xml new file mode 100644 index 0000000..ddf9410 --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/mapper/SystemUserPostMapper.xml @@ -0,0 +1,23 @@ + + + + + + + UPDATE system_user_post + SET deleted = 1, + update_time = NOW() + WHERE user_id = #{userId} + AND deleted = 0 + + + + + INSERT INTO system_user_post (user_id, post_id, creator, create_time, updater, update_time, deleted, tenant_id) + VALUES + + (#{userId}, #{postId}, #{creator}, NOW(), #{creator}, NOW(), 0, 0) + + + + \ No newline at end of file diff --git a/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/mapper/SystemUserRoleMapper.xml b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/mapper/SystemUserRoleMapper.xml new file mode 100644 index 0000000..e40d60f --- /dev/null +++ b/tashow-module/tashow-module-user/tashow-module-user-biz/src/main/resources/mapper/SystemUserRoleMapper.xml @@ -0,0 +1,23 @@ + + + + + + + UPDATE system_user_role + SET deleted = 1, + update_time = NOW() + WHERE user_id = #{userId} + AND deleted = 0 + + + + + INSERT INTO system_user_role (user_id, role_id, creator, create_time, updater, update_time, deleted, tenant_id) + VALUES + + (#{userId}, #{roleId}, #{creator}, NOW(), #{creator}, NOW(), 0, 0) + + + + \ No newline at end of file