diff --git a/backend/src/main/java/com/qqchen/deploy/backend/api/TenantApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/api/TenantApiController.java index 36ed715a..0fd86baa 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/api/TenantApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/api/TenantApiController.java @@ -1,8 +1,8 @@ package com.qqchen.deploy.backend.api; -import com.qqchen.deploy.backend.dto.TenantDTO; +import com.qqchen.deploy.backend.model.TenantDTO; import com.qqchen.deploy.backend.framework.controller.BaseController; -import com.qqchen.deploy.backend.dto.query.TenantQuery; +import com.qqchen.deploy.backend.model.query.TenantQuery; import com.qqchen.deploy.backend.entity.Tenant; import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/api/UserApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/api/UserApiController.java index 8dcb1bd4..29062235 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/api/UserApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/api/UserApiController.java @@ -1,14 +1,14 @@ package com.qqchen.deploy.backend.api; -import com.qqchen.deploy.backend.dto.RoleDTO; -import com.qqchen.deploy.backend.dto.query.UserQuery; -import com.qqchen.deploy.backend.dto.request.UserRequest; +import com.qqchen.deploy.backend.model.RoleDTO; +import com.qqchen.deploy.backend.model.query.UserQuery; +import com.qqchen.deploy.backend.model.request.UserRequest; import com.qqchen.deploy.backend.framework.controller.BaseController; import com.qqchen.deploy.backend.framework.api.Response; import com.qqchen.deploy.backend.entity.User; -import com.qqchen.deploy.backend.dto.UserDTO; -import com.qqchen.deploy.backend.dto.request.LoginRequest; -import com.qqchen.deploy.backend.dto.response.LoginResponse; +import com.qqchen.deploy.backend.model.UserDTO; +import com.qqchen.deploy.backend.model.request.LoginRequest; +import com.qqchen.deploy.backend.model.response.LoginResponse; import com.qqchen.deploy.backend.service.IUserService; import io.swagger.v3.oas.annotations.Operation; import jakarta.annotation.Resource; @@ -21,7 +21,7 @@ import java.io.OutputStream; import java.util.List; @RestController -@RequestMapping("/api/v1/users") +@RequestMapping("/api/v1/user") public class UserApiController extends BaseController { @Resource @@ -34,10 +34,10 @@ public class UserApiController extends BaseController register(@Validated @RequestBody UserRequest request) { - return Response.success(userService.register(request)); + @Operation(summary = "获取当前用户信息") + @GetMapping("/current") + public Response getCurrentUser() { + return Response.success(userService.getCurrentUser()); } @Override @@ -52,15 +52,4 @@ public class UserApiController extends BaseController> getCurrentUserRoles() { - return Response.success(userService.getCurrentUserRoles()); - } - - @GetMapping("/{id}/roles") - @Operation(summary = "获取指定用户的角色") - public Response> getUserRoles(@PathVariable Long id) { - return Response.success(userService.getUserRoles(id)); - } } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/controller/TenantController.java b/backend/src/main/java/com/qqchen/deploy/backend/controller/TenantController.java index ce156bc1..6d7835c5 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/controller/TenantController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/controller/TenantController.java @@ -1,9 +1,9 @@ package com.qqchen.deploy.backend.controller; -import com.qqchen.deploy.backend.dto.query.TenantQuery; +import com.qqchen.deploy.backend.model.query.TenantQuery; import com.qqchen.deploy.backend.entity.Tenant; import com.qqchen.deploy.backend.framework.controller.BaseController; -import com.qqchen.deploy.backend.dto.TenantDTO; +import com.qqchen.deploy.backend.model.TenantDTO; import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/controller/UserController.java b/backend/src/main/java/com/qqchen/deploy/backend/controller/UserController.java index 061d5918..a6e00993 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/controller/UserController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/controller/UserController.java @@ -1,7 +1,7 @@ package com.qqchen.deploy.backend.controller; import com.qqchen.deploy.backend.api.UserApiController; -import com.qqchen.deploy.backend.dto.UserDTO; +import com.qqchen.deploy.backend.model.UserDTO; import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController -@RequestMapping("/mgmt/users") +@RequestMapping("/mgmt/user") public class UserController extends UserApiController { @Override diff --git a/backend/src/main/java/com/qqchen/deploy/backend/converter/RoleConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/converter/RoleConverter.java index 09c24b3b..ab748597 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/converter/RoleConverter.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/converter/RoleConverter.java @@ -1,6 +1,6 @@ package com.qqchen.deploy.backend.converter; -import com.qqchen.deploy.backend.dto.RoleDTO; +import com.qqchen.deploy.backend.model.RoleDTO; import com.qqchen.deploy.backend.entity.Role; import com.qqchen.deploy.backend.framework.converter.BaseConverter; import org.mapstruct.Mapper; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/converter/SysParamConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/converter/SysParamConverter.java new file mode 100644 index 00000000..b3276053 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/converter/SysParamConverter.java @@ -0,0 +1,10 @@ +package com.qqchen.deploy.backend.converter; + +import com.qqchen.deploy.backend.entity.SysParam; +import com.qqchen.deploy.backend.framework.converter.BaseConverter; +import com.qqchen.deploy.backend.model.SysParamDTO; +import org.mapstruct.Mapper; + +@Mapper(config = BaseConverter.class) +public interface SysParamConverter extends BaseConverter { +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/converter/TenantConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/converter/TenantConverter.java index a1c3691e..3ae7d650 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/converter/TenantConverter.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/converter/TenantConverter.java @@ -1,6 +1,6 @@ package com.qqchen.deploy.backend.converter; -import com.qqchen.deploy.backend.dto.TenantDTO; +import com.qqchen.deploy.backend.model.TenantDTO; import com.qqchen.deploy.backend.entity.Tenant; import com.qqchen.deploy.backend.framework.converter.BaseConverter; import org.mapstruct.Mapper; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/converter/UserConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/converter/UserConverter.java index 8dff4cbf..95808382 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/converter/UserConverter.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/converter/UserConverter.java @@ -1,11 +1,19 @@ package com.qqchen.deploy.backend.converter; -import com.qqchen.deploy.backend.framework.converter.BaseConverter; import com.qqchen.deploy.backend.entity.User; -import com.qqchen.deploy.backend.dto.UserDTO; +import com.qqchen.deploy.backend.framework.converter.BaseConverter; +import com.qqchen.deploy.backend.model.UserDTO; +import com.qqchen.deploy.backend.model.response.LoginResponse; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; @Mapper(config = BaseConverter.class) public interface UserConverter extends BaseConverter { // MapStruct 会自动实现所有方法 + + @Mapping(target = "token", ignore = true) + LoginResponse toLoginResponse(User user); + + @Mapping(target = "token", source = "token") + LoginResponse toLoginResponse(User user, String token); } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/entity/SysParam.java b/backend/src/main/java/com/qqchen/deploy/backend/entity/SysParam.java new file mode 100644 index 00000000..5a792f69 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/entity/SysParam.java @@ -0,0 +1,32 @@ +package com.qqchen.deploy.backend.entity; + +import com.qqchen.deploy.backend.framework.annotation.LogicDelete; +import com.qqchen.deploy.backend.framework.domain.Entity; +import jakarta.persistence.Column; +import jakarta.persistence.Table; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@jakarta.persistence.Entity +@Table(name = "sys_param") +@LogicDelete +public class SysParam extends Entity { + + @Column(nullable = false, length = 100) + private String code; + + @Column(nullable = false, length = 100) + private String name; + + @Column(columnDefinition = "TEXT") + private String value; + + @Column(nullable = false, length = 50) + private String type; + + private String description; + + private Boolean enabled; + +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/audit/annotation/Audited.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/annotation/Audited.java similarity index 77% rename from backend/src/main/java/com/qqchen/deploy/backend/framework/audit/annotation/Audited.java rename to backend/src/main/java/com/qqchen/deploy/backend/framework/annotation/Audited.java index 04963393..3cbc22d0 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/audit/annotation/Audited.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/annotation/Audited.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.framework.audit.annotation; +package com.qqchen.deploy.backend.framework.annotation; import java.lang.annotation.*; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/audit/aspect/AuditAspect.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/audit/aspect/AuditAspect.java index 356e7eed..d51ce11d 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/audit/aspect/AuditAspect.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/audit/aspect/AuditAspect.java @@ -1,7 +1,7 @@ package com.qqchen.deploy.backend.framework.audit.aspect; import com.qqchen.deploy.backend.framework.audit.AuditMetadata; -import com.qqchen.deploy.backend.framework.audit.annotation.Audited; +import com.qqchen.deploy.backend.framework.annotation.Audited; import com.qqchen.deploy.backend.framework.audit.event.AuditEvent; import com.qqchen.deploy.backend.framework.security.SecurityUtils; import jakarta.servlet.http.HttpServletRequest; @@ -26,7 +26,7 @@ public class AuditAspect { private final ApplicationEventPublisher eventPublisher; - @Around("@annotation(com.qqchen.deploy.backend.framework.audit.annotation.Audited)") + @Around("@annotation(com.qqchen.deploy.backend.framework.annotation.Audited)") public Object auditMethod(ProceedingJoinPoint joinPoint) throws Throwable { // 获取审计元数据 AuditMetadata metadata = extractAuditMetadata(joinPoint); diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/config/JpaAuditingConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/audit/config/JpaAuditingConfig.java similarity index 93% rename from backend/src/main/java/com/qqchen/deploy/backend/framework/config/JpaAuditingConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/framework/audit/config/JpaAuditingConfig.java index aed9e6f0..24b29207 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/config/JpaAuditingConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/audit/config/JpaAuditingConfig.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.framework.config; +package com.qqchen.deploy.backend.framework.audit.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/config/AppConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/config/AppConfig.java index 7323deab..e5db5f21 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/config/AppConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/config/AppConfig.java @@ -1,6 +1,5 @@ package com.qqchen.deploy.backend.framework.config; -import com.qqchen.deploy.backend.framework.interceptor.TenantInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/config/DependencyInjectionPostProcessor.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/config/DependencyInjectionPostProcessor.java index 994cf2e6..785effce 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/config/DependencyInjectionPostProcessor.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/config/DependencyInjectionPostProcessor.java @@ -55,14 +55,11 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp if (bean instanceof BaseServiceImpl service) { return injectServiceDependencies(service, beanName); } - } catch (DependencyInjectionException e) { - log.error("Dependency injection failed for bean: {}", beanName, e); - throw e; } catch (Exception e) { - log.error("Unexpected error during dependency injection for bean: {}", beanName, e); - throw new DependencyInjectionException( - String.format("Failed to inject dependencies for bean: %s", beanName), - e); + String errorMsg = String.format("依赖注入失败 - Bean: %s, 类型: %s, 原因: %s", + beanName, bean.getClass().getName(), e.getMessage()); + log.error(errorMsg, e); + throw new DependencyInjectionException(errorMsg, e); } return bean; } @@ -83,12 +80,12 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp try { IBaseService service = (IBaseService) cachedService; ReflectionUtils.setField("service", controller, service); - log.debug("Successfully injected service {} for controller {}", - service.getClass().getSimpleName(), + log.debug("Successfully injected service {} for controller {}", + service.getClass().getSimpleName(), controller.getClass().getSimpleName()); } catch (Exception e) { throw new DependencyInjectionException( - String.format("Failed to inject service for controller: %s", controller.getClass().getSimpleName()), + String.format("Failed to inject service for controller: %s", controller.getClass().getSimpleName()), e); } @@ -151,12 +148,9 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp log.debug("Successfully injected all dependencies for service: {}", beanName); return service; - } catch (DependencyInjectionException e) { - throw e; } catch (Exception e) { throw new DependencyInjectionException( - String.format("Failed to inject dependencies for service: %s", service.getClass().getSimpleName()), - e); + String.format("Failed to inject dependencies for service: %s", service.getClass().getSimpleName()), e); } } @@ -189,20 +183,28 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp private , D extends BaseDTO, ID extends Serializable> void injectRepository(BaseServiceImpl service, Class entityClass) { String repositoryBeanName = "I" + entityClass.getSimpleName() + "Repository"; - log.debug("Looking for repository bean: {}", repositoryBeanName); + log.debug("正在查找 Repository: {}", repositoryBeanName); - IBaseRepository repository = (IBaseRepository) repositoryCache.computeIfAbsent( - entityClass, - key -> { - if (!applicationContext.containsBean(repositoryBeanName)) { - throw new BusinessException( - ResponseCode.DEPENDENCY_INJECTION_REPOSITORY_NOT_FOUND, - new Object[] {key.getSimpleName(), repositoryBeanName}); - } - return (IBaseRepository) applicationContext.getBean(repositoryBeanName); - }); + try { + IBaseRepository repository = (IBaseRepository) repositoryCache.computeIfAbsent( + entityClass, + key -> { + if (!applicationContext.containsBean(repositoryBeanName)) { + String errorMsg = String.format("找不到 Repository - 服务类: %s, 实体类: %s, Repository名称: %s", + service.getClass().getName(), key.getSimpleName(), repositoryBeanName); + log.error(errorMsg); + throw new DependencyInjectionException(errorMsg, new RuntimeException(errorMsg)); + } + return (IBaseRepository) applicationContext.getBean(repositoryBeanName); + }); - ReflectionUtils.setField("repository", service, repository); + ReflectionUtils.setField("repository", service, repository); + } catch (Exception e) { + String errorMsg = String.format("注入 Repository 失败 - 服务类: %s, 实体类: %s, Repository名称: %s, 原因: %s", + service.getClass().getName(), entityClass.getSimpleName(), repositoryBeanName, e.getMessage()); + log.error(errorMsg, e); + throw new DependencyInjectionException(errorMsg, e); + } } @SuppressWarnings("unchecked") @@ -210,44 +212,68 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp void injectConverter(BaseServiceImpl service, Class entityClass) { String converterBeanName = entityClass.getSimpleName().substring(0, 1).toLowerCase() + entityClass.getSimpleName().substring(1) + "ConverterImpl"; - log.debug("Looking for converter bean: {}", converterBeanName); + log.debug("正在查找 Converter: {}", converterBeanName); - BaseConverter converter = (BaseConverter) converterCache.computeIfAbsent( - entityClass, - key -> { - if (!applicationContext.containsBean(converterBeanName)) { - throw new BusinessException( - ResponseCode.DEPENDENCY_INJECTION_CONVERTER_NOT_FOUND, - new Object[] {key.getSimpleName(), converterBeanName}); - } - return (BaseConverter) applicationContext.getBean(converterBeanName); - }); + try { + BaseConverter converter = (BaseConverter) converterCache.computeIfAbsent( + entityClass, + key -> { + if (!applicationContext.containsBean(converterBeanName)) { + String errorMsg = String.format("找不到 Converter - 服务类: %s, 实体类: %s, Converter名称: %s", + service.getClass().getName(), key.getSimpleName(), converterBeanName); + log.error(errorMsg); + throw new DependencyInjectionException(errorMsg, new RuntimeException(errorMsg)); + } + return (BaseConverter) applicationContext.getBean(converterBeanName); + }); - ReflectionUtils.setField("converter", service, converter); + ReflectionUtils.setField("converter", service, converter); + } catch (Exception e) { + String errorMsg = String.format("注入 Converter 失败 - 服务类: %s, 实体类: %s, Converter名称: %s, 原因: %s", + service.getClass().getName(), entityClass.getSimpleName(), converterBeanName, e.getMessage()); + log.error(errorMsg, e); + throw new DependencyInjectionException(errorMsg, e); + } } @SuppressWarnings("unchecked") - private , D extends BaseDTO, ID extends Serializable> void injectEntityPath(BaseServiceImpl service, Class entityClass) { + private , D extends BaseDTO, ID extends Serializable> + void injectEntityPath(BaseServiceImpl service, Class entityClass) { try { EntityPath entityPath = (EntityPath) entityPathCache.computeIfAbsent( entityClass, key -> { + String qClassName = key.getPackageName() + ".Q" + key.getSimpleName(); try { - String qClassName = key.getPackageName() + ".Q" + key.getSimpleName(); Class qClass = Class.forName(qClassName); - Field instanceField = qClass.getDeclaredField(key.getSimpleName().toLowerCase()); + String fieldName = key.getSimpleName(); + fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1); + Field instanceField = qClass.getDeclaredField(fieldName); return (EntityPath) instanceField.get(null); + } catch (ClassNotFoundException e) { + String errorMsg = String.format("找不到 QueryDSL 实体类 - 服务类: %s, 实体类: %s, Q类名: %s", + service.getClass().getName(), key.getSimpleName(), qClassName); + log.error(errorMsg, e); + throw new DependencyInjectionException(errorMsg, e); + } catch (NoSuchFieldException e) { + String errorMsg = String.format("找不到 QueryDSL 实体字段 - 服务类: %s, 实体类: %s, Q类名: %s", + service.getClass().getName(), key.getSimpleName(), qClassName); + log.error(errorMsg, e); + throw new DependencyInjectionException(errorMsg, e); } catch (Exception e) { - throw new BusinessException( - ResponseCode.DEPENDENCY_INJECTION_ENTITYPATH_FAILED, - new Object[] {key.getSimpleName(), e.getMessage()}); + String errorMsg = String.format("获取 QueryDSL 实体失败 - 服务类: %s, 实体类: %s, Q类名: %s, 原因: %s", + service.getClass().getName(), key.getSimpleName(), qClassName, e.getMessage()); + log.error(errorMsg, e); + throw new DependencyInjectionException(errorMsg, e); } }); + ReflectionUtils.setField("entityPath", service, entityPath); - } catch (BusinessException e) { - throw e; } catch (Exception e) { - throw new BusinessException(ResponseCode.DEPENDENCY_INJECTION_ENTITYPATH_FAILED, new Object[] {entityClass.getSimpleName(), e.getMessage()}); + String errorMsg = String.format("注入 EntityPath 失败 - 服务类: %s, 实体类: %s, 原因: %s", + service.getClass().getName(), entityClass.getSimpleName(), e.getMessage()); + log.error(errorMsg, e); + throw new DependencyInjectionException(errorMsg, e); } } } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/filter/TenantFilter.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/filter/TenantFilter.java index 4e7e95bd..38353bc5 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/filter/TenantFilter.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/filter/TenantFilter.java @@ -1,14 +1,12 @@ package com.qqchen.deploy.backend.framework.filter; -import com.qqchen.deploy.backend.framework.context.TenantContext; +import com.qqchen.deploy.backend.framework.tenant.TenantContext; import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; import java.io.IOException; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/handler/GlobalExceptionHandler.java similarity index 91% rename from backend/src/main/java/com/qqchen/deploy/backend/framework/exception/GlobalExceptionHandler.java rename to backend/src/main/java/com/qqchen/deploy/backend/framework/handler/GlobalExceptionHandler.java index c884e09e..740bd1db 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/handler/GlobalExceptionHandler.java @@ -1,13 +1,14 @@ -package com.qqchen.deploy.backend.framework.exception; +package com.qqchen.deploy.backend.framework.handler; import com.qqchen.deploy.backend.framework.api.Response; import com.qqchen.deploy.backend.framework.enums.ResponseCode; +import com.qqchen.deploy.backend.framework.exception.BusinessException; +import com.qqchen.deploy.backend.framework.exception.SystemException; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.MalformedJwtException; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; -import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/config/MessageConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/i18n/MessageConfig.java similarity index 94% rename from backend/src/main/java/com/qqchen/deploy/backend/framework/config/MessageConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/framework/i18n/MessageConfig.java index 1f8b8ffb..b98344db 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/config/MessageConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/i18n/MessageConfig.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.framework.config; +package com.qqchen.deploy.backend.framework.i18n; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/config/JacksonConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/json/JacksonConfig.java similarity index 95% rename from backend/src/main/java/com/qqchen/deploy/backend/framework/config/JacksonConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/framework/json/JacksonConfig.java index cfc11319..389d02e1 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/config/JacksonConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/json/JacksonConfig.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.framework.config; +package com.qqchen.deploy.backend.framework.json; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/security/config/SecurityConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/security/config/SecurityConfig.java index eb6470fa..52fa7d9b 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/security/config/SecurityConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/security/config/SecurityConfig.java @@ -22,48 +22,45 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic @RequiredArgsConstructor public class SecurityConfig { - private final CustomAuthenticationEntryPoint authenticationEntryPoint; - + private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint; + private final JwtTokenUtil jwtTokenUtil; private final UserDetailsService userDetailsService; - private final JwtTokenUtil jwtTokenUtil; + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http + .csrf(csrf -> csrf.disable()) + .cors(cors -> cors.disable()) + .sessionManagement(session -> + session.sessionCreationPolicy(SessionCreationPolicy.STATELESS) + ) + .authorizeHttpRequests(auth -> auth + .requestMatchers( + "/api/v1/user/login", + "/api/v1/user/register", + "/api/v1/tenant/list", + "/swagger-ui/**", + "/v3/api-docs/**", + "/actuator/health" + ).permitAll() + .anyRequest().authenticated() + ) + .addFilterBefore( + jwtAuthenticationFilter(), + UsernamePasswordAuthenticationFilter.class + ) + .exceptionHandling(ex -> ex + .authenticationEntryPoint(customAuthenticationEntryPoint) + ); + + return http.build(); + } @Bean public JwtAuthenticationFilter jwtAuthenticationFilter() { return new JwtAuthenticationFilter(jwtTokenUtil, userDetailsService); } - @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http -// .cors(cors -> cors.configurationSource(corsConfigurationSource())) - .csrf(csrf -> csrf.disable()) - .sessionManagement(session -> session - .sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .exceptionHandling(exceptions -> exceptions - .authenticationEntryPoint(authenticationEntryPoint)) - .authorizeHttpRequests(auth -> auth - .requestMatchers("/api/v1/users/login", "/api/v1/users/register", "/api/v1/tenant/list").permitAll() - .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll() - .requestMatchers("/actuator/health").permitAll() - .anyRequest().authenticated() - ) - .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); - - return http.build(); - } - - //TODO 这里会导致无限递归循环报错 -// @Bean -// public UserDetailsService userDetailsService() { -// UserDetails user = User.withUsername("anonymous") -// .password("{noop}") -// .roles("ANONYMOUS") -// .build(); -// return new InMemoryUserDetailsManager(user); -// } - - @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/security/filter/JwtAuthenticationFilter.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/security/filter/JwtAuthenticationFilter.java index 690ee162..3856d551 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/security/filter/JwtAuthenticationFilter.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/security/filter/JwtAuthenticationFilter.java @@ -2,7 +2,7 @@ package com.qqchen.deploy.backend.framework.security.filter; import com.fasterxml.jackson.databind.ObjectMapper; import com.qqchen.deploy.backend.framework.api.Response; -import com.qqchen.deploy.backend.framework.context.TenantContext; +import com.qqchen.deploy.backend.framework.tenant.TenantContext; import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.framework.exception.BusinessException; import com.qqchen.deploy.backend.framework.exception.JwtAuthenticationException; @@ -39,8 +39,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { private final UserDetailsService userDetailsService; private static final List WHITELIST = Arrays.asList( - "/api/v1/users/login", - "/api/v1/users/register", + "/api/v1/user/login", + "/api/v1/user/register", "/api/v1/tenant/list", "/swagger-ui/**", "/v3/api-docs/**", @@ -59,10 +59,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { String jwt = getJwtFromRequest(request); if (StringUtils.hasText(jwt)) { String username = jwtTokenUtil.getUsernameFromToken(jwt); - if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = userDetailsService.loadUserByUsername(username); - if (jwtTokenUtil.validateToken(jwt, userDetails)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/security/handler/CustomAuthenticationEntryPoint.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/security/handler/CustomAuthenticationEntryPoint.java index 82e48e11..75e19bf2 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/security/handler/CustomAuthenticationEntryPoint.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/security/handler/CustomAuthenticationEntryPoint.java @@ -39,7 +39,18 @@ public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding(StandardCharsets.UTF_8.name()); - Response errorResponse = Response.error(ResponseCode.UNAUTHORIZED); + Response errorResponse; + + if (authException instanceof BadCredentialsException) { + errorResponse = Response.error(ResponseCode.LOGIN_ERROR); + } else if (authException instanceof InternalAuthenticationServiceException) { + errorResponse = Response.error(ResponseCode.ERROR); + } else if (authException instanceof InsufficientAuthenticationException) { + errorResponse = Response.error(ResponseCode.AUTH_REQUIRED); + } else { + errorResponse = Response.error(ResponseCode.UNAUTHORIZED); + } + objectMapper.writeValue(response.getOutputStream(), errorResponse); } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/context/TenantContext.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/tenant/TenantContext.java similarity index 90% rename from backend/src/main/java/com/qqchen/deploy/backend/framework/context/TenantContext.java rename to backend/src/main/java/com/qqchen/deploy/backend/framework/tenant/TenantContext.java index c2bdb595..28b1ff74 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/context/TenantContext.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/tenant/TenantContext.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.framework.context; +package com.qqchen.deploy.backend.framework.tenant; public class TenantContext { private static final ThreadLocal CURRENT_TENANT = new ThreadLocal<>(); diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/interceptor/TenantInterceptor.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/tenant/TenantInterceptor.java similarity index 90% rename from backend/src/main/java/com/qqchen/deploy/backend/framework/interceptor/TenantInterceptor.java rename to backend/src/main/java/com/qqchen/deploy/backend/framework/tenant/TenantInterceptor.java index 4e940479..03dffd00 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/interceptor/TenantInterceptor.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/tenant/TenantInterceptor.java @@ -1,11 +1,9 @@ -package com.qqchen.deploy.backend.framework.interceptor; +package com.qqchen.deploy.backend.framework.tenant; -import com.qqchen.deploy.backend.framework.context.TenantContext; import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.framework.exception.BusinessException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.springframework.stereotype.Component; import org.springframework.util.AntPathMatcher; import org.springframework.web.servlet.HandlerInterceptor; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/dto/RoleDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/model/RoleDTO.java similarity index 87% rename from backend/src/main/java/com/qqchen/deploy/backend/dto/RoleDTO.java rename to backend/src/main/java/com/qqchen/deploy/backend/model/RoleDTO.java index 58e59792..48140e87 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/dto/RoleDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/RoleDTO.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.dto; +package com.qqchen.deploy.backend.model; import com.qqchen.deploy.backend.framework.dto.BaseDTO; import lombok.Data; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/model/SysParamDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/model/SysParamDTO.java new file mode 100644 index 00000000..b626826c --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/SysParamDTO.java @@ -0,0 +1,20 @@ +package com.qqchen.deploy.backend.model; + +import com.qqchen.deploy.backend.framework.dto.BaseDTO; +import lombok.Data; + +@Data +public class SysParamDTO extends BaseDTO { + + private String code; + + private String name; + + private String value; + + private String type; + + private String description; + + private Boolean enabled; +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/dto/TenantDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/model/TenantDTO.java similarity index 91% rename from backend/src/main/java/com/qqchen/deploy/backend/dto/TenantDTO.java rename to backend/src/main/java/com/qqchen/deploy/backend/model/TenantDTO.java index 0280f4a5..87b5db3d 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/dto/TenantDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/TenantDTO.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.dto; +package com.qqchen.deploy.backend.model; import com.qqchen.deploy.backend.framework.dto.BaseDTO; import lombok.Data; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/dto/UserDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/model/UserDTO.java similarity index 90% rename from backend/src/main/java/com/qqchen/deploy/backend/dto/UserDTO.java rename to backend/src/main/java/com/qqchen/deploy/backend/model/UserDTO.java index 6fa5d58d..af622d10 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/dto/UserDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/UserDTO.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.dto; +package com.qqchen.deploy.backend.model; import com.qqchen.deploy.backend.framework.dto.BaseDTO; import lombok.Data; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/model/query/SysParamQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/model/query/SysParamQuery.java new file mode 100644 index 00000000..9c7f1186 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/query/SysParamQuery.java @@ -0,0 +1,16 @@ +package com.qqchen.deploy.backend.model.query; + +import com.qqchen.deploy.backend.framework.query.BaseQuery; +import lombok.Data; + +@Data +public class SysParamQuery extends BaseQuery { + + private String code; + + private String name; + + private String type; + + private Boolean enabled; +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/dto/query/TenantQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/model/query/TenantQuery.java similarity index 92% rename from backend/src/main/java/com/qqchen/deploy/backend/dto/query/TenantQuery.java rename to backend/src/main/java/com/qqchen/deploy/backend/model/query/TenantQuery.java index abceb610..18d6f804 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/dto/query/TenantQuery.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/query/TenantQuery.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.dto.query; +package com.qqchen.deploy.backend.model.query; import com.qqchen.deploy.backend.framework.annotation.QueryField; import com.qqchen.deploy.backend.framework.enums.QueryType; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/dto/query/UserQuery.java b/backend/src/main/java/com/qqchen/deploy/backend/model/query/UserQuery.java similarity index 95% rename from backend/src/main/java/com/qqchen/deploy/backend/dto/query/UserQuery.java rename to backend/src/main/java/com/qqchen/deploy/backend/model/query/UserQuery.java index 3def907e..efa34212 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/dto/query/UserQuery.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/query/UserQuery.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.dto.query; +package com.qqchen.deploy.backend.model.query; import com.qqchen.deploy.backend.framework.annotation.QueryField; import com.qqchen.deploy.backend.framework.query.BaseQuery; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/dto/request/LoginRequest.java b/backend/src/main/java/com/qqchen/deploy/backend/model/request/LoginRequest.java similarity index 67% rename from backend/src/main/java/com/qqchen/deploy/backend/dto/request/LoginRequest.java rename to backend/src/main/java/com/qqchen/deploy/backend/model/request/LoginRequest.java index c095c577..f1ae44f9 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/dto/request/LoginRequest.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/request/LoginRequest.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.dto.request; +package com.qqchen.deploy.backend.model.request; import jakarta.validation.constraints.NotBlank; import lombok.Data; @@ -11,4 +11,7 @@ public class LoginRequest { @NotBlank(message = "密码不能为空") private String password; + + @NotBlank(message = "租户不能为空") + private String tenantId; } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/dto/request/UserRegisterRequest.java b/backend/src/main/java/com/qqchen/deploy/backend/model/request/UserRegisterRequest.java similarity index 88% rename from backend/src/main/java/com/qqchen/deploy/backend/dto/request/UserRegisterRequest.java rename to backend/src/main/java/com/qqchen/deploy/backend/model/request/UserRegisterRequest.java index f7c19417..6ef352e5 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/dto/request/UserRegisterRequest.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/request/UserRegisterRequest.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.dto.request; +package com.qqchen.deploy.backend.model.request; import jakarta.validation.constraints.NotEmpty; import lombok.Data; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/dto/request/UserRequest.java b/backend/src/main/java/com/qqchen/deploy/backend/model/request/UserRequest.java similarity index 90% rename from backend/src/main/java/com/qqchen/deploy/backend/dto/request/UserRequest.java rename to backend/src/main/java/com/qqchen/deploy/backend/model/request/UserRequest.java index d21d6b8c..5342bb06 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/dto/request/UserRequest.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/request/UserRequest.java @@ -1,10 +1,9 @@ -package com.qqchen.deploy.backend.dto.request; +package com.qqchen.deploy.backend.model.request; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; import lombok.Data; -import lombok.EqualsAndHashCode; @Data public class UserRequest { diff --git a/backend/src/main/java/com/qqchen/deploy/backend/dto/response/LoginResponse.java b/backend/src/main/java/com/qqchen/deploy/backend/model/response/LoginResponse.java similarity index 77% rename from backend/src/main/java/com/qqchen/deploy/backend/dto/response/LoginResponse.java rename to backend/src/main/java/com/qqchen/deploy/backend/model/response/LoginResponse.java index 8aa5937d..7a4d1d34 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/dto/response/LoginResponse.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/response/LoginResponse.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.dto.response; +package com.qqchen.deploy.backend.model.response; import lombok.Data; import lombok.EqualsAndHashCode; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/dto/response/TenantResponse.java b/backend/src/main/java/com/qqchen/deploy/backend/model/response/TenantResponse.java similarity index 89% rename from backend/src/main/java/com/qqchen/deploy/backend/dto/response/TenantResponse.java rename to backend/src/main/java/com/qqchen/deploy/backend/model/response/TenantResponse.java index e7aed94d..9a087813 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/dto/response/TenantResponse.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/response/TenantResponse.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.dto.response; +package com.qqchen.deploy.backend.model.response; import com.qqchen.deploy.backend.framework.dto.BaseResponse; import lombok.Data; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/dto/response/UserResponse.java b/backend/src/main/java/com/qqchen/deploy/backend/model/response/UserResponse.java similarity index 77% rename from backend/src/main/java/com/qqchen/deploy/backend/dto/response/UserResponse.java rename to backend/src/main/java/com/qqchen/deploy/backend/model/response/UserResponse.java index fadbb83f..2522f9f0 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/dto/response/UserResponse.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/response/UserResponse.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.dto.response; +package com.qqchen.deploy.backend.model.response; import com.qqchen.deploy.backend.framework.dto.BaseResponse; import lombok.Data; @@ -9,8 +9,6 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) public class UserResponse extends BaseResponse { - private Long id; - private String username; private String email; @@ -21,5 +19,4 @@ public class UserResponse extends BaseResponse { private Boolean enabled; - private String password; } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/repository/ISysParamRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/repository/ISysParamRepository.java new file mode 100644 index 00000000..b6a58518 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/repository/ISysParamRepository.java @@ -0,0 +1,39 @@ +package com.qqchen.deploy.backend.repository; + +import com.qqchen.deploy.backend.entity.SysParam; +import com.qqchen.deploy.backend.framework.repository.IBaseRepository; + +import java.util.List; +import java.util.Optional; + +public interface ISysParamRepository extends IBaseRepository { + + /** + * 根据参数编码查询参数 + * @param code 参数编码 + * @return 参数对象 + */ + Optional findByCodeAndDeletedFalse(String code); + + /** + * 根据参数编码和启用状态查询参数 + * @param code 参数编码 + * @param enabled 启用状态 + * @return 参数对象 + */ + Optional findByCodeAndEnabledAndDeletedFalse(String code, Boolean enabled); + + /** + * 根据参数类型查询参数列表 + * @param type 参数类型 + * @return 参数列表 + */ + List findByTypeAndDeletedFalse(String type); + + /** + * 检查参数编码是否存在 + * @param code 参数编码 + * @return 是否存在 + */ + boolean existsByCodeAndDeletedFalse(String code); +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/service/ISysParamService.java b/backend/src/main/java/com/qqchen/deploy/backend/service/ISysParamService.java new file mode 100644 index 00000000..241f6af7 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/service/ISysParamService.java @@ -0,0 +1,8 @@ +package com.qqchen.deploy.backend.service; + +import com.qqchen.deploy.backend.entity.SysParam; +import com.qqchen.deploy.backend.framework.service.IBaseService; +import com.qqchen.deploy.backend.model.SysParamDTO; + +public interface ISysParamService extends IBaseService { +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/service/ITenantService.java b/backend/src/main/java/com/qqchen/deploy/backend/service/ITenantService.java index a8713c97..3dfff3c3 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/service/ITenantService.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/service/ITenantService.java @@ -2,7 +2,7 @@ package com.qqchen.deploy.backend.service; import com.qqchen.deploy.backend.entity.Tenant; import com.qqchen.deploy.backend.framework.service.IBaseService; -import com.qqchen.deploy.backend.dto.TenantDTO; +import com.qqchen.deploy.backend.model.TenantDTO; public interface ITenantService extends IBaseService { // 添加租户特有的业务方法 diff --git a/backend/src/main/java/com/qqchen/deploy/backend/service/IUserService.java b/backend/src/main/java/com/qqchen/deploy/backend/service/IUserService.java index c5c37655..5c5909dc 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/service/IUserService.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/service/IUserService.java @@ -1,13 +1,13 @@ package com.qqchen.deploy.backend.service; -import com.qqchen.deploy.backend.dto.UserDTO; -import com.qqchen.deploy.backend.framework.audit.annotation.Audited; +import com.qqchen.deploy.backend.model.UserDTO; +import com.qqchen.deploy.backend.framework.annotation.Audited; import com.qqchen.deploy.backend.framework.service.IBaseService; -import com.qqchen.deploy.backend.dto.request.LoginRequest; -import com.qqchen.deploy.backend.dto.response.LoginResponse; +import com.qqchen.deploy.backend.model.request.LoginRequest; +import com.qqchen.deploy.backend.model.response.LoginResponse; import com.qqchen.deploy.backend.entity.User; -import com.qqchen.deploy.backend.dto.request.UserRequest; -import com.qqchen.deploy.backend.dto.RoleDTO; +import com.qqchen.deploy.backend.model.request.UserRequest; +import com.qqchen.deploy.backend.model.RoleDTO; import org.springframework.transaction.annotation.Transactional; import java.util.List; @@ -23,4 +23,7 @@ public interface IUserService extends IBaseService { @Transactional(readOnly = false) @Audited(action = "CHANGE_PASSWORD", detail = "修改密码") void changePassword(Long userId, String oldPassword, String newPassword); + + @Transactional(readOnly = true) + LoginResponse getCurrentUser(); } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/service/impl/SysParamServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/service/impl/SysParamServiceImpl.java new file mode 100644 index 00000000..371a8def --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/service/impl/SysParamServiceImpl.java @@ -0,0 +1,26 @@ +package com.qqchen.deploy.backend.service.impl; + +import com.qqchen.deploy.backend.converter.SysParamConverter; +import com.qqchen.deploy.backend.entity.SysParam; +import com.qqchen.deploy.backend.framework.annotation.ServiceType; +import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; +import com.qqchen.deploy.backend.model.SysParamDTO; +import com.qqchen.deploy.backend.repository.ISysParamRepository; +import com.qqchen.deploy.backend.service.ISysParamService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import static com.qqchen.deploy.backend.framework.annotation.ServiceType.Type.DATABASE; + +@Slf4j +@Service +@ServiceType(DATABASE) +public class SysParamServiceImpl extends BaseServiceImpl implements ISysParamService { + + @Resource + private SysParamConverter converter; + + @Resource + private ISysParamRepository repository; +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/service/impl/TenantServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/service/impl/TenantServiceImpl.java index a97241d2..d55e5a9a 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/service/impl/TenantServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/service/impl/TenantServiceImpl.java @@ -1,16 +1,11 @@ package com.qqchen.deploy.backend.service.impl; import com.qqchen.deploy.backend.entity.Tenant; -import com.qqchen.deploy.backend.framework.query.BaseQuery; import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; -import com.qqchen.deploy.backend.repository.ITenantRepository; import com.qqchen.deploy.backend.service.ITenantService; -import com.qqchen.deploy.backend.dto.TenantDTO; -import com.qqchen.deploy.backend.converter.TenantConverter; +import com.qqchen.deploy.backend.model.TenantDTO; import org.springframework.stereotype.Service; -import java.util.List; - @Service public class TenantServiceImpl extends BaseServiceImpl implements ITenantService { diff --git a/backend/src/main/java/com/qqchen/deploy/backend/service/impl/UserServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/service/impl/UserServiceImpl.java index 2fb939c8..b7e5bf58 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/service/impl/UserServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/service/impl/UserServiceImpl.java @@ -1,21 +1,22 @@ package com.qqchen.deploy.backend.service.impl; +import com.qqchen.deploy.backend.converter.UserConverter; import com.qqchen.deploy.backend.framework.annotation.ServiceType; -import com.qqchen.deploy.backend.framework.audit.annotation.Audited; +import com.qqchen.deploy.backend.framework.annotation.Audited; import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.framework.exception.BusinessException; +import com.qqchen.deploy.backend.framework.security.SecurityUtils; import com.qqchen.deploy.backend.framework.security.util.JwtTokenUtil; import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; -import com.qqchen.deploy.backend.dto.request.LoginRequest; -import com.qqchen.deploy.backend.dto.request.UserRequest; -import com.qqchen.deploy.backend.dto.response.LoginResponse; +import com.qqchen.deploy.backend.model.request.LoginRequest; +import com.qqchen.deploy.backend.model.request.UserRequest; +import com.qqchen.deploy.backend.model.response.LoginResponse; import com.qqchen.deploy.backend.entity.User; import com.qqchen.deploy.backend.repository.IUserRepository; import com.qqchen.deploy.backend.service.IUserService; import com.qqchen.deploy.backend.converter.RoleConverter; -import com.qqchen.deploy.backend.converter.UserConverter; -import com.qqchen.deploy.backend.dto.UserDTO; -import com.qqchen.deploy.backend.dto.RoleDTO; +import com.qqchen.deploy.backend.model.UserDTO; +import com.qqchen.deploy.backend.model.RoleDTO; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.hibernate.Hibernate; @@ -38,6 +39,9 @@ public class UserServiceImpl extends BaseServiceImpl implem @Resource private RoleConverter roleConverter; + + @Resource + private UserConverter userConverter; @Resource private AuthenticationManager authenticationManager; @@ -88,13 +92,8 @@ public class UserServiceImpl extends BaseServiceImpl implem String token = jwtTokenUtil.generateToken(userDetails); User user = userRepository.findByUsernameAndDeletedFalse(userDetails.getUsername()) .orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND)); - LoginResponse response = new LoginResponse(); - response.setId(user.getId()); - response.setUsername(user.getUsername()); - response.setNickname(user.getNickname()); - response.setEmail(user.getEmail()); - response.setPhone(user.getPhone()); - response.setToken(token); + + LoginResponse response = userConverter.toLoginResponse(user, token); log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname()); return response; } @@ -129,4 +128,17 @@ public class UserServiceImpl extends BaseServiceImpl implem public void changePassword(Long userId, String oldPassword, String newPassword) { // ... 密码修改逻辑 ... } + + @Override + @Transactional(readOnly = true) + @Audited(action = "GET_CURRENT_USER", detail = "获取当前用户信息") + public LoginResponse getCurrentUser() { + String username = SecurityUtils.getCurrentUsername(); + User user = userRepository.findByUsernameAndDeletedFalse(username) + .orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND)); + + LoginResponse response = userConverter.toLoginResponse(user); + log.debug("获取当前用户信息: {}", user.getUsername()); + return response; + } } \ No newline at end of file diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 63e90926..55e3fc87 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -2,9 +2,9 @@ server: port: 8080 spring: datasource: - url: jdbc:mysql://127.0.0.1:3306/deploy-ease-platform?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true - username: root - password: root + url: jdbc:mysql://192.168.1.111:3306/deploy-ease-platform?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true + username: deploy-ease-platform + password: qichen5210523 driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: @@ -46,4 +46,11 @@ jwt: expiration: 86400 jackson: - time-zone: Asia/Shanghai \ No newline at end of file + time-zone: Asia/Shanghai + flyway: + enabled: true + baseline-on-migrate: true + locations: classpath:db/migration + table: flyway_schema_history + baseline-version: 0 + validate-on-migrate: true \ No newline at end of file diff --git a/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql b/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql index b42c9416..e74a7ba6 100644 --- a/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql +++ b/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql @@ -33,4 +33,25 @@ CREATE TABLE IF NOT EXISTS sys_user ( phone VARCHAR(255) NULL, username VARCHAR(255) NOT NULL, CONSTRAINT UK_user_username UNIQUE (username) -); \ No newline at end of file +); + +-- 创建系统参数表 +CREATE TABLE sys_param ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + create_by VARCHAR(255), + create_time DATETIME(6), + deleted BIT NOT NULL DEFAULT 0, + update_by VARCHAR(255), + update_time DATETIME(6), + version INT NOT NULL DEFAULT 0, + + code VARCHAR(100) NOT NULL COMMENT '参数编码', + name VARCHAR(100) NOT NULL COMMENT '参数名称', + value TEXT COMMENT '参数值', + type VARCHAR(50) NOT NULL COMMENT '参数类型', + description VARCHAR(255) COMMENT '参数描述', + enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用', + + CONSTRAINT UK_sys_param_code UNIQUE (code) +) COMMENT '系统参数表'; + \ No newline at end of file diff --git a/backend/src/main/resources/db/migration/V1.0.1__init_data.sql b/backend/src/main/resources/db/migration/V1.0.1__init_data.sql index d8aac844..7b097ac5 100644 --- a/backend/src/main/resources/db/migration/V1.0.1__init_data.sql +++ b/backend/src/main/resources/db/migration/V1.0.1__init_data.sql @@ -3,15 +3,24 @@ INSERT INTO sys_tenant (create_by, create_time, deleted, update_by, update_time, version, address, code, contact_name, contact_phone, email, enabled, name) VALUES -('system', NOW(), 0, 'system', NOW(), 0, -'北京市朝阳区xxx街道', 'default', '张三', '13900000001', 'default@example.com', 1, '默认租户'); +('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0, +'北京市朝阳区望京SOHO T1 C座', 'default', '张三', '13900000001', +'admin@deploy-ease.com', 1, '默认租户'); -- 插入管理员用户 INSERT INTO sys_user (create_by, create_time, deleted, update_by, update_time, version, email, enabled, nickname, password, phone, username) VALUES -('system', NOW(), 0, 'system', NOW(), 0, -'admin@example.com', 1, '系统管理员', -'$2a$10$mW/yJPHjyueQ1g82qWXg8eYqyUVNxFQPagkUvqtWPhKhqB8Z3Vw2y', -'13800138000', 'admin'); \ No newline at end of file +('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0, +'admin@deploy-ease.com', 1, '系统管理员', +'$2a$10$B5qWUPyWyXxfm6Jq4JKcAOp/XcQLjtv3jifafsqPqZvzY9owae2ve', -- 密码: admin123 +'13800138000', 'admin'); + +-- 系统参数初始化 +INSERT INTO sys_param (code, name, value, type, description, enabled, create_by, create_time) +VALUES +('SYSTEM_NAME', '系统名称', 'DevOps平台', 'TEXT', '系统显示名称', 1, 'system', '2024-01-01 00:00:00'), +('SYSTEM_LOGO', '系统Logo', '/logo.png', 'TEXT', '系统Logo路径', 1, 'system', '2024-01-01 00:00:00'), +('GENDER_ENUM', '性别枚举', '[{"code":"1","name":"男"},{"code":"2","name":"女"}]', 'ENUM', '性别枚举值', 1, 'system', '2024-01-01 00:00:00'), +('USER_STATUS_ENUM', '用户状态枚举', '[{"code":"0","name":"禁用"},{"code":"1","name":"启用"}]', 'ENUM', '用户状态枚举值', 1, 'system', '2024-01-01 00:00:00'); \ No newline at end of file