迁移合理目录,增加系统参数

This commit is contained in:
戚辰先生 2024-11-30 00:13:37 +08:00
parent 6655f120de
commit 39b26ac2f8
46 changed files with 410 additions and 188 deletions

View File

@ -1,8 +1,8 @@
package com.qqchen.deploy.backend.api; 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.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 com.qqchen.deploy.backend.entity.Tenant;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;

View File

@ -1,14 +1,14 @@
package com.qqchen.deploy.backend.api; package com.qqchen.deploy.backend.api;
import com.qqchen.deploy.backend.dto.RoleDTO; import com.qqchen.deploy.backend.model.RoleDTO;
import com.qqchen.deploy.backend.dto.query.UserQuery; import com.qqchen.deploy.backend.model.query.UserQuery;
import com.qqchen.deploy.backend.dto.request.UserRequest; import com.qqchen.deploy.backend.model.request.UserRequest;
import com.qqchen.deploy.backend.framework.controller.BaseController; import com.qqchen.deploy.backend.framework.controller.BaseController;
import com.qqchen.deploy.backend.framework.api.Response; import com.qqchen.deploy.backend.framework.api.Response;
import com.qqchen.deploy.backend.entity.User; import com.qqchen.deploy.backend.entity.User;
import com.qqchen.deploy.backend.dto.UserDTO; import com.qqchen.deploy.backend.model.UserDTO;
import com.qqchen.deploy.backend.dto.request.LoginRequest; import com.qqchen.deploy.backend.model.request.LoginRequest;
import com.qqchen.deploy.backend.dto.response.LoginResponse; import com.qqchen.deploy.backend.model.response.LoginResponse;
import com.qqchen.deploy.backend.service.IUserService; import com.qqchen.deploy.backend.service.IUserService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -21,7 +21,7 @@ import java.io.OutputStream;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/api/v1/users") @RequestMapping("/api/v1/user")
public class UserApiController extends BaseController<User, UserDTO, Long, UserQuery> { public class UserApiController extends BaseController<User, UserDTO, Long, UserQuery> {
@Resource @Resource
@ -34,10 +34,10 @@ public class UserApiController extends BaseController<User, UserDTO, Long, UserQ
return Response.success(userService.login(request)); return Response.success(userService.login(request));
} }
@Operation(summary = "用户注册") @Operation(summary = "获取当前用户信息")
@PostMapping("/register") @GetMapping("/current")
public Response<UserDTO> register(@Validated @RequestBody UserRequest request) { public Response<LoginResponse> getCurrentUser() {
return Response.success(userService.register(request)); return Response.success(userService.getCurrentUser());
} }
@Override @Override
@ -52,15 +52,4 @@ public class UserApiController extends BaseController<User, UserDTO, Long, UserQ
} }
} }
@GetMapping("/roles")
@Operation(summary = "获取当前用户的角色")
public Response<List<RoleDTO>> getCurrentUserRoles() {
return Response.success(userService.getCurrentUserRoles());
}
@GetMapping("/{id}/roles")
@Operation(summary = "获取指定用户的角色")
public Response<List<RoleDTO>> getUserRoles(@PathVariable Long id) {
return Response.success(userService.getUserRoles(id));
}
} }

View File

@ -1,9 +1,9 @@
package com.qqchen.deploy.backend.controller; 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.entity.Tenant;
import com.qqchen.deploy.backend.framework.controller.BaseController; 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 jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;

View File

