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 949ec0db..bdaafaff 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 @@ -40,6 +40,13 @@ public class UserApiController extends BaseController resetPassword(@PathVariable Long id, @RequestBody String newPassword) { + userService.resetPassword(id, newPassword); + return Response.success(); + } + @Override protected void exportData(HttpServletResponse response, List data) { response.setContentType("application/vnd.ms-excel"); 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 ec31f97b..3ab42a5a 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 @@ -6,6 +6,8 @@ import com.qqchen.deploy.backend.model.UserDTO; import com.qqchen.deploy.backend.model.response.LoginResponse; import org.mapstruct.Mapper; import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.Mappings; @Mapper(config = BaseConverter.class) public interface UserConverter extends BaseConverter { @@ -22,4 +24,18 @@ public interface UserConverter extends BaseConverter { @Mapping(target = "token", ignore = true) @Mapping(target = "id", ignore = true) LoginResponse toLoginResponse(UserDTO userDTO); + + @Override + @Mappings({ + @Mapping(target = "id", ignore = true), + @Mapping(target = "password", ignore = true), + @Mapping(target = "createTime", ignore = true), + @Mapping(target = "createBy", ignore = true), + @Mapping(target = "updateTime", ignore = true), + @Mapping(target = "updateBy", ignore = true), + @Mapping(target = "version", ignore = true), + @Mapping(target = "deleted", ignore = true) + }) + void updateEntity(@MappingTarget User entity, UserDTO dto); + } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/converter/BaseConverter.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/converter/BaseConverter.java index 4eccba00..95c4be0e 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/converter/BaseConverter.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/converter/BaseConverter.java @@ -15,7 +15,7 @@ import java.util.stream.Collectors; unmappedTargetPolicy = org.mapstruct.ReportingPolicy.IGNORE ) public interface BaseConverter, D extends BaseDTO> { - + @Mappings({ @Mapping(target = "id", source = "id"), @Mapping(target = "createTime", source = "createTime"), @@ -26,7 +26,7 @@ public interface BaseConverter, D extends BaseDTO> { @Mapping(target = "deleted", source = "deleted") }) D toDto(T entity); - + @Mappings({ @Mapping(target = "id", source = "id"), @Mapping(target = "createTime", source = "createTime"), @@ -37,22 +37,24 @@ public interface BaseConverter, D extends BaseDTO> { @Mapping(target = "deleted", source = "deleted") }) T toEntity(D dto); - + @Mappings({ @Mapping(target = "id", ignore = true), @Mapping(target = "createTime", ignore = true), @Mapping(target = "createBy", ignore = true), + @Mapping(target = "updateTime", ignore = true), + @Mapping(target = "updateBy", ignore = true), @Mapping(target = "version", ignore = true), @Mapping(target = "deleted", ignore = true) }) void updateEntity(@MappingTarget T entity, D dto); - + List toDtoList(List entityList); - + default Page toDtoPage(Page page) { return page.map(this::toDto); } - + default List toEntityList(List dtos) { if (dtos == null) return null; return dtos.stream() diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/dto/BaseDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/dto/BaseDTO.java index dee7d80c..e00f7766 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/dto/BaseDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/dto/BaseDTO.java @@ -21,7 +21,7 @@ public class BaseDTO implements Serializable { private Integer version; - private Boolean deleted; + private Boolean deleted = false; // 扩展字段,用于存储额外的属性 private Map extraData; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/utils/PasswordGenerator.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/utils/PasswordGenerator.java index b0ba18bd..44475cfe 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/framework/utils/PasswordGenerator.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/utils/PasswordGenerator.java @@ -3,15 +3,30 @@ package com.qqchen.deploy.backend.framework.utils; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; public class PasswordGenerator { + private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + + /** + * 加密密码 + */ + public static String encode(String rawPassword) { + return encoder.encode(rawPassword); + } + + /** + * 验证密码 + */ + public static boolean matches(String rawPassword, String encodedPassword) { + return encoder.matches(rawPassword, encodedPassword); + } + + /** + * 生成示例密码(仅用于测试) + */ public static void main(String[] args) { - BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); String rawPassword = "admin123"; - String encodedPassword = encoder.encode(rawPassword); + String encodedPassword = encode(rawPassword); System.out.println("Raw password: " + rawPassword); System.out.println("Encoded password: " + encodedPassword); - - // 验证密码 - boolean matches = encoder.matches(rawPassword, encodedPassword); - System.out.println("Password matches: " + matches); + System.out.println("Password matches: " + matches(rawPassword, encodedPassword)); } } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/model/UserDTO.java b/backend/src/main/java/com/qqchen/deploy/backend/model/UserDTO.java index 9517d02c..07adbc3f 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/model/UserDTO.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/model/UserDTO.java @@ -10,8 +10,6 @@ import java.util.Set; @EqualsAndHashCode(callSuper = true) public class UserDTO extends BaseDTO { - private Long id; - private String username; private String nickname; 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 3885c619..80162f34 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 @@ -38,4 +38,8 @@ public interface IUserService extends IBaseService { */ @Transactional(readOnly = true) LoginResponse getCurrentUserResponse(); + + @Transactional(readOnly = false) + @Audited(action = "RESET_PASSWORD", detail = "重置密码") + void resetPassword(Long userId, String newPassword); } \ No newline at end of file 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 ad3eff71..5104af85 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 @@ -8,6 +8,7 @@ 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.framework.utils.PasswordGenerator; import com.qqchen.deploy.backend.model.request.LoginRequest; import com.qqchen.deploy.backend.model.request.UserRequest; import com.qqchen.deploy.backend.model.response.LoginResponse; @@ -148,4 +149,15 @@ public class UserServiceImpl extends BaseServiceImpl implem UserDTO userDTO = getCurrentUser(); return userConverter.toLoginResponse(userDTO); } + + @Override + @Transactional(readOnly = false) + @Audited(action = "RESET_PASSWORD", detail = "重置密码") + public void resetPassword(Long userId, String newPassword) { + User user = findEntityById(userId); + String encodedPassword = PasswordGenerator.encode(newPassword); + user.setPassword(encodedPassword); + repository.save(user); + log.info("用户 {} 密码已重置", user.getUsername()); + } } \ No newline at end of file