diff --git a/backend/src/main/java/com/postdm/backend/domain/auth/api/TestController.java b/backend/src/main/java/com/postdm/backend/domain/auth/api/TestController.java index a11a632..e2307d9 100644 --- a/backend/src/main/java/com/postdm/backend/domain/auth/api/TestController.java +++ b/backend/src/main/java/com/postdm/backend/domain/auth/api/TestController.java @@ -1,7 +1,9 @@ package com.postdm.backend.domain.auth.api; +import com.postdm.backend.domain.member.dto.MemberPrincipalDto; import com.postdm.backend.global.template.ResponseTemplate; import org.springframework.http.HttpStatus; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -9,11 +11,11 @@ @RestController public class TestController { // 현재 사용자 세션 확인용 테스트 컨트롤러 @GetMapping("/test") - public ResponseTemplate test() { - String username = SecurityContextHolder.getContext().getAuthentication().getName(); + public ResponseTemplate test(@AuthenticationPrincipal MemberPrincipalDto member) { + String nickname = member.getNickname(); String role = SecurityContextHolder.getContext().getAuthentication().getAuthorities().iterator().next().getAuthority(); - return new ResponseTemplate<>(HttpStatus.OK, "환영합니다, " + role + ", " + username + "님!", username); + return new ResponseTemplate<>(HttpStatus.OK, "환영합니다, " + role + ", " + nickname + "님!", nickname); } } diff --git a/backend/src/main/java/com/postdm/backend/domain/auth/application/AuthService.java b/backend/src/main/java/com/postdm/backend/domain/auth/application/AuthService.java index 3655e74..1f23f2a 100644 --- a/backend/src/main/java/com/postdm/backend/domain/auth/application/AuthService.java +++ b/backend/src/main/java/com/postdm/backend/domain/auth/application/AuthService.java @@ -117,10 +117,8 @@ public void signUp(SignUpRequestDto signUpRequestDto) { // 회원가입 서비 public TokenInfo signIn(SignInRequestDto signInRequestDto, HttpServletResponse response) { // 로그인 서비스 String username = signInRequestDto.getUsername(); - Member member = memberRepository.findByUsername(username); - if(member == null) { - throw new CustomException(ErrorCode.MEMBER_NOT_FOUND); - } + Member member = memberRepository.findByUsername(username) + .orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND)); String password = signInRequestDto.getPassword(); String encodedPassword = member.getPassword(); diff --git a/backend/src/main/java/com/postdm/backend/domain/member/api/MemberController.java b/backend/src/main/java/com/postdm/backend/domain/member/api/MemberController.java index 8ee49eb..73108e4 100644 --- a/backend/src/main/java/com/postdm/backend/domain/member/api/MemberController.java +++ b/backend/src/main/java/com/postdm/backend/domain/member/api/MemberController.java @@ -5,6 +5,8 @@ import com.postdm.backend.domain.member.application.MemberService; import com.postdm.backend.domain.member.domain.entity.Member; import com.postdm.backend.domain.member.dto.FindUsernameRequestDto; +import com.postdm.backend.domain.member.dto.MemberInfoDto; +import com.postdm.backend.domain.member.dto.MemberPrincipalDto; import com.postdm.backend.domain.member.dto.ResetPasswordRequestDto; import com.postdm.backend.global.template.ResponseTemplate; import io.swagger.v3.oas.annotations.Operation; @@ -12,10 +14,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.validation.Valid; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/v1/member") @@ -66,4 +66,28 @@ public ResponseTemplate resetPassword(@RequestBody @Valid ResetPasswordR return new ResponseTemplate<>(HttpStatus.OK, "비밀번호 변경 성공", member); } + + @Operation(summary = "마이페이지 조회 컨트롤러") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "성공"), + }) + @GetMapping("/my-page") + public ResponseTemplate memberInfo(@AuthenticationPrincipal MemberPrincipalDto memberPrincipalDto) { + String username = memberPrincipalDto.getUsername(); + MemberInfoDto member = memberService.loadMemberInfo(username); + return new ResponseTemplate<>(HttpStatus.OK, "조회 성공", member); + } + + @Operation(summary = "마이페이지 수정 컨트롤러") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "성공"), + }) + @PatchMapping("/my-page/edit") + public ResponseTemplate editMemberInfo(@AuthenticationPrincipal MemberPrincipalDto memberPrincipalDto, + @RequestBody @Valid MemberInfoDto memberInfoDto) { + String username = memberPrincipalDto.getUsername(); + memberService.updateMemberInfo(username, memberInfoDto); + + return new ResponseTemplate<>(HttpStatus.OK, "회원 정보 수정 성공"); + } } diff --git a/backend/src/main/java/com/postdm/backend/domain/member/application/MemberService.java b/backend/src/main/java/com/postdm/backend/domain/member/application/MemberService.java index e8cb0ac..1260a61 100644 --- a/backend/src/main/java/com/postdm/backend/domain/member/application/MemberService.java +++ b/backend/src/main/java/com/postdm/backend/domain/member/application/MemberService.java @@ -6,10 +6,19 @@ import com.postdm.backend.domain.member.dto.FindUsernameRequestDto; import com.postdm.backend.domain.member.domain.entity.Member; import com.postdm.backend.domain.member.domain.repository.MemberRepository; +import com.postdm.backend.domain.member.dto.MemberInfoDto; import com.postdm.backend.domain.member.dto.ResetPasswordRequestDto; +import com.postdm.backend.global.common.exception.CustomException; +import com.postdm.backend.global.common.response.ErrorCode; +import jakarta.validation.Valid; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; + @Service public class MemberService { @@ -51,7 +60,8 @@ public Member resetPassword(ResetPasswordRequestDto resetPasswordRequestDto) { throw new IllegalArgumentException(); } - Member member = memberRepository.findByUsername(username); + Member member = memberRepository.findByUsername(username) + .orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND)); member.setPassword(encodedPassword); memberRepository.save(member); @@ -59,4 +69,46 @@ public Member resetPassword(ResetPasswordRequestDto resetPasswordRequestDto) { return member; } + + public MemberInfoDto loadMemberInfo(String username) { + Member member = memberRepository.findByUsername(username) + .orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND)); + + return MemberInfoDto.builder(). + nickname(member.getNickname()). + email(member.getEmail()). + phone(member.getPhone()). + build(); + } + + public void updateMemberInfo(String username, @Valid MemberInfoDto memberInfoDto) { + Member member = memberRepository.findByUsername(username) + .orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND)); + + List list = new ArrayList<>(); + list.add(memberInfoDto); + + for (MemberInfoDto infoDto : list) { + if (infoDto.getNickname() != null) { + if (infoDto.getNickname().isEmpty()) { + throw new CustomException(ErrorCode.VALIDATION_FAIL); + } + member.setNickname(infoDto.getNickname()); + }; + if (infoDto.getEmail() != null) { + if(infoDto.getEmail().isEmpty()) { + throw new CustomException(ErrorCode.VALIDATION_FAIL); + } + member.setEmail(infoDto.getEmail()); + }; + if (infoDto.getPhone() != null) { + if (infoDto.getPhone().isEmpty()) { + throw new CustomException(ErrorCode.VALIDATION_FAIL); + } + member.setPhone(infoDto.getPhone()); + }; + } + + memberRepository.save(member); + } } diff --git a/backend/src/main/java/com/postdm/backend/domain/member/domain/repository/MemberRepository.java b/backend/src/main/java/com/postdm/backend/domain/member/domain/repository/MemberRepository.java index bf1b289..c9b3075 100644 --- a/backend/src/main/java/com/postdm/backend/domain/member/domain/repository/MemberRepository.java +++ b/backend/src/main/java/com/postdm/backend/domain/member/domain/repository/MemberRepository.java @@ -4,10 +4,12 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface MemberRepository extends JpaRepository { boolean existsByEmail(String email); boolean existsByUsername(String username); - Member findByUsername(String username); + Optional findByUsername(String username); Member findByEmail(String email); } diff --git a/backend/src/main/java/com/postdm/backend/domain/member/dto/MemberInfoDto.java b/backend/src/main/java/com/postdm/backend/domain/member/dto/MemberInfoDto.java new file mode 100644 index 0000000..e0855eb --- /dev/null +++ b/backend/src/main/java/com/postdm/backend/domain/member/dto/MemberInfoDto.java @@ -0,0 +1,22 @@ +package com.postdm.backend.domain.member.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Email; +import lombok.Builder; +import lombok.Data; + +@Schema(description = "마이페이지 정보 DTO") +@Data +@Builder +public class MemberInfoDto { + + @Schema(description = "사용자 이름", example = "홍길동") + private String nickname; + + @Schema(description = "사용자 이메일", example = "test1@test.com") + @Email + private String email; + + @Schema(description = "사용자 전화번호", example = "01012345678") + private String phone; +} diff --git a/backend/src/main/java/com/postdm/backend/domain/member/dto/MemberPrincipalDto.java b/backend/src/main/java/com/postdm/backend/domain/member/dto/MemberPrincipalDto.java new file mode 100644 index 0000000..1b5f838 --- /dev/null +++ b/backend/src/main/java/com/postdm/backend/domain/member/dto/MemberPrincipalDto.java @@ -0,0 +1,19 @@ +package com.postdm.backend.domain.member.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class MemberPrincipalDto { + + private Long id; + + @Schema(description = "사용자 이름", example = "홍길동") + private String nickname; + + @Schema(description = "사용자 아이디", example = "test123") + private String username; + +} diff --git a/backend/src/main/java/com/postdm/backend/global/jwt/util/JwtProvider.java b/backend/src/main/java/com/postdm/backend/global/jwt/util/JwtProvider.java index de8a634..d4bb7ae 100644 --- a/backend/src/main/java/com/postdm/backend/global/jwt/util/JwtProvider.java +++ b/backend/src/main/java/com/postdm/backend/global/jwt/util/JwtProvider.java @@ -2,6 +2,9 @@ import com.postdm.backend.domain.member.domain.entity.Member; import com.postdm.backend.domain.member.domain.repository.MemberRepository; +import com.postdm.backend.domain.member.dto.MemberPrincipalDto; +import com.postdm.backend.global.common.exception.CustomException; +import com.postdm.backend.global.common.response.ErrorCode; import com.postdm.backend.global.jwt.dto.TokenInfo; import io.jsonwebtoken.*; import io.jsonwebtoken.security.SecurityException; @@ -94,7 +97,6 @@ public boolean validateToken(String token) { // 토큰 유효성 검사 public TokenInfo generateToken(String username, String role) { // 토큰 생성 String accessToken = generateAccessToken(username, role); - String refreshToken = generateRefreshToken(username, role); return TokenInfo.builder() .grantType("Bearer") @@ -110,15 +112,19 @@ public Authentication getAuthentication(String token) { // 토큰에서 사용 String role = claims.get("role", String.class); // role 추출 - Member member = memberRepository.findByUsername(username); - if (member == null) { - throw new RuntimeException("해당 사용자 정보를 찾을 수 없습니다."); - } + Member member = memberRepository.findByUsername(username) + .orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND)); + + MemberPrincipalDto memberPrincipalDto = MemberPrincipalDto.builder() + .id(member.getId()) + .nickname(member.getNickname()) + .username(username) + .build(); List authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role)); // Spring Security에서 Authentication 객체의 principal을 Member 객체로 저장 - return new UsernamePasswordAuthenticationToken(member, "", authorities); + return new UsernamePasswordAuthenticationToken(memberPrincipalDto, "", authorities); } // JWT 토큰 만료 시간 반환