diff --git a/src/main/java/com/mycom/socket/auth/config/SecurityConfig.java b/src/main/java/com/mycom/socket/auth/config/SecurityConfig.java index 5295378..6252357 100644 --- a/src/main/java/com/mycom/socket/auth/config/SecurityConfig.java +++ b/src/main/java/com/mycom/socket/auth/config/SecurityConfig.java @@ -40,7 +40,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .authorizeHttpRequests(auth -> auth .requestMatchers( - "/","/api/auth/**", "/swagger-ui/**", "/v3/api-docs/**" + "/","/api/auth/**", "/api/profile/**", "/swagger-ui/**", "/v3/api-docs/**" ).permitAll() .anyRequest() .authenticated()); diff --git a/src/main/java/com/mycom/socket/go_socket/controller/ProfileController.java b/src/main/java/com/mycom/socket/go_socket/controller/ProfileController.java index c7e37db..ee151c0 100644 --- a/src/main/java/com/mycom/socket/go_socket/controller/ProfileController.java +++ b/src/main/java/com/mycom/socket/go_socket/controller/ProfileController.java @@ -1,20 +1,51 @@ package com.mycom.socket.go_socket.controller; import com.mycom.socket.auth.security.MemberDetails; +import com.mycom.socket.go_socket.dto.request.PasswordUpdateRequest; +import com.mycom.socket.go_socket.dto.request.ProfileUpdateRequest; import com.mycom.socket.go_socket.dto.response.ProfileResponse; +import com.mycom.socket.go_socket.entity.Member; +import com.mycom.socket.go_socket.service.MemberService; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor @RequestMapping("/api/profile") public class ProfileController { + private final MemberService memberService; + @GetMapping public ProfileResponse getProfile(@AuthenticationPrincipal MemberDetails memberDetails) { return ProfileResponse.of(memberDetails.getMember()); } + + @PutMapping + public ProfileResponse updateProfile( + @AuthenticationPrincipal MemberDetails memberDetails, + @RequestBody @Valid ProfileUpdateRequest request + ) { + Member updatedMember = memberService.updateProfile( + memberDetails.getMember().getEmail(), + request.nickname(), + request.intro() + ); + return ProfileResponse.of(updatedMember); + } + + @PutMapping("/password") + public void updatePassword( + @AuthenticationPrincipal MemberDetails memberDetails, + @RequestBody @Valid PasswordUpdateRequest request + ) { + memberService.updatePassword( + memberDetails.getMember().getEmail(), + request.currentPassword(), + request.newPassword() + ); + } + } diff --git a/src/main/java/com/mycom/socket/go_socket/dto/request/PasswordUpdateRequest.java b/src/main/java/com/mycom/socket/go_socket/dto/request/PasswordUpdateRequest.java new file mode 100644 index 0000000..c4b074f --- /dev/null +++ b/src/main/java/com/mycom/socket/go_socket/dto/request/PasswordUpdateRequest.java @@ -0,0 +1,12 @@ +package com.mycom.socket.go_socket.dto.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public record PasswordUpdateRequest( + @NotBlank(message = "현재 비밀번호는 필수입니다") + String currentPassword, + @NotBlank(message = "새 비밀번호는 필수입니다") + @Size(min = 8, message = "비밀번호는 8자 이상이어야 합니다") + String newPassword +) {} diff --git a/src/main/java/com/mycom/socket/go_socket/dto/request/ProfileUpdateRequest.java b/src/main/java/com/mycom/socket/go_socket/dto/request/ProfileUpdateRequest.java new file mode 100644 index 0000000..43324bd --- /dev/null +++ b/src/main/java/com/mycom/socket/go_socket/dto/request/ProfileUpdateRequest.java @@ -0,0 +1,12 @@ +package com.mycom.socket.go_socket.dto.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public record ProfileUpdateRequest( + @NotBlank(message = "닉네임은 필수입니다") + @Size(min = 2, max = 20, message = "닉네임은 2자 이상 20자 이하여야 합니다") + String nickname, + @Size(max = 100, message = "자기소개는 100자를 초과할 수 없습니다") + String intro +) {} \ No newline at end of file diff --git a/src/main/java/com/mycom/socket/go_socket/entity/Member.java b/src/main/java/com/mycom/socket/go_socket/entity/Member.java index c02f966..79c95b3 100644 --- a/src/main/java/com/mycom/socket/go_socket/entity/Member.java +++ b/src/main/java/com/mycom/socket/go_socket/entity/Member.java @@ -50,4 +50,13 @@ public Member(String email, String nickname, String password, String intro, Memb public void updateRefreshToken(String updateRefreshToken) { this.refreshToken = updateRefreshToken; } + + public void updateProfile(String nickname, String intro) { + this.nickname = nickname; + this.intro = intro; + } + + public void updatePassword(String encodedPassword) { + this.password = encodedPassword; + } } diff --git a/src/main/java/com/mycom/socket/go_socket/service/MemberService.java b/src/main/java/com/mycom/socket/go_socket/service/MemberService.java index c1f09f1..9c19ce7 100644 --- a/src/main/java/com/mycom/socket/go_socket/service/MemberService.java +++ b/src/main/java/com/mycom/socket/go_socket/service/MemberService.java @@ -1,7 +1,10 @@ package com.mycom.socket.go_socket.service; +import com.mycom.socket.global.exception.NotFoundException; +import com.mycom.socket.go_socket.entity.Member; import com.mycom.socket.go_socket.repository.MemberRepository; import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -11,4 +14,26 @@ public class MemberService { private final MemberRepository memberRepository; + private final PasswordEncoder passwordEncoder; + + @Transactional + public Member updateProfile(String email, String nickname, String intro) { + Member member = memberRepository.findByEmail(email) + .orElseThrow(() -> new NotFoundException("사용자를 찾을 수 없습니다.")); + + member.updateProfile(nickname, intro); + return member; + } + + @Transactional + public void updatePassword(String email, String currentPassword, String newPassword) { + Member member = memberRepository.findByEmail(email) + .orElseThrow(() -> new NotFoundException("현재 비밀번호가 일치하지 않습니다.")); + + if (!passwordEncoder.matches(currentPassword, member.getPassword())) { + throw new NotFoundException("새 비밀번호는 현재 비밀번호와 달라야 합니다."); + } + + member.updatePassword(passwordEncoder.encode(newPassword)); + } }