Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -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};
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand All @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;
Expand All @@ -30,28 +31,29 @@ 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());
}


@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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ public Optional<Member> findActiveMemberById(final Long id) {
}

@Override
public Optional<Member> findByNickname(final String nickname) {
Optional<MemberEntity> memberEntity = memberRepository.findByNickname(nickname);
public Optional<Member> findActiveMemberByNickname(final String nickname) {
Optional<MemberEntity> memberEntity = memberRepository.findActiveMemberByNickname(nickname);
return memberEntity.map(memberPersistenceMapper::toDomain);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public interface MemberRepository extends JpaRepository<MemberEntity, Long>, Me

Optional<MemberEntity> findByStatusAndMemberId(MemberStatus memberStatus, Long memberId);

Optional<MemberEntity> findByNickname(String nickname);
@Query("SELECT m FROM MemberEntity m WHERE m.nickname = :nickname AND m.status = 'ACTIVE'")
Optional<MemberEntity> findActiveMemberByNickname(@Param("nickname") String nickname);

List<MemberEntity> findByIsReviewerTrue();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 임포트
Expand All @@ -22,7 +21,7 @@ public interface LoadMemberPort {

Optional<Member> findReviewerById(Long id);

Optional<Member> findByNickname(String nickname);
Optional<Member> findActiveMemberByNickname(String nickname);

List<Member> findReviewers();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -88,7 +86,7 @@ void testRegisterMembersFromCsv_success() throws Exception {
List<Member> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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
Expand All @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down