可正常启动

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; package com.qqchen.deploy.backend.api;
//
//import com.qqchen.deploy.backend.framework.api.Response; import com.qqchen.deploy.backend.dto.TenantDTO;
//import com.qqchen.deploy.backend.framework.controller.BaseController; 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.query.TenantQuery; import com.qqchen.deploy.backend.entity.Tenant;
//import com.qqchen.deploy.backend.dto.request.TenantRequest; import com.qqchen.deploy.backend.service.ITenantService;
//import com.qqchen.deploy.backend.dto.response.TenantResponse; import jakarta.servlet.http.HttpServletResponse;
//import com.qqchen.deploy.backend.entity.Tenant; import org.springframework.web.bind.annotation.RequestMapping;
//import com.qqchen.deploy.backend.service.ITenantService; import org.springframework.web.bind.annotation.RestController;
//import org.springframework.web.bind.annotation.GetMapping;
//import org.springframework.web.bind.annotation.PathVariable; import java.util.List;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RestController; @RestController
// @RequestMapping("/api/v1/tenant")
//@RestController public class TenantApiController extends BaseController<Tenant, TenantDTO, Long, TenantQuery> {
//@RequestMapping("/api/v1/tenant")
//public class TenantApiController extends BaseController<Tenant, Long, TenantQuery, TenantRequest, TenantResponse> { protected final ITenantService service;
//
// protected final ITenantService service; public TenantApiController(ITenantService service) {
// super(service);
// public TenantApiController(ITenantService service, TenantConverter converter) { this.service = service;
// super(service, converter); }
// this.service = service;
// } @Override
// protected void exportData(HttpServletResponse response, List<TenantDTO> data) {
}
// @GetMapping("/code/{code}") // @GetMapping("/code/{code}")
// public Response<TenantResponse> findByCode(@PathVariable String code) { // public Response<TenantResponse> findByCode(@PathVariable String code) {
// Tenant tenant = service.findByCode(code); // Tenant tenant = service.findByCode(code);
// return Response.success(converter.toResponse(tenant)); // 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> { public interface IUserRepository extends IBaseRepository<User, Long> {
Optional<User> findByUsernameAndDeletedFalse(String username); 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; package com.qqchen.deploy.backend.service;
import com.qqchen.deploy.backend.dto.UserDTO; 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.framework.service.IBaseService;
import com.qqchen.deploy.backend.dto.request.LoginRequest; import com.qqchen.deploy.backend.dto.request.LoginRequest;
import com.qqchen.deploy.backend.dto.response.LoginResponse; import com.qqchen.deploy.backend.dto.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.dto.request.UserRequest;
import com.qqchen.deploy.backend.dto.RoleDTO; import com.qqchen.deploy.backend.dto.RoleDTO;
import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
@ -17,4 +19,8 @@ public interface IUserService extends IBaseService<User, UserDTO, Long> {
boolean checkEmailExists(String email); boolean checkEmailExists(String email);
List<RoleDTO> getUserRoles(Long userId); List<RoleDTO> getUserRoles(Long userId);
List<RoleDTO> getCurrentUserRoles(); 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); super(repository, converter);
} }
@Override // @Override
public List<TenantDTO> findAll(BaseQuery query) { // public List<TenantDTO> findAll(BaseQuery query) {
return null; // return null;
} // }
} }

View File

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