diff --git a/src/main/java/com/onixbyte/deltaforceguide/config/SecurityConfig.java b/src/main/java/com/onixbyte/deltaforceguide/config/SecurityConfig.java index 6158bd8..dd52daa 100644 --- a/src/main/java/com/onixbyte/deltaforceguide/config/SecurityConfig.java +++ b/src/main/java/com/onixbyte/deltaforceguide/config/SecurityConfig.java @@ -3,6 +3,8 @@ package com.onixbyte.deltaforceguide.config; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; +import com.onixbyte.deltaforceguide.exeption.ForbiddenException; +import com.onixbyte.deltaforceguide.exeption.UnauthorisedException; import com.onixbyte.deltaforceguide.filter.TokenAuthenticationFilter; import com.onixbyte.deltaforceguide.properties.CookieProperties; import com.onixbyte.deltaforceguide.properties.TokenProperties; @@ -12,7 +14,6 @@ import org.slf4j.LoggerFactory; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpStatus; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; @@ -22,7 +23,6 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHt import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; -import com.onixbyte.deltaforceguide.exeption.BizException; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.ExceptionTranslationFilter; import org.springframework.web.cors.CorsConfigurationSource; @@ -43,7 +43,7 @@ public class SecurityConfig { /** * Configures the HTTP security filter chain including endpoint authorisation and JWT filter. * - * @param http the HTTP security builder + * @param httpSecurity the HTTP security builder * @return the configured security filter chain */ @Bean @@ -64,11 +64,11 @@ public class SecurityConfig { .exceptionHandling(customiser -> customiser .authenticationEntryPoint((request, response, authException) -> { log.error("Unauthenticated request: {}", request, authException); - throw new BizException(HttpStatus.UNAUTHORIZED, "请先登录"); + throw new UnauthorisedException("请先登录"); }) .accessDeniedHandler((request, response, accessDeniedException) -> { log.error("Denied request: {}", request, accessDeniedException); - throw new BizException(HttpStatus.FORBIDDEN, "权限不足"); + throw new ForbiddenException("权限不足"); }) ) .addFilterAfter(tokenAuthenticationFilter, ExceptionTranslationFilter.class) @@ -77,6 +77,7 @@ public class SecurityConfig { /** * Provides the BCrypt password encoder for credential hashing. + * * @return the BCrypt password encoder */ @Bean diff --git a/src/main/java/com/onixbyte/deltaforceguide/controller/GlobalExceptionHandler.java b/src/main/java/com/onixbyte/deltaforceguide/controller/GlobalExceptionHandler.java index fc20ba4..f00fdb2 100644 --- a/src/main/java/com/onixbyte/deltaforceguide/controller/GlobalExceptionHandler.java +++ b/src/main/java/com/onixbyte/deltaforceguide/controller/GlobalExceptionHandler.java @@ -1,7 +1,6 @@ package com.onixbyte.deltaforceguide.controller; import com.onixbyte.deltaforceguide.domain.dto.ErrorResponse; -import com.onixbyte.deltaforceguide.exeption.BizException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; @@ -9,6 +8,7 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.server.ResponseStatusException; /** * Global exception handler that translates exceptions into standard error responses. @@ -17,12 +17,11 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; */ @RestControllerAdvice public class GlobalExceptionHandler { - - @ExceptionHandler(BizException.class) - public ResponseEntity handleBizException(BizException exception) { - var status = exception.getStatus(); + @ExceptionHandler(ResponseStatusException.class) + public ResponseEntity handleResponseStatusException(ResponseStatusException exception) { + var status = exception.getStatusCode(); return ResponseEntity.status(status) - .body(new ErrorResponse(exception.getMessage())); + .body(new ErrorResponse(exception.getReason())); } @ExceptionHandler(AuthenticationException.class) diff --git a/src/main/java/com/onixbyte/deltaforceguide/exeption/BadRequestException.java b/src/main/java/com/onixbyte/deltaforceguide/exeption/BadRequestException.java new file mode 100644 index 0000000..60d37de --- /dev/null +++ b/src/main/java/com/onixbyte/deltaforceguide/exeption/BadRequestException.java @@ -0,0 +1,11 @@ +package com.onixbyte.deltaforceguide.exeption; + +import org.springframework.http.HttpStatus; +import org.springframework.web.server.ResponseStatusException; + +public class BadRequestException extends ResponseStatusException { + + public BadRequestException(String reason) { + super(HttpStatus.BAD_REQUEST, reason); + } +} diff --git a/src/main/java/com/onixbyte/deltaforceguide/exeption/BizException.java b/src/main/java/com/onixbyte/deltaforceguide/exeption/BizException.java deleted file mode 100644 index d1b7ff2..0000000 --- a/src/main/java/com/onixbyte/deltaforceguide/exeption/BizException.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.onixbyte.deltaforceguide.exeption; - -import org.springframework.http.HttpStatus; - -/** - * Custom runtime exception that carries an HTTP status code for API error responses. - * - * @author zihluwang - */ -public class BizException extends RuntimeException { - - /** - * The HTTP status code associated with this business exception. - *

- * This status code indicates the appropriate HTTP response status that should be returned to - * clients when this exception occurs. It enables consistent error handling across - * REST API endpoints. - */ - private final HttpStatus status; - - public BizException(String message) { - super(message); - this.status = HttpStatus.INTERNAL_SERVER_ERROR; - } - - public BizException(HttpStatus status, String message) { - super(message); - this.status = status; - } - - /** - * Returns the HTTP status code associated with this business exception. - * - * @return the HTTP status code that should be used in the error response - */ - public HttpStatus getStatus() { - return status; - } -} - diff --git a/src/main/java/com/onixbyte/deltaforceguide/exeption/ForbiddenException.java b/src/main/java/com/onixbyte/deltaforceguide/exeption/ForbiddenException.java new file mode 100644 index 0000000..8f7cc55 --- /dev/null +++ b/src/main/java/com/onixbyte/deltaforceguide/exeption/ForbiddenException.java @@ -0,0 +1,11 @@ +package com.onixbyte.deltaforceguide.exeption; + +import org.springframework.http.HttpStatus; +import org.springframework.web.server.ResponseStatusException; + +public class ForbiddenException extends ResponseStatusException { + + public ForbiddenException(String reason) { + super(HttpStatus.FORBIDDEN, reason); + } +} diff --git a/src/main/java/com/onixbyte/deltaforceguide/exeption/InternalServerErrorException.java b/src/main/java/com/onixbyte/deltaforceguide/exeption/InternalServerErrorException.java new file mode 100644 index 0000000..7eba228 --- /dev/null +++ b/src/main/java/com/onixbyte/deltaforceguide/exeption/InternalServerErrorException.java @@ -0,0 +1,11 @@ +package com.onixbyte.deltaforceguide.exeption; + +import org.springframework.http.HttpStatus; +import org.springframework.web.server.ResponseStatusException; + +public class InternalServerErrorException extends ResponseStatusException { + + public InternalServerErrorException(String reason) { + super(HttpStatus.INTERNAL_SERVER_ERROR, reason); + } +} diff --git a/src/main/java/com/onixbyte/deltaforceguide/exeption/NotFoundException.java b/src/main/java/com/onixbyte/deltaforceguide/exeption/NotFoundException.java new file mode 100644 index 0000000..e88caac --- /dev/null +++ b/src/main/java/com/onixbyte/deltaforceguide/exeption/NotFoundException.java @@ -0,0 +1,11 @@ +package com.onixbyte.deltaforceguide.exeption; + +import org.springframework.http.HttpStatus; +import org.springframework.web.server.ResponseStatusException; + +public class NotFoundException extends ResponseStatusException { + + public NotFoundException(String reason) { + super(HttpStatus.NOT_FOUND, reason); + } +} diff --git a/src/main/java/com/onixbyte/deltaforceguide/exeption/UnauthorisedException.java b/src/main/java/com/onixbyte/deltaforceguide/exeption/UnauthorisedException.java new file mode 100644 index 0000000..5abbd86 --- /dev/null +++ b/src/main/java/com/onixbyte/deltaforceguide/exeption/UnauthorisedException.java @@ -0,0 +1,11 @@ +package com.onixbyte.deltaforceguide.exeption; + +import org.springframework.http.HttpStatus; +import org.springframework.web.server.ResponseStatusException; + +public class UnauthorisedException extends ResponseStatusException { + + public UnauthorisedException(String reason) { + super(HttpStatus.UNAUTHORIZED, reason); + } +} diff --git a/src/main/java/com/onixbyte/deltaforceguide/filter/TokenAuthenticationFilter.java b/src/main/java/com/onixbyte/deltaforceguide/filter/TokenAuthenticationFilter.java index 1a690e1..9a1da51 100644 --- a/src/main/java/com/onixbyte/deltaforceguide/filter/TokenAuthenticationFilter.java +++ b/src/main/java/com/onixbyte/deltaforceguide/filter/TokenAuthenticationFilter.java @@ -2,7 +2,7 @@ package com.onixbyte.deltaforceguide.filter; import com.auth0.jwt.exceptions.JWTVerificationException; import com.onixbyte.deltaforceguide.client.TokenClient; -import com.onixbyte.deltaforceguide.exeption.BizException; +import com.onixbyte.deltaforceguide.exeption.UnauthorisedException; import com.onixbyte.deltaforceguide.manager.UserManager; import com.onixbyte.deltaforceguide.manager.UserRoleManager; import com.onixbyte.deltaforceguide.security.authentication.UsernamePasswordAuthentication; @@ -16,11 +16,11 @@ import org.jspecify.annotations.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.util.WebUtils; @@ -89,7 +89,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter { var userWrapper = userManager.findByUsername(username); if (userWrapper.isEmpty()) { - throw new BizException(HttpStatus.UNAUTHORIZED, "登录已过期,请重新登录"); + throw new UnauthorisedException("登录已过期,请重新登录"); } var user = userWrapper.get(); @@ -110,8 +110,8 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter { } catch (JWTVerificationException e) { log.error("JWT verification failed.", e); handlerExceptionResolver.resolveException(request, response, null, - new BizException(HttpStatus.UNAUTHORIZED, "登录已过期,请重新登录")); - } catch (BizException e) { + new UnauthorisedException("登录已过期,请重新登录")); + } catch (ResponseStatusException e) { handlerExceptionResolver.resolveException(request, response, null, e); } } diff --git a/src/main/java/com/onixbyte/deltaforceguide/interceptor/GitHubWebhookInterceptor.java b/src/main/java/com/onixbyte/deltaforceguide/interceptor/GitHubWebhookInterceptor.java index c1b552a..0184525 100644 --- a/src/main/java/com/onixbyte/deltaforceguide/interceptor/GitHubWebhookInterceptor.java +++ b/src/main/java/com/onixbyte/deltaforceguide/interceptor/GitHubWebhookInterceptor.java @@ -1,7 +1,8 @@ package com.onixbyte.deltaforceguide.interceptor; import com.onixbyte.crypto.util.CryptoUtil; -import com.onixbyte.deltaforceguide.exeption.BizException; +import com.onixbyte.deltaforceguide.exeption.InternalServerErrorException; +import com.onixbyte.deltaforceguide.exeption.UnauthorisedException; import com.onixbyte.deltaforceguide.manager.WebhookManager; import com.onixbyte.deltaforceguide.shared.GitHubWebhookHeader; import com.onixbyte.deltaforceguide.wrapper.RepeatedlyReadRequestWrapper; @@ -10,7 +11,6 @@ import jakarta.servlet.http.HttpServletResponse; import org.jspecify.annotations.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; @@ -44,7 +44,7 @@ public class GitHubWebhookInterceptor implements HandlerInterceptor { @NonNull Object handler ) { if (!(request instanceof RepeatedlyReadRequestWrapper req)) { - throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, + throw new InternalServerErrorException( "Request body is not readable"); } @@ -58,7 +58,7 @@ public class GitHubWebhookInterceptor implements HandlerInterceptor { if (signatureHeader == null || signatureHeader.isBlank()) { log.warn("Missing {} header from ip={}", GitHubWebhookHeader.SIGNATURE_256, request.getRemoteAddr()); - throw new BizException(HttpStatus.UNAUTHORIZED, + throw new UnauthorisedException( "Missing webhook signature header"); } @@ -70,13 +70,13 @@ public class GitHubWebhookInterceptor implements HandlerInterceptor { computed.getBytes(StandardCharsets.UTF_8), signatureHeader.getBytes(StandardCharsets.UTF_8))) { log.warn("Invalid webhook signature from ip={}", request.getRemoteAddr()); - throw new BizException(HttpStatus.UNAUTHORIZED, "Invalid webhook signature"); + throw new UnauthorisedException("Invalid webhook signature"); } return true; } catch (NoSuchAlgorithmException | InvalidKeyException e) { log.error("Failed to compute HMAC-SHA256", e); - throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, + throw new InternalServerErrorException( "Failed to verify webhook signature"); } } diff --git a/src/main/java/com/onixbyte/deltaforceguide/manager/DailyPasswordManager.java b/src/main/java/com/onixbyte/deltaforceguide/manager/DailyPasswordManager.java index 6b6ac59..33be178 100644 --- a/src/main/java/com/onixbyte/deltaforceguide/manager/DailyPasswordManager.java +++ b/src/main/java/com/onixbyte/deltaforceguide/manager/DailyPasswordManager.java @@ -4,11 +4,10 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.onixbyte.deltaforceguide.domain.dto.DailyPasswordResponse; -import com.onixbyte.deltaforceguide.exeption.BizException; +import com.onixbyte.deltaforceguide.exeption.InternalServerErrorException; import com.onixbyte.deltaforceguide.shared.JacksonModules; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.http.HttpStatus; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.stereotype.Component; import org.springframework.web.client.RestClient; @@ -76,7 +75,7 @@ public class DailyPasswordManager { .body(DailyPasswordResponse.class); if (Objects.isNull(response)) { - throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, "暂无每日密码数据。"); + throw new InternalServerErrorException("暂无每日密码数据。"); } redisTemplate.opsForValue().set(key, response, Duration.ofDays(1L)); diff --git a/src/main/java/com/onixbyte/deltaforceguide/security/provider/UsernamePasswordAuthenticationProvider.java b/src/main/java/com/onixbyte/deltaforceguide/security/provider/UsernamePasswordAuthenticationProvider.java index 01e6baa..8fc1614 100644 --- a/src/main/java/com/onixbyte/deltaforceguide/security/provider/UsernamePasswordAuthenticationProvider.java +++ b/src/main/java/com/onixbyte/deltaforceguide/security/provider/UsernamePasswordAuthenticationProvider.java @@ -1,7 +1,8 @@ package com.onixbyte.deltaforceguide.security.provider; import com.onixbyte.deltaforceguide.domain.entity.UserCredential; -import com.onixbyte.deltaforceguide.exeption.BizException; +import com.onixbyte.deltaforceguide.exeption.InternalServerErrorException; +import com.onixbyte.deltaforceguide.exeption.UnauthorisedException; import com.onixbyte.deltaforceguide.manager.UserManager; import com.onixbyte.deltaforceguide.repository.UserCredentialRepository; import com.onixbyte.deltaforceguide.security.authentication.UsernamePasswordAuthentication; @@ -10,7 +11,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Example; -import org.springframework.http.HttpStatus; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -50,14 +50,14 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { if (!(authentication instanceof UsernamePasswordAuthentication usernamePasswordAuthentication)) { - throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, "用户认证失败,请稍后再试。"); + throw new InternalServerErrorException("用户认证失败,请稍后再试。"); } // get userContainer from database var userContainer = userManager.findByUsernameOrEmail(usernamePasswordAuthentication.getPrincipal()); if (userContainer.isEmpty()) { log.error("User {} is trying to authenticate but no userContainer found.", usernamePasswordAuthentication.getPrincipal()); - throw new BizException(HttpStatus.UNAUTHORIZED, "用户名或密码错误。"); + throw new UnauthorisedException("用户名或密码错误。"); } var user = userContainer.get(); @@ -68,12 +68,12 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro // get userContainer credentials from database var userCredentials = userCredentialRepository.findOne(Example.of(userCredentialExample)) - .orElseThrow(() -> new BizException(HttpStatus.UNAUTHORIZED, "您还没有配置密码,请联系管理员处理。")); + .orElseThrow(() -> new UnauthorisedException("您还没有配置密码,请联系管理员处理。")); // validate password if (!passwordEncoder.matches(usernamePasswordAuthentication.getCredentials(), userCredentials.getCredential())) { log.error("User {} is trying to authenticate but password is incorrect.", usernamePasswordAuthentication.getPrincipal()); - throw new BizException(HttpStatus.UNAUTHORIZED, "用户名或密码错误。"); + throw new UnauthorisedException("用户名或密码错误。"); } // erase credentials diff --git a/src/main/java/com/onixbyte/deltaforceguide/service/AuthService.java b/src/main/java/com/onixbyte/deltaforceguide/service/AuthService.java index da41902..440ea31 100644 --- a/src/main/java/com/onixbyte/deltaforceguide/service/AuthService.java +++ b/src/main/java/com/onixbyte/deltaforceguide/service/AuthService.java @@ -2,11 +2,10 @@ package com.onixbyte.deltaforceguide.service; import com.onixbyte.deltaforceguide.domain.dto.LoginRequest; import com.onixbyte.deltaforceguide.domain.entity.User; -import com.onixbyte.deltaforceguide.exeption.BizException; +import com.onixbyte.deltaforceguide.exeption.InternalServerErrorException; import com.onixbyte.deltaforceguide.security.authentication.UsernamePasswordAuthentication; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.http.HttpStatus; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.stereotype.Service; @@ -33,7 +32,6 @@ public class AuthService { * * @param request the login credentials containing principle and password * @return the authenticated {@link User} - * @throws BizException if authentication fails or the result type is unexpected */ public User login(LoginRequest request) { var _authentication = authenticationManager.authenticate(UsernamePasswordAuthentication @@ -43,7 +41,7 @@ public class AuthService { "Type mismatched, required type is UsernamePasswordAuthentication but got {}.", _authentication.getClass() ); - throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, "登录服务异常,请稍后再试。"); + throw new InternalServerErrorException("登录服务异常,请稍后再试。"); } return authentication.getDetails(); diff --git a/src/main/java/com/onixbyte/deltaforceguide/service/FirearmService.java b/src/main/java/com/onixbyte/deltaforceguide/service/FirearmService.java index 5f5098b..f113276 100644 --- a/src/main/java/com/onixbyte/deltaforceguide/service/FirearmService.java +++ b/src/main/java/com/onixbyte/deltaforceguide/service/FirearmService.java @@ -5,7 +5,7 @@ import com.onixbyte.deltaforceguide.domain.dto.FirearmResponse; import com.onixbyte.deltaforceguide.domain.dto.PageResponse; import com.onixbyte.deltaforceguide.domain.entity.Firearm; import com.onixbyte.deltaforceguide.enumeration.FirearmType; -import com.onixbyte.deltaforceguide.exeption.BizException; +import com.onixbyte.deltaforceguide.exeption.NotFoundException; import com.onixbyte.deltaforceguide.repository.FirearmRepository; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -84,7 +84,7 @@ public class FirearmService { */ public FirearmResponse updateFirearm(Long id, FirearmRequest request) { var firearm = firearmRepository.findById(id) - .orElseThrow(() -> new BizException(HttpStatus.NOT_FOUND, "Firearm not found: " + id)); + .orElseThrow(() -> new NotFoundException("Firearm not found: " + id)); firearm.setName(request.name()); firearm.setType(request.type()); @@ -105,7 +105,7 @@ public class FirearmService { */ public void deleteFirearm(Long id) { Firearm firearm = firearmRepository.findById(id) - .orElseThrow(() -> new BizException(HttpStatus.NOT_FOUND, "Firearm not found: " + id)); + .orElseThrow(() -> new NotFoundException("Firearm not found: " + id)); firearmRepository.delete(firearm); } } diff --git a/src/main/java/com/onixbyte/deltaforceguide/service/UserService.java b/src/main/java/com/onixbyte/deltaforceguide/service/UserService.java index 0d4a433..cabefe7 100644 --- a/src/main/java/com/onixbyte/deltaforceguide/service/UserService.java +++ b/src/main/java/com/onixbyte/deltaforceguide/service/UserService.java @@ -1,14 +1,10 @@ package com.onixbyte.deltaforceguide.service; -import com.onixbyte.deltaforceguide.domain.dto.BuildSummaryResponse; -import com.onixbyte.deltaforceguide.domain.dto.ChangePasswordRequest; -import com.onixbyte.deltaforceguide.domain.dto.PageResponse; -import com.onixbyte.deltaforceguide.domain.dto.UpdateProfileRequest; -import com.onixbyte.deltaforceguide.domain.dto.UserProfileResponse; +import com.onixbyte.deltaforceguide.domain.dto.*; import com.onixbyte.deltaforceguide.domain.entity.User; import com.onixbyte.deltaforceguide.domain.entity.UserCredential; import com.onixbyte.deltaforceguide.domain.entity.UserRole; -import com.onixbyte.deltaforceguide.exeption.BizException; +import com.onixbyte.deltaforceguide.exeption.BadRequestException; import com.onixbyte.deltaforceguide.manager.UserCredentialManager; import com.onixbyte.deltaforceguide.manager.UserManager; import com.onixbyte.deltaforceguide.manager.UserRoleManager; @@ -213,12 +209,11 @@ public class UserService { * * @param user the authenticated user * @param request the change password request containing old and new passwords - * @throws BizException if the old password is incorrect */ public void changePassword(User user, ChangePasswordRequest request) { var credential = userCredentialManager.findByUserIdAndProvider(user.getId(), CredentialProvider.LOCAL); if (credential.isEmpty() || !passwordEncoder.matches(request.oldPassword(), credential.get().getCredential())) { - throw new BizException(HttpStatus.BAD_REQUEST, "旧密码不正确。"); + throw new BadRequestException("旧密码不正确。"); } var encoded = passwordEncoder.encode(request.newPassword()); upsertCredential(user.getId(), CredentialProvider.LOCAL, encoded); @@ -243,11 +238,10 @@ public class UserService { * * @param userId the target user ID * @param role the role to assign - * @throws BizException if attempting to assign a protected role */ public void assignRole(Long userId, String role) { if (!Role.ROLE_ADMIN.equals(role)) { - throw new BizException(HttpStatus.BAD_REQUEST, "只能通过API分配ROLE_ADMIN角色。"); + throw new BadRequestException("只能通过API分配ROLE_ADMIN角色。"); } var user = ensureUserExists(userId); if (userRoleManager.existsByUserIdAndRole(userId, role)) { @@ -265,11 +259,10 @@ public class UserService { * * @param userId the target user ID * @param role the role to remove - * @throws BizException if attempting to remove a protected role */ public void removeRole(Long userId, String role) { if (!Role.ROLE_ADMIN.equals(role)) { - throw new BizException(HttpStatus.BAD_REQUEST, "只能通过API移除ROLE_ADMIN角色。"); + throw new BadRequestException("只能通过API移除ROLE_ADMIN角色。"); } ensureUserExists(userId); userRoleManager.deleteByUserIdAndRole(userId, role); diff --git a/src/main/java/com/onixbyte/deltaforceguide/service/WebhookService.java b/src/main/java/com/onixbyte/deltaforceguide/service/WebhookService.java index e864a77..6b7810e 100644 --- a/src/main/java/com/onixbyte/deltaforceguide/service/WebhookService.java +++ b/src/main/java/com/onixbyte/deltaforceguide/service/WebhookService.java @@ -1,14 +1,13 @@ package com.onixbyte.deltaforceguide.service; import com.onixbyte.deltaforceguide.domain.dto.*; +import com.onixbyte.deltaforceguide.exeption.BadRequestException; import com.onixbyte.deltaforceguide.manager.ModificationManager; import com.onixbyte.deltaforceguide.manager.WebhookManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; -import com.onixbyte.deltaforceguide.exeption.BizException; import org.yaml.snakeyaml.Yaml; import java.time.Duration; @@ -111,7 +110,7 @@ public class WebhookService { toLong(data.get("firearmId")), (String) data.get("firearmName")); if (firearmId == null) { - throw new BizException(HttpStatus.BAD_REQUEST, + throw new BadRequestException( "YAML must contain firearmId or firearmName"); } String name = (String) data.get("name");