可正常启动

This commit is contained in:
dengqichen 2024-11-29 13:21:19 +08:00
parent 00de9c57cb
commit c913ab3cc5
11 changed files with 260 additions and 61 deletions

View File

@ -1,33 +1,36 @@
//package com.qqchen.deploy.backend.api;
//
//import com.qqchen.deploy.backend.framework.api.Response;
//import com.qqchen.deploy.backend.framework.controller.BaseController;
//import com.qqchen.deploy.backend.converter.TenantConverter;
//import com.qqchen.deploy.backend.dto.query.TenantQuery;
//import com.qqchen.deploy.backend.dto.request.TenantRequest;
//import com.qqchen.deploy.backend.dto.response.TenantResponse;
//import com.qqchen.deploy.backend.entity.Tenant;
//import com.qqchen.deploy.backend.service.ITenantService;
//import org.springframework.web.bind.annotation.GetMapping;
//import org.springframework.web.bind.annotation.PathVariable;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RestController;
//
//@RestController
//@RequestMapping("/api/v1/tenant")
//public class TenantApiController extends BaseController<Tenant, Long, TenantQuery, TenantRequest, TenantResponse> {
//
// protected final ITenantService service;
//
// public TenantApiController(ITenantService service, TenantConverter converter) {
// super(service, converter);
// this.service = service;
// }
//
package com.qqchen.deploy.backend.api;
import com.qqchen.deploy.backend.dto.TenantDTO;
import com.qqchen.deploy.backend.framework.controller.BaseController;
import com.qqchen.deploy.backend.dto.query.TenantQuery;
import com.qqchen.deploy.backend.entity.Tenant;
import com.qqchen.deploy.backend.service.ITenantService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api/v1/tenant")
public class TenantApiController extends BaseController<Tenant, TenantDTO, Long, TenantQuery> {
protected final ITenantService service;
public TenantApiController(ITenantService service) {
super(service);
this.service = service;
}
@Override
protected void exportData(HttpServletResponse response, List<TenantDTO> data) {
}
// @GetMapping("/code/{code}")
// public Response<TenantResponse> findByCode(@PathVariable String code) {
// Tenant tenant = service.findByCode(code);
// return Response.success(converter.toResponse(tenant));
// }
//
//}
}

View File

@ -0,0 +1,27 @@
package com.qqchen.deploy.backend.dto.response;
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class TenantResponse extends BaseResponse {
private Long id;
private String name;
private String code;
private String contactName;
private String contactPhone;
private String email;
private String address;
private Boolean enabled = true;
}

View File

@ -0,0 +1,16 @@
package com.qqchen.deploy.backend.framework.audit;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class AuditMetadata {
private String operator; // 操作人
private String action; // 操作类型CREATE/UPDATE/DELETE
private String entityType; // 实体类型
private String entityId; // 实体ID
private String detail; // 操作详情
private LocalDateTime timestamp; // 操作时间
private String ip; // 操作IP
private String tenantId; // 租户ID
}

View File

@ -0,0 +1,11 @@
package com.qqchen.deploy.backend.framework.audit.annotation;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Audited {
String action() default "";
String detail() default "";
}

View File

@ -0,0 +1,90 @@
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.audit.event.AuditEvent;
import com.qqchen.deploy.backend.framework.security.SecurityUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.time.LocalDateTime;
@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class AuditAspect {
private final ApplicationEventPublisher eventPublisher;
@Around("@annotation(com.qqchen.deploy.backend.framework.audit.annotation.Audited)")
public Object auditMethod(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取审计元数据
AuditMetadata metadata = extractAuditMetadata(joinPoint);
try {
// 执行原方法
Object result = joinPoint.proceed();
// 发布审计事件
eventPublisher.publishEvent(new AuditEvent(this, metadata));
return result;
} catch (Exception e) {
// 记录异常信息
metadata.setDetail(metadata.getDetail() + " [Error: " + e.getMessage() + "]");
eventPublisher.publishEvent(new AuditEvent(this, metadata));
throw e;
}
}
private AuditMetadata extractAuditMetadata(ProceedingJoinPoint joinPoint) {
AuditMetadata metadata = new AuditMetadata();
// 设置基本信息
metadata.setOperator(SecurityUtils.getCurrentUsername());
metadata.setTimestamp(LocalDateTime.now());
// metadata.setTenantId(SecurityUtils.getCurrentTenantId());
// 设置IP地址
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
metadata.setIp(getClientIp(request));
// 获取方法上的注解信息
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Audited audited = signature.getMethod().getAnnotation(Audited.class);
metadata.setAction(audited.action());
metadata.setDetail(audited.detail());
// 设置实体信息
String className = joinPoint.getTarget().getClass().getSimpleName();
metadata.setEntityType(className.replace("ServiceImpl", ""));
return metadata;
}
private String getClientIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}

