Skip to content

Commit 40b17cb

Browse files
committed
feat: #73 내 프로필 사진 변경 API 구현
1 parent d9cb14f commit 40b17cb

File tree

6 files changed

+109
-0
lines changed

6 files changed

+109
-0
lines changed

src/main/java/com/ajou/hertz/domain/user/controller/UserController.java

+19
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.springframework.validation.annotation.Validated;
1010
import org.springframework.web.bind.annotation.GetMapping;
1111
import org.springframework.web.bind.annotation.PostMapping;
12+
import org.springframework.web.bind.annotation.PutMapping;
1213
import org.springframework.web.bind.annotation.RequestBody;
1314
import org.springframework.web.bind.annotation.RequestMapping;
1415
import org.springframework.web.bind.annotation.RequestParam;
@@ -18,6 +19,7 @@
1819
import com.ajou.hertz.common.validator.PhoneNumber;
1920
import com.ajou.hertz.domain.user.dto.UserDto;
2021
import com.ajou.hertz.domain.user.dto.request.SignUpRequest;
22+
import com.ajou.hertz.domain.user.dto.request.UpdateProfileImageUrlRequest;
2123
import com.ajou.hertz.domain.user.dto.response.UserEmailResponse;
2224
import com.ajou.hertz.domain.user.dto.response.UserExistenceResponse;
2325
import com.ajou.hertz.domain.user.dto.response.UserResponse;
@@ -114,4 +116,21 @@ public ResponseEntity<UserResponse> signUpV1(
114116
.created(URI.create("/users/" + userCreated.getId()))
115117
.body(UserResponse.from(userCreated));
116118
}
119+
120+
@Operation(
121+
summary = "프로필 이미지 변경",
122+
description = "프로필 이미지를 변경합니다.",
123+
security = @SecurityRequirement(name = "access-token")
124+
)
125+
@PutMapping(value = "/me/profile-image", headers = API_VERSION_HEADER_NAME + "=" + 1)
126+
public UserResponse updateProfileImageUrlV1(
127+
@AuthenticationPrincipal UserPrincipal userPrincipal,
128+
@RequestBody @Valid UpdateProfileImageUrlRequest updateProfileImageUrlRequest
129+
) {
130+
UserDto userUpdated = userCommandService.updateProfileImageUrl(userPrincipal.getUserId(),
131+
updateProfileImageUrlRequest.getProfileImageUrl());
132+
UserDto userDto = userQueryService.getDtoById(userPrincipal.getUserId());
133+
return UserResponse.from(userUpdated);
134+
}
135+
117136
}

src/main/java/com/ajou/hertz/domain/user/entity/User.java

+9
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,13 @@ public static User create(
100100
profileImageUrl, birth, gender, phone, null
101101
);
102102
}
103+
104+
public void changeProfileImageUrl(String profileImageUrl) {
105+
this.profileImageUrl = profileImageUrl;
106+
}
107+
108+
public UserProfileImage getProfileImage() {
109+
return UserProfileImage.of(profileImageUrl);
110+
}
111+
103112
}

src/main/java/com/ajou/hertz/domain/user/entity/UserProfileImage.java

+4
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,8 @@ private UserProfileImage(Long id, User user, String originalName, String storedN
3333
this.id = id;
3434
this.user = user;
3535
}
36+
37+
public static UserProfileImage of(String profileImageUrl) {
38+
return new UserProfileImage(null, null, null, null, profileImageUrl);
39+
}
3640
}

src/main/java/com/ajou/hertz/domain/user/service/UserCommandService.java

+15
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,19 @@ private String generateRandom16CharString() {
129129
.toString()
130130
.substring(0, 16);
131131
}
132+
133+
/**
134+
* 회원의 프로필 이미지를 변경한다.
135+
*
136+
* @param userId 회원 id
137+
* @param profileImageUrl 변경할 프로필 이미지 url
138+
*
139+
* @return 변경된 회원 정보
140+
*/
141+
public UserDto updateProfileImageUrl(Long userId, String profileImageUrl) {
142+
User user = userQueryService.getById(userId);
143+
user.changeProfileImageUrl(profileImageUrl);
144+
return UserDto.from(user);
145+
}
146+
132147
}

src/test/java/com/ajou/hertz/unit/domain/user/controller/UserControllerTest.java

+28
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.ajou.hertz.domain.user.controller.UserController;
3636
import com.ajou.hertz.domain.user.dto.UserDto;
3737
import com.ajou.hertz.domain.user.dto.request.SignUpRequest;
38+
import com.ajou.hertz.domain.user.dto.request.UpdateProfileImageUrlRequest;
3839
import com.ajou.hertz.domain.user.service.UserCommandService;
3940
import com.ajou.hertz.domain.user.service.UserQueryService;
4041
import com.ajou.hertz.util.ReflectionUtils;
@@ -212,6 +213,33 @@ public void securitySetUp() throws Exception {
212213
verifyEveryMocksShouldHaveNoMoreInteractions();
213214
}
214215

