diff --git a/build.gradle b/build.gradle index 1979f082..78ec39ed 100644 --- a/build.gradle +++ b/build.gradle @@ -37,6 +37,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.openapitools:jackson-databind-nullable:0.2.1' + implementation 'org.springframework.security:spring-security-crypto' } tasks.named('test') { diff --git a/src/main/java/umc/kkijuk/server/common/controller/ExceptionControllerAdvice.java b/src/main/java/umc/kkijuk/server/common/controller/ExceptionControllerAdvice.java index c0288543..8c93649c 100644 --- a/src/main/java/umc/kkijuk/server/common/controller/ExceptionControllerAdvice.java +++ b/src/main/java/umc/kkijuk/server/common/controller/ExceptionControllerAdvice.java @@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import umc.kkijuk.server.common.domian.exception.*; import umc.kkijuk.server.common.domian.response.ErrorResponse; +import umc.kkijuk.server.common.domian.exception.ConfirmPasswordMismatchException; import umc.kkijuk.server.common.domian.response.ErrorResultResponse; @RestControllerAdvice @@ -42,6 +43,36 @@ public ErrorResponse InvalidTagNameException(InvalidTagNameException exception) } @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(ConfirmPasswordMismatchException.class) + public ErrorResponse ConfirmPasswordMismatchException(ConfirmPasswordMismatchException e) { + return new ErrorResponse(e.getMessage()); + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(FieldUpdateException.class) + public ErrorResponse FieldUpdateException(FieldUpdateException e) { + return new ErrorResponse(e.getMessage()); + } + + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(InvalidMemberDataException.class) + public ErrorResponse InvalidMemberDataException(InvalidMemberDataException e) { + return new ErrorResponse(e.getMessage()); + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(CurrentPasswordMismatchException.class) + public ErrorResponse CurrentPasswordMismatchException(CurrentPasswordMismatchException e) { + return new ErrorResponse(e.getMessage()); + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(EmailNotFoundException.class) + public ErrorResponse EmailNotFoundException(EmailNotFoundException e) { + return new ErrorResponse(e.getMessage()); + } + @ExceptionHandler(CareerValidationException.class) public ErrorResponse CareerValidationException(CareerValidationException exception) { return new ErrorResponse(exception.getMessage()); diff --git a/src/main/java/umc/kkijuk/server/common/domian/exception/ConfirmPasswordMismatchException.java b/src/main/java/umc/kkijuk/server/common/domian/exception/ConfirmPasswordMismatchException.java new file mode 100644 index 00000000..d98d0d6e --- /dev/null +++ b/src/main/java/umc/kkijuk/server/common/domian/exception/ConfirmPasswordMismatchException.java @@ -0,0 +1,7 @@ +package umc.kkijuk.server.common.domian.exception; + +public class ConfirmPasswordMismatchException extends RuntimeException { + public ConfirmPasswordMismatchException() { + super("비밀번호가 일치하지 않습니다."); + } +} diff --git a/src/main/java/umc/kkijuk/server/common/domian/exception/CurrentPasswordMismatchException.java b/src/main/java/umc/kkijuk/server/common/domian/exception/CurrentPasswordMismatchException.java new file mode 100644 index 00000000..f9233657 --- /dev/null +++ b/src/main/java/umc/kkijuk/server/common/domian/exception/CurrentPasswordMismatchException.java @@ -0,0 +1,6 @@ +package umc.kkijuk.server.common.domian.exception; + +public class CurrentPasswordMismatchException extends RuntimeException { + public CurrentPasswordMismatchException() {super("현재 비밀번호가 일치하지 않습니다."); + } +} diff --git a/src/main/java/umc/kkijuk/server/common/domian/exception/EmailNotFoundException.java b/src/main/java/umc/kkijuk/server/common/domian/exception/EmailNotFoundException.java new file mode 100644 index 00000000..f1fe9aa2 --- /dev/null +++ b/src/main/java/umc/kkijuk/server/common/domian/exception/EmailNotFoundException.java @@ -0,0 +1,6 @@ +package umc.kkijuk.server.common.domian.exception; + +public class EmailNotFoundException extends RuntimeException{ + public EmailNotFoundException() {super("이메일을 찾을 수 없습니다."); + } +} diff --git a/src/main/java/umc/kkijuk/server/common/domian/exception/FieldUpdateException.java b/src/main/java/umc/kkijuk/server/common/domian/exception/FieldUpdateException.java new file mode 100644 index 00000000..47133d3c --- /dev/null +++ b/src/main/java/umc/kkijuk/server/common/domian/exception/FieldUpdateException.java @@ -0,0 +1,6 @@ +package umc.kkijuk.server.common.domian.exception; + +public class FieldUpdateException extends RuntimeException{ + public FieldUpdateException() {super("Field update fail."); + } +} diff --git a/src/main/java/umc/kkijuk/server/common/domian/exception/InvalidMemberDataException.java b/src/main/java/umc/kkijuk/server/common/domian/exception/InvalidMemberDataException.java new file mode 100644 index 00000000..3ef2a45e --- /dev/null +++ b/src/main/java/umc/kkijuk/server/common/domian/exception/InvalidMemberDataException.java @@ -0,0 +1,6 @@ +package umc.kkijuk.server.common.domian.exception; + +public class InvalidMemberDataException extends RuntimeException{ + public InvalidMemberDataException() {super("MemberData cannot be null."); + } +} diff --git a/src/main/java/umc/kkijuk/server/member/controller/MemberController.java b/src/main/java/umc/kkijuk/server/member/controller/MemberController.java index b89a055f..10d146f8 100644 --- a/src/main/java/umc/kkijuk/server/member/controller/MemberController.java +++ b/src/main/java/umc/kkijuk/server/member/controller/MemberController.java @@ -10,11 +10,8 @@ import umc.kkijuk.server.member.controller.response.CreateMemberResponse; import umc.kkijuk.server.member.controller.response.MemberFieldResponse; import umc.kkijuk.server.member.controller.response.MemberInfoResponse; -import umc.kkijuk.server.member.controller.response.ResultResponse; import umc.kkijuk.server.member.domain.Member; -import umc.kkijuk.server.member.dto.MemberFieldDto; -import umc.kkijuk.server.member.dto.MemberInfoChangeDto; -import umc.kkijuk.server.member.dto.MemberJoinDto; +import umc.kkijuk.server.member.dto.*; import umc.kkijuk.server.member.service.MemberService; import lombok.RequiredArgsConstructor; @@ -34,25 +31,11 @@ public class MemberController { description = "회원가입 요청을 받아 성공/실패 여부를 반환합니다.") @PostMapping public ResponseEntity saveMember(@RequestBody @Valid MemberJoinDto memberJoinDto) { - String passwordConfirm = memberJoinDto.getPasswordConfirm(); - if (!passwordConfirm.equals(memberJoinDto.getPassword())) { - return ResponseEntity - .status(HttpStatus.BAD_REQUEST) - .body(new CreateMemberResponse("Passwords do not match")); - } - - try { - Long loginUser = LoginUser.get().getId(); - memberService.join(memberJoinDto.toEntity()); - return ResponseEntity - .status(HttpStatus.CREATED) - .body(new CreateMemberResponse(loginUser , "Member created successfully")); - } catch (Exception e) { - e.printStackTrace(); - return ResponseEntity - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(new CreateMemberResponse("Member creation failed")); - } + Member joinMember = memberService.join(memberJoinDto); + + return ResponseEntity + .status(HttpStatus.CREATED) + .body(new CreateMemberResponse(joinMember.getId(), "Member created successfully")); } @Operation( @@ -60,37 +43,21 @@ public ResponseEntity saveMember(@RequestBody @Valid Membe description = "마이페이지에서 내 정보들을 가져옵니다.") @GetMapping("/myPage/info") public ResponseEntity getInfo() { - try { - Long loginUser = LoginUser.get().getId(); - Member member = memberService.getMemberInfo(loginUser); - MemberInfoResponse response = new MemberInfoResponse( - member.getEmail(), - member.getName(), - member.getPhoneNumber(), - member.getBirthDate() - ); - return ResponseEntity.ok(response); - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); - } + Long loginUser = LoginUser.get().getId(); + MemberInfoResponse memberInfoResponse = memberService.getMemberInfo(loginUser); + return ResponseEntity + .status(HttpStatus.OK) + .body(memberInfoResponse); } @Operation( summary = "내 정보 수정", description = "내 정보 수정 요청을 받아 성공/실패를 반환합니다.") @PutMapping("/myPage/info") - public ResponseEntity changeMemberInfo(@RequestBody MemberInfoChangeDto memberInfoChangeDto) { + public ResponseEntity changeMemberInfo(@RequestBody @Valid MemberInfoChangeDto memberInfoChangeDto) { Long loginUser = LoginUser.get().getId(); - try { - memberService.updateMemberInfo(loginUser, memberInfoChangeDto); - return ResponseEntity.ok() - .body(new ResultResponse("information update success")); - }catch (Exception e){ - return ResponseEntity - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(new ResultResponse("information update failed")); - } - + memberService.updateMemberInfo(loginUser, memberInfoChangeDto); + return ResponseEntity.ok(Boolean.TRUE); } @Operation( @@ -98,30 +65,46 @@ public ResponseEntity changeMemberInfo(@RequestBody MemberInfoCh description = "마이페이지에서 관심분야를 조회합니다.") @GetMapping("/myPage/field") public ResponseEntity getField() { - try { - Long loginUser = LoginUser.get().getId(); - List memberField = memberService.getMemberField(loginUser); - return ResponseEntity.ok().body(new MemberFieldResponse(memberField)); - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); - } + Long loginUser = LoginUser.get().getId(); + List memberField = memberService.getMemberField(loginUser); + return ResponseEntity.ok().body(new MemberFieldResponse(memberField)); } @Operation( summary = "관심분야 등록/수정", description = "초기/마이페이지에서 관심분야를 등록/수정합니다.") @PostMapping({"/field", "/myPage/field"}) - public ResponseEntity postField(@RequestBody @Valid MemberFieldDto memberFieldDto) { - try { - Long loginUserId = LoginUser.get().getId(); - List updatedMember = memberService.updateMemberField(loginUserId, memberFieldDto); - MemberFieldResponse response = new MemberFieldResponse(updatedMember); - return ResponseEntity.ok(response); - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); - } + public ResponseEntity postField(@RequestBody MemberFieldDto memberFieldDto) { + + Long loginUser = LoginUser.get().getId(); + memberService.updateMemberField(loginUser, memberFieldDto); + return ResponseEntity.ok(Boolean.TRUE); + } + + @Operation( + summary = "비밀번호 변경", + description = "비밀번호를 변경합니다.") + @PostMapping("myPage/password") + public ResponseEntity changeMemberPassword(@RequestBody @Valid MemberPasswordChangeDto memberPasswordChangeDto){ + Long loginUser = LoginUser.get().getId(); + memberService.changeMemberPassword(loginUser, memberPasswordChangeDto); + return ResponseEntity.ok(Boolean.TRUE); + } + + @Operation( + summary = "내정보 조회용 비밀번호 인증", + description = "내 정보를 조회하기 위해 비밀번호를 인증합니다.") + @PostMapping("/myPage") + public ResponseEntity myPagePasswordAuth(@RequestBody @Valid MyPagePasswordAuthDto myPagePasswordAuthDto){{ + Long loginUser = LoginUser.get().getId(); + memberService.myPagePasswordAuth(loginUser, myPagePasswordAuthDto); + return ResponseEntity.ok(Boolean.TRUE); } + } + + + } diff --git a/src/main/java/umc/kkijuk/server/member/controller/response/MemberInfoResponse.java b/src/main/java/umc/kkijuk/server/member/controller/response/MemberInfoResponse.java index ec0be718..58e05b5b 100644 --- a/src/main/java/umc/kkijuk/server/member/controller/response/MemberInfoResponse.java +++ b/src/main/java/umc/kkijuk/server/member/controller/response/MemberInfoResponse.java @@ -1,5 +1,6 @@ package umc.kkijuk.server.member.controller.response; +import lombok.Builder; import lombok.Data; import java.time.LocalDate; @@ -14,6 +15,7 @@ public class MemberInfoResponse { public MemberInfoResponse() { } + @Builder public MemberInfoResponse(String email, String name, String phoneNumber, LocalDate birthDate) { this.email = email; this.name = name; diff --git a/src/main/java/umc/kkijuk/server/member/domain/Member.java b/src/main/java/umc/kkijuk/server/member/domain/Member.java index a3e9016e..83e254f3 100644 --- a/src/main/java/umc/kkijuk/server/member/domain/Member.java +++ b/src/main/java/umc/kkijuk/server/member/domain/Member.java @@ -8,6 +8,7 @@ import java.time.LocalDate; import java.util.List; +import umc.kkijuk.server.career.domain.base.BaseEntity; import umc.kkijuk.server.common.converter.StringListToStringConverter; @Entity @@ -71,5 +72,8 @@ public void changeMemberInfo(String phoneNumber, LocalDate birthDate, MarketingA this.marketingAgree = marketingAgree; } + public void changeMemberPassword(String password){ + this.password = password; + } } diff --git a/src/main/java/umc/kkijuk/server/member/dto/MemberInfoChangeDto.java b/src/main/java/umc/kkijuk/server/member/dto/MemberInfoChangeDto.java index b4df23ea..df5eca8b 100644 --- a/src/main/java/umc/kkijuk/server/member/dto/MemberInfoChangeDto.java +++ b/src/main/java/umc/kkijuk/server/member/dto/MemberInfoChangeDto.java @@ -1,6 +1,7 @@ package umc.kkijuk.server.member.dto; +import jakarta.validation.constraints.NotNull; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @@ -11,9 +12,11 @@ @Data @NoArgsConstructor public class MemberInfoChangeDto { - private Long id; //jwt토큰으로 받을땐 제거 + @NotNull private String phoneNumber; + @NotNull private LocalDate birthDate; + @NotNull private MarketingAgree marketingAgree; @Builder diff --git a/src/main/java/umc/kkijuk/server/member/dto/MemberJoinDto.java b/src/main/java/umc/kkijuk/server/member/dto/MemberJoinDto.java index 85bd9421..8a319faa 100644 --- a/src/main/java/umc/kkijuk/server/member/dto/MemberJoinDto.java +++ b/src/main/java/umc/kkijuk/server/member/dto/MemberJoinDto.java @@ -1,5 +1,6 @@ package umc.kkijuk.server.member.dto; +import jakarta.validation.constraints.NotNull; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @@ -13,13 +14,21 @@ @NoArgsConstructor public class MemberJoinDto { + @NotNull private String email; + @NotNull private String name; + @NotNull private String phoneNumber; + @NotNull private LocalDate birthDate; + @NotNull private String password; + @NotNull private String passwordConfirm; + @NotNull private MarketingAgree marketingAgree; + @NotNull private State userState; // @Builder diff --git a/src/main/java/umc/kkijuk/server/member/dto/MemberPasswordChangeDto.java b/src/main/java/umc/kkijuk/server/member/dto/MemberPasswordChangeDto.java new file mode 100644 index 00000000..c2f93c77 --- /dev/null +++ b/src/main/java/umc/kkijuk/server/member/dto/MemberPasswordChangeDto.java @@ -0,0 +1,25 @@ +package umc.kkijuk.server.member.dto; + +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class MemberPasswordChangeDto { + + @NotNull + private String currentPassword; + @NotNull + private String newPassword; + @NotNull + private String newPasswordConfirm; + + @Builder + public MemberPasswordChangeDto(String currentPassword, String newPassword, String newPasswordConfirm) { + this.currentPassword = currentPassword; + this.newPassword = newPassword; + this.newPasswordConfirm = newPasswordConfirm; + } +} diff --git a/src/main/java/umc/kkijuk/server/member/dto/MemberPhoneNumberDto.java b/src/main/java/umc/kkijuk/server/member/dto/MemberPhoneNumberDto.java index 968a6e5c..62ded14a 100644 --- a/src/main/java/umc/kkijuk/server/member/dto/MemberPhoneNumberDto.java +++ b/src/main/java/umc/kkijuk/server/member/dto/MemberPhoneNumberDto.java @@ -1,5 +1,6 @@ package umc.kkijuk.server.member.dto; +import jakarta.validation.constraints.NotNull; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @@ -7,6 +8,7 @@ @Data @NoArgsConstructor public class MemberPhoneNumberDto { + @NotNull private String phoneNumber; @Builder diff --git a/src/main/java/umc/kkijuk/server/member/dto/MyPagePasswordAuthDto.java b/src/main/java/umc/kkijuk/server/member/dto/MyPagePasswordAuthDto.java new file mode 100644 index 00000000..c0785147 --- /dev/null +++ b/src/main/java/umc/kkijuk/server/member/dto/MyPagePasswordAuthDto.java @@ -0,0 +1,17 @@ +package umc.kkijuk.server.member.dto; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class MyPagePasswordAuthDto { + + @NotNull + private String currentPassword; + + public MyPagePasswordAuthDto(String currentPassword) { + this.currentPassword = currentPassword; + } +} diff --git a/src/main/java/umc/kkijuk/server/member/passwordcrypto/AuthConfig.java b/src/main/java/umc/kkijuk/server/member/passwordcrypto/AuthConfig.java new file mode 100644 index 00000000..834df037 --- /dev/null +++ b/src/main/java/umc/kkijuk/server/member/passwordcrypto/AuthConfig.java @@ -0,0 +1,19 @@ +package umc.kkijuk.server.member.passwordcrypto; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.factory.PasswordEncoderFactories; +import org.springframework.security.crypto.password.DelegatingPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class AuthConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + DelegatingPasswordEncoder passwordEncoder = (DelegatingPasswordEncoder) PasswordEncoderFactories.createDelegatingPasswordEncoder(); + passwordEncoder.setDefaultPasswordEncoderForMatches(new BCryptPasswordEncoder()); + return passwordEncoder; + } +} diff --git a/src/main/java/umc/kkijuk/server/member/repository/MemberJpaRepository.java b/src/main/java/umc/kkijuk/server/member/repository/MemberJpaRepository.java index 25100fd3..8aadf3fa 100644 --- a/src/main/java/umc/kkijuk/server/member/repository/MemberJpaRepository.java +++ b/src/main/java/umc/kkijuk/server/member/repository/MemberJpaRepository.java @@ -7,4 +7,5 @@ public interface MemberJpaRepository extends JpaRepository{ Optional findById(Long id); + Optional findByEmail(String email); } diff --git a/src/main/java/umc/kkijuk/server/member/service/MemberService.java b/src/main/java/umc/kkijuk/server/member/service/MemberService.java index 5aa2ebf8..d7167233 100644 --- a/src/main/java/umc/kkijuk/server/member/service/MemberService.java +++ b/src/main/java/umc/kkijuk/server/member/service/MemberService.java @@ -1,69 +1,18 @@ package umc.kkijuk.server.member.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import umc.kkijuk.server.common.domian.exception.ResourceNotFoundException; +import umc.kkijuk.server.member.controller.response.MemberInfoResponse; import umc.kkijuk.server.member.domain.Member; -import umc.kkijuk.server.member.dto.MemberFieldDto; -import umc.kkijuk.server.member.dto.MemberInfoChangeDto; -import umc.kkijuk.server.member.repository.MemberJpaRepository; +import umc.kkijuk.server.member.dto.*; import java.util.List; -@Service -@Transactional(readOnly = true) -@RequiredArgsConstructor -public class MemberService { - private final MemberJpaRepository memberJpaRepository; - - public Member findOne(Long memberId) { - return memberJpaRepository.findById(memberId) - .orElseThrow(() -> new ResourceNotFoundException("Member", memberId)); - } - - - //아직 인터페이스 구현 x, 추후에 구현 후 MemberService -> MemberServiceImpl로 수정 예정. - @Transactional - public Long join(Member member) { - memberJpaRepository.save(member); - return member.getId(); - } - - /* security 의존성 추가후 변경할 join 함수 */ -// @Transactional -// public Long join(Member member) { -// member.changeMemberPassword(passwordEncoder.encode(member.getPassword())); -// memberJpaRepository.save(member); -// return member.getId(); -// } - - public Member getMemberInfo(Long memberId) { - return memberJpaRepository.findById(memberId) - .orElseThrow(() -> new IllegalArgumentException("Member not found")); - } - - public List getMemberField(Long memberId){ - Member member = memberJpaRepository.findById(memberId) - .orElseThrow(() -> new IllegalArgumentException("Member not found")); - return member.getField(); - } - - @Transactional - public List updateMemberField(Long id,MemberFieldDto memberFieldDto){ - Member member = memberJpaRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("Member not found")); - member.changeFieldInfo(memberFieldDto.getField()); - return member.getField(); - } - - @Transactional - public Long updateMemberInfo(Long id,MemberInfoChangeDto memberInfoChangeDto){ - Member member = memberJpaRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("Member not found")); - member.changeMemberInfo(memberInfoChangeDto.getPhoneNumber(), memberInfoChangeDto.getBirthDate(), memberInfoChangeDto.getMarketingAgree()); - return member.getId(); - } - - +public interface MemberService { + Member getById(Long memberId); + Member join(MemberJoinDto memberJoinDto); + MemberInfoResponse getMemberInfo(Long memberId); + List getMemberField(Long memberId); + Member updateMemberField(Long memberId, MemberFieldDto memberFieldDto); + Member updateMemberInfo(Long memberId, MemberInfoChangeDto memberInfoChangeDto); + Member changeMemberPassword(Long memberId, MemberPasswordChangeDto memberPasswordChangeDto); + Member myPagePasswordAuth(Long memberId, MyPagePasswordAuthDto myPagePasswordAuthDto); } diff --git a/src/main/java/umc/kkijuk/server/member/service/MemberServiceImpl.java b/src/main/java/umc/kkijuk/server/member/service/MemberServiceImpl.java new file mode 100644 index 00000000..ab336040 --- /dev/null +++ b/src/main/java/umc/kkijuk/server/member/service/MemberServiceImpl.java @@ -0,0 +1,118 @@ +package umc.kkijuk.server.member.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import umc.kkijuk.server.common.domian.exception.*; +import umc.kkijuk.server.member.controller.response.MemberInfoResponse; +import umc.kkijuk.server.member.domain.Member; +import umc.kkijuk.server.member.dto.*; +import umc.kkijuk.server.member.repository.MemberJpaRepository; + +import java.util.List; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class MemberServiceImpl implements MemberService { + private final MemberJpaRepository memberJpaRepository; + private final PasswordEncoder passwordEncoder; + + @Override + public Member getById(Long memberId) { + return memberJpaRepository.findById(memberId) + .orElseThrow(() -> new ResourceNotFoundException("Member", memberId)); + } + + @Override + @Transactional + public Member join(MemberJoinDto memberJoinDto) { + String passwordConfirm = memberJoinDto.getPasswordConfirm(); + if (!passwordConfirm.equals(memberJoinDto.getPassword())) { + throw new ConfirmPasswordMismatchException(); + } + + Member joinMember = memberJoinDto.toEntity(); + + String encodedPassword = passwordEncoder.encode(memberJoinDto.getPassword()); + joinMember.changeMemberPassword(encodedPassword); + + memberJpaRepository.save(joinMember); + return joinMember; + } + + @Override + public MemberInfoResponse getMemberInfo(Long memberId) { + Member member = this.getById(memberId); + if(member.getEmail() == null || member.getName() == null || member.getPhoneNumber() == null || member.getBirthDate() == null){ + throw new InvalidMemberDataException(); + } + return MemberInfoResponse.builder() + .email(member.getEmail()) + .name(member.getName()) + .phoneNumber(member.getPhoneNumber()) + .birthDate(member.getBirthDate()) + .build(); + } + + @Override + public List getMemberField(Long memberId){ + Member member = this.getById(memberId); + return member.getField(); + } + + @Override + @Transactional + public Member updateMemberField(Long memberId, MemberFieldDto memberFieldDto){ + Member member = this.getById(memberId); + member.changeFieldInfo(memberFieldDto.getField()); + if(!member.getField().equals(memberFieldDto.getField())){ + throw new FieldUpdateException(); + } + return member; + } + + @Override + @Transactional + public Member updateMemberInfo(Long memberId, MemberInfoChangeDto memberInfoChangeDto){ + Member member = this.getById(memberId); + member.changeMemberInfo(memberInfoChangeDto.getPhoneNumber(), memberInfoChangeDto.getBirthDate(), memberInfoChangeDto.getMarketingAgree()); + if(member.getPhoneNumber() == null || member.getBirthDate() == null || member.getMarketingAgree() == null){ + throw new InvalidMemberDataException(); + } + return member; + } + + @Override + @Transactional + public Member changeMemberPassword(Long memberId, MemberPasswordChangeDto memberPasswordChangeDto){ + Member member = this.getById(memberId); + if(!memberPasswordChangeDto.getNewPassword().equals(memberPasswordChangeDto.getNewPasswordConfirm())){ + throw new ConfirmPasswordMismatchException(); + } + if(!passwordEncoder.matches(memberPasswordChangeDto.getCurrentPassword(), member.getPassword())){ + throw new CurrentPasswordMismatchException(); + } + + + String encodedPassword = passwordEncoder.encode(memberPasswordChangeDto.getNewPassword()); + member.changeMemberPassword(encodedPassword); + + memberJpaRepository.save(member); + return member; + } + + @Override + @Transactional + public Member myPagePasswordAuth(Long memberId, MyPagePasswordAuthDto myPagePasswordAuthDto) { + Member member = this.getById(memberId); + + if(!passwordEncoder.matches(myPagePasswordAuthDto.getCurrentPassword(), member.getPassword())){ + throw new CurrentPasswordMismatchException(); + } + + return member; + } + +} diff --git a/src/test/java/umc/kkijuk/server/introduce/controller/IntroduceControllerTest.java b/src/test/java/umc/kkijuk/server/introduce/controller/IntroduceControllerTest.java index f96408c6..1ba8a74f 100644 --- a/src/test/java/umc/kkijuk/server/introduce/controller/IntroduceControllerTest.java +++ b/src/test/java/umc/kkijuk/server/introduce/controller/IntroduceControllerTest.java @@ -27,6 +27,7 @@ import umc.kkijuk.server.member.domain.MarketingAgree; import umc.kkijuk.server.member.domain.Member; import umc.kkijuk.server.member.domain.State; +import umc.kkijuk.server.member.dto.MemberJoinDto; import umc.kkijuk.server.member.service.MemberService; import umc.kkijuk.server.recruit.domain.Recruit; import umc.kkijuk.server.recruit.domain.RecruitStatus; @@ -76,9 +77,8 @@ class IntroduceControllerTest { @BeforeEach public void Init() { - Member member = new Member("asd@naver.com", "홍길동", "010-7444-1768", LocalDate.parse("1999-03-31"), "passwordTest", MarketingAgree.BOTH, State.ACTIVATE); - Long savedId = memberService.join(member); - requestMember = memberService.findOne(savedId); + MemberJoinDto memberJoinDto = new MemberJoinDto("asd@naver.com", "홍길동", "010-7444-1768", LocalDate.parse("1999-03-31"), "passwordTest", "passwordTest", MarketingAgree.BOTH, State.ACTIVATE); + requestMember = memberService.join(memberJoinDto); } @Test diff --git a/src/test/java/umc/kkijuk/server/member/service/MemberInfoTest.java b/src/test/java/umc/kkijuk/server/member/service/MemberInfoTest.java deleted file mode 100644 index 647af9bb..00000000 --- a/src/test/java/umc/kkijuk/server/member/service/MemberInfoTest.java +++ /dev/null @@ -1,144 +0,0 @@ -package umc.kkijuk.server.member.service; - -import org.junit.jupiter.api.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.test.annotation.DirtiesContext; -import umc.kkijuk.server.member.controller.response.MemberFieldResponse; -import umc.kkijuk.server.member.controller.response.MemberInfoResponse; -import umc.kkijuk.server.member.controller.response.ResultResponse; -import umc.kkijuk.server.member.domain.MarketingAgree; -import umc.kkijuk.server.member.domain.Member; -import umc.kkijuk.server.member.domain.State; -import umc.kkijuk.server.member.dto.MemberFieldDto; -import umc.kkijuk.server.member.dto.MemberInfoChangeDto; -import umc.kkijuk.server.member.repository.MemberJpaRepository; - -import java.time.LocalDate; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class MemberInfoTest { - - - @Autowired - private TestRestTemplate restTemplate; - - @Autowired - private MemberJpaRepository memberJpaRepository; - - @BeforeEach - public void setup() { - memberJpaRepository.deleteAll(); - } - - - - @Test - @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - public void 내정보_조회() { - // Given - Member member1 = new Member("asd@naver.com", "홍길동", "010-1234-5678", - LocalDate.parse("1999-03-31"), "passwordTest", MarketingAgree.BOTH, State.ACTIVATE); - memberJpaRepository.save(member1); - // When - ResponseEntity response = restTemplate.getForEntity("/member/myPage/info", MemberInfoResponse.class); - - // Then - assertEquals(HttpStatus.OK, response.getStatusCode()); - - MemberInfoResponse body = response.getBody(); - assertNotNull(body); - assertEquals("asd@naver.com", body.getEmail()); - assertEquals("홍길동", body.getName()); - assertEquals("010-1234-5678", body.getPhoneNumber()); - assertEquals(LocalDate.parse("1999-03-31"), body.getBirthDate()); - } - - @Test - @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - public void 내정보_수정() { - // Given - Member member1 = new Member("asd@naver.com", "홍길동", "010-1234-5678", - LocalDate.parse("1999-03-31"), "passwordTest", MarketingAgree.BOTH, State.ACTIVATE); - memberJpaRepository.save(member1); - - - MemberInfoChangeDto changeDto = MemberInfoChangeDto.builder() - .phoneNumber("010-5678-1234") - .birthDate(LocalDate.parse("2000-01-01")) - .marketingAgree(MarketingAgree.EMAIL) - .build(); - - HttpEntity requestEntity = new HttpEntity<>(changeDto); - - // When - ResponseEntity response = restTemplate.exchange("/member/myPage/info", HttpMethod.PUT, requestEntity, ResultResponse.class); - - // Then - assertEquals(HttpStatus.OK, response.getStatusCode()); - ResultResponse body = response.getBody(); - assertNotNull(body); - assertEquals("information update success", body.getMessage()); - - // Verify changes - Member updatedMember = memberJpaRepository.findById(member1.getId()).orElse(null); - assertNotNull(updatedMember); - assertEquals("010-5678-1234", updatedMember.getPhoneNumber()); - assertEquals(LocalDate.parse("2000-01-01"), updatedMember.getBirthDate()); - assertEquals(MarketingAgree.EMAIL, updatedMember.getMarketingAgree()); - } - - @Test - @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - public void 관심분야_조회(){ - // 회원추가 - Member member1 = new Member("asd@naver.com", "홍길동", "010-1234-5678", - LocalDate.parse("1999-03-31"), "passwordTest", MarketingAgree.BOTH, State.ACTIVATE); - member1.changeFieldInfo(List.of("game", "computer")); - memberJpaRepository.save(member1); - - ResponseEntity response = restTemplate.getForEntity("/member/myPage/field", MemberFieldResponse.class); - - assertEquals(HttpStatus.OK, response.getStatusCode()); - MemberFieldResponse body = response.getBody(); - assertNotNull(body); - assertEquals(List.of("game", "computer"), body.getField()); - } - - - @Test - @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - public void 관심분야_수정(){ - //given - //회원추가 - Member member1 = new Member("asd@naver.com", "홍길동", "010-1234-5678", - LocalDate.parse("1999-03-31"), "passwordTest", MarketingAgree.BOTH, State.ACTIVATE); - member1.changeFieldInfo(List.of("game", "computer")); - memberJpaRepository.save(member1); - - - MemberFieldDto memberFieldDto = MemberFieldDto.builder().field(List.of("book", "movie")).build(); - HttpEntity request = new HttpEntity<>(memberFieldDto); - //when - ResponseEntity response = restTemplate.postForEntity("/member/myPage/field", request, MemberFieldResponse.class); - //then - assertEquals(HttpStatus.OK, response.getStatusCode()); - MemberFieldResponse body = response.getBody(); - assertNotNull(body); - assertEquals(List.of("book", "movie"), body.getField()); - - Member updatedMember = memberJpaRepository.findById(1L).orElse(null); - assertNotNull(updatedMember); - assertEquals(List.of("book", "movie"), updatedMember.getField()); - } - -} diff --git a/src/test/java/umc/kkijuk/server/member/service/MemberServiceTest.java b/src/test/java/umc/kkijuk/server/member/service/MemberServiceTest.java index 44a54e1d..47cf567b 100644 --- a/src/test/java/umc/kkijuk/server/member/service/MemberServiceTest.java +++ b/src/test/java/umc/kkijuk/server/member/service/MemberServiceTest.java @@ -1,28 +1,35 @@ package umc.kkijuk.server.member.service; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.annotation.DirtiesContext; -import org.springframework.transaction.annotation.Transactional; +import umc.kkijuk.server.member.controller.response.MemberFieldResponse; +import umc.kkijuk.server.member.controller.response.MemberInfoResponse; +import umc.kkijuk.server.common.domian.exception.ConfirmPasswordMismatchException; import umc.kkijuk.server.member.domain.MarketingAgree; import umc.kkijuk.server.member.domain.Member; import umc.kkijuk.server.member.domain.State; +import umc.kkijuk.server.member.dto.MemberFieldDto; +import umc.kkijuk.server.member.dto.MemberInfoChangeDto; import umc.kkijuk.server.member.dto.MemberJoinDto; import umc.kkijuk.server.member.repository.MemberJpaRepository; import java.time.LocalDate; -import java.util.Optional; +import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@Transactional public class MemberServiceTest { @Autowired @@ -34,20 +41,45 @@ public class MemberServiceTest { @Autowired private TestRestTemplate restTemplate; + @BeforeEach + public void setUp() { + Member member = new Member("test@naver.com", "홍길동", + "01012345678", LocalDate.parse("1999-03-31"), + "testpassword", MarketingAgree.BOTH, State.ACTIVATE); + member.changeFieldInfo(List.of("game", "computer")); + memberJpaRepository.save(member); + } + + private String testMemberEmail = "asd@naver.com"; @Test @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) public void 유저정보db저장및조회() throws Exception { // given - Member member1 = new Member("asd@naver.com", "홍길동", "010-7444-1768", LocalDate.parse("1999-03-31"), "passwordTest", MarketingAgree.BOTH, State.ACTIVATE); + MemberJoinDto memberJoinDto = new MemberJoinDto(testMemberEmail, "홍길동", "010-7444-1768", LocalDate.parse("1999-03-31"), "passwordTest", "passwordTest", MarketingAgree.BOTH, State.ACTIVATE); // when - Long savedId = memberService.join(member1); - Optional member2 = memberJpaRepository.findById(savedId); + Member joinMember = memberService.join(memberJoinDto); // then - assertEquals(member1, member2.get()); + assertAll( + () -> assertEquals(joinMember.getEmail(), testMemberEmail), + () -> assertEquals(joinMember.getName(), "홍길동") + ); } + @Test + @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) + public void joinExceptionWIthPasswordIncorrect() { + // given + MemberJoinDto memberJoinDto = new MemberJoinDto(testMemberEmail, "홍길동", "010-7444-1768", LocalDate.parse("1999-03-31"), "passwordTest", "incorrectPassword", MarketingAgree.BOTH, State.ACTIVATE); + + // when + // then + assertThatThrownBy(() -> memberService.join(memberJoinDto)) + .isInstanceOf(ConfirmPasswordMismatchException.class); + } + + @Test @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) public void 회원가입성공() { @@ -73,30 +105,111 @@ public class MemberServiceTest { assertThat(response.getBody()).contains("Member created successfully"); } +// @Test +// @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) +// public void 회원가입실패_비밀번호불일치() { +// // given +// MemberJoinDto memberJoinDto = MemberJoinDto.builder() +// .email("asd@naver.com") +// .name("홍길동") +// .phoneNumber("010-7444-1768") +// .birthDate(LocalDate.parse("1999-03-31")) +// .password("passwordTest") +// .passwordConfirm("wrongPassword") +// .marketingAgree(MarketingAgree.BOTH) +// .userState(State.ACTIVATE) +// .build(); +// +// HttpEntity request = new HttpEntity<>(memberJoinDto); +// +// // when +// ResponseEntity response = restTemplate.postForEntity("/member", request, String.class); +// +// // then +// assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); +// assertThat(response.getBody()).contains("비밀번호가 일치하지 않습니다."); +// } + @Test @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) - public void 회원가입실패_비밀번호불일치() { - // given - MemberJoinDto memberJoinDto = MemberJoinDto.builder() - .email("asd@naver.com") - .name("홍길동") - .phoneNumber("010-7444-1768") - .birthDate(LocalDate.parse("1999-03-31")) - .password("passwordTest") - .passwordConfirm("wrongPassword") - .marketingAgree(MarketingAgree.BOTH) - .userState(State.ACTIVATE) + public void 내정보_조회_성공() { + // Given + + // When + ResponseEntity response = restTemplate.getForEntity("/member/myPage/info", MemberInfoResponse.class); + + // Then + assertEquals(HttpStatus.OK, response.getStatusCode()); + + MemberInfoResponse body = response.getBody(); + assertNotNull(body); + assertEquals("test@naver.com", body.getEmail()); + assertEquals("홍길동", body.getName()); + assertEquals("01012345678", body.getPhoneNumber()); + assertEquals(LocalDate.parse("1999-03-31"), body.getBirthDate()); + } + + @Test + @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) + public void 내정보_수정() { + // Given + + MemberInfoChangeDto changeDto = MemberInfoChangeDto.builder() + .phoneNumber("010-5678-1234") + .birthDate(LocalDate.parse("2000-01-01")) + .marketingAgree(MarketingAgree.EMAIL) .build(); - HttpEntity request = new HttpEntity<>(memberJoinDto); + HttpEntity requestEntity = new HttpEntity<>(changeDto); - // when - ResponseEntity response = restTemplate.postForEntity("/member", request, String.class); + // When + ResponseEntity response = restTemplate.exchange("/member/myPage/info", HttpMethod.PUT, requestEntity, Boolean.class); - // then - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); - assertThat(response.getBody()).contains("Passwords do not match"); + // Then + assertEquals(HttpStatus.OK, response.getStatusCode()); + Boolean body = response.getBody(); + assertNotNull(body); + assertEquals(true, body); + + // Verify changes + Member updatedMember = memberJpaRepository.findById(1L).orElse(null); + assertNotNull(updatedMember); + assertEquals("010-5678-1234", updatedMember.getPhoneNumber()); + assertEquals(LocalDate.parse("2000-01-01"), updatedMember.getBirthDate()); + assertEquals(MarketingAgree.EMAIL, updatedMember.getMarketingAgree()); + } + + @Test + @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) + public void 관심분야_조회(){ + // 회원추가 + + ResponseEntity response = restTemplate.getForEntity("/member/myPage/field", MemberFieldResponse.class); + + assertEquals(HttpStatus.OK, response.getStatusCode()); + MemberFieldResponse body = response.getBody(); + assertNotNull(body); + assertEquals(List.of("game", "computer"), body.getField()); } + @Test + @DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD) + public void 관심분야_수정(){ + //given + + MemberFieldDto memberFieldDto = MemberFieldDto.builder().field(List.of("book", "movie")).build(); + HttpEntity request = new HttpEntity<>(memberFieldDto); + //when + ResponseEntity response = restTemplate.postForEntity("/member/myPage/field", request, Boolean.class); + //then + assertEquals(HttpStatus.OK, response.getStatusCode()); + Boolean body = response.getBody(); + assertNotNull(body); + assertEquals(true, body); + + Member updatedMember = memberJpaRepository.findById(1L).orElse(null); + assertNotNull(updatedMember); + assertEquals(List.of("book", "movie"), updatedMember.getField()); + } }