diff --git a/src/main/java/com/retrip/auth/application/in/MemberService.java b/src/main/java/com/retrip/auth/application/in/MemberService.java index 75ce6b7..515484f 100644 --- a/src/main/java/com/retrip/auth/application/in/MemberService.java +++ b/src/main/java/com/retrip/auth/application/in/MemberService.java @@ -1,12 +1,19 @@ package com.retrip.auth.application.in; import com.retrip.auth.application.in.request.MemberCreateRequest; +import com.retrip.auth.application.in.request.MemberUpdateRequest; import com.retrip.auth.application.in.response.MemberCreateResponse; +import com.retrip.auth.application.in.response.MemberUpdateResponse; import com.retrip.auth.application.in.usercase.ManageMemberUseCase; import com.retrip.auth.application.out.repository.MemberRepository; import com.retrip.auth.domain.entity.Member; +import com.retrip.auth.domain.exception.MemberNotFoundException; +import com.retrip.auth.domain.exception.common.EntityNotFoundException; +import com.retrip.auth.domain.vo.MemberEmail; +import com.sun.jdi.request.DuplicateRequestException; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @@ -21,7 +28,37 @@ public class MemberService implements ManageMemberUseCase { @Override public MemberCreateResponse createUser(MemberCreateRequest request) { String encode = passwordEncoder.encode(request.password()); + boolean isDuplicate = !memberRepository.findByEmail(new MemberEmail(request.email())).isEmpty(); + if (isDuplicate) { + throw new DuplicateRequestException("Email already exists"); + } Member member = memberRepository.save(request.to(encode)); return MemberCreateResponse.of(member); } + + @Override + public MemberUpdateResponse updateUser(MemberUpdateRequest request) { + String encodePassword = passwordEncoder.encode(request.password()); + String encodeNewPassword = passwordEncoder.encode(request.newPassword()); + + Member member = findByEmail(request.email()); + if(isUpdatable(member.getPassword().getValue(), encodePassword)) { //여기에 패스워드 검증 로직이 들어가는게 맞는지..? + member.update(encodeNewPassword, request.name()); + } + return MemberUpdateResponse.of(member); + } + + private Member findByEmail(String email) { + return memberRepository.findByEmail(new MemberEmail(email)) + .stream().findAny().orElseThrow(MemberNotFoundException::new); + } + + private boolean isUpdatable(String password, String inputPassword) { + if (!passwordEncoder.matches(password, inputPassword)) { + throw new BadCredentialsException("Bad credentials"); + } + return true; + } + + } diff --git a/src/main/java/com/retrip/auth/application/in/request/MemberUpdateRequest.java b/src/main/java/com/retrip/auth/application/in/request/MemberUpdateRequest.java new file mode 100644 index 0000000..89db2ca --- /dev/null +++ b/src/main/java/com/retrip/auth/application/in/request/MemberUpdateRequest.java @@ -0,0 +1,17 @@ +package com.retrip.auth.application.in.request; + +import com.retrip.auth.domain.entity.Member; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "Member 회원가입 Request") +public record MemberUpdateRequest( + @Schema(description = "이메일") + String email, + @Schema(description = "기존 비밀번호") + String password, + @Schema(description = "새로운 비밀번호") + String newPassword, + @Schema(description = "사용자 이름") + String name +) { +} diff --git a/src/main/java/com/retrip/auth/application/in/response/MemberUpdateResponse.java b/src/main/java/com/retrip/auth/application/in/response/MemberUpdateResponse.java new file mode 100644 index 0000000..133c413 --- /dev/null +++ b/src/main/java/com/retrip/auth/application/in/response/MemberUpdateResponse.java @@ -0,0 +1,15 @@ +package com.retrip.auth.application.in.response; + +import com.retrip.auth.domain.entity.Member; + +import java.util.UUID; + +public record MemberUpdateResponse( + UUID id, + String email, + String name +) { + public static MemberUpdateResponse of(Member member) { + return new MemberUpdateResponse(member.getId(), member.getEmail().getValue(), member.getName().getValue()); + } +} diff --git a/src/main/java/com/retrip/auth/application/in/usercase/ManageMemberUseCase.java b/src/main/java/com/retrip/auth/application/in/usercase/ManageMemberUseCase.java index bf3790a..4364f47 100644 --- a/src/main/java/com/retrip/auth/application/in/usercase/ManageMemberUseCase.java +++ b/src/main/java/com/retrip/auth/application/in/usercase/ManageMemberUseCase.java @@ -2,8 +2,12 @@ import com.retrip.auth.application.in.request.MemberCreateRequest; +import com.retrip.auth.application.in.request.MemberUpdateRequest; import com.retrip.auth.application.in.response.MemberCreateResponse; +import com.retrip.auth.application.in.response.MemberUpdateResponse; public interface ManageMemberUseCase { MemberCreateResponse createUser(MemberCreateRequest request); + + MemberUpdateResponse updateUser(MemberUpdateRequest request); } diff --git a/src/main/java/com/retrip/auth/application/out/repository/MemberRepository.java b/src/main/java/com/retrip/auth/application/out/repository/MemberRepository.java index c5ff13b..e064f5a 100644 --- a/src/main/java/com/retrip/auth/application/out/repository/MemberRepository.java +++ b/src/main/java/com/retrip/auth/application/out/repository/MemberRepository.java @@ -2,9 +2,13 @@ import com.retrip.auth.domain.entity.Member; +import com.retrip.auth.domain.vo.MemberEmail; + +import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; public interface MemberRepository extends JpaRepository { + List findByEmail(MemberEmail email); } diff --git a/src/main/java/com/retrip/auth/domain/entity/Member.java b/src/main/java/com/retrip/auth/domain/entity/Member.java index aca4b04..5a4fdb8 100644 --- a/src/main/java/com/retrip/auth/domain/entity/Member.java +++ b/src/main/java/com/retrip/auth/domain/entity/Member.java @@ -57,4 +57,9 @@ public static Member create(String name, String email, String password) { member.authorities = new Authorities(List.of("user"), member); return member; } + + public void update(String password, String name) { + this.password = new MemberPassword(password); + this.name = new MemberName(name); + } } diff --git a/src/main/java/com/retrip/auth/infra/adapter/in/rest/in/MemberController.java b/src/main/java/com/retrip/auth/infra/adapter/in/rest/in/MemberController.java index fdf1e8a..d0a88b4 100644 --- a/src/main/java/com/retrip/auth/infra/adapter/in/rest/in/MemberController.java +++ b/src/main/java/com/retrip/auth/infra/adapter/in/rest/in/MemberController.java @@ -1,15 +1,14 @@ package com.retrip.auth.infra.adapter.in.rest.in; import com.retrip.auth.application.in.request.MemberCreateRequest; +import com.retrip.auth.application.in.request.MemberUpdateRequest; import com.retrip.auth.application.in.response.MemberCreateResponse; +import com.retrip.auth.application.in.response.MemberUpdateResponse; import com.retrip.auth.application.in.usercase.ManageMemberUseCase; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -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.web.bind.annotation.*; @RestController @RequestMapping("/users") @@ -26,4 +25,12 @@ public MemberCreateResponse createUser( ){ return manageMemberUseCase.createUser(request); } + + @PutMapping + @Schema(description = "회원 정보 수정") + public MemberUpdateResponse updateUser( + @RequestBody MemberUpdateRequest request + ){ + return manageMemberUseCase.updateUser(request); + } } diff --git a/src/test/java/com/retrip/auth/application/in/MemberServiceTest.java b/src/test/java/com/retrip/auth/application/in/MemberServiceTest.java index 46d17ce..72d8957 100644 --- a/src/test/java/com/retrip/auth/application/in/MemberServiceTest.java +++ b/src/test/java/com/retrip/auth/application/in/MemberServiceTest.java @@ -1,19 +1,21 @@ package com.retrip.auth.application.in; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import com.retrip.auth.application.in.factory.BaseMemberServiceTest; import com.retrip.auth.application.in.request.MemberCreateRequest; +import com.retrip.auth.application.in.request.MemberUpdateRequest; import com.retrip.auth.application.in.response.MemberCreateResponse; +import com.retrip.auth.application.in.response.MemberUpdateResponse; +import com.retrip.auth.domain.entity.Member; +import com.retrip.auth.domain.exception.MemberNotFoundException; +import com.sun.jdi.request.DuplicateRequestException; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.authentication.BadCredentialsException; -@SpringBootTest -class MemberServiceTest { - - @Autowired - private MemberService memberService; +class MemberServiceTest extends BaseMemberServiceTest { @Test void 회원가입_성공() throws Exception { @@ -29,4 +31,64 @@ class MemberServiceTest { assertThat(response.email()).isEqualTo("test@naver.com"); } + @Test + void 회원가입_중복_회원가입() throws Exception { + // given + memberRepository.save(Member.create("test", "test@naver.com", "1234")); + MemberCreateRequest request = new MemberCreateRequest("test@naver.com", "1111", "중복 테스트"); + + //when + + //then + assertThatThrownBy(() -> memberService.createUser(request)) + .isInstanceOf(DuplicateRequestException.class) + .hasMessageContaining("Email already exists"); + } + + + @Test + void 회원정보_수정_패스워드_달라_실패() throws Exception { + // given + memberRepository.save(Member.create("test", "test@naver.com", "1234")); + MemberUpdateRequest request = new MemberUpdateRequest("test@naver.com", "1235", "1111", + "수정 테스트"); + + //when + + //then + assertThatThrownBy(() -> memberService.updateUser(request)) + .isInstanceOf(BadCredentialsException.class) + .hasMessageContaining("Bad credentials"); + } + + @Test + void 저장된_회원_정보가_없어서_실패() throws Exception { + // given + MemberUpdateRequest request = new MemberUpdateRequest("test@naver.com", "1234", "1111", + "수정 테스트"); + + //when + + //then + assertThatThrownBy(() -> memberService.updateUser(request)) + .isInstanceOf(MemberNotFoundException.class) + .hasMessageContaining("멤버 엔티티를 찾을 수 없습니다."); + } + + @Test + void 회원정보_수정_성공() throws Exception { + // given + memberRepository.save(Member.create("test", "test@naver.com", "1234")); + MemberUpdateRequest request = new MemberUpdateRequest("test@naver.com", "1234", "1111", + "수정 테스트"); + + //when + MemberUpdateResponse response = memberService.updateUser(request); + + //then + assertThat(response.id()).isNotNull(); + assertThat(response.name()).isEqualTo("수정 테스트"); + assertThat(response.email()).isEqualTo("test@naver.com"); + } + } diff --git a/src/test/java/com/retrip/auth/application/in/factory/BaseMemberServiceTest.java b/src/test/java/com/retrip/auth/application/in/factory/BaseMemberServiceTest.java index ffdd347..07f7ea0 100644 --- a/src/test/java/com/retrip/auth/application/in/factory/BaseMemberServiceTest.java +++ b/src/test/java/com/retrip/auth/application/in/factory/BaseMemberServiceTest.java @@ -1,16 +1,20 @@ package com.retrip.auth.application.in.factory; import com.retrip.auth.application.in.MemberService; +import com.retrip.auth.application.out.repository.MemberRepository; +import jakarta.transaction.Transactional; import org.junit.jupiter.api.BeforeEach; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest +@Transactional public class BaseMemberServiceTest { @Autowired protected MemberService memberService; - + @Autowired + protected MemberRepository memberRepository; @BeforeEach void setUp() {