Skip to content

Commit

Permalink
feat: #64 마이페이지-사용자 프로필 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
dldmsql committed Nov 25, 2023
1 parent 010728e commit 63b3cb4
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 3 deletions.
22 changes: 22 additions & 0 deletions src/main/java/everymeal/server/user/controller/UserController.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import everymeal.server.user.controller.dto.request.UserEmailAuthReq;
import everymeal.server.user.controller.dto.request.UserEmailLoginReq;
import everymeal.server.user.controller.dto.request.UserEmailSingReq;
import everymeal.server.user.controller.dto.request.UserProfileUpdateReq;
import everymeal.server.user.controller.dto.response.UserEmailAuthRes;
import everymeal.server.user.controller.dto.response.UserLoginRes;
import everymeal.server.user.controller.dto.response.UserProfileRes;
Expand All @@ -26,6 +27,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
Expand Down Expand Up @@ -145,6 +147,26 @@ public ApplicationResponse<UserProfileRes> getUserProfile(
return ApplicationResponse.ok(userService.getUserProfile(authenticatedUser));
}

@Auth(require = true)
@PutMapping("/profile")
@SecurityRequirement(name = "jwt-user-auth")
@Operation(summary = "인증된 사용자의 프로필 정보 수정", description = "인증된 사용자의 프로필 정보를 수정합니다.")
@ApiResponses({
@ApiResponse(
responseCode = "409",
description =
"""
(U0005)이미 등록된 닉네임입니다.<br>
""",
content = @Content(schema = @Schema())),
})
public ApplicationResponse<Boolean> updateUserProfile(
@Parameter(hidden = true) @AuthUser AuthenticatedUser authenticatedUser,
@RequestBody UserProfileUpdateReq userProfileUpdateReq) {
return ApplicationResponse.ok(
userService.updateUserProfile(authenticatedUser, userProfileUpdateReq));
}