216+
@Test
217+
void 주어진_id와_새로운_프로필_이미지로_프로필_이미지를_변경한다() throws Exception {
218+
// given
219+
long userId = 1L;
220+
String profileImageUrl = "https://example.com/new_profile_image.jpg";
221+
UpdateProfileImageUrlRequest updateProfileImageUrlRequest = new UpdateProfileImageUrlRequest(profileImageUrl);
222+
UserDetails userDetails = createTestUser(userId);
223+
UserDto updatedUserDto = createUserDto(userId);
224+
given(userCommandService.updateProfileImageUrl(userId, profileImageUrl)).willReturn(updatedUserDto);
225+
given(userQueryService.getDtoById(userId)).willReturn(createUserDto(userId));
226+
227+
// when & then
228+
mvc.perform(
229+
put("/api/users/me/profile-image")
230+
.header(API_VERSION_HEADER_NAME, 1)
231+
.contentType(MediaType.APPLICATION_JSON)
232+
.content(objectMapper.writeValueAsString(updateProfileImageUrlRequest))
233+
.with(user(userDetails))
234+
)
235+
.andExpect(status().isOk())
236+
.andExpect(jsonPath("$.profileImageUrl").value(updatedUserDto.getProfileImageUrl()));
237+
238+
then(userCommandService).should().updateProfileImageUrl(userId, profileImageUrl);
239+
then(userQueryService).should().getDtoById(userId);
240+
verifyEveryMocksShouldHaveNoMoreInteractions();
241+
}
242+
215243
private void verifyEveryMocksShouldHaveNoMoreInteractions() {
216244
then(userCommandService).shouldHaveNoMoreInteractions();
217245
then(userQueryService).shouldHaveNoMoreInteractions();

src/test/java/com/ajou/hertz/unit/domain/user/service/UserCommandServiceTest.java

+34
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.ajou.hertz.domain.user.entity.User;
3030
import com.ajou.hertz.domain.user.exception.UserEmailDuplicationException;
3131
import com.ajou.hertz.domain.user.exception.UserKakaoUidDuplicationException;
32+
import com.ajou.hertz.domain.user.exception.UserNotFoundByIdException;
3233
import com.ajou.hertz.domain.user.exception.UserPhoneDuplicationException;
3334
import com.ajou.hertz.domain.user.repository.UserRepository;
3435
import com.ajou.hertz.domain.user.service.UserCommandService;
@@ -171,6 +172,39 @@ static Stream<Arguments> testDataForCreateNewUserWithKakao() throws Exception {
171172
assertThat(t).isInstanceOf(UserKakaoUidDuplicationException.class);
172173
}
173174

175+
@Test
176+
void 주어진_id와_새_프로필_이미지로_프로필_이미지를_변경한다() throws Exception {
177+
// given
178+
Long userId = 1L;
179+
String newProfileImageUrl = "https://new-profile-image-url";
180+
User user = createUser(userId, "$2a$abc123", "12345");
181+
given(userQueryService.getById(userId)).willReturn(user);
182+
183+
// when
184+
UserDto updatedUserDto = sut.updateProfileImageUrl(userId, newProfileImageUrl);
185+
186+
// then
187+
then(userQueryService).should().getById(userId);
188+
verifyEveryMocksShouldHaveNoMoreInteractions();
189+
assertThat(updatedUserDto.getProfileImageUrl()).isEqualTo(newProfileImageUrl);
190+
}
191+
192+
@Test
193+
void 주어진_유저_ID와_새로운_프로필_이미지로_기존의_프로필_이미지를_변경한다_존재하지_않는_유저라면_예외가_발생한다() throws Exception {
194+
// given
195+
Long userId = 1L;
196+
String newProfileImageUrl = "https://new-profile-image-url";
197+
given(userQueryService.getById(userId)).willThrow(UserNotFoundByIdException.class);
198+
199+
// when
200+
Throwable t = catchThrowable(() -> sut.updateProfileImageUrl(userId, newProfileImageUrl));
201+
202+
// then
203+
then(userQueryService).should().getById(userId);
204+
verifyEveryMocksShouldHaveNoMoreInteractions();
205+
assertThat(t).isInstanceOf(UserNotFoundByIdException.class);
206+
}
207+
174208
private void verifyEveryMocksShouldHaveNoMoreInteractions() {
175209
then(userQueryService).shouldHaveNoMoreInteractions();
176210
then(userRepository).shouldHaveNoMoreInteractions();

0 commit comments

Comments
 (0)