From 4b5c9736b845d8bb4db05158e54a01dc3332a11a Mon Sep 17 00:00:00 2001 From: "1576302867@qq.com" <1576302867@qq.com> Date: Tue, 19 Dec 2023 03:50:18 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9B=86=E6=88=90Authing=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- charts/README.md | 14 +-- mvnw.cmd | 2 +- .../qing/config/QingConfiguration.java | 16 ++- .../qing/config/security/SecurityConfig.java | 12 -- .../CustomAuthenticationFailureHandler.java | 8 +- .../CustomAuthenticationSuccessHandler.java | 38 ++++++ .../handler/CustomLogoutSuccessHandler.java | 4 +- ...SignUpUrlAuthenticationSuccessHandler.java | 103 ++++++++++++++++ .../auth/connection/UserConnection.java | 110 +++++++++++++++++ .../controller/UserConnectionController.java | 109 +++++++++++++++++ .../MyConnectionService.java | 32 ++++- .../dto/creator/UserConnectionCreator.java | 80 +++++++++++++ .../dto/query/UserConnectionQuery.java | 9 ++ .../request/UserConnectionCreateRequest.java | 75 ++++++++++++ .../request/UserConnectionQueryRequest.java | 10 ++ .../request/UserConnectionUpdateRequest.java | 85 ++++++++++++++ .../dto/response/UserConnectionResponse.java | 79 +++++++++++++ .../dto/updater/UserConnectionUpdater.java | 101 ++++++++++++++++ .../connection/dto/vo/UserConnectionVO.java | 108 +++++++++++++++++ .../mapper/UserConnectionMapper.java | 51 ++++++++ .../repository/UserConnectionRepository.java | 13 ++ .../service/IUserConnectionService.java | 40 +++++++ .../service/UserConnectionFeignService.java | 58 +++++++++ .../impl/UserConnectionServiceImpl.java | 95 +++++++++++++++ .../auth/user/{User.java => QingUser.java} | 2 +- .../user/controller/QingUserController.java | 100 ++++++++++++++++ .../domainservice/IUserDomainService.java | 14 +-- .../UmsUserDetailsServiceImpl.java | 31 +++-- .../user/dto/creator/QingUserCreator.java | 69 +++++++++++ .../auth/user/dto/creator/UserCreator.java | 79 ------------- .../auth/user/dto/query/QingUserQuery.java | 9 ++ .../dto/request/QingUserCreateRequest.java | 78 ++++++++++++ .../dto/request/QingUserQueryRequest.java | 10 ++ .../dto/request/QingUserUpdateRequest.java | 88 ++++++++++++++ .../user/dto/response/QingUserResponse.java | 82 +++++++++++++ .../user/dto/updater/QingUserUpdater.java | 103 ++++++++++++++++ .../auth/user/dto/updater/UserUpdater.java | 4 +- .../domain/auth/user/dto/vo/QingUserVO.java | 111 ++++++++++++++++++ .../qing/domain/auth/user/dto/vo/UserVO.java | 4 +- .../auth/user/mapper/QingUserMapper.java | 41 +++++++ .../domain/auth/user/mapper/UserMapper.java | 6 +- .../user/repository/QingUserRepository.java | 7 ++ .../auth/user/repository/UserRepository.java | 8 +- .../auth/user/service/IQingUserService.java | 40 +++++++ .../auth/user/service/IUserService.java | 4 +- .../user/service/QingUserFeignService.java | 58 +++++++++ .../service/impl/QingUserServiceImpl.java | 95 +++++++++++++++ .../user/service/impl/UserServiceImpl.java | 10 +- .../qing/domain/zan/LikeModel.java | 4 +- .../domain/zan/filters/UserQueryFilter.java | 6 +- .../zan/service/impl/ZanServiceImpl.java | 8 +- .../src/main/resources/application-dev.yml | 2 +- .../entity/service/IEntityServiceTest.java | 10 +- ...iceTest.java => IQingUserServiceTest.java} | 2 +- qing-domain/src/test/resources/zhangli.sql | 8 +- .../base/JwtAuthenticationTokenFilter.java | 7 +- .../security/config/SecurityConfig.java | 17 --- .../CustomAuthenticationSuccessHandler.java | 27 ----- .../authing/AuthingLoginConfigurer.java | 46 ++++---- .../authing/AuthingLoginFilter.java | 13 -- .../configures/authing/AuthingProvider.java | 28 ++++- .../my/MyAuthenticationSuccessHandler.java | 2 - .../security/entity/AuthToken.java | 2 +- .../service/UserDetailsRegisterService.java | 5 +- .../security/signup/ConnectionService.java | 18 ++- .../main/resources/META-INF/spring.factories | 1 - ...ot.autoconfigure.AutoConfiguration.imports | 3 +- sql/scripts/migrate.sql | 4 +- sql/scripts/qing.sql | 10 +- 69 files changed, 2244 insertions(+), 284 deletions(-) rename {qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security => qing-domain/src/main/java/cn/chenyunlong/qing}/config/security/handler/CustomAuthenticationFailureHandler.java (72%) create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/CustomAuthenticationSuccessHandler.java rename {qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security => qing-domain/src/main/java/cn/chenyunlong/qing}/config/security/handler/CustomLogoutSuccessHandler.java (93%) create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/DemoSignUpUrlAuthenticationSuccessHandler.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/UserConnection.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/controller/UserConnectionController.java rename qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/{ => domainservice}/MyConnectionService.java (70%) create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/creator/UserConnectionCreator.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/query/UserConnectionQuery.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionCreateRequest.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionQueryRequest.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionUpdateRequest.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/response/UserConnectionResponse.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/updater/UserConnectionUpdater.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/vo/UserConnectionVO.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/mapper/UserConnectionMapper.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/repository/UserConnectionRepository.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/IUserConnectionService.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/UserConnectionFeignService.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/impl/UserConnectionServiceImpl.java rename qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/{User.java => QingUser.java} (97%) create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/controller/QingUserController.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/creator/QingUserCreator.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/query/QingUserQuery.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserCreateRequest.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserQueryRequest.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserUpdateRequest.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/response/QingUserResponse.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/updater/QingUserUpdater.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/vo/QingUserVO.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/mapper/QingUserMapper.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/repository/QingUserRepository.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/IQingUserService.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/QingUserFeignService.java create mode 100644 qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/impl/QingUserServiceImpl.java rename qing-domain/src/test/java/cn/chenyunlong/qing/domain/user/service/{IUserServiceTest.java => IQingUserServiceTest.java} (95%) delete mode 100644 qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/SecurityConfig.java delete mode 100644 qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/security/handler/CustomAuthenticationSuccessHandler.java diff --git a/charts/README.md b/charts/README.md index 14991e1ba..7229b9384 100644 --- a/charts/README.md +++ b/charts/README.md @@ -54,7 +54,7 @@ helm install qing qing/qing | Name | Description | Value | |----------------------|----------------------------------------------------------------------|-------------------------| | `qingUsername` | Qing username | `admin` | -| `qingPassword` | Qing user password | `""` | +| `qingPassword` | Qing qingUser password | `""` | | `existingSecret` | Name of existing secret containing Qing credentials | `""` | | `qingExternalUrl` | 外部访问地址,请根据实际需要修改 | `http://localhost:8090` | | `qingScheme` | Scheme to use to generate Qing URLs | `http` | @@ -72,8 +72,8 @@ helm install qing qing/qing | `postgresql.architecture` | PostgreSQL architecture. Allowed values: `standalone` or `replication` | `standalone` | | `postgresql.auth.rootPassword` | PostgreSQL root password | `""` | | `postgresql.auth.database` | PostgreSQL custom database | `qing` | -| `postgresql.auth.username` | PostgreSQL custom user name | `qing` | -| `postgresql.auth.password` | PostgreSQL custom user password | `""` | +| `postgresql.auth.username` | PostgreSQL custom qingUser name | `qing` | +| `postgresql.auth.password` | PostgreSQL custom qingUser password | `""` | | `postgresql.primary.persistence.enabled` | Enable persistence on PostgreSQL using PVC(s) | `true` | | `postgresql.primary.persistence.storageClass` | Persistent Volume storage class | `""` | | `postgresql.primary.persistence.accessModes` | Persistent Volume access modes | `[]` | @@ -82,8 +82,8 @@ helm install qing qing/qing | `mysql.architecture` | MySQL architecture. Allowed values: `standalone` or `replication` | `standalone` | | `mysql.auth.rootPassword` | MySQL root password | `""` | | `mysql.auth.database` | MySQL custom database | `qing` | -| `mysql.auth.username` | MySQL custom user name | `qing` | -| `mysql.auth.password` | MySQL custom user password | `""` | +| `mysql.auth.username` | MySQL custom qingUser name | `qing` | +| `mysql.auth.password` | MySQL custom qingUser password | `""` | | `mysql.primary.persistence.enabled` | Enable persistence on MySQL using PVC(s) | `true` | | `mysql.primary.persistence.storageClass` | Persistent Volume storage class | `""` | | `mysql.primary.persistence.accessModes` | Persistent Volume access modes | `[]` | @@ -91,8 +91,8 @@ helm install qing qing/qing | `externalDatabase.platform` | External Database platform | `postgresql` | | `externalDatabase.host` | External Database server host | `""` | | `externalDatabase.port` | External Database server port | `""` | -| `externalDatabase.user` | External Database username | `""` | -| `externalDatabase.password` | External Database user password | `""` | +| `externalDatabase.qingUser` | External Database username | `""` | +| `externalDatabase.password` | External Database qingUser password | `""` | | `externalDatabase.database` | External Database database name | `""` | | `externalDatabase.existingSecret` | The name of an existing secret with database credentials. Evaluated as a template | `""` | diff --git a/mvnw.cmd b/mvnw.cmd index 86115719e..49bde1ffd 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -43,7 +43,7 @@ title %0 @REM set %HOME% to equivalent of $HOME if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") -@REM Execute a user defined script before this one +@REM Execute a qingUser defined script before this one if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre @REM check for pre script, once with legacy .bat ending and once with .cmd ending if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/config/QingConfiguration.java b/qing-domain/src/main/java/cn/chenyunlong/qing/config/QingConfiguration.java index d2c52925c..84b3df428 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/config/QingConfiguration.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/config/QingConfiguration.java @@ -20,22 +20,26 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import java.security.KeyPair; -import java.util.Collections; -import javax.net.ssl.SSLContext; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.config.AuthConfig; import me.zhyd.oauth.request.AuthGithubRequest; import org.apache.http.ssl.SSLContextBuilder; import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.rsa.crypto.KeyStoreKeyFactory; import org.springframework.web.client.RestTemplate; +import javax.net.ssl.SSLContext; +import java.security.KeyPair; +import java.util.Collections; + /** * 全局配置 * @@ -103,4 +107,10 @@ public KeyPair keyPair() { new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "123456".toCharArray()); return keyStoreKeyFactory.getKeyPair("jwt", "123456".toCharArray()); } + + @Bean + @ConditionalOnMissingBean(PasswordEncoder.class) + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } } diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/SecurityConfig.java b/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/SecurityConfig.java index c8e437325..8d223b738 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/SecurityConfig.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/SecurityConfig.java @@ -13,11 +13,9 @@ package cn.chenyunlong.qing.config.security; -import cn.chenyunlong.security.base.JwtAuthenticationTokenFilter; import cn.chenyunlong.security.base.extension.DummyUserContextAware; import cn.chenyunlong.security.base.extension.UserContextAware; import cn.chenyunlong.security.config.SecurityCommonProperties; -import cn.chenyunlong.security.config.security.entrypoint.CustomAuthenticationEntryPoint; import cn.chenyunlong.security.configures.authing.AuthingLoginConfigurer; import cn.chenyunlong.security.configures.authing.properties.AuthingProperties; import jakarta.annotation.Resource; @@ -29,7 +27,6 @@ import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.SecurityFilterChain; /** @@ -64,13 +61,4 @@ public SecurityFilterChain userLoginFilterChain(HttpSecurity http) throws Except return http.build(); } - @Bean - public JwtAuthenticationTokenFilter authenticationTokenFilterBean() { - return new JwtAuthenticationTokenFilter(); - } - - @Bean - public AuthenticationEntryPoint entrypoint() { - return new CustomAuthenticationEntryPoint(); - } } diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/security/handler/CustomAuthenticationFailureHandler.java b/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/CustomAuthenticationFailureHandler.java similarity index 72% rename from qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/security/handler/CustomAuthenticationFailureHandler.java rename to qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/CustomAuthenticationFailureHandler.java index f014cf765..93378dee6 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/security/handler/CustomAuthenticationFailureHandler.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/CustomAuthenticationFailureHandler.java @@ -1,5 +1,6 @@ -package cn.chenyunlong.security.config.security.handler; +package cn.chenyunlong.qing.config.security.handler; +import cn.chenyunlong.common.model.JsonResult; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; @@ -16,8 +17,7 @@ public class CustomAuthenticationFailureHandler implements AuthenticationFailure @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { ObjectMapper mapper = new ObjectMapper(); - response.setStatus(200); - response.getWriter().write("{构建成功}"); - response.setContentType("application/json;charset=utf-8"); + response.setStatus(HttpServletResponse.SC_BAD_GATEWAY); + response.getWriter().write(mapper.writeValueAsString(JsonResult.fail(null, "登录失败:" + exception.getMessage()))); } } diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/CustomAuthenticationSuccessHandler.java b/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/CustomAuthenticationSuccessHandler.java new file mode 100644 index 000000000..fb540b0e5 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/CustomAuthenticationSuccessHandler.java @@ -0,0 +1,38 @@ +package cn.chenyunlong.qing.config.security.handler; + +import cn.chenyunlong.common.model.JsonResult; +import cn.chenyunlong.security.userdetails.TemporaryUser; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.MediaType; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +/** + * 定制成功处理器 + */ +@Component +public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, + Authentication authentication) throws IOException { + + ObjectMapper mapper = new ObjectMapper(); + + // start: 判断是否为临时用户, 进行相关逻辑的处理 + final Object principal = authentication.getPrincipal(); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + if (principal instanceof TemporaryUser temporaryUser) { + // 自己的处理逻辑, 如返回 json 数据 + // ... + response.getWriter().write(mapper.writeValueAsString(JsonResult.success(temporaryUser.toString()))); + } else { + response.getWriter().write(mapper.writeValueAsString(JsonResult.success(principal))); + } + } +} diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/security/handler/CustomLogoutSuccessHandler.java b/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/CustomLogoutSuccessHandler.java similarity index 93% rename from qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/security/handler/CustomLogoutSuccessHandler.java rename to qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/CustomLogoutSuccessHandler.java index 1e2abb6fe..3b0f9501f 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/security/handler/CustomLogoutSuccessHandler.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/CustomLogoutSuccessHandler.java @@ -11,7 +11,7 @@ * */ -package cn.chenyunlong.security.config.security.handler; +package cn.chenyunlong.qing.config.security.handler; import cn.chenyunlong.common.model.ApiResult; import cn.hutool.json.JSONUtil; @@ -20,7 +20,6 @@ import org.springframework.http.MediaType; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; -import org.springframework.stereotype.Component; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -30,7 +29,6 @@ * * @author 陈云龙 */ -@Component public class CustomLogoutSuccessHandler implements LogoutSuccessHandler { @Override diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/DemoSignUpUrlAuthenticationSuccessHandler.java b/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/DemoSignUpUrlAuthenticationSuccessHandler.java new file mode 100644 index 000000000..5b84c771e --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/config/security/handler/DemoSignUpUrlAuthenticationSuccessHandler.java @@ -0,0 +1,103 @@ +/* + * MIT License + * Copyright (c) 2020-2029 YongWu zheng (dcenter.top and gitee.com/pcore and github.com/ZeroOrInfinity) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package cn.chenyunlong.qing.config.security.handler; + +import cn.chenyunlong.security.userdetails.TemporaryUser; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.savedrequest.RequestCache; +import org.springframework.security.web.savedrequest.SavedRequest; + +import java.io.IOException; + +import static org.springframework.util.StringUtils.hasText; + +/** + * 演示 signUpUrl 设置为 null 时的一种处理方式 + * + * @author YongWu zheng + * @version V2.0 Created by 2020/10/30 10:19 + */ +public class DemoSignUpUrlAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { + private RequestCache requestCache = new HttpSessionRequestCache(); + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, + HttpServletResponse response, Authentication authentication) + throws IOException { + + + // start: 判断是否为临时用户, 进行相关逻辑的处理 + final Object principal = authentication.getPrincipal(); + if (principal instanceof TemporaryUser) { + TemporaryUser temporaryUser = ((TemporaryUser) principal); + // 自己的处理逻辑, 如返回 json 数据 + // ... + + return; + } + // end: 判断是否为临时用户, 进行相关逻辑的处理 + + String targetUrl = null; + if (isAlwaysUseDefaultTargetUrl()) { + targetUrl = getDefaultTargetUrl(); + } else { + String targetUrlParameter = getTargetUrlParameter(); + if (targetUrlParameter != null && hasText(request.getParameter(targetUrlParameter))) { + String parameterUrl = request.getParameter(targetUrlParameter); + if (hasText(parameterUrl)) { + targetUrl = parameterUrl; + } + } else { + // Use the DefaultSavedRequest URL + SavedRequest savedRequest = requestCache.getRequest(request, response); + if (savedRequest != null) { + targetUrl = savedRequest.getRedirectUrl(); + } + } + } + + clearAuthenticationAttributes(request); + + if (!hasText(targetUrl)) { + targetUrl = getDefaultTargetUrl(); + } + + logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl); + +// if (isAjaxOrJson(request)) { +// responseWithJson(response, HttpStatus.OK.value(), toJsonString(ResponseResult.success("url", targetUrl))); +// return; +// } + + getRedirectStrategy().sendRedirect(request, response, targetUrl); + } + + @Override + public void setRequestCache(RequestCache requestCache) { + this.requestCache = requestCache; + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/UserConnection.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/UserConnection.java new file mode 100644 index 000000000..f7b5fa16e --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/UserConnection.java @@ -0,0 +1,110 @@ +/* + * Copyright 2015 the original author or authors. + * + * 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 cn.chenyunlong.qing.domain.auth.connection; + + +import cn.chenyunlong.codegen.annotation.*; +import cn.chenyunlong.jpa.support.BaseJpaAggregate; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.*; + +/** + * A data transfer object that allows the internal state of a Connection to be persisted and transferred between layers of an application. + * Some fields may be null . + * For example, an OAuth2Connection has a null 'secret' field while an OAuth1Connection has null 'refreshToken' and 'expireTime' fields. + * + * @author Keith Donald + * @author YongWu zheng + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@ToString +@GenVo +@GenCreator +@GenUpdater +@GenQuery +@GenCreateRequest +@GenUpdateRequest +@GenQueryRequest +@GenResponse +@GenRepository +@GenService +@GenServiceImpl +@GenFeign(serverName = "stanic") +@GenController +@GenMapper +@Entity +@Table(name = "sys_user_connection") +public class UserConnection extends BaseJpaAggregate { + + /** + * 本地用户id + */ + private String userId; + /** + * 第三方服务商 + */ + private String providerId; + /** + * 第三方用户id + */ + private String providerUserId; + + /** + * userId 绑定同一个 providerId 的排序 + */ + private Integer rank; + /** + * 第三方用户名 + */ + private String displayName; + /** + * 主页 + */ + private String profileUrl; + /** + * 头像 + */ + private String imageUrl; + /** + * accessToken + */ + private String accessToken; + /** + * auth_token.id + */ + private Long tokenId; + /** + * refreshToken + */ + private String refreshToken; + + /** + * 过期日期, 基于 1970-01-01T00:00:00Z, 无过期时间默认为 -1 + */ + private Long expireTime; + + + @Override + public void init() { + super.init(); + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/controller/UserConnectionController.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/controller/UserConnectionController.java new file mode 100644 index 000000000..47b62d022 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/controller/UserConnectionController.java @@ -0,0 +1,109 @@ +package cn.chenyunlong.qing.domain.auth.connection.controller; + +import cn.chenyunlong.common.constants.CodeEnum; +import cn.chenyunlong.common.model.JsonResult; +import cn.chenyunlong.common.model.PageRequestWrapper; +import cn.chenyunlong.common.model.PageResult; +import cn.chenyunlong.qing.domain.auth.connection.dto.creator.UserConnectionCreator; +import cn.chenyunlong.qing.domain.auth.connection.dto.query.UserConnectionQuery; +import cn.chenyunlong.qing.domain.auth.connection.dto.request.UserConnectionCreateRequest; +import cn.chenyunlong.qing.domain.auth.connection.dto.request.UserConnectionQueryRequest; +import cn.chenyunlong.qing.domain.auth.connection.dto.request.UserConnectionUpdateRequest; +import cn.chenyunlong.qing.domain.auth.connection.dto.response.UserConnectionResponse; +import cn.chenyunlong.qing.domain.auth.connection.dto.updater.UserConnectionUpdater; +import cn.chenyunlong.qing.domain.auth.connection.dto.vo.UserConnectionVO; +import cn.chenyunlong.qing.domain.auth.connection.mapper.UserConnectionMapper; +import cn.chenyunlong.qing.domain.auth.connection.service.IUserConnectionService; + +import java.lang.Long; +import java.lang.String; +import java.util.stream.Collectors; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Slf4j +@RequestMapping("api/v1/user-connection") +@RequiredArgsConstructor +public class UserConnectionController { + private final IUserConnectionService userConnectionService; + + /** + * createRequest + */ + @PostMapping + public JsonResult createUserConnection(@RequestBody UserConnectionCreateRequest request) { + UserConnectionCreator creator = UserConnectionMapper.INSTANCE.request2Dto(request); + return JsonResult.success(userConnectionService.createUserConnection(creator)); + } + + /** + * update request + */ + @PostMapping("updateUserConnection") + public JsonResult updateUserConnection( + @RequestBody UserConnectionUpdateRequest request) { + UserConnectionUpdater updater = UserConnectionMapper.INSTANCE.request2Updater(request); + userConnectionService.updateUserConnection(updater); + return JsonResult.success(CodeEnum.Success.getName()); + } + + /** + * valid + */ + @PostMapping("valid/{id}") + public JsonResult validUserConnection(@PathVariable Long id) { + userConnectionService.validUserConnection(id); + return JsonResult.success(CodeEnum.Success.getName()); + } + + /** + * invalid + */ + @PostMapping("invalid/{id}") + public JsonResult invalidUserConnection(@PathVariable Long id) { + userConnectionService.invalidUserConnection(id); + return JsonResult.success(CodeEnum.Success.getName()); + } + + /** + * findById + */ + @GetMapping("findById/{id}") + public JsonResult findById(@PathVariable Long id) { + UserConnectionVO vo = userConnectionService.findById(id); + UserConnectionResponse response = UserConnectionMapper.INSTANCE.vo2CustomResponse(vo); + return JsonResult.success(response); + } + + /** + * findByPage request + */ + @PostMapping("page") + public JsonResult> page( + @RequestBody PageRequestWrapper request) { + PageRequestWrapper wrapper = new PageRequestWrapper<>(); + wrapper.setBean(UserConnectionMapper.INSTANCE.request2Query(request.getBean())); + wrapper.setSorts(request.getSorts()); + wrapper.setPageSize(request.getPageSize()); + wrapper.setPage(request.getPage()); + Page page = userConnectionService.findByPage(wrapper); + return JsonResult.success( + PageResult.of( + page.getContent().stream() + .map(UserConnectionMapper.INSTANCE::vo2CustomResponse) + .collect(Collectors.toList()), + page.getTotalElements(), + page.getSize(), + page.getNumber()) + ); + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/MyConnectionService.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/domainservice/MyConnectionService.java similarity index 70% rename from qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/MyConnectionService.java rename to qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/domainservice/MyConnectionService.java index a838b4e29..8eb91d9d9 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/MyConnectionService.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/domainservice/MyConnectionService.java @@ -1,6 +1,11 @@ -package cn.chenyunlong.qing.domain.auth.connection; +package cn.chenyunlong.qing.domain.auth.connection.domainservice; +import cn.chenyunlong.qing.domain.auth.connection.dto.creator.UserConnectionCreator; +import cn.chenyunlong.qing.domain.auth.connection.mapper.UserConnectionMapper; +import cn.chenyunlong.qing.domain.auth.connection.repository.UserConnectionRepository; +import cn.chenyunlong.qing.domain.auth.connection.service.IUserConnectionService; import cn.chenyunlong.security.configures.authing.properties.AuthingProperties; +import cn.chenyunlong.security.entity.AuthToken; import cn.chenyunlong.security.entity.AuthUser; import cn.chenyunlong.security.entity.ConnectionData; import cn.chenyunlong.security.enums.ErrorCodeEnum; @@ -16,6 +21,7 @@ import org.springframework.util.MultiValueMap; import java.util.List; +import java.util.stream.Collectors; @Slf4j @Service @@ -24,13 +30,14 @@ public class MyConnectionService implements ConnectionService { private final UmsUserDetailsService userDetailsService; private final AuthingProperties authingProperties; + private final IUserConnectionService userConnectionService; + private final UserConnectionRepository connectionRepository; + @Override public UserDetails signUp(AuthUser authUser, String providerId, String encodeState) throws RegisterUserFailureException { - String username = authUser.getUsername(); String[] usernames = userDetailsService.generateUsernames(authUser); - try { // 重名检查 username = null; @@ -65,7 +72,19 @@ public UserDetails signUp(AuthUser authUser, String providerId, String encodeSta * @param userDetails 用户详情 */ private void registerConnection(String providerId, AuthUser authUser, UserDetails userDetails) { - + AuthToken token = authUser.getToken(); + UserConnectionCreator creator = UserConnectionCreator.builder() + .accessToken(authUser.getToken().getAccessToken()) + .providerId(providerId) + .displayName(authUser.getUsername()) + .rank(1) + .imageUrl(authUser.getAvatar()) + .refreshToken(authUser.getToken().getRefreshToken()) + .expireTime(authUser.getToken().getExpireIn()) + .userId(userDetails.getUsername()) + .providerUserId(authUser.getUuid()) + .build(); + Long userConnection = userConnectionService.createUserConnection(creator); } @Override @@ -85,7 +104,10 @@ public void unbinding(String userId, String providerId, String providerUserId) { @Override public List findConnectionByProviderIdAndProviderUserId(String providerId, String providerUserId) { - return null; + return connectionRepository.findConnectionByProviderIdAndProviderUserId(providerId, providerUserId) + .stream() + .map(UserConnectionMapper.INSTANCE::entityToConnectionData) + .collect(Collectors.toList()); } @Override diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/creator/UserConnectionCreator.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/creator/UserConnectionCreator.java new file mode 100644 index 000000000..a715cbbf9 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/creator/UserConnectionCreator.java @@ -0,0 +1,80 @@ +package cn.chenyunlong.qing.domain.auth.connection.dto.creator; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserConnectionCreator { + @Schema( + title = "userId", + description = "userId" + ) + private String userId; + + @Schema( + title = "providerId", + description = "providerId" + ) + private String providerId; + + @Schema( + title = "providerUserId", + description = "providerUserId" + ) + private String providerUserId; + + @Schema( + title = "rank", + description = "rank" + ) + private Integer rank; + + @Schema( + title = "displayName", + description = "displayName" + ) + private String displayName; + + @Schema( + title = "profileUrl", + description = "profileUrl" + ) + private String profileUrl; + + @Schema( + title = "imageUrl", + description = "imageUrl" + ) + private String imageUrl; + + @Schema( + title = "accessToken", + description = "accessToken" + ) + private String accessToken; + + @Schema( + title = "tokenId", + description = "tokenId" + ) + private Long tokenId; + + @Schema( + title = "refreshToken", + description = "refreshToken" + ) + private String refreshToken; + + @Schema( + title = "expireTime", + description = "expireTime" + ) + private Long expireTime; +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/query/UserConnectionQuery.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/query/UserConnectionQuery.java new file mode 100644 index 000000000..a24f1d6c5 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/query/UserConnectionQuery.java @@ -0,0 +1,9 @@ +package cn.chenyunlong.qing.domain.auth.connection.dto.query; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema +@Data +public class UserConnectionQuery { +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionCreateRequest.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionCreateRequest.java new file mode 100644 index 000000000..03677d781 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionCreateRequest.java @@ -0,0 +1,75 @@ +package cn.chenyunlong.qing.domain.auth.connection.dto.request; + +import cn.chenyunlong.common.model.Request; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema +@Data +public class UserConnectionCreateRequest implements Request { + @Schema( + title = "userId", + description = "userId" + ) + private String userId; + + @Schema( + title = "providerId", + description = "providerId" + ) + private String providerId; + + @Schema( + title = "providerUserId", + description = "providerUserId" + ) + private String providerUserId; + + @Schema( + title = "rank", + description = "rank" + ) + private Integer rank; + + @Schema( + title = "displayName", + description = "displayName" + ) + private String displayName; + + @Schema( + title = "profileUrl", + description = "profileUrl" + ) + private String profileUrl; + + @Schema( + title = "imageUrl", + description = "imageUrl" + ) + private String imageUrl; + + @Schema( + title = "accessToken", + description = "accessToken" + ) + private String accessToken; + + @Schema( + title = "tokenId", + description = "tokenId" + ) + private Long tokenId; + + @Schema( + title = "refreshToken", + description = "refreshToken" + ) + private String refreshToken; + + @Schema( + title = "expireTime", + description = "expireTime" + ) + private Long expireTime; +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionQueryRequest.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionQueryRequest.java new file mode 100644 index 000000000..a34fa5e9e --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionQueryRequest.java @@ -0,0 +1,10 @@ +package cn.chenyunlong.qing.domain.auth.connection.dto.request; + +import cn.chenyunlong.common.model.Request; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema +@Data +public class UserConnectionQueryRequest implements Request { +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionUpdateRequest.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionUpdateRequest.java new file mode 100644 index 000000000..4f605d86e --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/request/UserConnectionUpdateRequest.java @@ -0,0 +1,85 @@ +package cn.chenyunlong.qing.domain.auth.connection.dto.request; + +import cn.chenyunlong.common.model.Request; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema +@Data +public class UserConnectionUpdateRequest implements Request { + @Schema( + title = "userId", + description = "userId" + ) + private String userId; + + @Schema( + title = "providerId", + description = "providerId" + ) + private String providerId; + + @Schema( + title = "providerUserId", + description = "providerUserId" + ) + private String providerUserId; + + @Schema( + title = "rank", + description = "rank" + ) + private Integer rank; + + @Schema( + title = "displayName", + description = "displayName" + ) + private String displayName; + + @Schema( + title = "profileUrl", + description = "profileUrl" + ) + private String profileUrl; + + @Schema( + title = "imageUrl", + description = "imageUrl" + ) + private String imageUrl; + + @Schema( + title = "accessToken", + description = "accessToken" + ) + private String accessToken; + + @Schema( + title = "tokenId", + description = "tokenId" + ) + private Long tokenId; + + @Schema( + title = "refreshToken", + description = "refreshToken" + ) + private String refreshToken; + + @Schema( + title = "expireTime", + description = "expireTime" + ) + private Long expireTime; + + private Long id; + + public Long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/response/UserConnectionResponse.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/response/UserConnectionResponse.java new file mode 100644 index 000000000..3466568bf --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/response/UserConnectionResponse.java @@ -0,0 +1,79 @@ +package cn.chenyunlong.qing.domain.auth.connection.dto.response; + +import cn.chenyunlong.common.model.AbstractJpaResponse; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@Schema +@EqualsAndHashCode( + callSuper = true +) +public class UserConnectionResponse extends AbstractJpaResponse { + @Schema( + title = "userId", + description = "userId" + ) + private String userId; + + @Schema( + title = "providerId", + description = "providerId" + ) + private String providerId; + + @Schema( + title = "providerUserId", + description = "providerUserId" + ) + private String providerUserId; + + @Schema( + title = "rank", + description = "rank" + ) + private Integer rank; + + @Schema( + title = "displayName", + description = "displayName" + ) + private String displayName; + + @Schema( + title = "profileUrl", + description = "profileUrl" + ) + private String profileUrl; + + @Schema( + title = "imageUrl", + description = "imageUrl" + ) + private String imageUrl; + + @Schema( + title = "accessToken", + description = "accessToken" + ) + private String accessToken; + + @Schema( + title = "tokenId", + description = "tokenId" + ) + private Long tokenId; + + @Schema( + title = "refreshToken", + description = "refreshToken" + ) + private String refreshToken; + + @Schema( + title = "expireTime", + description = "expireTime" + ) + private Long expireTime; +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/updater/UserConnectionUpdater.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/updater/UserConnectionUpdater.java new file mode 100644 index 000000000..abc5704e7 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/updater/UserConnectionUpdater.java @@ -0,0 +1,101 @@ +package cn.chenyunlong.qing.domain.auth.connection.dto.updater; + +import cn.chenyunlong.qing.domain.auth.connection.UserConnection; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Optional; + +@Schema +@Data +public class UserConnectionUpdater { + @Schema( + title = "userId", + description = "userId" + ) + private String userId; + + @Schema( + title = "providerId", + description = "providerId" + ) + private String providerId; + + @Schema( + title = "providerUserId", + description = "providerUserId" + ) + private String providerUserId; + + @Schema( + title = "rank", + description = "rank" + ) + private Integer rank; + + @Schema( + title = "displayName", + description = "displayName" + ) + private String displayName; + + @Schema( + title = "profileUrl", + description = "profileUrl" + ) + private String profileUrl; + + @Schema( + title = "imageUrl", + description = "imageUrl" + ) + private String imageUrl; + + @Schema( + title = "accessToken", + description = "accessToken" + ) + private String accessToken; + + @Schema( + title = "tokenId", + description = "tokenId" + ) + private Long tokenId; + + @Schema( + title = "refreshToken", + description = "refreshToken" + ) + private String refreshToken; + + @Schema( + title = "expireTime", + description = "expireTime" + ) + private Long expireTime; + + private Long id; + + public void updateUserConnection(UserConnection param) { + Optional.ofNullable(getUserId()).ifPresent(param::setUserId); + Optional.ofNullable(getProviderId()).ifPresent(param::setProviderId); + Optional.ofNullable(getProviderUserId()).ifPresent(param::setProviderUserId); + Optional.ofNullable(getRank()).ifPresent(param::setRank); + Optional.ofNullable(getDisplayName()).ifPresent(param::setDisplayName); + Optional.ofNullable(getProfileUrl()).ifPresent(param::setProfileUrl); + Optional.ofNullable(getImageUrl()).ifPresent(param::setImageUrl); + Optional.ofNullable(getAccessToken()).ifPresent(param::setAccessToken); + Optional.ofNullable(getTokenId()).ifPresent(param::setTokenId); + Optional.ofNullable(getRefreshToken()).ifPresent(param::setRefreshToken); + Optional.ofNullable(getExpireTime()).ifPresent(param::setExpireTime); + } + + public Long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/vo/UserConnectionVO.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/vo/UserConnectionVO.java new file mode 100644 index 000000000..9db4f190b --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/dto/vo/UserConnectionVO.java @@ -0,0 +1,108 @@ +package cn.chenyunlong.qing.domain.auth.connection.dto.vo; + +import cn.chenyunlong.common.model.AbstractBaseJpaVo; +import cn.chenyunlong.qing.domain.auth.connection.UserConnection; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Schema +@Data +@EqualsAndHashCode( + callSuper = true +) +@NoArgsConstructor( + access = AccessLevel.PROTECTED +) +public class UserConnectionVO extends AbstractBaseJpaVo { + @Schema( + title = "userId", + description = "userId" + ) + private String userId; + + @Schema( + title = "providerId", + description = "providerId" + ) + private String providerId; + + @Schema( + title = "providerUserId", + description = "providerUserId" + ) + private String providerUserId; + + @Schema( + title = "rank", + description = "rank" + ) + private Integer rank; + + @Schema( + title = "displayName", + description = "displayName" + ) + private String displayName; + + @Schema( + title = "profileUrl", + description = "profileUrl" + ) + private String profileUrl; + + @Schema( + title = "imageUrl", + description = "imageUrl" + ) + private String imageUrl; + + @Schema( + title = "accessToken", + description = "accessToken" + ) + private String accessToken; + + @Schema( + title = "tokenId", + description = "tokenId" + ) + private Long tokenId; + + @Schema( + title = "refreshToken", + description = "refreshToken" + ) + private String refreshToken; + + @Schema( + title = "expireTime", + description = "expireTime" + ) + private Long expireTime; + + public UserConnectionVO(UserConnection source) { + super(); + this.setId(source.getId()); + ; + this.setCreatedAt(source.getCreatedAt()); + ; + this.setUpdatedAt(source.getCreatedAt()); + ; + this.setVersion(source.getVersion()); + ; + this.setUserId(source.getUserId()); + this.setProviderId(source.getProviderId()); + this.setProviderUserId(source.getProviderUserId()); + this.setRank(source.getRank()); + this.setDisplayName(source.getDisplayName()); + this.setProfileUrl(source.getProfileUrl()); + this.setImageUrl(source.getImageUrl()); + this.setAccessToken(source.getAccessToken()); + this.setTokenId(source.getTokenId()); + this.setRefreshToken(source.getRefreshToken()); + this.setExpireTime(source.getExpireTime()); + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/mapper/UserConnectionMapper.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/mapper/UserConnectionMapper.java new file mode 100644 index 000000000..175281c39 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/mapper/UserConnectionMapper.java @@ -0,0 +1,51 @@ +package cn.chenyunlong.qing.domain.auth.connection.mapper; + +import cn.chenyunlong.qing.domain.auth.connection.UserConnection; +import cn.chenyunlong.qing.domain.auth.connection.dto.creator.UserConnectionCreator; +import cn.chenyunlong.qing.domain.auth.connection.dto.query.UserConnectionQuery; +import cn.chenyunlong.qing.domain.auth.connection.dto.request.UserConnectionCreateRequest; +import cn.chenyunlong.qing.domain.auth.connection.dto.request.UserConnectionQueryRequest; +import cn.chenyunlong.qing.domain.auth.connection.dto.request.UserConnectionUpdateRequest; +import cn.chenyunlong.qing.domain.auth.connection.dto.response.UserConnectionResponse; +import cn.chenyunlong.qing.domain.auth.connection.dto.updater.UserConnectionUpdater; +import cn.chenyunlong.qing.domain.auth.connection.dto.vo.UserConnectionVO; +import cn.chenyunlong.security.entity.ConnectionData; +import cn.hutool.core.bean.BeanUtil; + +public interface UserConnectionMapper { + UserConnectionMapper INSTANCE = new UserConnectionMapper() { + }; + + default UserConnection dtoToEntity(UserConnectionCreator dto) { + return BeanUtil.copyProperties(dto, UserConnection.class); + } + + default UserConnectionUpdater request2Updater(UserConnectionUpdateRequest request) { + return BeanUtil.copyProperties(request, UserConnectionUpdater.class); + } + + default UserConnectionCreator request2Dto(UserConnectionCreateRequest request) { + return BeanUtil.copyProperties(request, UserConnectionCreator.class); + } + + default UserConnectionQuery request2Query(UserConnectionQueryRequest request) { + return BeanUtil.copyProperties(request, UserConnectionQuery.class); + } + + default ConnectionData entityToConnectionData(UserConnection userConnection) { + return ConnectionData.builder() + .providerId(userConnection.getProviderId()) + .userId(userConnection.getUserId()) + .accessToken(userConnection.getAccessToken()) + .expireTime(userConnection.getExpireTime()) + .build(); + } + + default UserConnectionResponse vo2Response(UserConnectionVO vo) { + return BeanUtil.copyProperties(vo, UserConnectionResponse.class); + } + + default UserConnectionResponse vo2CustomResponse(UserConnectionVO vo) { + return vo2Response(vo); + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/repository/UserConnectionRepository.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/repository/UserConnectionRepository.java new file mode 100644 index 000000000..f62eacd05 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/repository/UserConnectionRepository.java @@ -0,0 +1,13 @@ +package cn.chenyunlong.qing.domain.auth.connection.repository; + +import cn.chenyunlong.jpa.support.BaseRepository; +import cn.chenyunlong.qing.domain.auth.connection.UserConnection; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; + +public interface UserConnectionRepository extends BaseRepository { + + @Query("select c from UserConnection c where c.providerId = ?1 and c.providerUserId = ?2") + List findConnectionByProviderIdAndProviderUserId(String providerId, String providerUserId); +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/IUserConnectionService.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/IUserConnectionService.java new file mode 100644 index 000000000..66adcbaae --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/IUserConnectionService.java @@ -0,0 +1,40 @@ +package cn.chenyunlong.qing.domain.auth.connection.service; + +import cn.chenyunlong.common.model.PageRequestWrapper; +import cn.chenyunlong.qing.domain.auth.connection.dto.creator.UserConnectionCreator; +import cn.chenyunlong.qing.domain.auth.connection.dto.query.UserConnectionQuery; +import cn.chenyunlong.qing.domain.auth.connection.dto.updater.UserConnectionUpdater; +import cn.chenyunlong.qing.domain.auth.connection.dto.vo.UserConnectionVO; +import org.springframework.data.domain.Page; + +public interface IUserConnectionService { + /** + * create + */ + Long createUserConnection(UserConnectionCreator creator); + + /** + * update + */ + void updateUserConnection(UserConnectionUpdater updater); + + /** + * valid + */ + void validUserConnection(Long id); + + /** + * invalid + */ + void invalidUserConnection(Long id); + + /** + * findById + */ + UserConnectionVO findById(Long id); + + /** + * findByPage + */ + Page findByPage(PageRequestWrapper query); +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/UserConnectionFeignService.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/UserConnectionFeignService.java new file mode 100644 index 000000000..87afc7f93 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/UserConnectionFeignService.java @@ -0,0 +1,58 @@ +package cn.chenyunlong.qing.domain.auth.connection.service; + +import cn.chenyunlong.common.model.JsonResult; +import cn.chenyunlong.common.model.PageRequestWrapper; +import cn.chenyunlong.common.model.PageResult; +import cn.chenyunlong.qing.domain.auth.connection.dto.request.UserConnectionCreateRequest; +import cn.chenyunlong.qing.domain.auth.connection.dto.request.UserConnectionQueryRequest; +import cn.chenyunlong.qing.domain.auth.connection.dto.request.UserConnectionUpdateRequest; +import cn.chenyunlong.qing.domain.auth.connection.dto.response.UserConnectionResponse; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@FeignClient( + value = "stanic", + contextId = "userConnectionClient", + path = "userConnection/v1" +) +public interface UserConnectionFeignService { + /** + * 创建 + */ + @PostMapping("createUserConnection") + JsonResult createUserConnection(@RequestBody UserConnectionCreateRequest request); + + /** + * 更新请求 + */ + @PostMapping("updateUserConnection") + JsonResult updateUserConnection(@RequestBody UserConnectionUpdateRequest request); + + /** + * 有效 + */ + @PostMapping("valid/{id}") + JsonResult validUserConnection(@PathVariable("id") Long id); + + /** + * 无效 + */ + @PostMapping("invalid/{id}") + JsonResult invalidUserConnection(@PathVariable("id") Long id); + + /** + * 根据ID查询 + */ + @GetMapping("findById/{id}") + JsonResult findById(@PathVariable("id") Long id); + + /** + * 分页查询 + */ + @PostMapping("findByPage") + JsonResult> page( + @RequestBody PageRequestWrapper request); +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/impl/UserConnectionServiceImpl.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/impl/UserConnectionServiceImpl.java new file mode 100644 index 000000000..102aed6ff --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/connection/service/impl/UserConnectionServiceImpl.java @@ -0,0 +1,95 @@ +package cn.chenyunlong.qing.domain.auth.connection.service.impl; + +import cn.chenyunlong.common.constants.CodeEnum; +import cn.chenyunlong.common.exception.BusinessException; +import cn.chenyunlong.common.model.PageRequestWrapper; +import cn.chenyunlong.jpa.support.BaseJpaAggregate; +import cn.chenyunlong.jpa.support.EntityOperations; +import cn.chenyunlong.qing.domain.auth.connection.UserConnection; +import cn.chenyunlong.qing.domain.auth.connection.dto.creator.UserConnectionCreator; +import cn.chenyunlong.qing.domain.auth.connection.dto.query.UserConnectionQuery; +import cn.chenyunlong.qing.domain.auth.connection.dto.updater.UserConnectionUpdater; +import cn.chenyunlong.qing.domain.auth.connection.dto.vo.UserConnectionVO; +import cn.chenyunlong.qing.domain.auth.connection.mapper.UserConnectionMapper; +import cn.chenyunlong.qing.domain.auth.connection.repository.UserConnectionRepository; +import cn.chenyunlong.qing.domain.auth.connection.service.IUserConnectionService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Transactional +@Service +@Slf4j +@RequiredArgsConstructor +public class UserConnectionServiceImpl implements IUserConnectionService { + private final UserConnectionRepository userConnectionRepository; + + /** + * createImpl + */ + @Override + public Long createUserConnection(UserConnectionCreator creator) { + Optional userConnection = EntityOperations.doCreate(userConnectionRepository) + .create(() -> UserConnectionMapper.INSTANCE.dtoToEntity(creator)) + .update(UserConnection::init) + .execute(); + return userConnection.isPresent() ? userConnection.get().getId() : 0; + } + + /** + * update + */ + @Override + public void updateUserConnection(UserConnectionUpdater updater) { + EntityOperations.doUpdate(userConnectionRepository) + .loadById(updater.getId()) + .update(updater::updateUserConnection) + .execute(); + } + + /** + * valid + */ + @Override + public void validUserConnection(Long id) { + EntityOperations.doUpdate(userConnectionRepository) + .loadById(id) + .update(BaseJpaAggregate::valid) + .execute(); + } + + /** + * invalid + */ + @Override + public void invalidUserConnection(Long id) { + EntityOperations.doUpdate(userConnectionRepository) + .loadById(id) + .update(BaseJpaAggregate::invalid) + .execute(); + } + + /** + * findById + */ + @Override + public UserConnectionVO findById(Long id) { + Optional userConnection = userConnectionRepository.findById(id); + return new UserConnectionVO(userConnection.orElseThrow(() -> new BusinessException(CodeEnum.NotFindError))); + } + + /** + * findByPage + */ + @Override + public Page findByPage(PageRequestWrapper query) { + PageRequest pageRequest = PageRequest.of(query.getPage(), query.getPageSize(), Sort.Direction.DESC, "createdAt"); + return userConnectionRepository.findAll(pageRequest).map(UserConnectionVO::new); + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/User.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/QingUser.java similarity index 97% rename from qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/User.java rename to qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/QingUser.java index 1bc325fe9..c415f96c8 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/User.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/QingUser.java @@ -51,7 +51,7 @@ @GenMapper @Entity @Table(name = "sys_user") -public class User extends BaseJpaAggregate { +public class QingUser extends BaseJpaAggregate { @Column(unique = true) @FieldDesc(name = "用户唯一ID") diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/controller/QingUserController.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/controller/QingUserController.java new file mode 100644 index 000000000..af20cc5e3 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/controller/QingUserController.java @@ -0,0 +1,100 @@ +package cn.chenyunlong.qing.domain.auth.user.controller; + +import cn.chenyunlong.common.constants.CodeEnum; +import cn.chenyunlong.common.model.JsonResult; +import cn.chenyunlong.common.model.PageRequestWrapper; +import cn.chenyunlong.common.model.PageResult; +import cn.chenyunlong.qing.domain.auth.user.dto.creator.QingUserCreator; +import cn.chenyunlong.qing.domain.auth.user.dto.query.QingUserQuery; +import cn.chenyunlong.qing.domain.auth.user.dto.request.QingUserCreateRequest; +import cn.chenyunlong.qing.domain.auth.user.dto.request.QingUserQueryRequest; +import cn.chenyunlong.qing.domain.auth.user.dto.request.QingUserUpdateRequest; +import cn.chenyunlong.qing.domain.auth.user.dto.response.QingUserResponse; +import cn.chenyunlong.qing.domain.auth.user.dto.updater.QingUserUpdater; +import cn.chenyunlong.qing.domain.auth.user.dto.vo.QingUserVO; +import cn.chenyunlong.qing.domain.auth.user.mapper.QingUserMapper; +import cn.chenyunlong.qing.domain.auth.user.service.IQingUserService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.web.bind.annotation.*; + +import java.util.stream.Collectors; + +@RestController +@Slf4j +@RequestMapping("api/v1/qing-user") +@RequiredArgsConstructor +public class QingUserController { + private final IQingUserService qingUserService; + + /** + * createRequest + */ + @PostMapping + public JsonResult createQingUser(@RequestBody QingUserCreateRequest request) { + QingUserCreator creator = QingUserMapper.INSTANCE.request2Dto(request); + return JsonResult.success(qingUserService.createQingUser(creator)); + } + + /** + * update request + */ + @PostMapping("updateQingUser") + public JsonResult updateQingUser(@RequestBody QingUserUpdateRequest request) { + QingUserUpdater updater = QingUserMapper.INSTANCE.request2Updater(request); + qingUserService.updateQingUser(updater); + return JsonResult.success(CodeEnum.Success.getName()); + } + + /** + * valid + */ + @PostMapping("valid/{id}") + public JsonResult validQingUser(@PathVariable Long id) { + qingUserService.validQingUser(id); + return JsonResult.success(CodeEnum.Success.getName()); + } + + /** + * invalid + */ + @PostMapping("invalid/{id}") + public JsonResult invalidQingUser(@PathVariable Long id) { + qingUserService.invalidQingUser(id); + return JsonResult.success(CodeEnum.Success.getName()); + } + + /** + * findById + */ + @GetMapping("findById/{id}") + public JsonResult findById(@PathVariable Long id) { + QingUserVO vo = qingUserService.findById(id); + QingUserResponse response = QingUserMapper.INSTANCE.vo2CustomResponse(vo); + return JsonResult.success(response); + } + + /** + * findByPage request + */ + @PostMapping("page") + public JsonResult> page( + @RequestBody PageRequestWrapper request) { + PageRequestWrapper wrapper = new PageRequestWrapper<>(); + wrapper.setBean(QingUserMapper.INSTANCE.request2Query(request.getBean())); + wrapper.setSorts(request.getSorts()); + wrapper.setPageSize(request.getPageSize()); + wrapper.setPage(request.getPage()); + Page page = qingUserService.findByPage(wrapper); + return JsonResult.success( + PageResult.of( + page.getContent().stream() + .map(QingUserMapper.INSTANCE::vo2CustomResponse) + .collect(Collectors.toList()), + page.getTotalElements(), + page.getSize(), + page.getNumber()) + ); + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/domainservice/IUserDomainService.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/domainservice/IUserDomainService.java index c5672e7a5..1a7cc264a 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/domainservice/IUserDomainService.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/domainservice/IUserDomainService.java @@ -1,8 +1,8 @@ package cn.chenyunlong.qing.domain.auth.user.domainservice; import cn.chenyunlong.common.constants.ValidStatus; -import cn.chenyunlong.qing.domain.auth.user.QUser; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.qing.domain.auth.user.QQingUser; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import cn.chenyunlong.qing.domain.auth.user.dto.request.LoginParam; import cn.chenyunlong.qing.domain.auth.user.dto.response.QingTokenResponse; import cn.chenyunlong.qing.domain.auth.user.repository.UserRepository; @@ -26,15 +26,15 @@ public class IUserDomainService { */ public QingTokenResponse login(LoginParam loginParam) { - QUser user = QUser.user; - User userName = queryFactory.selectFrom(user).where(user.username.eq(loginParam.getUsername())).fetchOne(); - if (userName == null) { + QQingUser user = QQingUser.qingUser; + QingUser qingUserName = queryFactory.selectFrom(user).where(user.username.eq(loginParam.getUsername())).fetchOne(); + if (qingUserName == null) { throw new RuntimeException("用户不存在"); } - if (!userName.getPassword().equals(loginParam.getPassword())) { + if (!qingUserName.getPassword().equals(loginParam.getPassword())) { throw new RuntimeException("密码错误"); } - if (userName.getValidStatus() != ValidStatus.VALID) { + if (qingUserName.getValidStatus() != ValidStatus.VALID) { throw new RuntimeException("用户已被禁用"); } // 创建一个token 返回到前端 diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/domainservice/UmsUserDetailsServiceImpl.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/domainservice/UmsUserDetailsServiceImpl.java index 9993419f6..251fe32f8 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/domainservice/UmsUserDetailsServiceImpl.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/domainservice/UmsUserDetailsServiceImpl.java @@ -1,12 +1,17 @@ package cn.chenyunlong.qing.domain.auth.user.domainservice; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.common.enums.MFAType; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import cn.chenyunlong.qing.domain.auth.user.dto.creator.UserCreator; import cn.chenyunlong.qing.domain.auth.user.service.IUserService; import cn.chenyunlong.security.entity.AuthUser; import cn.chenyunlong.security.exception.RegisterUserFailureException; import cn.chenyunlong.security.service.UmsUserDetailsService; +import cn.hutool.core.util.IdUtil; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; @@ -18,8 +23,7 @@ import java.util.Optional; import java.util.stream.Collectors; -import static java.util.Collections.emptyList; - +@Slf4j @Service @RequiredArgsConstructor public class UmsUserDetailsServiceImpl implements UmsUserDetailsService { @@ -38,24 +42,35 @@ public List existedByUsernames(String... usernames) { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - Optional userOptional = userService.findByUsername(username); + Optional userOptional = userService.findByUsername(username); if (userOptional.isEmpty()) { throw new UsernameNotFoundException("用户名未找到!"); } - User user = userOptional.get(); - return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), emptyList()); + QingUser qingUser = userOptional.get(); + log.info("Demo ======>: 登录用户名:{}, 登录成功", username); + return new User(qingUser.getUsername(), qingUser.getPassword(), + true, + true, + true, + true, + AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_VISIT, ROLE_USER")); } @Override public UserDetails registerUser(AuthUser authUser, String username, String defaultAuthority, String decodeState) throws RegisterUserFailureException { UserCreator creator = new UserCreator(); + creator.setUid(IdUtil.getSnowflakeNextId()); creator.setUsername(username); creator.setPassword("test"); creator.setEmail(authUser.getEmail()); creator.setDescription(authUser.getRemark()); + // 默认密码,123456 + String encodedPassword = passwordEncoder.encode("123456"); + creator.setPassword(encodedPassword); + creator.setAvatar(authUser.getAvatar()); + creator.setMfaType(MFAType.NONE); Long user = userService.createUser(creator); - String encodedPassword = passwordEncoder.encode("12312"); - return org.springframework.security.core.userdetails.User.builder() + return User.builder() .username(username) .password(encodedPassword) .disabled(false) diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/creator/QingUserCreator.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/creator/QingUserCreator.java new file mode 100644 index 000000000..02f8956c1 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/creator/QingUserCreator.java @@ -0,0 +1,69 @@ +package cn.chenyunlong.qing.domain.auth.user.dto.creator; + +import cn.chenyunlong.common.enums.MFAType; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema +@Data +public class QingUserCreator { + @Schema( + title = "uid", + description = "用户唯一ID" + ) + private Long uid; + + @Schema( + title = "username", + description = "用户名" + ) + private String username; + + @Schema( + title = "nickname", + description = "昵称" + ) + private String nickname; + + @Schema( + title = "password", + description = "password" + ) + private String password; + + @Schema( + title = "phone", + description = "phone" + ) + private String phone; + + @Schema( + title = "email", + description = "email" + ) + private String email; + + @Schema( + title = "avatar", + description = "avatar" + ) + private String avatar; + + @Schema( + title = "description", + description = "description" + ) + private String description; + + @Schema( + title = "mfaType", + description = "mfaType" + ) + private MFAType mfaType; + + @Schema( + title = "mfaKey", + description = "mfaKey" + ) + private String mfaKey; +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/creator/UserCreator.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/creator/UserCreator.java index 330df2d64..5abdc1adf 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/creator/UserCreator.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/creator/UserCreator.java @@ -67,83 +67,4 @@ public class UserCreator { ) private String mfaKey; - public Long getUid() { - return uid; - } - - public void setUid(Long uid) { - this.uid = uid; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getNickname() { - return nickname; - } - - public void setNickname(String nickname) { - this.nickname = nickname; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getPhone() { - return phone; - } - - public void setPhone(String phone) { - this.phone = phone; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getAvatar() { - return avatar; - } - - public void setAvatar(String avatar) { - this.avatar = avatar; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public MFAType getMfaType() { - return mfaType; - } - - public void setMfaType(MFAType mfaType) { - this.mfaType = mfaType; - } - - public String getMfaKey() { - return mfaKey; - } - - public void setMfaKey(String mfaKey) { - this.mfaKey = mfaKey; - } } diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/query/QingUserQuery.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/query/QingUserQuery.java new file mode 100644 index 000000000..fb09570d8 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/query/QingUserQuery.java @@ -0,0 +1,9 @@ +package cn.chenyunlong.qing.domain.auth.user.dto.query; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema +@Data +public class QingUserQuery { +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserCreateRequest.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserCreateRequest.java new file mode 100644 index 000000000..ec48e1558 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserCreateRequest.java @@ -0,0 +1,78 @@ +package cn.chenyunlong.qing.domain.auth.user.dto.request; + +import cn.chenyunlong.common.enums.MFAType; +import cn.chenyunlong.common.model.Request; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema +@Data +public class QingUserCreateRequest implements Request { + @Schema( + title = "uid", + description = "用户唯一ID" + ) + private Long uid; + + @Schema( + title = "username", + description = "用户名" + ) + private String username; + + @Schema( + title = "nickname", + description = "昵称" + ) + private String nickname; + + @Schema( + title = "password", + description = "password" + ) + private String password; + + @Schema( + title = "phone", + description = "phone" + ) + private String phone; + + @Schema( + title = "email", + description = "email" + ) + private String email; + + @Schema( + title = "avatar", + description = "avatar" + ) + private String avatar; + + @Schema( + title = "description", + description = "description" + ) + private String description; + + @Schema( + title = "expireTime", + description = "expireTime" + ) + private LocalDateTime expireTime; + + @Schema( + title = "mfaType", + description = "mfaType" + ) + private MFAType mfaType; + + @Schema( + title = "mfaKey", + description = "mfaKey" + ) + private String mfaKey; +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserQueryRequest.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserQueryRequest.java new file mode 100644 index 000000000..842194299 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserQueryRequest.java @@ -0,0 +1,10 @@ +package cn.chenyunlong.qing.domain.auth.user.dto.request; + +import cn.chenyunlong.common.model.Request; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema +@Data +public class QingUserQueryRequest implements Request { +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserUpdateRequest.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserUpdateRequest.java new file mode 100644 index 000000000..80d24f544 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/request/QingUserUpdateRequest.java @@ -0,0 +1,88 @@ +package cn.chenyunlong.qing.domain.auth.user.dto.request; + +import cn.chenyunlong.common.enums.MFAType; +import cn.chenyunlong.common.model.Request; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema +@Data +public class QingUserUpdateRequest implements Request { + @Schema( + title = "uid", + description = "用户唯一ID" + ) + private Long uid; + + @Schema( + title = "username", + description = "用户名" + ) + private String username; + + @Schema( + title = "nickname", + description = "昵称" + ) + private String nickname; + + @Schema( + title = "password", + description = "password" + ) + private String password; + + @Schema( + title = "phone", + description = "phone" + ) + private String phone; + + @Schema( + title = "email", + description = "email" + ) + private String email; + + @Schema( + title = "avatar", + description = "avatar" + ) + private String avatar; + + @Schema( + title = "description", + description = "description" + ) + private String description; + + @Schema( + title = "expireTime", + description = "expireTime" + ) + private LocalDateTime expireTime; + + @Schema( + title = "mfaType", + description = "mfaType" + ) + private MFAType mfaType; + + @Schema( + title = "mfaKey", + description = "mfaKey" + ) + private String mfaKey; + + private Long id; + + public Long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/response/QingUserResponse.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/response/QingUserResponse.java new file mode 100644 index 000000000..6f847ca5c --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/response/QingUserResponse.java @@ -0,0 +1,82 @@ +package cn.chenyunlong.qing.domain.auth.user.dto.response; + +import cn.chenyunlong.common.enums.MFAType; +import cn.chenyunlong.common.model.AbstractJpaResponse; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +@Data +@Schema +@EqualsAndHashCode( + callSuper = true +) +public class QingUserResponse extends AbstractJpaResponse { + @Schema( + title = "uid", + description = "用户唯一ID" + ) + private Long uid; + + @Schema( + title = "username", + description = "用户名" + ) + private String username; + + @Schema( + title = "nickname", + description = "昵称" + ) + private String nickname; + + @Schema( + title = "password", + description = "password" + ) + private String password; + + @Schema( + title = "phone", + description = "phone" + ) + private String phone; + + @Schema( + title = "email", + description = "email" + ) + private String email; + + @Schema( + title = "avatar", + description = "avatar" + ) + private String avatar; + + @Schema( + title = "description", + description = "description" + ) + private String description; + + @Schema( + title = "expireTime", + description = "expireTime" + ) + private LocalDateTime expireTime; + + @Schema( + title = "mfaType", + description = "mfaType" + ) + private MFAType mfaType; + + @Schema( + title = "mfaKey", + description = "mfaKey" + ) + private String mfaKey; +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/updater/QingUserUpdater.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/updater/QingUserUpdater.java new file mode 100644 index 000000000..0e4420553 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/updater/QingUserUpdater.java @@ -0,0 +1,103 @@ +package cn.chenyunlong.qing.domain.auth.user.dto.updater; + +import cn.chenyunlong.common.enums.MFAType; +import cn.chenyunlong.qing.domain.auth.user.QingUser; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Optional; + +@Schema +@Data +public class QingUserUpdater { + @Schema( + title = "uid", + description = "用户唯一ID" + ) + private Long uid; + + @Schema( + title = "username", + description = "用户名" + ) + private String username; + + @Schema( + title = "nickname", + description = "昵称" + ) + private String nickname; + + @Schema( + title = "password", + description = "password" + ) + private String password; + + @Schema( + title = "phone", + description = "phone" + ) + private String phone; + + @Schema( + title = "email", + description = "email" + ) + private String email; + + @Schema( + title = "avatar", + description = "avatar" + ) + private String avatar; + + @Schema( + title = "description", + description = "description" + ) + private String description; + + @Schema( + title = "expireTime", + description = "expireTime" + ) + private LocalDateTime expireTime; + + @Schema( + title = "mfaType", + description = "mfaType" + ) + private MFAType mfaType; + + @Schema( + title = "mfaKey", + description = "mfaKey" + ) + private String mfaKey; + + private Long id; + + public void updateQingUser(QingUser param) { + Optional.ofNullable(getUid()).ifPresent(param::setUid); + Optional.ofNullable(getUsername()).ifPresent(param::setUsername); + Optional.ofNullable(getNickname()).ifPresent(param::setNickname); + Optional.ofNullable(getPassword()).ifPresent(param::setPassword); + Optional.ofNullable(getPhone()).ifPresent(param::setPhone); + Optional.ofNullable(getEmail()).ifPresent(param::setEmail); + Optional.ofNullable(getAvatar()).ifPresent(param::setAvatar); + Optional.ofNullable(getDescription()).ifPresent(param::setDescription); + Optional.ofNullable(getExpireTime()).ifPresent(param::setExpireTime); + Optional.ofNullable(getMfaType()).ifPresent(param::setMfaType); + Optional.ofNullable(getMfaKey()).ifPresent(param::setMfaKey); + } + + public Long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/updater/UserUpdater.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/updater/UserUpdater.java index 6d4728347..8c17d821b 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/updater/UserUpdater.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/updater/UserUpdater.java @@ -1,7 +1,7 @@ package cn.chenyunlong.qing.domain.auth.user.dto.updater; import cn.chenyunlong.common.enums.MFAType; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -79,7 +79,7 @@ public class UserUpdater { private Long id; - public void updateUser(User param) { + public void updateUser(QingUser param) { Optional.ofNullable(getUid()).ifPresent(param::setUid); Optional.ofNullable(getUsername()).ifPresent(param::setUsername); Optional.ofNullable(getNickname()).ifPresent(param::setNickname); diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/vo/QingUserVO.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/vo/QingUserVO.java new file mode 100644 index 000000000..a5e6890c0 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/vo/QingUserVO.java @@ -0,0 +1,111 @@ +package cn.chenyunlong.qing.domain.auth.user.dto.vo; + +import cn.chenyunlong.common.enums.MFAType; +import cn.chenyunlong.common.model.AbstractBaseJpaVo; +import cn.chenyunlong.qing.domain.auth.user.QingUser; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Schema +@Data +@EqualsAndHashCode( + callSuper = true +) +@NoArgsConstructor( + access = AccessLevel.PROTECTED +) +public class QingUserVO extends AbstractBaseJpaVo { + @Schema( + title = "uid", + description = "用户唯一ID" + ) + private Long uid; + + @Schema( + title = "username", + description = "用户名" + ) + private String username; + + @Schema( + title = "nickname", + description = "昵称" + ) + private String nickname; + + @Schema( + title = "password", + description = "password" + ) + private String password; + + @Schema( + title = "phone", + description = "phone" + ) + private String phone; + + @Schema( + title = "email", + description = "email" + ) + private String email; + + @Schema( + title = "avatar", + description = "avatar" + ) + private String avatar; + + @Schema( + title = "description", + description = "description" + ) + private String description; + + @Schema( + title = "expireTime", + description = "expireTime" + ) + private LocalDateTime expireTime; + + @Schema( + title = "mfaType", + description = "mfaType" + ) + private MFAType mfaType; + + @Schema( + title = "mfaKey", + description = "mfaKey" + ) + private String mfaKey; + + public QingUserVO(QingUser source) { + super(); + this.setId(source.getId()); + ; + this.setCreatedAt(source.getCreatedAt()); + ; + this.setUpdatedAt(source.getCreatedAt()); + ; + this.setVersion(source.getVersion()); + ; + this.setUid(source.getUid()); + this.setUsername(source.getUsername()); + this.setNickname(source.getNickname()); + this.setPassword(source.getPassword()); + this.setPhone(source.getPhone()); + this.setEmail(source.getEmail()); + this.setAvatar(source.getAvatar()); + this.setDescription(source.getDescription()); + this.setExpireTime(source.getExpireTime()); + this.setMfaType(source.getMfaType()); + this.setMfaKey(source.getMfaKey()); + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/vo/UserVO.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/vo/UserVO.java index 42266a329..5b78348e7 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/vo/UserVO.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/dto/vo/UserVO.java @@ -2,7 +2,7 @@ import cn.chenyunlong.common.enums.MFAType; import cn.chenyunlong.common.model.AbstractBaseJpaVo; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AccessLevel; import lombok.Data; @@ -86,7 +86,7 @@ public class UserVO extends AbstractBaseJpaVo { ) private String mfaKey; - public UserVO(User source) { + public UserVO(QingUser source) { super(); this.setId(source.getId()); this.setCreatedAt(source.getCreatedAt()); diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/mapper/QingUserMapper.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/mapper/QingUserMapper.java new file mode 100644 index 000000000..b19f8b63f --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/mapper/QingUserMapper.java @@ -0,0 +1,41 @@ +package cn.chenyunlong.qing.domain.auth.user.mapper; + +import cn.chenyunlong.qing.domain.auth.user.QingUser; +import cn.chenyunlong.qing.domain.auth.user.dto.creator.QingUserCreator; +import cn.chenyunlong.qing.domain.auth.user.dto.query.QingUserQuery; +import cn.chenyunlong.qing.domain.auth.user.dto.request.QingUserCreateRequest; +import cn.chenyunlong.qing.domain.auth.user.dto.request.QingUserQueryRequest; +import cn.chenyunlong.qing.domain.auth.user.dto.request.QingUserUpdateRequest; +import cn.chenyunlong.qing.domain.auth.user.dto.response.QingUserResponse; +import cn.chenyunlong.qing.domain.auth.user.dto.updater.QingUserUpdater; +import cn.chenyunlong.qing.domain.auth.user.dto.vo.QingUserVO; +import cn.hutool.core.bean.BeanUtil; + +public interface QingUserMapper { + QingUserMapper INSTANCE = new QingUserMapper() { + }; + + default QingUser dtoToEntity(QingUserCreator dto) { + return BeanUtil.copyProperties(dto, QingUser.class); + } + + default QingUserUpdater request2Updater(QingUserUpdateRequest request) { + return BeanUtil.copyProperties(request, QingUserUpdater.class); + } + + default QingUserCreator request2Dto(QingUserCreateRequest request) { + return BeanUtil.copyProperties(request, QingUserCreator.class); + } + + default QingUserQuery request2Query(QingUserQueryRequest request) { + return BeanUtil.copyProperties(request, QingUserQuery.class); + } + + default QingUserResponse vo2Response(QingUserVO vo) { + return BeanUtil.copyProperties(vo, QingUserResponse.class); + } + + default QingUserResponse vo2CustomResponse(QingUserVO vo) { + return vo2Response(vo); + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/mapper/UserMapper.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/mapper/UserMapper.java index fcdd59d33..6e79469dd 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/mapper/UserMapper.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/mapper/UserMapper.java @@ -1,6 +1,6 @@ package cn.chenyunlong.qing.domain.auth.user.mapper; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import cn.chenyunlong.qing.domain.auth.user.dto.creator.UserCreator; import cn.chenyunlong.qing.domain.auth.user.dto.query.UserQuery; import cn.chenyunlong.qing.domain.auth.user.dto.request.UserCreateRequest; @@ -15,8 +15,8 @@ public interface UserMapper { UserMapper INSTANCE = new UserMapper() { }; - default User dtoToEntity(UserCreator dto) { - return BeanUtil.copyProperties(dto, User.class); + default QingUser dtoToEntity(UserCreator dto) { + return BeanUtil.copyProperties(dto, QingUser.class); } default UserUpdater request2Updater(UserUpdateRequest request) { diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/repository/QingUserRepository.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/repository/QingUserRepository.java new file mode 100644 index 000000000..619ac7bd8 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/repository/QingUserRepository.java @@ -0,0 +1,7 @@ +package cn.chenyunlong.qing.domain.auth.user.repository; + +import cn.chenyunlong.jpa.support.BaseRepository; +import cn.chenyunlong.qing.domain.auth.user.QingUser; + +public interface QingUserRepository extends BaseRepository { +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/repository/UserRepository.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/repository/UserRepository.java index a79a82086..367ceac2a 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/repository/UserRepository.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/repository/UserRepository.java @@ -1,11 +1,11 @@ package cn.chenyunlong.qing.domain.auth.user.repository; import cn.chenyunlong.jpa.support.BaseRepository; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import org.springframework.data.jpa.repository.Query; -public interface UserRepository extends BaseRepository { +public interface UserRepository extends BaseRepository { - @Query("select u from User u where u.username = ?1") - User findByUsername(String username); + @Query("select u from QingUser u where u.username = ?1") + QingUser findByUsername(String username); } diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/IQingUserService.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/IQingUserService.java new file mode 100644 index 000000000..a7cea5127 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/IQingUserService.java @@ -0,0 +1,40 @@ +package cn.chenyunlong.qing.domain.auth.user.service; + +import cn.chenyunlong.common.model.PageRequestWrapper; +import cn.chenyunlong.qing.domain.auth.user.dto.creator.QingUserCreator; +import cn.chenyunlong.qing.domain.auth.user.dto.query.QingUserQuery; +import cn.chenyunlong.qing.domain.auth.user.dto.updater.QingUserUpdater; +import cn.chenyunlong.qing.domain.auth.user.dto.vo.QingUserVO; +import org.springframework.data.domain.Page; + +public interface IQingUserService { + /** + * create + */ + Long createQingUser(QingUserCreator creator); + + /** + * update + */ + void updateQingUser(QingUserUpdater updater); + + /** + * valid + */ + void validQingUser(Long id); + + /** + * invalid + */ + void invalidQingUser(Long id); + + /** + * findById + */ + QingUserVO findById(Long id); + + /** + * findByPage + */ + Page findByPage(PageRequestWrapper query); +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/IUserService.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/IUserService.java index a2c5016ea..b9acd0d23 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/IUserService.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/IUserService.java @@ -1,7 +1,7 @@ package cn.chenyunlong.qing.domain.auth.user.service; import cn.chenyunlong.common.model.PageRequestWrapper; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import cn.chenyunlong.qing.domain.auth.user.dto.creator.UserCreator; import cn.chenyunlong.qing.domain.auth.user.dto.query.UserQuery; import cn.chenyunlong.qing.domain.auth.user.dto.updater.UserUpdater; @@ -41,5 +41,5 @@ public interface IUserService { */ Page findByPage(PageRequestWrapper query); - Optional findByUsername(String username); + Optional findByUsername(String username); } diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/QingUserFeignService.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/QingUserFeignService.java new file mode 100644 index 000000000..261ff8804 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/QingUserFeignService.java @@ -0,0 +1,58 @@ +package cn.chenyunlong.qing.domain.auth.user.service; + +import cn.chenyunlong.common.model.JsonResult; +import cn.chenyunlong.common.model.PageRequestWrapper; +import cn.chenyunlong.common.model.PageResult; +import cn.chenyunlong.qing.domain.auth.user.dto.request.QingUserCreateRequest; +import cn.chenyunlong.qing.domain.auth.user.dto.request.QingUserQueryRequest; +import cn.chenyunlong.qing.domain.auth.user.dto.request.QingUserUpdateRequest; +import cn.chenyunlong.qing.domain.auth.user.dto.response.QingUserResponse; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@FeignClient( + value = "stanic", + contextId = "qingUserClient", + path = "qingUser/v1" +) +public interface QingUserFeignService { + /** + * 创建 + */ + @PostMapping("createQingUser") + JsonResult createQingUser(@RequestBody QingUserCreateRequest request); + + /** + * 更新请求 + */ + @PostMapping("updateQingUser") + JsonResult updateQingUser(@RequestBody QingUserUpdateRequest request); + + /** + * 有效 + */ + @PostMapping("valid/{id}") + JsonResult validQingUser(@PathVariable("id") Long id); + + /** + * 无效 + */ + @PostMapping("invalid/{id}") + JsonResult invalidQingUser(@PathVariable("id") Long id); + + /** + * 根据ID查询 + */ + @GetMapping("findById/{id}") + JsonResult findById(@PathVariable("id") Long id); + + /** + * 分页查询 + */ + @PostMapping("findByPage") + JsonResult> page( + @RequestBody PageRequestWrapper request); +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/impl/QingUserServiceImpl.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/impl/QingUserServiceImpl.java new file mode 100644 index 000000000..971374126 --- /dev/null +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/impl/QingUserServiceImpl.java @@ -0,0 +1,95 @@ +package cn.chenyunlong.qing.domain.auth.user.service.impl; + +import cn.chenyunlong.common.constants.CodeEnum; +import cn.chenyunlong.common.exception.BusinessException; +import cn.chenyunlong.common.model.PageRequestWrapper; +import cn.chenyunlong.jpa.support.BaseJpaAggregate; +import cn.chenyunlong.jpa.support.EntityOperations; +import cn.chenyunlong.qing.domain.auth.user.QingUser; +import cn.chenyunlong.qing.domain.auth.user.dto.creator.QingUserCreator; +import cn.chenyunlong.qing.domain.auth.user.dto.query.QingUserQuery; +import cn.chenyunlong.qing.domain.auth.user.dto.updater.QingUserUpdater; +import cn.chenyunlong.qing.domain.auth.user.dto.vo.QingUserVO; +import cn.chenyunlong.qing.domain.auth.user.mapper.QingUserMapper; +import cn.chenyunlong.qing.domain.auth.user.repository.QingUserRepository; +import cn.chenyunlong.qing.domain.auth.user.service.IQingUserService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Transactional +@Service +@Slf4j +@RequiredArgsConstructor +public class QingUserServiceImpl implements IQingUserService { + private final QingUserRepository qingUserRepository; + + /** + * createImpl + */ + @Override + public Long createQingUser(QingUserCreator creator) { + Optional qingUser = EntityOperations.doCreate(qingUserRepository) + .create(() -> QingUserMapper.INSTANCE.dtoToEntity(creator)) + .update(QingUser::init) + .execute(); + return qingUser.isPresent() ? qingUser.get().getId() : 0; + } + + /** + * update + */ + @Override + public void updateQingUser(QingUserUpdater updater) { + EntityOperations.doUpdate(qingUserRepository) + .loadById(updater.getId()) + .update(updater::updateQingUser) + .execute(); + } + + /** + * valid + */ + @Override + public void validQingUser(Long id) { + EntityOperations.doUpdate(qingUserRepository) + .loadById(id) + .update(BaseJpaAggregate::valid) + .execute(); + } + + /** + * invalid + */ + @Override + public void invalidQingUser(Long id) { + EntityOperations.doUpdate(qingUserRepository) + .loadById(id) + .update(BaseJpaAggregate::invalid) + .execute(); + } + + /** + * findById + */ + @Override + public QingUserVO findById(Long id) { + Optional qingUser = qingUserRepository.findById(id); + return new QingUserVO(qingUser.orElseThrow(() -> new BusinessException(CodeEnum.NotFindError))); + } + + /** + * findByPage + */ + @Override + public Page findByPage(PageRequestWrapper query) { + PageRequest pageRequest = PageRequest.of(query.getPage(), query.getPageSize(), Sort.Direction.DESC, "createdAt"); + return qingUserRepository.findAll(pageRequest).map(QingUserVO::new); + } +} diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/impl/UserServiceImpl.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/impl/UserServiceImpl.java index 1cc36afe1..0fdb97620 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/impl/UserServiceImpl.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/auth/user/service/impl/UserServiceImpl.java @@ -5,7 +5,7 @@ import cn.chenyunlong.common.model.PageRequestWrapper; import cn.chenyunlong.jpa.support.BaseJpaAggregate; import cn.chenyunlong.jpa.support.EntityOperations; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import cn.chenyunlong.qing.domain.auth.user.dto.creator.UserCreator; import cn.chenyunlong.qing.domain.auth.user.dto.query.UserQuery; import cn.chenyunlong.qing.domain.auth.user.dto.updater.UserUpdater; @@ -37,9 +37,9 @@ public class UserServiceImpl implements IUserService { */ @Override public Long createUser(UserCreator creator) { - Optional user = EntityOperations.doCreate(userRepository) + Optional user = EntityOperations.doCreate(userRepository) .create(() -> UserMapper.INSTANCE.dtoToEntity(creator)) - .update(User::init) + .update(QingUser::init) .execute(); return user.isPresent() ? user.get().getId() : 0; } @@ -82,7 +82,7 @@ public void invalidUser(Long id) { */ @Override public UserVO findById(Long id) { - Optional user = userRepository.findById(id); + Optional user = userRepository.findById(id); return new UserVO(user.orElseThrow(() -> new BusinessException(CodeEnum.NotFindError))); } @@ -97,7 +97,7 @@ public Page findByPage(PageRequestWrapper query) { } @Override - public Optional findByUsername(String username) { + public Optional findByUsername(String username) { return Optional.ofNullable(userRepository.findByUsername(username)); } } diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/LikeModel.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/LikeModel.java index d57a72c43..907d2b1f2 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/LikeModel.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/LikeModel.java @@ -1,6 +1,6 @@ package cn.chenyunlong.qing.domain.zan; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import cn.chenyunlong.qing.domain.entity.Entity; import cn.chenyunlong.qing.domain.zan.service.plugin.SmsType; import lombok.Data; @@ -9,7 +9,7 @@ public class LikeModel { private SmsType smsType = SmsType.A_LI_YUN; - private User user; + private QingUser qingUser; private Entity entity; /** diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/filters/UserQueryFilter.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/filters/UserQueryFilter.java index c25076b2b..da0279c4d 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/filters/UserQueryFilter.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/filters/UserQueryFilter.java @@ -1,7 +1,7 @@ package cn.chenyunlong.qing.domain.zan.filters; import cn.chenyunlong.common.exception.NotFoundException; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import cn.chenyunlong.qing.domain.auth.user.repository.UserRepository; import cn.chenyunlong.qing.domain.zan.LikeContext; import cn.chenyunlong.qing.domain.zan.dto.request.ZanCreateRequest; @@ -20,9 +20,9 @@ protected void handleEvent(LikeContext eventContext) { log.info("获取用户信息!"); ZanCreateRequest createRequest = eventContext.getCreateRequest(); Long userId = createRequest.getUserId(); - User user = userService.findById(userId) + QingUser qingUser = userService.findById(userId) .orElseThrow(() -> new NotFoundException("未查询到用户:" + userId)); // 将用户信息添加到上下文中 - eventContext.getLikeModel().setUser(user); + eventContext.getLikeModel().setQingUser(qingUser); } } diff --git a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/service/impl/ZanServiceImpl.java b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/service/impl/ZanServiceImpl.java index 8c5b2db17..2f01b3342 100644 --- a/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/service/impl/ZanServiceImpl.java +++ b/qing-domain/src/main/java/cn/chenyunlong/qing/domain/zan/service/impl/ZanServiceImpl.java @@ -5,7 +5,7 @@ import cn.chenyunlong.common.model.PageRequestWrapper; import cn.chenyunlong.jpa.support.BaseJpaAggregate; import cn.chenyunlong.jpa.support.EntityOperations; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import cn.chenyunlong.qing.domain.auth.user.repository.UserRepository; import cn.chenyunlong.qing.domain.entity.Entity; import cn.chenyunlong.qing.domain.entity.repository.EntityRepository; @@ -60,7 +60,7 @@ public Long createZan(ZanCreator creator) { if (entity.isEmpty()) { throw new BusinessException("创建zan失败,实体不存在"); } - Optional userRepositoryById = userRepository.findById(creator.getUserId()); + Optional userRepositoryById = userRepository.findById(creator.getUserId()); if (userRepositoryById.isEmpty()) { throw new BusinessException("创建zan失败,用户不存在"); } @@ -136,8 +136,8 @@ public Long like(ZanCreateRequest createRequest) { // 通过插件处理业务扩展 pluginRegistry.getPluginsFor(likeModel).forEach( likeModelLikePlugin -> - likeModelLikePlugin.sendSms(likeModel.getUser().getPhone(), - likeModel.getUser().getEmail())); + likeModelLikePlugin.sendSms(likeModel.getQingUser().getPhone(), + likeModel.getQingUser().getEmail())); // 业务处理完毕,读取处理结果 return likeContext.getCreateRequest().getEntityId(); diff --git a/qing-domain/src/main/resources/application-dev.yml b/qing-domain/src/main/resources/application-dev.yml index 1a402c6a2..cd7dbf5ec 100644 --- a/qing-domain/src/main/resources/application-dev.yml +++ b/qing-domain/src/main/resources/application-dev.yml @@ -38,7 +38,7 @@ qing: appId: 6432d5c9e0502f0bb45319bf appSecret: a599ddfc87b4478596b31a17e46d2360 appHost: https://stanic.authing.cn/6432d5c9e0502f0bb45319bf - redirectUrl: http://localhost:8080/auth2/authorization + redirectUrl: http://localhost:8080/api/auth2/authorization authLoginUrlPrefix: /api/auth2/authorization mp: # 测试账号 diff --git a/qing-domain/src/test/java/cn/chenyunlong/qing/domain/entity/service/IEntityServiceTest.java b/qing-domain/src/test/java/cn/chenyunlong/qing/domain/entity/service/IEntityServiceTest.java index 6c0c97cb1..116af0bef 100644 --- a/qing-domain/src/test/java/cn/chenyunlong/qing/domain/entity/service/IEntityServiceTest.java +++ b/qing-domain/src/test/java/cn/chenyunlong/qing/domain/entity/service/IEntityServiceTest.java @@ -2,7 +2,7 @@ import cn.chenyunlong.common.constants.ValidStatus; import cn.chenyunlong.common.exception.BusinessException; -import cn.chenyunlong.qing.domain.auth.user.User; +import cn.chenyunlong.qing.domain.auth.user.QingUser; import cn.chenyunlong.qing.domain.auth.user.repository.UserRepository; import cn.chenyunlong.qing.domain.entity.Entity; import cn.chenyunlong.qing.domain.entity.repository.EntityRepository; @@ -65,11 +65,11 @@ void testCreateZan_ReturnsZanIdWhenSuccessful() { creator.setEntityId(1L); creator.setUserId(2L); - User user = new User(); - user.setId(2L); + QingUser qingUser = new QingUser(); + qingUser.setId(2L); doReturn(Optional.of(new Entity())).when(entityRepository).findById(creator.getEntityId()); - doReturn(Optional.of(new User())).when(userRepository).findById(creator.getUserId()); + doReturn(Optional.of(new QingUser())).when(userRepository).findById(creator.getUserId()); doReturn(Optional.of(new Zan())).when(zanRepository).findById(anyLong()); doAnswer(answer -> { Object argument = answer.getArgument(0); @@ -89,7 +89,7 @@ void testCreateZan_ReturnsZeroWhenZanNotCreated() { creator.setUserId(2L); doReturn(Optional.of(new Entity())).when(entityRepository).findById(creator.getEntityId()); - doReturn(Optional.of(new User())).when(userRepository).findById(creator.getUserId()); + doReturn(Optional.of(new QingUser())).when(userRepository).findById(creator.getUserId()); doReturn(Optional.empty()).when(zanRepository).findById(anyLong()); doAnswer(answer -> { Object argument = answer.getArgument(0); diff --git a/qing-domain/src/test/java/cn/chenyunlong/qing/domain/user/service/IUserServiceTest.java b/qing-domain/src/test/java/cn/chenyunlong/qing/domain/user/service/IQingUserServiceTest.java similarity index 95% rename from qing-domain/src/test/java/cn/chenyunlong/qing/domain/user/service/IUserServiceTest.java rename to qing-domain/src/test/java/cn/chenyunlong/qing/domain/user/service/IQingUserServiceTest.java index c70dda04b..fb5fbe4a4 100644 --- a/qing-domain/src/test/java/cn/chenyunlong/qing/domain/user/service/IUserServiceTest.java +++ b/qing-domain/src/test/java/cn/chenyunlong/qing/domain/user/service/IQingUserServiceTest.java @@ -11,7 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.Rollback; -public class IUserServiceTest extends AbstractDomainTests { +public class IQingUserServiceTest extends AbstractDomainTests { @Autowired private IUserService userService; diff --git a/qing-domain/src/test/resources/zhangli.sql b/qing-domain/src/test/resources/zhangli.sql index 414004390..6b8ffb342 100644 --- a/qing-domain/src/test/resources/zhangli.sql +++ b/qing-domain/src/test/resources/zhangli.sql @@ -520,7 +520,7 @@ TABLES `role` WRITE; DISABLE KEYS */; INSERT INTO `role` VALUES (1, 'admin', '管理团', now(), now(), 'stan', '', '', ''), - (2, 'user', '普通用户', now(), now(), 'stan', '', '', ''); + (2, 'qingUser', '普通用户', now(), now(), 'stan', '', '', ''); /*!40000 ALTER TABLE `role` ENABLE KEYS */; UNLOCK @@ -636,10 +636,10 @@ CREATE TABLE `upload_file` AUTO_INCREMENT = 138 DEFAULT CHARSET = utf8; -DROP TABLE IF EXISTS `user`; +DROP TABLE IF EXISTS `qingUser`; /*!40101 SET @saved_cs_client = @@character_set_client */; -CREATE TABLE `user` +CREATE TABLE `qingUser` ( `userid` bigint(20) not null AUTO_INCREMENT, `username` varchar(10) DEFAULT NULL COMMENT '用户登录的账号,长度为十位字符', @@ -687,7 +687,7 @@ CREATE TABLE `user_third` -INSERT INTO `user` +INSERT INTO `qingUser` VALUES (123, 'stan', '纯纯的黑色幽默', 'avatar_path', 'description', '1576302867@qq.com', '13628091432', '$2a$10$45ScSS1BeuYizV2QYJ9HVOfpBoTOxnjXyCkNPFkTJnf9o3bW0l.4G', '13628091432', now(), now(), 'stan', '', '', ''); diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/base/JwtAuthenticationTokenFilter.java b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/base/JwtAuthenticationTokenFilter.java index 4603a1eee..b21f97507 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/base/JwtAuthenticationTokenFilter.java +++ b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/base/JwtAuthenticationTokenFilter.java @@ -20,17 +20,20 @@ import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; import org.springframework.lang.NonNull; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; +import java.io.IOException; +import java.util.List; + /** * token 拦截器,加入上下文参数 user-agent ,也可以加入其它的扩展 */ +@Component public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { public static final String USER_AGENT = "user-agent"; diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/SecurityConfig.java b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/SecurityConfig.java deleted file mode 100644 index 4b1e20055..000000000 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/SecurityConfig.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.chenyunlong.security.config; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; - -@Configuration -public class SecurityConfig { - - @Bean - @ConditionalOnMissingBean(PasswordEncoder.class) - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } -} diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/security/handler/CustomAuthenticationSuccessHandler.java b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/security/handler/CustomAuthenticationSuccessHandler.java deleted file mode 100644 index 413deeaed..000000000 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/config/security/handler/CustomAuthenticationSuccessHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.chenyunlong.security.config.security.handler; - -import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; -import org.springframework.stereotype.Component; - -import java.io.IOException; - -/** - * 定制成功处理器 - */ -@Component -public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler { - - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, - Authentication authentication) throws IOException, ServletException { - - ObjectMapper mapper = new ObjectMapper(); - -// response.getWriter().write(); - } -} diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingLoginConfigurer.java b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingLoginConfigurer.java index ac5656c4f..bc6d23840 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingLoginConfigurer.java +++ b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingLoginConfigurer.java @@ -13,59 +13,55 @@ package cn.chenyunlong.security.configures.authing; -import cn.authing.sdk.java.dto.authentication.OIDCTokenResponse; -import cn.chenyunlong.common.model.ApiResult; import cn.chenyunlong.security.configures.authing.properties.AuthingProperties; import cn.chenyunlong.security.signup.ConnectionService; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.InitializingBean; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Slf4j @EnableConfigurationProperties(AuthingProperties.class) -@AutoConfigureAfter(AuthenticationManager.class) @RequiredArgsConstructor public final class AuthingLoginConfigurer extends AbstractHttpConfigurer implements InitializingBean { private final AuthingProperties authingProperty; private final ConnectionService connectionService; private final UserDetailsService userDetailsService; + private final AuthenticationSuccessHandler authenticationSuccessHandler; + private final AuthenticationFailureHandler authenticationFailureHandler; + + + @Override + public void afterPropertiesSet() { + log.info("Authing应用{{}}配置完毕!", authingProperty.getAppName()); + } @Override public void configure(HttpSecurity httpSecurity) throws Exception { super.configure(httpSecurity); AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class); - AuthingLoginFilter authingLoginFilter = new AuthingLoginFilter(authenticationManager, authingProperty); - authingLoginFilter.setAuthenticationFailureHandler((request, response, exception) -> { - ObjectMapper objectMapper = new ObjectMapper(); - //构建一个Token - ApiResult success = ApiResult.fail("登录失败"); - response.setContentType("application/json;charset=UTF-8"); - response.getWriter().write(objectMapper.writeValueAsString(success)); - }); - authingLoginFilter.setAuthenticationSuccessHandler((request, response, authentication) -> { - ObjectMapper objectMapper = new ObjectMapper(); - AuthingLoginToken authingLoginToken = (AuthingLoginToken) authentication; - //构建一个Token - ApiResult success = ApiResult.success(authingLoginToken.getResponse()); - response.setContentType("application/json;charset=UTF-8"); - response.getWriter().write(objectMapper.writeValueAsString(success)); - }); - authingLoginFilter.setRememberMeServices(new AuthingRememberMeServices(authingProperty)); + AuthingLoginFilter authingLoginFilter = getAuthingLoginFilter(authenticationManager); httpSecurity.authenticationProvider(new AuthingProvider(authingProperty, userDetailsService, connectionService)); httpSecurity.addFilterBefore(authingLoginFilter, UsernamePasswordAuthenticationFilter.class); } - @Override - public void afterPropertiesSet() throws Exception { - log.info("Authing应用{{}}配置完毕!", authingProperty.getAppName()); + private AuthingLoginFilter getAuthingLoginFilter(AuthenticationManager authenticationManager) { + AuthingLoginFilter authingLoginFilter = new AuthingLoginFilter(authenticationManager, authingProperty); + if (authenticationFailureHandler != null) { + authingLoginFilter.setAuthenticationFailureHandler(authenticationFailureHandler); + } + if (authenticationSuccessHandler != null) { + authingLoginFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler); + } + authingLoginFilter.setRememberMeServices(new AuthingRememberMeServices(authingProperty)); + return authingLoginFilter; } } diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingLoginFilter.java b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingLoginFilter.java index d077b76a4..7d9925549 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingLoginFilter.java +++ b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingLoginFilter.java @@ -15,8 +15,6 @@ import cn.chenyunlong.security.configures.authing.properties.AuthingProperties; import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.HttpMethod; @@ -24,7 +22,6 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; -import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import java.io.IOException; @@ -55,14 +52,4 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ AuthingLoginToken passToken = new AuthingLoginToken(loginRequest); return this.getAuthenticationManager().authenticate(passToken); } - - @Override - protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { - super.successfulAuthentication(request, response, chain, authResult); - } - - @Override - public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) { - super.setAuthenticationFailureHandler(failureHandler); - } } diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingProvider.java b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingProvider.java index c8d6265ac..eef616b1a 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingProvider.java +++ b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/authing/AuthingProvider.java @@ -18,8 +18,10 @@ import cn.authing.sdk.java.dto.authentication.UserInfo; import cn.authing.sdk.java.model.AuthenticationClientOptions; import cn.chenyunlong.security.configures.authing.properties.AuthingProperties; +import cn.chenyunlong.security.entity.AuthToken; import cn.chenyunlong.security.entity.AuthUser; import cn.chenyunlong.security.entity.ConnectionData; +import cn.chenyunlong.security.exception.NotConnectedException; import cn.chenyunlong.security.signup.ConnectionService; import cn.chenyunlong.security.token.Auth2AuthenticationToken; import cn.hutool.core.collection.CollectionUtil; @@ -63,9 +65,9 @@ public Authentication authenticate(Authentication authentication) throws Authent try { authenticationClient = new AuthenticationClient(clientOptions); //1.3 通过code 获取OIDCTokenResponse - OIDCTokenResponse accessTokenByCode = authenticationClient.getAccessTokenByCode(loginRequest.getCode()); - log.info("【Authing】通过Authing登录成功:accessToken:{}", accessTokenByCode.getAccessToken()); - UserInfo userInfo = authenticationClient.getUserInfoByAccessToken(accessTokenByCode.getAccessToken()); + OIDCTokenResponse accessToken = authenticationClient.getAccessTokenByCode(loginRequest.getCode()); + log.info("【Authing】通过Authing登录成功:accessToken:{}", accessToken.getAccessToken()); + UserInfo userInfo = authenticationClient.getUserInfoByAccessToken(accessToken.getAccessToken()); log.info("【Authing】通过Authing登录成功:userInfo:{}", JSONUtil.toJsonPrettyStr(userInfo)); String name = userInfo.getName(); log.info("【Authing】通过Authing登录成功:authing用户名:{},sub:{}", name, userInfo.getSub()); @@ -78,16 +80,30 @@ public Authentication authenticate(Authentication authentication) throws Authent String providerId = "authing"; List connectionDataList = connectionService.findConnectionByProviderIdAndProviderUserId(providerId, userInfo.getSub()); if (CollectionUtil.isEmpty(connectionDataList)) { - // 自动注册// 自动注册 - userDetails = connectionService.signUp(AuthUser.builder() + // 自动注册 + AuthUser authUser = AuthUser.builder() .username(userInfo.getName()) .uuid(userInfo.getSub()) .avatar(userInfo.getPicture()) .source(providerId) - .build(), providerId, loginRequest.getState()); + .token(AuthToken.builder() + .accessCode(accessToken.getAccessToken()) + .expireIn(accessToken.getExpiresIn().longValue()) + .code(loginRequest.getCode()) + .userId(userInfo.getSub()) + .idToken(accessToken.getIdToken()) + .openId(userInfo.getSub()) + .refreshToken(accessToken.getRefreshToken()) + .build()) + .build(); + userDetails = connectionService.signUp(authUser, providerId, loginRequest.getState()); + } else { + ConnectionData connectionData = connectionDataList.stream().findFirst().orElseThrow(() -> new IllegalArgumentException("未找到匹配的连接信息")); + userDetails = userDetailsService.loadUserByUsername(connectionData.getUserId()); } //4.2 第三方登录用户已存在, 直接登录 if (userDetails == null) { + throw new NotConnectedException(providerId); } // 7 创建成功认证 token 并返回 Auth2AuthenticationToken auth2AuthenticationToken = new Auth2AuthenticationToken(userDetails, userDetails.getAuthorities(), providerId); diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/my/MyAuthenticationSuccessHandler.java b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/my/MyAuthenticationSuccessHandler.java index 01d6a66c2..8d36cdff3 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/my/MyAuthenticationSuccessHandler.java +++ b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/configures/my/MyAuthenticationSuccessHandler.java @@ -25,7 +25,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; -import org.springframework.stereotype.Component; import java.io.IOException; import java.util.Date; @@ -36,7 +35,6 @@ * @author 陈云龙 */ @Slf4j -@Component @AllArgsConstructor public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/entity/AuthToken.java b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/entity/AuthToken.java index baf3ab777..456be305a 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/entity/AuthToken.java +++ b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/entity/AuthToken.java @@ -11,7 +11,7 @@ @AllArgsConstructor public class AuthToken implements Serializable { private String accessToken; - private int expireIn; + private long expireIn; private String refreshToken; private int refreshTokenExpireIn; private String uid; diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/service/UserDetailsRegisterService.java b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/service/UserDetailsRegisterService.java index 3afae725b..4dcafaf8a 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/service/UserDetailsRegisterService.java +++ b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/service/UserDetailsRegisterService.java @@ -26,7 +26,6 @@ import cn.chenyunlong.security.entity.AuthUser; import cn.chenyunlong.security.enums.ErrorCodeEnum; import cn.chenyunlong.security.exception.RegisterUserFailureException; -import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.context.request.ServletWebRequest; @@ -75,7 +74,7 @@ default UserDetails registerUser(ServletWebRequest request) throws RegisterUserF * @return 注册后的 UserDetails 信息 * @throws RegisterUserFailureException 用户注册失败 */ - default UserDetails registerUser(@NonNull AuthUser authUser, @NonNull String username, @NonNull String defaultAuthority) throws RegisterUserFailureException { + default UserDetails registerUser(AuthUser authUser, String username, String defaultAuthority) throws RegisterUserFailureException { return this.registerUser(authUser, username, defaultAuthority, null); } @@ -94,7 +93,7 @@ default UserDetails registerUser(@NonNull AuthUser authUser, @NonNull String use * @return 注册后的 UserDetails 信息 * @throws RegisterUserFailureException 用户注册失败 */ - default UserDetails registerUser(@NonNull AuthUser authUser, @NonNull String username, @NonNull String defaultAuthority, + default UserDetails registerUser(AuthUser authUser, String username, String defaultAuthority, @Nullable String decodeState) throws RegisterUserFailureException { throw new RegisterUserFailureException(ErrorCodeEnum.USER_REGISTER_FAILURE, null); } diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/signup/ConnectionService.java b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/signup/ConnectionService.java index 42a196b7e..c74ae9412 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/signup/ConnectionService.java +++ b/qing-starters/qing-security-spring-boot-starter/src/main/java/cn/chenyunlong/security/signup/ConnectionService.java @@ -19,7 +19,6 @@ import cn.chenyunlong.security.entity.ConnectionData; import cn.chenyunlong.security.exception.RegisterUserFailureException; import cn.chenyunlong.security.exception.UpdateConnectionException; -import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.util.MultiValueMap; @@ -49,8 +48,7 @@ public interface ConnectionService { * @return the new user UserDetails. * @throws RegisterUserFailureException 用户重名或注册失败 */ - @NonNull - UserDetails signUp(@NonNull AuthUser authUser, @NonNull String providerId, @NonNull String encodeState) throws RegisterUserFailureException; + UserDetails signUp(AuthUser authUser, String providerId, String encodeState) throws RegisterUserFailureException; /** * 根据传入的参数更新第三方授权登录的用户信息, 包括 accessToken 信息, @@ -59,7 +57,7 @@ public interface ConnectionService { * @param connectionData 第三方授权登录的用户信息 * @throws UpdateConnectionException 更新异常 */ - void updateUserConnectionAndAuthToken(@NonNull final AuthUser authUser, @NonNull final ConnectionData connectionData) throws UpdateConnectionException; + void updateUserConnectionAndAuthToken(final AuthUser authUser, final ConnectionData connectionData) throws UpdateConnectionException; /** * 第三方授权登录信息{@link AuthUser}绑定到本地账号{@link UserDetails}, 且添加第三方授权登录信息到 user_connection 与 auth_token @@ -68,7 +66,7 @@ public interface ConnectionService { * @param authUser 第三方用户信息 * @param providerId 第三方服务商 Id */ - void binding(@NonNull UserDetails principal, @NonNull AuthUser authUser, @NonNull String providerId); + void binding(UserDetails principal, AuthUser authUser, String providerId); /** * 解除绑定(第三方) @@ -77,7 +75,7 @@ public interface ConnectionService { * @param providerId 第三方服务商 Id * @param providerUserId 第三方用户 Id */ - void unbinding(@NonNull String userId, @NonNull String providerId, @NonNull String providerUserId); + void unbinding(String userId, String providerId, String providerUserId); /** * 根据 providerId 与 providerUserId 获取 ConnectionData list. @@ -87,8 +85,8 @@ public interface ConnectionService { * @return connection data list */ @Nullable - List findConnectionByProviderIdAndProviderUserId(@NonNull String providerId, - @NonNull String providerUserId); + List findConnectionByProviderIdAndProviderUserId(String providerId, + String providerUserId); /** * 获取当前账号下所有绑定的第三方账号接口.
@@ -108,6 +106,6 @@ List findConnectionByProviderIdAndProviderUserId(@NonNull String * @param userId the userId * @return all connections the current user has across all providers. */ - @NonNull - MultiValueMap listAllConnections(@NonNull String userId); + + MultiValueMap listAllConnections(String userId); } diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/resources/META-INF/spring.factories b/qing-starters/qing-security-spring-boot-starter/src/main/resources/META-INF/spring.factories index 8bf1e4eb1..718b7fcd3 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/qing-starters/qing-security-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -1,3 +1,2 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.chenyunlong.security.config.SecurityConfig\ cn.chenyunlong.security.configures.authing.AuthingLoginConfigurer diff --git a/qing-starters/qing-security-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/qing-starters/qing-security-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 620a56ed9..5bdde8990 100644 --- a/qing-starters/qing-security-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/qing-starters/qing-security-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1 @@ -cn.chenyunlong.security.configures.authing.AuthingLoginConfigurer -cn.chenyunlong.security.config.SecurityConfig \ No newline at end of file +cn.chenyunlong.security.configures.authing.AuthingLoginConfigurer \ No newline at end of file diff --git a/sql/scripts/migrate.sql b/sql/scripts/migrate.sql index 32f7acecf..f8327ec39 100644 --- a/sql/scripts/migrate.sql +++ b/sql/scripts/migrate.sql @@ -15,9 +15,9 @@ alter table anime_episode add playlist_id bigint not null comment '播放列表ID' after anime_id; -create unique index user_email_index on user (email); +create unique index user_email_index on qingUser (email); -create unique index user_username_index on user (username); +create unique index user_username_index on qingUser (username); SELECT concat('ALTER TABLE ', table_schema, '.', table_name, diff --git a/sql/scripts/qing.sql b/sql/scripts/qing.sql index 72f97d572..a1050d268 100644 --- a/sql/scripts/qing.sql +++ b/sql/scripts/qing.sql @@ -508,7 +508,7 @@ TABLES `role` WRITE; DISABLE KEYS */; INSERT INTO `role` VALUES (1, 'admin', '管理团', now(), now(), 'stan', '', '', ''), - (2, 'user', '普通用户', now(), now(), 'stan', '', '', ''); + (2, 'qingUser', '普通用户', now(), now(), 'stan', '', '', ''); /*!40000 ALTER TABLE `role` ENABLE KEYS */; UNLOCK @@ -624,10 +624,10 @@ CREATE TABLE `upload_file` AUTO_INCREMENT = 138 DEFAULT CHARSET = utf8; -DROP TABLE IF EXISTS `user`; +DROP TABLE IF EXISTS `qingUser`; /*!40101 SET @saved_cs_client = @@character_set_client */; -CREATE TABLE `user` +CREATE TABLE `qingUser` ( `userid` bigint(20) not null AUTO_INCREMENT, `username` varchar(10) DEFAULT NULL COMMENT '用户登录的账号,长度为十位字符', @@ -675,7 +675,7 @@ CREATE TABLE `user_third` # 导入默认的用户信息 -INSERT INTO `user` +INSERT INTO `qingUser` VALUES (123, 'stan', '纯纯的黑色幽默', 'avatar_path', 'description', '1576302867@qq.com', '13628091432', '$2a$10$45ScSS1BeuYizV2QYJ9HVOfpBoTOxnjXyCkNPFkTJnf9o3bW0l.4G', '13628091432', now(), now(), 'stan', '', '', ''); @@ -845,7 +845,7 @@ insert into sys_config values (1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', sysdate(), '', null, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow'); insert into sys_config -values (2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', sysdate(), '', null, +values (2, '用户管理-账号初始密码', 'sys.qingUser.initPassword', '123456', 'Y', 'admin', sysdate(), '', null, '初始化密码 123456'); insert into sys_config values (3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', sysdate(), '', null,