@ -1,7 +1,7 @@
package com.qqchen.deploy.backend.controller; package com.qqchen.deploy.backend.controller;
import com.qqchen.deploy.backend.api.UserApiController; 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 jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
@RestController @RestController
@RequestMapping("/mgmt/users") @RequestMapping("/mgmt/user")
public class UserController extends UserApiController { public class UserController extends UserApiController {
@Override @Override

View File

@ -1,6 +1,6 @@
package com.qqchen.deploy.backend.converter; 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.entity.Role;
import com.qqchen.deploy.backend.framework.converter.BaseConverter; import com.qqchen.deploy.backend.framework.converter.BaseConverter;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;

View File

@ -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<SysParam, SysParamDTO> {
}

View File

@ -1,6 +1,6 @@
package com.qqchen.deploy.backend.converter; 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.entity.Tenant;
import com.qqchen.deploy.backend.framework.converter.BaseConverter; import com.qqchen.deploy.backend.framework.converter.BaseConverter;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;

View File

@ -1,11 +1,19 @@
package com.qqchen.deploy.backend.converter; 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.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.Mapper;
import org.mapstruct.Mapping;
@Mapper(config = BaseConverter.class) @Mapper(config = BaseConverter.class)
public interface UserConverter extends BaseConverter<User, UserDTO> { public interface UserConverter extends BaseConverter<User, UserDTO> {
// MapStruct 会自动实现所有方法 // MapStruct 会自动实现所有方法
@Mapping(target = "token", ignore = true)
LoginResponse toLoginResponse(User user);
@Mapping(target = "token", source = "token")
LoginResponse toLoginResponse(User user, String token);
} }

View File

@ -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<Long> {
@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;
}

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.framework.audit.annotation; package com.qqchen.deploy.backend.framework.annotation;
import java.lang.annotation.*; import java.lang.annotation.*;

View File

@ -1,7 +1,7 @@
package com.qqchen.deploy.backend.framework.audit.aspect; package com.qqchen.deploy.backend.framework.audit.aspect;
import com.qqchen.deploy.backend.framework.audit.AuditMetadata; 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.audit.event.AuditEvent;
import com.qqchen.deploy.backend.framework.security.SecurityUtils; import com.qqchen.deploy.backend.framework.security.SecurityUtils;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
@ -26,7 +26,7 @@ public class AuditAspect {
private final ApplicationEventPublisher eventPublisher; 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 { public Object auditMethod(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取审计元数据 // 获取审计元数据
AuditMetadata metadata = extractAuditMetadata(joinPoint); AuditMetadata metadata = extractAuditMetadata(joinPoint);

View File

@ -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.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;

View File

@ -1,6 +1,5 @@
package com.qqchen.deploy.backend.framework.config; 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.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfiguration;

View File

@ -55,14 +55,11 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
if (bean instanceof BaseServiceImpl<?, ?, ?> service) { if (bean instanceof BaseServiceImpl<?, ?, ?> service) {
return injectServiceDependencies(service, beanName); return injectServiceDependencies(service, beanName);
} }
} catch (DependencyInjectionException e) {
log.error("Dependency injection failed for bean: {}", beanName, e);
throw e;
} catch (Exception e) { } catch (Exception e) {
log.error("Unexpected error during dependency injection for bean: {}", beanName, e); String errorMsg = String.format("依赖注入失败 - Bean: %s, 类型: %s, 原因: %s",
throw new DependencyInjectionException( beanName, bean.getClass().getName(), e.getMessage());
String.format("Failed to inject dependencies for bean: %s", beanName), log.error(errorMsg, e);
e); throw new DependencyInjectionException(errorMsg, e);
} }
return bean; return bean;
} }
@ -151,12 +148,9 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
log.debug("Successfully injected all dependencies for service: {}", beanName); log.debug("Successfully injected all dependencies for service: {}", beanName);
return service; return service;
} catch (DependencyInjectionException e) {
throw e;
} catch (Exception e) { } catch (Exception e) {
throw new DependencyInjectionException( throw new DependencyInjectionException(
String.format("Failed to inject dependencies for service: %s", service.getClass().getSimpleName()), String.format("Failed to inject dependencies for service: %s", service.getClass().getSimpleName()), e);
e);
} }
} }
@ -189,20 +183,28 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable> private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable>
void injectRepository(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) { void injectRepository(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) {
String repositoryBeanName = "I" + entityClass.getSimpleName() + "Repository"; String repositoryBeanName = "I" + entityClass.getSimpleName() + "Repository";
log.debug("Looking for repository bean: {}", repositoryBeanName); log.debug("正在查找 Repository: {}", repositoryBeanName);
IBaseRepository<T, ID> repository = (IBaseRepository<T, ID>) repositoryCache.computeIfAbsent( try {
entityClass, IBaseRepository<T, ID> repository = (IBaseRepository<T, ID>) repositoryCache.computeIfAbsent(
key -> { entityClass,
if (!applicationContext.containsBean(repositoryBeanName)) { key -> {
throw new BusinessException( if (!applicationContext.containsBean(repositoryBeanName)) {
ResponseCode.DEPENDENCY_INJECTION_REPOSITORY_NOT_FOUND, String errorMsg = String.format("找不到 Repository - 服务类: %s, 实体类: %s, Repository名称: %s",
new Object[] {key.getSimpleName(), repositoryBeanName}); service.getClass().getName(), key.getSimpleName(), repositoryBeanName);
} log.error(errorMsg);
return (IBaseRepository<?, ?>) applicationContext.getBean(repositoryBeanName); 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") @SuppressWarnings("unchecked")
@ -210,44 +212,68 @@ public class DependencyInjectionPostProcessor implements BeanPostProcessor, Disp
void injectConverter(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) { void injectConverter(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) {
String converterBeanName = entityClass.getSimpleName().substring(0, 1).toLowerCase() String converterBeanName = entityClass.getSimpleName().substring(0, 1).toLowerCase()
+ entityClass.getSimpleName().substring(1) + "ConverterImpl"; + entityClass.getSimpleName().substring(1) + "ConverterImpl";
log.debug("Looking for converter bean: {}", converterBeanName); log.debug("正在查找 Converter: {}", converterBeanName);
BaseConverter<T, D> converter = (BaseConverter<T, D>) converterCache.computeIfAbsent( try {
entityClass, BaseConverter<T, D> converter = (BaseConverter<T, D>) converterCache.computeIfAbsent(
key -> { entityClass,
if (!applicationContext.containsBean(converterBeanName)) { key -> {
throw new BusinessException( if (!applicationContext.containsBean(converterBeanName)) {
ResponseCode.DEPENDENCY_INJECTION_CONVERTER_NOT_FOUND, String errorMsg = String.format("找不到 Converter - 服务类: %s, 实体类: %s, Converter名称: %s",
new Object[] {key.getSimpleName(), converterBeanName}); service.getClass().getName(), key.getSimpleName(), converterBeanName);
} log.error(errorMsg);
return (BaseConverter<?, ?>) applicationContext.getBean(converterBeanName); 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") @SuppressWarnings("unchecked")
private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable> void injectEntityPath(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) { private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable>
void injectEntityPath(BaseServiceImpl<T, D, ID> service, Class<T> entityClass) {
try { try {
EntityPath<T> entityPath = (EntityPath<T>) entityPathCache.computeIfAbsent( EntityPath<T> entityPath = (EntityPath<T>) entityPathCache.computeIfAbsent(
entityClass, entityClass,
key -> { key -> {
String qClassName = key.getPackageName() + ".Q" + key.getSimpleName();
try { try {
String qClassName = key.getPackageName() + ".Q" + key.getSimpleName();
Class<?> qClass = Class.forName(qClassName); 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); 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) { } catch (Exception e) {
throw new BusinessException( String errorMsg = String.format("获取 QueryDSL 实体失败 - 服务类: %s, 实体类: %s, Q类名: %s, 原因: %s",
ResponseCode.DEPENDENCY_INJECTION_ENTITYPATH_FAILED, service.getClass().getName(), key.getSimpleName(), qClassName, e.getMessage());
new Object[] {key.getSimpleName(), e.getMessage()}); log.error(errorMsg, e);
throw new DependencyInjectionException(errorMsg, e);
} }
}); });
ReflectionUtils.setField("entityPath", service, entityPath); ReflectionUtils.setField("entityPath", service, entityPath);
} catch (BusinessException e) {
throw e;
} catch (Exception 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);
} }
} }
} }

View File

@ -1,14 +1,12 @@
package com.qqchen.deploy.backend.framework.filter; 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.Filter;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse; import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.io.IOException; import java.io.IOException;

View File

@ -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.api.Response;
import com.qqchen.deploy.backend.framework.enums.ResponseCode; 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.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.MalformedJwtException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;

View File

@ -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.MessageSource;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;

View File

@ -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.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

View File

@ -22,48 +22,45 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
@RequiredArgsConstructor @RequiredArgsConstructor
public class SecurityConfig { public class SecurityConfig {
private final CustomAuthenticationEntryPoint authenticationEntryPoint; private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
private final JwtTokenUtil jwtTokenUtil;
private final UserDetailsService userDetailsService; 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 @Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() { public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter(jwtTokenUtil, userDetailsService); 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 @Bean
public PasswordEncoder passwordEncoder() { public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); return new BCryptPasswordEncoder();

View File

@ -2,7 +2,7 @@ package com.qqchen.deploy.backend.framework.security.filter;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.framework.api.Response; 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.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException; import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.exception.JwtAuthenticationException; import com.qqchen.deploy.backend.framework.exception.JwtAuthenticationException;
@ -39,8 +39,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final UserDetailsService userDetailsService; private final UserDetailsService userDetailsService;
private static final List<String> WHITELIST = Arrays.asList( private static final List<String> WHITELIST = Arrays.asList(
"/api/v1/users/login", "/api/v1/user/login",
"/api/v1/users/register", "/api/v1/user/register",
"/api/v1/tenant/list", "/api/v1/tenant/list",
"/swagger-ui/**", "/swagger-ui/**",
"/v3/api-docs/**", "/v3/api-docs/**",
@ -59,10 +59,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
String jwt = getJwtFromRequest(request); String jwt = getJwtFromRequest(request);
if (StringUtils.hasText(jwt)) { if (StringUtils.hasText(jwt)) {
String username = jwtTokenUtil.getUsernameFromToken(jwt); String username = jwtTokenUtil.getUsernameFromToken(jwt);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username); UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwt, userDetails)) { if (jwtTokenUtil.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities()); userDetails, null, userDetails.getAuthorities());

View File

@ -39,7 +39,18 @@ public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint
response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name()); 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); objectMapper.writeValue(response.getOutputStream(), errorResponse);
} }

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.framework.context; package com.qqchen.deploy.backend.framework.tenant;
public class TenantContext { public class TenantContext {
private static final ThreadLocal<String> CURRENT_TENANT = new ThreadLocal<>(); private static final ThreadLocal<String> CURRENT_TENANT = new ThreadLocal<>();

View File

@ -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.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException; import com.qqchen.deploy.backend.framework.exception.BusinessException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher; import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor;

View File

@ -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 com.qqchen.deploy.backend.framework.dto.BaseDTO;
import lombok.Data; import lombok.Data;

View File

@ -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;
}

View File

@ -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 com.qqchen.deploy.backend.framework.dto.BaseDTO;
import lombok.Data; import lombok.Data;

View File

@ -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 com.qqchen.deploy.backend.framework.dto.BaseDTO;
import lombok.Data; import lombok.Data;

View File

@ -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;
}

View File

@ -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.annotation.QueryField;
import com.qqchen.deploy.backend.framework.enums.QueryType; import com.qqchen.deploy.backend.framework.enums.QueryType;

View File

@ -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.annotation.QueryField;
import com.qqchen.deploy.backend.framework.query.BaseQuery; import com.qqchen.deploy.backend.framework.query.BaseQuery;

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.dto.request; package com.qqchen.deploy.backend.model.request;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.Data; import lombok.Data;
@ -11,4 +11,7 @@ public class LoginRequest {
@NotBlank(message = "密码不能为空") @NotBlank(message = "密码不能为空")
private String password; private String password;
@NotBlank(message = "租户不能为空")
private String tenantId;
} }

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.dto.request; package com.qqchen.deploy.backend.model.request;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import lombok.Data; import lombok.Data;

View File

@ -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.Email;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
@Data @Data
public class UserRequest { public class UserRequest {

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.dto.response; package com.qqchen.deploy.backend.model.response;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;

View File

@ -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 com.qqchen.deploy.backend.framework.dto.BaseResponse;
import lombok.Data; import lombok.Data;

View File

@ -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 com.qqchen.deploy.backend.framework.dto.BaseResponse;
import lombok.Data; import lombok.Data;
@ -9,8 +9,6 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class UserResponse extends BaseResponse { public class UserResponse extends BaseResponse {
private Long id;
private String username; private String username;
private String email; private String email;
@ -21,5 +19,4 @@ public class UserResponse extends BaseResponse {
private Boolean enabled; private Boolean enabled;
private String password;
} }

View File

@ -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<SysParam, Long> {
/**
* 根据参数编码查询参数
* @param code 参数编码
* @return 参数对象
*/
Optional<SysParam> findByCodeAndDeletedFalse(String code);
/**
* 根据参数编码和启用状态查询参数
* @param code 参数编码
* @param enabled 启用状态
* @return 参数对象
*/
Optional<SysParam> findByCodeAndEnabledAndDeletedFalse(String code, Boolean enabled);
/**
* 根据参数类型查询参数列表
* @param type 参数类型
* @return 参数列表
*/
List<SysParam> findByTypeAndDeletedFalse(String type);
/**
* 检查参数编码是否存在
* @param code 参数编码
* @return 是否存在
*/
boolean existsByCodeAndDeletedFalse(String code);
}

View File

@ -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<SysParam, SysParamDTO, Long> {
}

View File

@ -2,7 +2,7 @@ package com.qqchen.deploy.backend.service;
import com.qqchen.deploy.backend.entity.Tenant; import com.qqchen.deploy.backend.entity.Tenant;
import com.qqchen.deploy.backend.framework.service.IBaseService; 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<Tenant, TenantDTO, Long> { public interface ITenantService extends IBaseService<Tenant, TenantDTO, Long> {
// 添加租户特有的业务方法 // 添加租户特有的业务方法

View File

@ -1,13 +1,13 @@
package com.qqchen.deploy.backend.service; package com.qqchen.deploy.backend.service;
import com.qqchen.deploy.backend.dto.UserDTO; import com.qqchen.deploy.backend.model.UserDTO;
import com.qqchen.deploy.backend.framework.audit.annotation.Audited; import com.qqchen.deploy.backend.framework.annotation.Audited;
import com.qqchen.deploy.backend.framework.service.IBaseService; import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.dto.request.LoginRequest; import com.qqchen.deploy.backend.model.request.LoginRequest;
import com.qqchen.deploy.backend.dto.response.LoginResponse; import com.qqchen.deploy.backend.model.response.LoginResponse;
import com.qqchen.deploy.backend.entity.User; import com.qqchen.deploy.backend.entity.User;
import com.qqchen.deploy.backend.dto.request.UserRequest; import com.qqchen.deploy.backend.model.request.UserRequest;
import com.qqchen.deploy.backend.dto.RoleDTO; import com.qqchen.deploy.backend.model.RoleDTO;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
@ -23,4 +23,7 @@ public interface IUserService extends IBaseService<User, UserDTO, Long> {
@Transactional(readOnly = false) @Transactional(readOnly = false)
@Audited(action = "CHANGE_PASSWORD", detail = "修改密码") @Audited(action = "CHANGE_PASSWORD", detail = "修改密码")
void changePassword(Long userId, String oldPassword, String newPassword); void changePassword(Long userId, String oldPassword, String newPassword);
@Transactional(readOnly = true)
LoginResponse getCurrentUser();
} }

View File

@ -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<SysParam, SysParamDTO, Long> implements ISysParamService {
@Resource
private SysParamConverter converter;
@Resource
private ISysParamRepository repository;
}

View File

@ -1,16 +1,11 @@
package com.qqchen.deploy.backend.service.impl; package com.qqchen.deploy.backend.service.impl;
import com.qqchen.deploy.backend.entity.Tenant; 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.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.repository.ITenantRepository;
import com.qqchen.deploy.backend.service.ITenantService; import com.qqchen.deploy.backend.service.ITenantService;
import com.qqchen.deploy.backend.dto.TenantDTO; import com.qqchen.deploy.backend.model.TenantDTO;
import com.qqchen.deploy.backend.converter.TenantConverter;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List;
@Service @Service
public class TenantServiceImpl extends BaseServiceImpl<Tenant, TenantDTO, Long> implements ITenantService { public class TenantServiceImpl extends BaseServiceImpl<Tenant, TenantDTO, Long> implements ITenantService {

View File

@ -1,21 +1,22 @@
package com.qqchen.deploy.backend.service.impl; 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.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.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException; 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.security.util.JwtTokenUtil;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.dto.request.LoginRequest; import com.qqchen.deploy.backend.model.request.LoginRequest;
import com.qqchen.deploy.backend.dto.request.UserRequest; import com.qqchen.deploy.backend.model.request.UserRequest;
import com.qqchen.deploy.backend.dto.response.LoginResponse; import com.qqchen.deploy.backend.model.response.LoginResponse;
import com.qqchen.deploy.backend.entity.User; import com.qqchen.deploy.backend.entity.User;
import com.qqchen.deploy.backend.repository.IUserRepository; import com.qqchen.deploy.backend.repository.IUserRepository;
import com.qqchen.deploy.backend.service.IUserService; import com.qqchen.deploy.backend.service.IUserService;
import com.qqchen.deploy.backend.converter.RoleConverter; import com.qqchen.deploy.backend.converter.RoleConverter;
import com.qqchen.deploy.backend.converter.UserConverter; import com.qqchen.deploy.backend.model.UserDTO;
import com.qqchen.deploy.backend.dto.UserDTO; import com.qqchen.deploy.backend.model.RoleDTO;
import com.qqchen.deploy.backend.dto.RoleDTO;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
@ -39,6 +40,9 @@ public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implem
@Resource @Resource
private RoleConverter roleConverter; private RoleConverter roleConverter;
@Resource
private UserConverter userConverter;
@Resource @Resource
private AuthenticationManager authenticationManager; private AuthenticationManager authenticationManager;
@ -88,13 +92,8 @@ public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implem
String token = jwtTokenUtil.generateToken(userDetails); String token = jwtTokenUtil.generateToken(userDetails);
User user = userRepository.findByUsernameAndDeletedFalse(userDetails.getUsername()) User user = userRepository.findByUsernameAndDeletedFalse(userDetails.getUsername())
.orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND)); .orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
LoginResponse response = new LoginResponse();
response.setId(user.getId()); LoginResponse response = userConverter.toLoginResponse(user, token);
response.setUsername(user.getUsername());
response.setNickname(user.getNickname());
response.setEmail(user.getEmail());
response.setPhone(user.getPhone());
response.setToken(token);
log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname()); log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname());
return response; return response;
} }
@ -129,4 +128,17 @@ public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implem
public void changePassword(Long userId, String oldPassword, String newPassword) { 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;
}
} }

View File

@ -2,9 +2,9 @@ server:
port: 8080 port: 8080
spring: spring:
datasource: datasource:
url: jdbc:mysql://127.0.0.1:3306/deploy-ease-platform?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true url: jdbc:mysql://192.168.1.111:3306/deploy-ease-platform?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
username: root username: deploy-ease-platform
password: root password: qichen5210523
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
jpa: jpa:
hibernate: hibernate:
@ -47,3 +47,10 @@ jwt:
jackson: jackson:
time-zone: Asia/Shanghai 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

View File

@ -34,3 +34,24 @@ CREATE TABLE IF NOT EXISTS sys_user (
username VARCHAR(255) NOT NULL, username VARCHAR(255) NOT NULL,
CONSTRAINT UK_user_username UNIQUE (username) CONSTRAINT UK_user_username UNIQUE (username)
); );
-- 创建系统参数表
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 '系统参数表';

View File

@ -3,15 +3,24 @@ INSERT INTO sys_tenant
(create_by, create_time, deleted, update_by, update_time, version, (create_by, create_time, deleted, update_by, update_time, version,
address, code, contact_name, contact_phone, email, enabled, name) address, code, contact_name, contact_phone, email, enabled, name)
VALUES VALUES
('system', NOW(), 0, 'system', NOW(), 0, ('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
'北京市朝阳区xxx街道', 'default', '张三', '13900000001', 'default@example.com', 1, '默认租户'); '北京市朝阳区望京SOHO T1 C座', 'default', '张三', '13900000001',
'admin@deploy-ease.com', 1, '默认租户');
-- 插入管理员用户 -- 插入管理员用户
INSERT INTO sys_user INSERT INTO sys_user
(create_by, create_time, deleted, update_by, update_time, version, (create_by, create_time, deleted, update_by, update_time, version,
email, enabled, nickname, password, phone, username) email, enabled, nickname, password, phone, username)
VALUES VALUES
('system', NOW(), 0, 'system', NOW(), 0, ('system', '2024-01-01 00:00:00', 0, 'system', '2024-01-01 00:00:00', 0,
'admin@example.com', 1, '系统管理员', 'admin@deploy-ease.com', 1, '系统管理员',
'$2a$10$mW/yJPHjyueQ1g82qWXg8eYqyUVNxFQPagkUvqtWPhKhqB8Z3Vw2y', '$2a$10$B5qWUPyWyXxfm6Jq4JKcAOp/XcQLjtv3jifafsqPqZvzY9owae2ve', -- 密码: admin123
'13800138000', 'admin'); '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');