diff --git a/src/main/java/com/sparta/oneandzerobest/auth/entity/User.java b/src/main/java/com/sparta/oneandzerobest/auth/entity/User.java index 005fd1d..d9b098d 100644 --- a/src/main/java/com/sparta/oneandzerobest/auth/entity/User.java +++ b/src/main/java/com/sparta/oneandzerobest/auth/entity/User.java @@ -1,5 +1,6 @@ package com.sparta.oneandzerobest.auth.entity; +import com.sparta.oneandzerobest.profile.dto.ProfileRequestDto; import jakarta.persistence.*; import lombok.Getter; import lombok.NoArgsConstructor; @@ -79,4 +80,14 @@ public boolean isEnabled() { public Collection getAuthorities() { return Collections.emptyList(); // 권한 관련 설정 } + + public void update(ProfileRequestDto requestDto) { + this.name = requestDto.getName(); + this.email = requestDto.getEmail(); + this.introduction = requestDto.getIntroduction(); + } + + public void updatePassword(String password) { + this.password = password; + } } diff --git a/src/main/java/com/sparta/oneandzerobest/profile/controller/ProfileController.java b/src/main/java/com/sparta/oneandzerobest/profile/controller/ProfileController.java new file mode 100644 index 0000000..061ab52 --- /dev/null +++ b/src/main/java/com/sparta/oneandzerobest/profile/controller/ProfileController.java @@ -0,0 +1,37 @@ +package com.sparta.oneandzerobest.profile.controller; + +import com.sparta.oneandzerobest.profile.dto.ProfileRequestDto; +import com.sparta.oneandzerobest.profile.dto.ProfileResponseDto; +import com.sparta.oneandzerobest.profile.service.ProfileService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/profile") +@RequiredArgsConstructor +public class ProfileController { + + private final ProfileService profileService; + + /** + * 선택한 프로필을 조회 + * @param id : userId + * @return : body로 유저의 정보 전달 + */ + @GetMapping("/{id}") + public ResponseEntity inquiryProfile(@PathVariable Long id) { + return ResponseEntity.status(200).body(profileService.inquiryProfile(id)); + } + + /** + * 프로필 수정 + * @param id : userId + * @param requestDto : 수정하고자하는 정보를 body로 받아옴 + * @return : body로 유저의 정보 전달 + */ + @PutMapping("/{id}") + public ResponseEntity editProfile(@PathVariable Long id, @RequestBody ProfileRequestDto requestDto) { + return ResponseEntity.status(200).body(profileService.editProfile(id, requestDto)); + } +} diff --git a/src/main/java/com/sparta/oneandzerobest/profile/dto/ProfileRequestDto.java b/src/main/java/com/sparta/oneandzerobest/profile/dto/ProfileRequestDto.java new file mode 100644 index 0000000..a52a5d5 --- /dev/null +++ b/src/main/java/com/sparta/oneandzerobest/profile/dto/ProfileRequestDto.java @@ -0,0 +1,12 @@ +package com.sparta.oneandzerobest.profile.dto; + +import lombok.Getter; + +@Getter +public class ProfileRequestDto { + private String name; + private String email; + private String introduction; + private String password; + private String newPassword; +} diff --git a/src/main/java/com/sparta/oneandzerobest/profile/dto/ProfileResponseDto.java b/src/main/java/com/sparta/oneandzerobest/profile/dto/ProfileResponseDto.java new file mode 100644 index 0000000..5275c7d --- /dev/null +++ b/src/main/java/com/sparta/oneandzerobest/profile/dto/ProfileResponseDto.java @@ -0,0 +1,19 @@ +package com.sparta.oneandzerobest.profile.dto; + +import com.sparta.oneandzerobest.auth.entity.User; +import lombok.Getter; + +@Getter +public class ProfileResponseDto { + private String username; + private String name; + private String introduction; + private String email; + + public ProfileResponseDto(User user) { + this.username = user.getUsername(); + this.name = user.getName(); + this.introduction = user.getIntroduction(); + this.email = user.getEmail(); + } +} diff --git a/src/main/java/com/sparta/oneandzerobest/profile/exception/GlobalExceptionHandler.java b/src/main/java/com/sparta/oneandzerobest/profile/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..8f734df --- /dev/null +++ b/src/main/java/com/sparta/oneandzerobest/profile/exception/GlobalExceptionHandler.java @@ -0,0 +1,45 @@ +package com.sparta.oneandzerobest.profile.exception; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + + /** + * 해당하는 유저를 찾을 수 없을 때, 클라이언트로 에러 코드와 메시지 반환 + * @return + */ + @ExceptionHandler(NotFoundUserException.class) + public ResponseEntity notFoundUserHandler() { + return ResponseEntity.status(400).body("해당 유저를 찾을 수 없습니다."); + } + + /** + * 비밀번호가 맞지 않을 때, 클라이언트로 에러 코드와 메시지 반환 + * @return + */ + @ExceptionHandler(IncorrectPasswordException.class) + public ResponseEntity incorrectPasswordHandler() { + return ResponseEntity.status(400).body("비밀번호가 맞지 않습니다."); + } + + /** + * 비밀번호가 형식이 맞지 않을 때, 클라이언트로 에러 코드와 메시지 반환 + * @return + */ + @ExceptionHandler(PasswordPatternException.class) + public ResponseEntity passwordPatternHandler() { + return ResponseEntity.status(400).body("비밀번호는 최소 10자 이상이며 알파벳 대소문자, 숫자, 특수문자를 포함해야 합니다."); + } + + /** + * 비밀번호가 변경이 불가능 할 때, 클라이언트로 에러 코드와 메시지 반환 + * @return + */ + @ExceptionHandler(UnacceptablePasswordException.class) + public ResponseEntity unacceptablePasswordHandler() { + return ResponseEntity.status(400).body("해당 비밀번호로 변경이 불가능합니다. (이전과 동일한 비밀번호로 변경할 수 없습니다.)"); + } +} diff --git a/src/main/java/com/sparta/oneandzerobest/profile/exception/IncorrectPasswordException.java b/src/main/java/com/sparta/oneandzerobest/profile/exception/IncorrectPasswordException.java new file mode 100644 index 0000000..bcadb2e --- /dev/null +++ b/src/main/java/com/sparta/oneandzerobest/profile/exception/IncorrectPasswordException.java @@ -0,0 +1,6 @@ +package com.sparta.oneandzerobest.profile.exception; + +public class IncorrectPasswordException extends RuntimeException { + public IncorrectPasswordException() { + } +} diff --git a/src/main/java/com/sparta/oneandzerobest/profile/exception/NotFoundUserException.java b/src/main/java/com/sparta/oneandzerobest/profile/exception/NotFoundUserException.java new file mode 100644 index 0000000..7fe6c36 --- /dev/null +++ b/src/main/java/com/sparta/oneandzerobest/profile/exception/NotFoundUserException.java @@ -0,0 +1,10 @@ +package com.sparta.oneandzerobest.profile.exception; + +public class NotFoundUserException extends RuntimeException { + public NotFoundUserException() { + } + + public NotFoundUserException(String message) { + super(message); + } +} diff --git a/src/main/java/com/sparta/oneandzerobest/profile/exception/PasswordPatternException.java b/src/main/java/com/sparta/oneandzerobest/profile/exception/PasswordPatternException.java new file mode 100644 index 0000000..3d0f0a9 --- /dev/null +++ b/src/main/java/com/sparta/oneandzerobest/profile/exception/PasswordPatternException.java @@ -0,0 +1,6 @@ +package com.sparta.oneandzerobest.profile.exception; + +public class PasswordPatternException extends RuntimeException { + public PasswordPatternException() { + } +} diff --git a/src/main/java/com/sparta/oneandzerobest/profile/exception/UnacceptablePasswordException.java b/src/main/java/com/sparta/oneandzerobest/profile/exception/UnacceptablePasswordException.java new file mode 100644 index 0000000..e587c2a --- /dev/null +++ b/src/main/java/com/sparta/oneandzerobest/profile/exception/UnacceptablePasswordException.java @@ -0,0 +1,6 @@ +package com.sparta.oneandzerobest.profile.exception; + +public class UnacceptablePasswordException extends RuntimeException { + public UnacceptablePasswordException() { + } +} diff --git a/src/main/java/com/sparta/oneandzerobest/profile/service/ProfileService.java b/src/main/java/com/sparta/oneandzerobest/profile/service/ProfileService.java new file mode 100644 index 0000000..3eadcee --- /dev/null +++ b/src/main/java/com/sparta/oneandzerobest/profile/service/ProfileService.java @@ -0,0 +1,76 @@ +package com.sparta.oneandzerobest.profile.service; + +import com.sparta.oneandzerobest.auth.entity.User; +import com.sparta.oneandzerobest.auth.repository.UserRepository; +import com.sparta.oneandzerobest.profile.dto.ProfileRequestDto; +import com.sparta.oneandzerobest.profile.dto.ProfileResponseDto; +import com.sparta.oneandzerobest.profile.exception.IncorrectPasswordException; +import com.sparta.oneandzerobest.profile.exception.NotFoundUserException; +import com.sparta.oneandzerobest.profile.exception.PasswordPatternException; +import com.sparta.oneandzerobest.profile.exception.UnacceptablePasswordException; +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ProfileService { + + private final UserRepository userRepository; + private final PasswordEncoder passwordEncoder; + + /** + * 해당 id를 가진 user의 프로필을 조회해주는 메서드 + * + * @param id : userId + * @return : ProfileResponseDto + */ + public ProfileResponseDto inquiryProfile(Long id) { + User user = userRepository.findById(id).orElseThrow( + () -> new NotFoundUserException() + ); + + return new ProfileResponseDto(user); + } + + /** + * 프로필을 수정해주는 메서드 + * + * @param id : userId + * @param requestDto : 수정 정보가 담긴 requestDto + * @return : ProfileResponseDto + */ + public ProfileResponseDto editProfile(Long id, ProfileRequestDto requestDto) { + User user = userRepository.findById(id).orElseThrow( + () -> new NotFoundUserException() + ); + + user.update(requestDto); // 이메일, 이름, 한줄소개 수정 + + if (requestDto.getPassword() != null && !requestDto.getPassword().isEmpty()) { // 비밀번호가 입력되어 있을때만 비밀번호 검사 시작 + if (passwordEncoder.matches(requestDto.getPassword(), user.getPassword())) { // DB에 저장된 비밀번호와 일치하지 않는지 검사 + validationPassword(requestDto, user.getPassword()); // 유효한 비밀번호로 변경하려는지 검사 + user.updatePassword(passwordEncoder.encode(requestDto.getNewPassword())); // 비밀번호 수정 + } else { + throw new IncorrectPasswordException(); + } + } + + return new ProfileResponseDto(userRepository.save(user)); + } + + /** + * 유효한 비밀번호로 변경하려는지 검사하는 메서드 + * + * @param requestDto : 유저가 입력한 입력한 기존 비밀번호와 새 비밀번호 정보가 담겨있다. + * @param userPassword : 원래 DB에 저장되어 있던 유저의 비밀번호 + */ + private void validationPassword(ProfileRequestDto requestDto, String userPassword) { + if (!requestDto.getNewPassword().matches("^(?=.*[a-zA-Z])(?=.*\\d)(?=.*[!@#$%^&*])[a-zA-Z\\d!@#$%^&*]{10,}$")) { // 비밀번호를 올바른 형식으로 바꾸려는 검사 + if (passwordEncoder.matches(requestDto.getNewPassword(), userPassword)) { // 이전과 같은 비밀번호로 수정하는지 검사 + throw new UnacceptablePasswordException(); + } + throw new PasswordPatternException(); + } + } +}