From 0951354bbcdebea53fed1f4abf86594ae14026c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=9D=80=EC=B1=84?= Date: Wed, 31 Jan 2024 19:28:22 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=9C=A0=EC=A0=80=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95=20=EB=B6=88=EA=B0=80=20+=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 5 +- .../user/dto/UpdateUserProfileRequestDTO.java | 2 + .../HHive/hhive/domain/user/entity/User.java | 2 + .../domain/user/service/UserService.java | 21 ++++--- .../global/exception/common/ErrorCode.java | 1 + .../KakaoUserEmailModificationException.java | 11 ++++ .../com/HHive/hhive/global/jwt/JwtUtil.java | 51 ---------------- .../hhive/domain/user/entity/UserTest.java | 18 ++++-- .../domain/user/service/UserServiceTest.java | 61 +++++++++++++++++++ 9 files changed, 105 insertions(+), 67 deletions(-) create mode 100644 src/main/java/com/HHive/hhive/global/exception/user/KakaoUserEmailModificationException.java create mode 100644 src/test/java/com/HHive/hhive/domain/user/service/UserServiceTest.java diff --git a/build.gradle b/build.gradle index 62e6355..46784a4 100644 --- a/build.gradle +++ b/build.gradle @@ -48,8 +48,9 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' //DB - runtimeOnly 'com.h2database:h2' - runtimeOnly 'com.mysql:mysql-connector-j' + implementation 'com.h2database:h2' + testImplementation 'com.h2database:h2' + implementation 'com.mysql:mysql-connector-j' testImplementation 'org.springframework.boot:spring-boot-starter-test' } diff --git a/src/main/java/com/HHive/hhive/domain/user/dto/UpdateUserProfileRequestDTO.java b/src/main/java/com/HHive/hhive/domain/user/dto/UpdateUserProfileRequestDTO.java index 0fdce24..4df8a6f 100644 --- a/src/main/java/com/HHive/hhive/domain/user/dto/UpdateUserProfileRequestDTO.java +++ b/src/main/java/com/HHive/hhive/domain/user/dto/UpdateUserProfileRequestDTO.java @@ -1,9 +1,11 @@ package com.HHive.hhive.domain.user.dto; import jakarta.validation.constraints.Pattern; +import lombok.AllArgsConstructor; import lombok.Getter; @Getter +@AllArgsConstructor public class UpdateUserProfileRequestDTO { @Pattern(regexp = "^[a-zA-Z0-9]+@[a-zA-Z0-9]+(\\.[a-zA-Z]{2,})+$", diff --git a/src/main/java/com/HHive/hhive/domain/user/entity/User.java b/src/main/java/com/HHive/hhive/domain/user/entity/User.java index c0ff4e9..3f8a2ce 100644 --- a/src/main/java/com/HHive/hhive/domain/user/entity/User.java +++ b/src/main/java/com/HHive/hhive/domain/user/entity/User.java @@ -8,10 +8,12 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.time.LocalDateTime; @Entity +@Setter @Getter @Table(name = "\"USER\"") @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/src/main/java/com/HHive/hhive/domain/user/service/UserService.java b/src/main/java/com/HHive/hhive/domain/user/service/UserService.java index ef7ffa8..0747ddd 100644 --- a/src/main/java/com/HHive/hhive/domain/user/service/UserService.java +++ b/src/main/java/com/HHive/hhive/domain/user/service/UserService.java @@ -96,24 +96,29 @@ public UserInfoResponseDTO getProfile(Long userId) { } @Transactional - public void updateProfile(Long user_id, UpdateUserProfileRequestDTO requestDTO, User loginUser) { + public void updateProfile(Long userId, UpdateUserProfileRequestDTO requestDTO, User loginUser) { - User user = getUser(user_id); + User user = getUser(userId); if (!loginUser.getId().equals(user.getId())) { throw new AuthenticationMismatchException(); } + // 카카오 로그인한 유저인 경우 이메일 수정을 허용하지 않음 + if (userRepository.findByKakaoId(user.getKakaoId()).isPresent() && requestDTO.getEmail() != null) { + throw new KakaoUserEmailModificationException(); + } + user.updateProfile(requestDTO); } @Transactional - public void updatePassword(Long user_id, UpdateUserPasswordRequestDTO requestDTO, User loginUser) { + public void updatePassword(Long userId, UpdateUserPasswordRequestDTO requestDTO, User loginUser) { String password = requestDTO.getPassword(); String updatePassword = requestDTO.getUpdatePassword(); String checkUpdatePassword = requestDTO.getCheckUpdatePassword(); - User user = getUser(user_id); + User user = getUser(userId); if (!loginUser.getUsername().equals(user.getUsername())) { throw new AuthenticationMismatchException(); @@ -156,8 +161,8 @@ public void processPendingDeletions() { userRepository.deleteAll(userToDelete); } - public User getUser(Long user_id) { - return userRepository.findById(user_id).orElseThrow(UserNotFoundException::new); + public User getUser(Long userId) { + return userRepository.findById(userId).orElseThrow(UserNotFoundException::new); } public User findUserByEmail(String email) { @@ -170,8 +175,8 @@ public User findUserByUsername(String username) { .orElseThrow(UserNotFoundException::new); } - public List getMyHives(Long user_Id) { - User user = getUser(user_Id); + public List getMyHives(Long userId) { + User user = getUser(userId); List myHives = hiveUserService.findAllHivesByHiveUser(user); return myHives.stream().map(HiveResponseDTO::of).toList(); diff --git a/src/main/java/com/HHive/hhive/global/exception/common/ErrorCode.java b/src/main/java/com/HHive/hhive/global/exception/common/ErrorCode.java index cc32ee3..1ff2fd8 100644 --- a/src/main/java/com/HHive/hhive/global/exception/common/ErrorCode.java +++ b/src/main/java/com/HHive/hhive/global/exception/common/ErrorCode.java @@ -20,6 +20,7 @@ public enum ErrorCode { PASSWORD_CONFIRMATION_EXCEPTION(401, "비밀번호와 비밀번호 확인이 일치하지 않습니다."), NOT_FOUND_USER_EXCEPTION(400, "해당 유저가 존재하지 않습니다"), INVALID_EMAIL_VERIFICATION_CODE_EXCEPTION(400, "입력하신 이메일 인증 코드가 유효하지 않습니다"), + KAKAO_USER_EMAIL_MODIFICATION_EXCEPTION(400, "카카오 로그인한 유저는 이메일을 수정할 수 없습니다."), //Hive ALREADY_EXIST_HIVE_EXCEPTION(401, "중복된 타이틀입니다."), diff --git a/src/main/java/com/HHive/hhive/global/exception/user/KakaoUserEmailModificationException.java b/src/main/java/com/HHive/hhive/global/exception/user/KakaoUserEmailModificationException.java new file mode 100644 index 0000000..7365c44 --- /dev/null +++ b/src/main/java/com/HHive/hhive/global/exception/user/KakaoUserEmailModificationException.java @@ -0,0 +1,11 @@ +package com.HHive.hhive.global.exception.user; + +import com.HHive.hhive.global.exception.common.CustomException; +import com.HHive.hhive.global.exception.common.ErrorCode; + +public class KakaoUserEmailModificationException extends CustomException { + + public KakaoUserEmailModificationException() { + super(ErrorCode.KAKAO_USER_EMAIL_MODIFICATION_EXCEPTION); + } +} diff --git a/src/main/java/com/HHive/hhive/global/jwt/JwtUtil.java b/src/main/java/com/HHive/hhive/global/jwt/JwtUtil.java index 7765764..1bb1303 100644 --- a/src/main/java/com/HHive/hhive/global/jwt/JwtUtil.java +++ b/src/main/java/com/HHive/hhive/global/jwt/JwtUtil.java @@ -59,22 +59,6 @@ public void init() { public String resolveToken(HttpServletRequest request) { -// Cookie[] cookies = request.getCookies(); -// -// if (cookies == null) { -// return null; -// } -// -// String bearerToken = Arrays.stream(cookies) -// .filter(cookie -> cookie.getName().equals(JWT_COOKIE_NAME)) -// .findFirst() -// .map(Cookie::getValue) -// .orElse(null); -// -// if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(BEARER_PREFIX)) { -// return bearerToken.substring(7); -// } - String bearerToken = request.getHeader(AUTHORIZATION_HEADER); if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(BEARER_PREFIX)) { return bearerToken.substring(7); @@ -102,41 +86,6 @@ public Claims getUserInfoFromToken(String token) { return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody(); } -// public Cookie createTokenCookie(String username) { -// -// long EXPIRED_TIME = 60 * 60; -// -// String jwtToken = createToken(username); -// -// Cookie cookie = new Cookie(JWT_COOKIE_NAME, jwtToken); -// cookie.setPath("/api"); -// cookie.setMaxAge((int) EXPIRED_TIME); -// cookie.setHttpOnly(true); -// -// return cookie; -// } -// -// public Cookie createUserInfoCookie(UserInfoResponseDTO responseDTO) { -// -// long EXPIRED_TIME = 60 * 60; -// -// String responseToString = null; -// -// try { -// responseToString = objectMapper.writeValueAsString(responseDTO); -// } catch (JsonProcessingException e) { -// throw new RuntimeException(e); -// } -// -// String encodedUserInfo = Base64.getEncoder().encodeToString(responseToString.getBytes()); -// -// Cookie cookie = new Cookie(USER_INFO_COOKIE_NAME, encodedUserInfo); -// cookie.setPath("/"); -// cookie.setMaxAge((int) EXPIRED_TIME); -// -// return cookie; -// } - public String createToken(String username) { Date date = new Date(); diff --git a/src/test/java/com/HHive/hhive/domain/user/entity/UserTest.java b/src/test/java/com/HHive/hhive/domain/user/entity/UserTest.java index 4cf61be..f1a107f 100644 --- a/src/test/java/com/HHive/hhive/domain/user/entity/UserTest.java +++ b/src/test/java/com/HHive/hhive/domain/user/entity/UserTest.java @@ -32,8 +32,10 @@ void kakaoIdUpdate() { @DisplayName("프로필 업데이트") void updateProfile() { // given - User user = new User("testUser", "testPassword", "testEmail@email.com", "testDescription"); - UpdateUserProfileRequestDTO requestDTO = new UpdateUserProfileRequestDTO(); + User user = new User( + "testUser", "testPassword", "testEmail@email.com", "testDescription"); + UpdateUserProfileRequestDTO requestDTO = new UpdateUserProfileRequestDTO( + "updateEmail@email.com", "updateDescription"); // when user.updateProfile(requestDTO); @@ -47,7 +49,8 @@ void updateProfile() { @DisplayName("계정 삭제 업데이트") void updateDeletedAt() { // given - User user = new User("testUser", "testPassword", "testEmail@email.com", "testDescription"); + User user = new User( + "testUser", "testPassword", "testEmail@email.com", "testDescription"); assertFalse(user.is_deleted()); // when @@ -67,7 +70,8 @@ class SetUserInfoTest { @DisplayName("비밀번호 설정") void setPassword() { // given - User user = new User("testUser", "testPassword", "testEmail@email.com", "testDescription"); + User user = new User( + "testUser", "testPassword", "testEmail@email.com", "testDescription"); String newPassword = "newPassword"; // when @@ -81,7 +85,8 @@ void setPassword() { @DisplayName("major 카테고리 설정") void setMajorCategory() { // given - User user = new User("testUser", "testPassword", "testEmail@email.com", "testDescription"); + User user = new User( + "testUser", "testPassword", "testEmail@email.com", "testDescription"); MajorCategory majorCategory = MajorCategory.GAME; // when @@ -95,7 +100,8 @@ void setMajorCategory() { @DisplayName("sub 카테고리 설정") void setSubCategory() { // given - User user = new User("testUser", "testPassword", "testEmail@email.com", "testDescription"); + User user = new User( + "testUser", "testPassword", "testEmail@email.com", "testDescription"); SubCategory subCategory = SubCategory.LOL; // when diff --git a/src/test/java/com/HHive/hhive/domain/user/service/UserServiceTest.java b/src/test/java/com/HHive/hhive/domain/user/service/UserServiceTest.java new file mode 100644 index 0000000..ab56acb --- /dev/null +++ b/src/test/java/com/HHive/hhive/domain/user/service/UserServiceTest.java @@ -0,0 +1,61 @@ +package com.HHive.hhive.domain.user.service; + +import com.HHive.hhive.domain.user.dto.UpdateUserProfileRequestDTO; +import com.HHive.hhive.domain.user.entity.User; +import com.HHive.hhive.domain.user.repository.UserRepository; +import com.HHive.hhive.global.exception.user.KakaoUserEmailModificationException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +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.mock.mockito.MockBean; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.when; + +@SpringBootTest +class UserServiceTest { + + @Autowired + private UserService userService; + + @MockBean + private UserRepository userRepository; + + @Nested + @DisplayName("프로필 수정") + class updateProfileTest { + + @Test + @DisplayName("카카오 로그인 유저의 이메일 수정") + void updateProfileByKakaoUserFailsWhenEmailIsChanged() { + + // given + // 카카오 로그인한 사용자를 생성 + User kakaoUser = new User("username", "password", "email@example.com", "description"); + kakaoUser.kakaoIdUpdate(12345L); // 카카오 로그인한 사용자라고 가정하기 위해 카카오 ID를 설정 + kakaoUser.setId(1L); // 사용자 ID 설정 + + // 이메일을 변경하는 요청을 생성 + UpdateUserProfileRequestDTO requestDTO = new UpdateUserProfileRequestDTO("newemail@example.com", "new description"); + + // userRepository에서 동일한 Id와 카카오 Id를 가진 사용자를 반환하도록 설정 + when(userRepository.findById(1L)).thenReturn(Optional.of(kakaoUser)); // findById() 메서드를 가장 + when(userRepository.findByKakaoId(kakaoUser.getKakaoId())).thenReturn(Optional.of(kakaoUser)); // findByKakaoId() 메서드를 가장 + + // 로그인한 사용자를 생성 + User loginUser = new User("username", "password", "email@example.com", "description"); + loginUser.kakaoIdUpdate(12345L); // 카카오 로그인한 사용자라고 가정하기 위해 카카오 ID를 설정 + loginUser.setId(1L); // 사용자 ID 설정 + + // then + // 이메일 수정을 시도하면 KakaoUserEmailModificationException 예외가 발생해야 함 + assertThrows(KakaoUserEmailModificationException.class, () -> { + userService.updateProfile(1L, requestDTO, loginUser); // 가장된 ID 사용 + }); + } + } +}