View File

@ -0,0 +1,15 @@
package com.qqchen.deploy.backend.framework.audit.event;
import com.qqchen.deploy.backend.framework.audit.AuditMetadata;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
@Getter
public class AuditEvent extends ApplicationEvent {
private final AuditMetadata metadata;
public AuditEvent(Object source, AuditMetadata metadata) {
super(source);
this.metadata = metadata;
}
}

View File

@ -0,0 +1,26 @@
package com.qqchen.deploy.backend.framework.audit.listener;
import com.qqchen.deploy.backend.framework.audit.event.AuditEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class AuditEventListener {
@Async
@EventListener
public void handleAuditEvent(AuditEvent event) {
// 这里可以将审计信息保存到数据库或发送到日志系统
log.info("Audit: {} performed {} on {} (ID: {}) at {}, detail: {}",
event.getMetadata().getOperator(),
event.getMetadata().getAction(),
event.getMetadata().getEntityType(),
event.getMetadata().getEntityId(),
event.getMetadata().getTimestamp(),
event.getMetadata().getDetail()
);
}
}

View File

@ -10,8 +10,4 @@ import java.util.Optional;
public interface IUserRepository extends IBaseRepository<User, Long> {
Optional<User> findByUsernameAndDeletedFalse(String username);
boolean existsByUsername(String username);
boolean existsByEmail(String email);
}

View File

@ -1,12 +1,14 @@
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.framework.service.IBaseService;
import com.qqchen.deploy.backend.dto.request.LoginRequest;
import com.qqchen.deploy.backend.dto.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 org.springframework.transaction.annotation.Transactional;
import java.util.List;
@ -17,4 +19,8 @@ public interface IUserService extends IBaseService<User, UserDTO, Long> {
boolean checkEmailExists(String email);
List<RoleDTO> getUserRoles(Long userId);
List<RoleDTO> getCurrentUserRoles();
@Transactional(readOnly = false)
@Audited(action = "CHANGE_PASSWORD", detail = "修改密码")
void changePassword(Long userId, String oldPassword, String newPassword);
}

View File

@ -18,8 +18,8 @@ public class TenantServiceImpl extends BaseServiceImpl<Tenant, TenantDTO, Long>
super(repository, converter);
}
@Override
public List<TenantDTO> findAll(BaseQuery query) {
return null;
}
// @Override
// public List<TenantDTO> findAll(BaseQuery query) {
// return null;
// }
}

View File

@ -1,9 +1,8 @@
package com.qqchen.deploy.backend.service.impl;
import com.qqchen.deploy.backend.framework.audit.annotation.Audited;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.query.BaseQuery;
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;
@ -39,6 +38,9 @@ public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implem
@Resource
private AuthenticationManager authenticationManager;
@Resource
private IUserRepository userRepository;
@Resource
private JwtTokenUtil jwtTokenUtil;
@ -50,6 +52,7 @@ public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implem
@Override
@Transactional(readOnly = false)
@Audited(action = "REGISTER", detail = "用户注册")
public UserDTO register(UserRequest request) {
if (checkUsernameExists(request.getUsername())) {
throw new BusinessException(ResponseCode.USERNAME_EXISTS);
@ -63,7 +66,6 @@ public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implem
userDTO.setEmail(request.getEmail());
userDTO.setNickname(request.getNickname());
userDTO.setPhone(request.getPhone());
return create(userDTO);
}
@ -79,28 +81,28 @@ public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implem
@Override
@Transactional(readOnly = true)
@Audited(action = "USER_LOGIN", detail = "登录")
public LoginResponse login(LoginRequest request) {
// Authentication authentication = authenticationManager.authenticate(
// new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
// );
//
// UserDetails userDetails = (UserDetails) authentication.getPrincipal();
// String token = jwtTokenUtil.generateToken(userDetails);
//
// User user = repository.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);
//
// log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname());
// return response;
return null;
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
);
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
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);
log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname());
return response;
}
@Override
@ -126,4 +128,11 @@ public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implem
// public List<UserDTO> findAll(BaseQuery query) {
// return null;
// }
@Override
@Transactional(readOnly = false)
@Audited(action = "CHANGE_PASSWORD", detail = "修改密码")
public void changePassword(Long userId, String oldPassword, String newPassword) {
// ... 密码修改逻辑 ...
}
}