diff --git a/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java b/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java index 108681996..74aa466c6 100644 --- a/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java +++ b/src/main/java/balancetalk/global/jwt/JwtTokenProvider.java @@ -1,6 +1,9 @@ package balancetalk.global.jwt; +import balancetalk.global.exception.BalanceTalkException; +import balancetalk.global.exception.ErrorCode; import balancetalk.global.redis.application.RedisService; +import balancetalk.module.member.dto.TokenDto; import io.jsonwebtoken.*; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -123,4 +126,20 @@ private void validateAuthentication(Authentication authentication) { throw new IllegalArgumentException("유저 정보가 존재하지 않습니다."); } } + + public TokenDto reissueToken(String refreshToken) { + validateToken(refreshToken); + Authentication authentication = getAuthentication(refreshToken); + // redis에 저장된 RefreshToken 값을 가져옴 + String redisRefreshToken = redisService.getValues(authentication.getName()); + if (!redisRefreshToken.equals(refreshToken)) { + throw new BalanceTalkException(ErrorCode.INVALID_REFRESH_TOKEN); + } + TokenDto tokenDto = new TokenDto( + "Bearer", + createAccessToken(authentication), + createRefreshToken(authentication) + ); + return tokenDto; + } } diff --git a/src/main/java/balancetalk/module/member/application/MemberService.java b/src/main/java/balancetalk/module/member/application/MemberService.java index 1bdfb1288..3a1edac19 100644 --- a/src/main/java/balancetalk/module/member/application/MemberService.java +++ b/src/main/java/balancetalk/module/member/application/MemberService.java @@ -49,7 +49,8 @@ public LoginSuccessDto login(final LoginDto loginDto) { Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(loginDto.getEmail(), loginDto.getPassword()) ); - TokenDto tokenDto = new TokenDto("Bearer", jwtTokenProvider.createAccessToken(authentication), jwtTokenProvider.createRefreshToken(authentication)); + String refreshToken = jwtTokenProvider.createRefreshToken(authentication); + TokenDto tokenDto = jwtTokenProvider.reissueToken(refreshToken); // 만료되었다면, 재발급 return LoginSuccessDto.builder() .email(member.getEmail()) .password(member.getPassword()) @@ -57,15 +58,13 @@ public LoginSuccessDto login(final LoginDto loginDto) { .tokenDto(tokenDto) .build(); } catch (BadCredentialsException e) { - throw new BalanceTalkException(ErrorCode.BAD_CREDENTIAL_ERROR); + throw new BadCredentialsException("credential 오류!!"); } } @Transactional(readOnly = true) - public MemberResponseDto findById(HttpServletRequest request) { - String token = jwtTokenProvider.resolveToken(request); - String email = jwtTokenProvider.getPayload(token); - Member member = memberRepository.findByEmail(email) + public MemberResponseDto findById(Long id) { + Member member = memberRepository.findById(id) .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); return MemberResponseDto.fromEntity(member); } @@ -79,31 +78,35 @@ public List findAll() { } @Transactional - public void updateNickname(Long memberId, final NicknameUpdate nicknameUpdate) { - Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); + public void updateNickname(final NicknameUpdate nicknameUpdate, HttpServletRequest request) { + Member member = extractMember(request); member.updateNickname(nicknameUpdate.getNickname()); } @Transactional - public void updatePassword(Long memberId, final PasswordUpdate passwordUpdate) { - Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); - member.updatePassword(passwordUpdate.getPassword()); + public void updatePassword(final PasswordUpdate passwordUpdate, HttpServletRequest request) { + Member member = extractMember(request); + member.updatePassword(passwordEncoder.encode(passwordUpdate.getPassword())); } @Transactional - public void delete(Long memberId, final LoginDto loginDto) { - Member member = memberRepository.findById(memberId) - .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); - + public void delete(final LoginDto loginDto, HttpServletRequest request) { + Member member = extractMember(request); if (!member.getEmail().equals(loginDto.getEmail())) { throw new BalanceTalkException(ErrorCode.FORBIDDEN_MEMBER_DELETE); } - if (!member.getPassword().equals(loginDto.getPassword())) { - throw new BalanceTalkException(ErrorCode.INCORRECT_PASSWORD); + + if (!passwordEncoder.matches(loginDto.getPassword(), member.getPassword())) { + throw new BalanceTalkException(ErrorCode.MISMATCHED_EMAIL_OR_PASSWORD); } + memberRepository.deleteByEmail(member.getEmail()); + } - memberRepository.deleteById(memberId); + private Member extractMember(HttpServletRequest request) { + String token = jwtTokenProvider.resolveToken(request); + String email = jwtTokenProvider.getPayload(token); + Member member = memberRepository.findByEmail(email) + .orElseThrow(() -> new BalanceTalkException(ErrorCode.NOT_FOUND_MEMBER)); + return member; } } diff --git a/src/main/java/balancetalk/module/member/domain/MemberRepository.java b/src/main/java/balancetalk/module/member/domain/MemberRepository.java index a1d8cd1d8..8ac4abb8b 100644 --- a/src/main/java/balancetalk/module/member/domain/MemberRepository.java +++ b/src/main/java/balancetalk/module/member/domain/MemberRepository.java @@ -4,4 +4,5 @@ import java.util.Optional; public interface MemberRepository extends JpaRepository { Optional findByEmail(String username); + void deleteByEmail(String email); } diff --git a/src/main/java/balancetalk/module/member/dto/LoginSuccessDto.java b/src/main/java/balancetalk/module/member/dto/LoginSuccessDto.java index 09217bfa0..bfe3e5096 100644 --- a/src/main/java/balancetalk/module/member/dto/LoginSuccessDto.java +++ b/src/main/java/balancetalk/module/member/dto/LoginSuccessDto.java @@ -21,4 +21,5 @@ public class LoginSuccessDto { private Role role; private TokenDto tokenDto; + } diff --git a/src/main/java/balancetalk/module/member/dto/MemberResponseDto.java b/src/main/java/balancetalk/module/member/dto/MemberResponseDto.java index 6a55a220e..41ac96819 100644 --- a/src/main/java/balancetalk/module/member/dto/MemberResponseDto.java +++ b/src/main/java/balancetalk/module/member/dto/MemberResponseDto.java @@ -13,6 +13,9 @@ @AllArgsConstructor public class MemberResponseDto { + @Schema(description = "회원 id", example = "1") + private Long id; + @Schema(description = "회원 닉네임", example = "닉네임") private String nickname; @Schema(description = "회원 프로필", example = "../") @@ -28,6 +31,7 @@ public class MemberResponseDto { public static MemberResponseDto fromEntity(Member member) { return MemberResponseDto.builder() + .id(member.getId()) .nickname(member.getNickname()) //.profilePhoto(file.getPath()) .createdAt(member.getCreatedAt()) diff --git a/src/main/java/balancetalk/module/member/dto/TokenDto.java b/src/main/java/balancetalk/module/member/dto/TokenDto.java index 0d5bb6b56..d9a2fe9ea 100644 --- a/src/main/java/balancetalk/module/member/dto/TokenDto.java +++ b/src/main/java/balancetalk/module/member/dto/TokenDto.java @@ -1,11 +1,11 @@ package balancetalk.module.member.dto; - import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @Data +@Builder @NoArgsConstructor @AllArgsConstructor public class TokenDto { diff --git a/src/main/java/balancetalk/module/member/presentation/MemberController.java b/src/main/java/balancetalk/module/member/presentation/MemberController.java index 65ed6ce73..e1f7f8d86 100644 --- a/src/main/java/balancetalk/module/member/presentation/MemberController.java +++ b/src/main/java/balancetalk/module/member/presentation/MemberController.java @@ -38,44 +38,39 @@ public LoginSuccessDto login(@Valid @RequestBody LoginDto loginDto) { @ResponseStatus(HttpStatus.OK) @GetMapping("/{memberId}") - @Operation(summary = "단일 회원 조회", description = "해당 jwt 토큰 값과 일치하는 회원 정보를 조회한다.") + @Operation(summary = "단일 회원 조회", description = "memberId와 일치하는 회원 정보를 조회한다.") public MemberResponseDto findMemberInfo(@PathVariable("memberId") Long memberId) { return memberService.findById(memberId); } @ResponseStatus(HttpStatus.OK) - @GetMapping("/findAll") + @GetMapping @Operation(summary = "전체 회원 조회", description = "모든 회원 정보를 조회한다.") public List findAllMemberInfo() { return memberService.findAll(); } @ResponseStatus(HttpStatus.OK) - @PutMapping("/nickname/{memberId}") + @PutMapping("/nickname") @Operation(summary = "회원 닉네임 수정", description = "회원 닉네임을 수정한다.") - public String updateNickname(@PathVariable("memberId") Long memberId, @Valid @RequestBody NicknameUpdate nicknameUpdate) { - memberService.updateNickname(memberId, nicknameUpdate); + public String updateNickname(@Valid @RequestBody NicknameUpdate nicknameUpdate, HttpServletRequest request) { + memberService.updateNickname(nicknameUpdate, request); return "회원 닉네임이 변경되었습니다."; } @ResponseStatus(HttpStatus.OK) - @PutMapping("/{memberId}") + @PutMapping("/password") @Operation(summary = "회원 비밀번호 수정", description = "회원 패스워드를 수정한다.") - public String updatePassword(@PathVariable("memberId") Long memberId, @Valid @RequestBody PasswordUpdate passwordUpdate) { - memberService.updatePassword(memberId, passwordUpdate); + public String updatePassword(@Valid @RequestBody PasswordUpdate passwordUpdate, HttpServletRequest request) { + memberService.updatePassword(passwordUpdate, request); return "회원 비밀번호가 변경되었습니다."; } @ResponseStatus(HttpStatus.OK) - @DeleteMapping("/{memberId}") + @DeleteMapping @Operation(summary = "회원 삭제", description = "해당 id값과 일치하는 회원 정보를 삭제한다.") - public String deleteMember(@PathVariable("memberId") Long memberId, @Valid @RequestBody LoginDto loginDto) { - memberService.delete(memberId, loginDto); + public String deleteMember(@Valid @RequestBody LoginDto loginDto, HttpServletRequest request) { + memberService.delete(loginDto, request); return "회원 탈퇴가 정상적으로 처리되었습니다."; } - - @PostMapping("/test") - public String test() { - return "success"; - } }