private ResponseEntity<ApplicationResponse<UserLoginRes>> setRefreshToken(
UserLoginRes response) {
ResponseCookie cookie =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package everymeal.server.user.controller.dto.request;


import io.swagger.v3.oas.annotations.media.Schema;

public record UserProfileUpdateReq(
@Schema(description = "닉네임", example = "연유크림") String nickName,
@Schema(description = "프로필 이미지 key", example = "user/bc90af33-bc6a-4009-bfc8-2c3efe0b16bd")
String profileImageKey) {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

public record UserProfileRes(
Long userId, String nickName, String profileImgUrl, String universityName) {
public static UserProfileRes of(Map<String, Object> user) {
public static UserProfileRes of(Map<String, Object> user, String profileImgUrl) {
return new UserProfileRes(
(Long) user.get("userId"),
(String) user.get("nickName"),
(String) user.get("profileImgUrl"),
profileImgUrl,
(String) user.get("universityName"));
}
}
5 changes: 5 additions & 0 deletions src/main/java/everymeal/server/user/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,9 @@ public User(String nickname, String email, String profileImgUrl, University univ
public void setEmail(String email) {
this.email = email;
}

public void updateProfile(String nickname, String profileImgUrl) {
this.nickname = nickname;
this.profileImgUrl = profileImgUrl;
}
}
4 changes: 4 additions & 0 deletions src/main/java/everymeal/server/user/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import everymeal.server.user.controller.dto.request.UserEmailAuthReq;
import everymeal.server.user.controller.dto.request.UserEmailLoginReq;
import everymeal.server.user.controller.dto.request.UserEmailSingReq;
import everymeal.server.user.controller.dto.request.UserProfileUpdateReq;
import everymeal.server.user.controller.dto.response.UserEmailAuthRes;
import everymeal.server.user.controller.dto.response.UserLoginRes;
import everymeal.server.user.controller.dto.response.UserProfileRes;
Expand All @@ -22,4 +23,7 @@ public interface UserService {
Boolean checkUser(String email);

UserProfileRes getUserProfile(AuthenticatedUser authenticatedUser);

Boolean updateUserProfile(
AuthenticatedUser authenticatedUser, UserProfileUpdateReq userProfileUpdateReq);
}
22 changes: 21 additions & 1 deletion src/main/java/everymeal/server/user/service/UserServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import everymeal.server.user.controller.dto.request.UserEmailAuthReq;
import everymeal.server.user.controller.dto.request.UserEmailLoginReq;
import everymeal.server.user.controller.dto.request.UserEmailSingReq;
import everymeal.server.user.controller.dto.request.UserProfileUpdateReq;
import everymeal.server.user.controller.dto.response.UserEmailAuthRes;
import everymeal.server.user.controller.dto.response.UserLoginRes;
import everymeal.server.user.controller.dto.response.UserProfileRes;
Expand All @@ -21,6 +22,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -153,6 +155,24 @@ public Boolean checkUser(String email) {
@Override
public UserProfileRes getUserProfile(AuthenticatedUser authenticatedUser) {
Map<String, Object> result = userMapper.getUserProfile(authenticatedUser.getIdx());
return UserProfileRes.of(result);
String profileImgUrl = s3Util.getImgUrl((String) result.get("profileImgUrl"));
return UserProfileRes.of(result, profileImgUrl);
}

@Override
@Transactional
public Boolean updateUserProfile(
AuthenticatedUser authenticatedUser, UserProfileUpdateReq request) {
User user =
userRepository
.findById(authenticatedUser.getIdx())
.orElseThrow(() -> new ApplicationException(ExceptionList.USER_NOT_FOUND));
// 닉네임 중복 검사
Optional<User> duplicatedNickName = userRepository.findByNickname(request.nickName());
if (duplicatedNickName.isPresent() && user != duplicatedNickName.get()) {
throw new ApplicationException(ExceptionList.NICKNAME_ALREADY_EXIST);
}
user.updateProfile(request.nickName(), request.profileImageKey());
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
Expand All @@ -14,6 +15,7 @@
import everymeal.server.user.controller.dto.request.UserEmailAuthReq;
import everymeal.server.user.controller.dto.request.UserEmailLoginReq;
import everymeal.server.user.controller.dto.request.UserEmailSingReq;
import everymeal.server.user.controller.dto.request.UserProfileUpdateReq;
import everymeal.server.user.controller.dto.response.UserLoginRes;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -134,4 +136,23 @@ void getUserProfile() throws Exception {
.andExpect(status().isOk())
.andExpect(jsonPath("$.message").value("OK"));
}

@DisplayName("인증된 유저의 프로필 정보 수정")
@Test
void updateUserProfile() throws Exception {
// given
UserProfileUpdateReq request = new UserProfileUpdateReq("연유크림", "imageKey");

given(userJwtResolver.resolveArgument(any(), any(), any(), any()))
.willReturn(AuthenticatedUser.builder().idx(1L).build());

// when-then
mockMvc.perform(
put("/api/v1/users/profile")
.content(objectMapper.writeValueAsString(request))
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.message").value("OK"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import everymeal.server.user.controller.dto.request.UserEmailAuthReq;
import everymeal.server.user.controller.dto.request.UserEmailLoginReq;
import everymeal.server.user.controller.dto.request.UserEmailSingReq;
import everymeal.server.user.controller.dto.request.UserProfileUpdateReq;
import everymeal.server.user.controller.dto.response.UserEmailAuthRes;
import everymeal.server.user.controller.dto.response.UserLoginRes;
import everymeal.server.user.entity.User;
Expand Down Expand Up @@ -249,6 +250,70 @@ void getUserProfile() {
assertEquals(response.nickName(), request.nickname());
}

@DisplayName("인증된 사용자의 프로필 정보 수정")
@Test
void updateUserProfile() {
// given
String token = jwtUtil.generateEmailToken("test@gmail.com", "12345");

University university =
universityRepository.save(
University.builder().name("명지대학교").campusName("인문캠퍼스").build());
UserEmailSingReq request =
new UserEmailSingReq("nickname", token, "12345", university.getIdx(), "imageKey");

UserLoginRes userLoginRes = userService.signUp(request);

AuthenticatedUser user =
jwtUtil.getAuthenticateUserFromAccessToken(userLoginRes.accessToken());

UserProfileUpdateReq userProfileUpdateReq = new UserProfileUpdateReq("연유크림", "imageKey2");

// when
var response = userService.updateUserProfile(user, userProfileUpdateReq);

var updatedUser = userService.getUserProfile(user);

// then
assertTrue(response);
assertEquals(updatedUser.nickName(), userProfileUpdateReq.nickName());
assertEquals(
updatedUser.profileImgUrl(),
s3Util.getImgUrl(userProfileUpdateReq.profileImageKey()));
}

@DisplayName("인증된 사용자의 프로필 정보 수정 - 닉네임 중복")
@Test
void updateUserProfile_duplicated() {
// given
String token = jwtUtil.generateEmailToken("test@gmail.com", "12345");

University university =
universityRepository.save(
University.builder().name("명지대학교").campusName("인문캠퍼스").build());
UserEmailSingReq request =
new UserEmailSingReq("nickname", token, "12345", university.getIdx(), "imageKey");

UserLoginRes userLoginRes = userService.signUp(request);

userRepository.saveAndFlush(createUser("hello@world.com", "연유크림"));

AuthenticatedUser user =
jwtUtil.getAuthenticateUserFromAccessToken(userLoginRes.accessToken());

UserProfileUpdateReq userProfileUpdateReq = new UserProfileUpdateReq("연유크림", "imageKey2");

// when then
ApplicationException applicationException =
assertThrows(
ApplicationException.class,
() -> userService.updateUserProfile(user, userProfileUpdateReq));

assertEquals(
applicationException.getErrorCode(),
ExceptionList.NICKNAME_ALREADY_EXIST.getCODE());
}

private User createUser(String email, String nickname) {
return User.builder().email(email).nickname(nickname).build();
}
Expand Down

0 comments on commit 63b3cb4

Please sign in to comment.