diff --git a/src/main/java/clap/server/adapter/inbound/security/WebSecurityUrl.java b/src/main/java/clap/server/adapter/inbound/security/WebSecurityUrl.java index 398db74d..cbfeb2d8 100644 --- a/src/main/java/clap/server/adapter/inbound/security/WebSecurityUrl.java +++ b/src/main/java/clap/server/adapter/inbound/security/WebSecurityUrl.java @@ -15,4 +15,5 @@ private WebSecurityUrl() { public static final String REISSUANCE_ENDPOINT = "/api/auths/reissuance"; public static final String PASSWORD_EMAIL_ENDPOINT = "/api/new-password"; public static final String TEMPORARY_TOKEN_ALLOWED_ENDPOINT = "/api/members/initial-password"; + public static final String[] ANONYMOUS_ENDPOINTS = {LOGIN_ENDPOINT, PASSWORD_EMAIL_ENDPOINT}; } diff --git a/src/main/java/clap/server/adapter/inbound/security/filter/JwtAuthenticationFilter.java b/src/main/java/clap/server/adapter/inbound/security/filter/JwtAuthenticationFilter.java index bc4cae49..3f454db6 100644 --- a/src/main/java/clap/server/adapter/inbound/security/filter/JwtAuthenticationFilter.java +++ b/src/main/java/clap/server/adapter/inbound/security/filter/JwtAuthenticationFilter.java @@ -49,8 +49,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { SWAGGER_ENDPOINTS ).flatMap(Arrays::stream).toArray(String[]::new); - public static final String[] ANONYMOUS_ENDPOINTS = {LOGIN_ENDPOINT, PASSWORD_EMAIL_ENDPOINT}; - @Override protected void doFilterInternal( @NotNull HttpServletRequest request, diff --git a/src/main/java/clap/server/adapter/inbound/security/filter/LoginAttemptFilter.java b/src/main/java/clap/server/adapter/inbound/security/filter/LoginAttemptFilter.java index 7d5110f8..f16e927b 100644 --- a/src/main/java/clap/server/adapter/inbound/security/filter/LoginAttemptFilter.java +++ b/src/main/java/clap/server/adapter/inbound/security/filter/LoginAttemptFilter.java @@ -12,14 +12,16 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.util.AntPathMatcher; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.util.ContentCachingRequestWrapper; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; -import static clap.server.adapter.inbound.security.WebSecurityUrl.LOGIN_ENDPOINT; +import static clap.server.adapter.inbound.security.WebSecurityUrl.ANONYMOUS_ENDPOINTS; import static clap.server.common.utils.ClientIpParseUtil.getClientIp; @@ -33,10 +35,10 @@ public class LoginAttemptFilter extends OncePerRequestFilter { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { try { - if (request.getRequestURI().equals(LOGIN_ENDPOINT)) { + if (Arrays.stream(ANONYMOUS_ENDPOINTS) + .anyMatch(endpoint -> new AntPathMatcher().match(endpoint, request.getRequestURI()))) { String nickname = request.getParameter("nickname"); checkAccountLockStatusUseCase.checkAccountIsLocked(nickname); - } } catch (AuthException e) { log.warn("Authentication failed for IP: {}. Error: {}", getClientIp(request), e.getMessage()); diff --git a/src/main/java/clap/server/adapter/inbound/web/member/ResetPasswordController.java b/src/main/java/clap/server/adapter/inbound/web/member/ResetPasswordController.java index 95b68994..448f9c5e 100644 --- a/src/main/java/clap/server/adapter/inbound/web/member/ResetPasswordController.java +++ b/src/main/java/clap/server/adapter/inbound/web/member/ResetPasswordController.java @@ -13,6 +13,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; @@ -30,14 +31,14 @@ public class ResetPasswordController { @Operation(summary = "초기 로그인 후 비밀번호 재설정 API") @PatchMapping("/members/initial-password") public void resetPasswordAndActivateMember(@AuthenticationPrincipal SecurityUserDetails userInfo, - @RequestBody @Valid UpdateInitialPasswordRequest request) { - resetInitialPasswordUsecase.resetPasswordAndActivateMember(userInfo.getUserId(),request.password()); + @RequestBody @Valid UpdateInitialPasswordRequest request) { + resetInitialPasswordUsecase.resetPasswordAndActivateMember(userInfo.getUserId(), request.password()); } @Operation(summary = "비밀번호 재설정 API") @PatchMapping("/members/password") public void resetPassword(@AuthenticationPrincipal SecurityUserDetails userInfo, - @RequestBody @Valid UpdatePasswordRequest request) { + @RequestBody @Valid UpdatePasswordRequest request) { resetPasswordUsecase.resetPassword(userInfo.getUserId(), request.password()); } @@ -45,13 +46,14 @@ public void resetPassword(@AuthenticationPrincipal SecurityUserDetails userInfo, @Operation(summary = "비밀번호 검증 API") @PostMapping("/members/password") public void verifyPassword(@AuthenticationPrincipal SecurityUserDetails userInfo, - @RequestBody @Valid VerifyPasswordRequest request) { + @RequestBody @Valid VerifyPasswordRequest request) { verifyPasswordUseCase.verifyPassword(userInfo.getUserId(), request.password()); } @Operation(summary = "비밀번호 재설정 이메일 전송 API") @PostMapping("/new-password") - public void sendNewPasswordEmail(@RequestBody @Valid SendInitialPasswordRequest request) { + public void sendNewPasswordEmail(@RequestParam @NotBlank String nickname, + @RequestBody @Valid SendInitialPasswordRequest request) { sendNewPasswordUsecase.sendInitialPassword(request); } } diff --git a/src/main/java/clap/server/adapter/outbound/persistense/MemberPersistenceAdapter.java b/src/main/java/clap/server/adapter/outbound/persistense/MemberPersistenceAdapter.java index 021210ca..5e670883 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/MemberPersistenceAdapter.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/MemberPersistenceAdapter.java @@ -38,8 +38,8 @@ public Optional findActiveMemberById(final Long id) { } @Override - public Optional findByNickname(final String nickname) { - Optional memberEntity = memberRepository.findByNickname(nickname); + public Optional findActiveMemberByNickname(final String nickname) { + Optional memberEntity = memberRepository.findActiveMemberByNickname(nickname); return memberEntity.map(memberPersistenceMapper::toDomain); } diff --git a/src/main/java/clap/server/adapter/outbound/persistense/repository/member/MemberRepository.java b/src/main/java/clap/server/adapter/outbound/persistense/repository/member/MemberRepository.java index a65dfdae..813521a0 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/repository/member/MemberRepository.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/repository/member/MemberRepository.java @@ -18,7 +18,8 @@ public interface MemberRepository extends JpaRepository, Me Optional findByStatusAndMemberId(MemberStatus memberStatus, Long memberId); - Optional findByNickname(String nickname); + @Query("SELECT m FROM MemberEntity m WHERE m.nickname = :nickname AND m.status = 'ACTIVE'") + Optional findActiveMemberByNickname(@Param("nickname") String nickname); List findByIsReviewerTrue(); diff --git a/src/main/java/clap/server/application/port/outbound/member/LoadMemberPort.java b/src/main/java/clap/server/application/port/outbound/member/LoadMemberPort.java index a377bdc6..d79baf83 100644 --- a/src/main/java/clap/server/application/port/outbound/member/LoadMemberPort.java +++ b/src/main/java/clap/server/application/port/outbound/member/LoadMemberPort.java @@ -2,8 +2,7 @@ import clap.server.adapter.inbound.web.dto.admin.request.FindMemberRequest; import clap.server.domain.model.member.Member; -import clap.server.domain.model.task.Task; // Task 클래스 임포트 확인 -import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus; // TaskStatus 임포트 + import java.util.List; // Task 클래스 임포트 확인 // TaskStatus 임포트 @@ -22,7 +21,7 @@ public interface LoadMemberPort { Optional findReviewerById(Long id); - Optional findByNickname(String nickname); + Optional findActiveMemberByNickname(String nickname); List findReviewers(); diff --git a/src/main/java/clap/server/application/service/auth/AuthService.java b/src/main/java/clap/server/application/service/auth/AuthService.java index 75b4667c..53002230 100644 --- a/src/main/java/clap/server/application/service/auth/AuthService.java +++ b/src/main/java/clap/server/application/service/auth/AuthService.java @@ -69,7 +69,7 @@ private void deleteAccessToken(Long memberId, String accessToken) { } private Member getMember(String inputNickname, String clientIp) { - return loadMemberPort.findByNickname(inputNickname).orElseThrow(() -> + return loadMemberPort.findActiveMemberByNickname(inputNickname).orElseThrow(() -> { loginAttemptService.recordFailedAttempt(inputNickname, clientIp); return new AuthException(AuthErrorCode.LOGIN_REQUEST_FAILED); diff --git a/src/main/java/clap/server/application/service/task/ApprovalTaskService.java b/src/main/java/clap/server/application/service/task/ApprovalTaskService.java index 2fb3e305..179bb257 100644 --- a/src/main/java/clap/server/application/service/task/ApprovalTaskService.java +++ b/src/main/java/clap/server/application/service/task/ApprovalTaskService.java @@ -44,7 +44,7 @@ public class ApprovalTaskService implements ApprovalTaskUsecase { public ApprovalTaskResponse approvalTaskByReviewer(Long reviewerId, Long taskId, ApprovalTaskRequest approvalTaskRequest) { Member reviewer = memberService.findReviewer(reviewerId); Task task = taskService.findById(taskId); - Member processor = memberService.findById(approvalTaskRequest.processorId()); + Member processor = memberService.findActiveMember(approvalTaskRequest.processorId()); Category category = categoryService.findById(approvalTaskRequest.categoryId()); Label label = null; if (approvalTaskRequest.labelId() != null) { diff --git a/src/main/java/clap/server/application/service/task/UpdateTaskService.java b/src/main/java/clap/server/application/service/task/UpdateTaskService.java index 9f3a4a92..b7eace8a 100644 --- a/src/main/java/clap/server/application/service/task/UpdateTaskService.java +++ b/src/main/java/clap/server/application/service/task/UpdateTaskService.java @@ -105,7 +105,7 @@ public void updateTaskProcessor(Long taskId, Long memberId, UpdateTaskProcessorR memberService.findActiveMember(memberId); Task task = taskService.findById(taskId); - Member processor = memberService.findById(request.processorId()); + Member processor = memberService.findActiveMember(request.processorId()); task.updateProcessor(processor); Task updateTask = taskService.upsert(task); diff --git a/src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java b/src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java index 623a9384..474ad2d7 100644 --- a/src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java +++ b/src/test/java/clap/server/application/service/admin/RegisterMemberCSVServiceTest.java @@ -3,8 +3,6 @@ import clap.server.application.port.inbound.domain.MemberService; import clap.server.application.port.outbound.member.CommandMemberPort; import clap.server.application.port.outbound.member.LoadMemberPort; -import clap.server.application.service.admin.CsvParseService; -import clap.server.application.service.admin.RegisterMemberCSVService; import clap.server.domain.model.member.Department; import clap.server.domain.model.member.Member; import clap.server.domain.model.member.MemberInfo; @@ -88,7 +86,7 @@ void testRegisterMembersFromCsv_success() throws Exception { List csvMembers = Arrays.asList(csvMember1, csvMember2); when(csvParser.parseDataAndMapToMember(file)).thenReturn(csvMembers); - when(loadMemberPort.findByNickname(anyString())).thenReturn(Optional.empty()); + when(loadMemberPort.findActiveMemberByNickname(anyString())).thenReturn(Optional.empty()); when(loadMemberPort.findByEmail(anyString())).thenReturn(Optional.empty()); Member adminMember = mock(Member.class); diff --git a/src/test/java/clap/server/application/service/auth/AuthServiceTest.java b/src/test/java/clap/server/application/service/auth/AuthServiceTest.java index ca836ba8..bc110b81 100644 --- a/src/test/java/clap/server/application/service/auth/AuthServiceTest.java +++ b/src/test/java/clap/server/application/service/auth/AuthServiceTest.java @@ -56,7 +56,7 @@ void loginSuccess() { Member member = user; CustomJwts jwtTokens = new CustomJwts("accessToken", "refreshToken"); - when(loadMemberPort.findByNickname(nickname)).thenReturn(Optional.of(member)); + when(loadMemberPort.findActiveMemberByNickname(nickname)).thenReturn(Optional.of(member)); when(passwordEncoder.matches(inputPassword, member.getPassword())).thenReturn(true); when(manageTokenService.issueTokens(member)).thenReturn(jwtTokens); @@ -80,7 +80,7 @@ void loginFailureWrongPassword() { String clientIp = "127.0.0.1"; Member member = user; - when(loadMemberPort.findByNickname(nickname)).thenReturn(Optional.of(member)); + when(loadMemberPort.findActiveMemberByNickname(nickname)).thenReturn(Optional.of(member)); when(passwordEncoder.matches(inputPassword, member.getPassword())).thenReturn(false); // When & Then @@ -100,7 +100,7 @@ void loginWithApprovalRequestStatus() { Member member = notApprovedUser; String temporaryToken = "temporaryToken"; - when(loadMemberPort.findByNickname(nickname)).thenReturn(Optional.of(member)); + when(loadMemberPort.findActiveMemberByNickname(nickname)).thenReturn(Optional.of(member)); when(passwordEncoder.matches(inputPassword, member.getPassword())).thenReturn(true); when(manageTokenService.issueTemporaryToken(notApprovedUser.getMemberId())).thenReturn(temporaryToken); diff --git a/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java b/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java index aeb225cb..e42af787 100644 --- a/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java +++ b/src/test/java/clap/server/application/service/task/ApprovalTaskServiceTest.java @@ -81,7 +81,7 @@ void approvalTask() { when(memberService.findReviewer(reviewerId)).thenReturn(reviewer); when(taskService.findById(taskId)).thenReturn(task); - when(memberService.findById(approvalTaskRequest.processorId())).thenReturn(processor); + when(memberService.findActiveMember(approvalTaskRequest.processorId())).thenReturn(processor); when(categoryService.findById(approvalTaskRequest.categoryId())).thenReturn(category); when(taskService.upsert(task)).thenReturn(task);