From f6b28117641d446dcfac79645af95c750afeb358 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 14:07:22 +0900 Subject: [PATCH 01/46] =?UTF-8?q?test:=EA=B8=B0=EC=98=A8=EA=B0=92=20?= =?UTF-8?q?=EB=B2=94=EC=9C=84=EA=B0=80=20=EC=9C=A0=ED=9A=A8=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=9D=84=20=EB=95=8C=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/TemperatureArrangeTest.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/backendoori/ootw/weather/domain/TemperatureArrangeTest.java b/src/test/java/com/backendoori/ootw/weather/domain/TemperatureArrangeTest.java index c1ae9abe..7fa50e81 100644 --- a/src/test/java/com/backendoori/ootw/weather/domain/TemperatureArrangeTest.java +++ b/src/test/java/com/backendoori/ootw/weather/domain/TemperatureArrangeTest.java @@ -1,5 +1,6 @@ package com.backendoori.ootw.weather.domain; +import static com.backendoori.ootw.weather.validation.Message.CAN_NOT_RETRIEVE_TEMPERATURE_ARRANGE; import static com.backendoori.ootw.weather.validation.Message.CAN_NOT_USE_FORECAST_API; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -56,7 +57,7 @@ void createTemperatureArrangeSuccess() { @ParameterizedTest @MethodSource("provideInvalidWeatherInfoMap") @DisplayName("TMN, TMX가 포함되지 않은 결과 맵(map)으로부터 TemperatureArrange 생성에 실패한다.") - void createTemperatureArrangeFail(Map weatherInfoMap) { + void createTemperatureArrangeFailWithInvalidValue(Map weatherInfoMap) { // given // when ThrowingCallable createTemperatureArrange = () -> TemperatureArrange.from(weatherInfoMap); @@ -66,4 +67,21 @@ void createTemperatureArrangeFail(Map weatherInfoMap) .withMessage(CAN_NOT_USE_FORECAST_API); } + @Test + @DisplayName("유효하지 않은 TMN, TMX가 포함된 결과 맵(map)으로부터 TemperatureArrange 생성에 실패한다.") + void createTemperatureArrangeFailWithInvalidArrange() { + // given + Map weatherInfoMap = new HashMap<>(); + weatherInfoMap.put(ForecastCategory.TMN, "10.0"); + weatherInfoMap.put(ForecastCategory.TMX, "0.0"); + + // when + ThrowingCallable createTemperatureArrange = () -> TemperatureArrange.from(weatherInfoMap); + + // then + assertThatExceptionOfType(IllegalStateException.class) + .isThrownBy(createTemperatureArrange) + .withMessage(CAN_NOT_RETRIEVE_TEMPERATURE_ARRANGE); + } + } From 1b7ec1c7fe0beb3a9f71f5867129424adee1b299 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 16:21:47 +0900 Subject: [PATCH 02/46] =?UTF-8?q?fix:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B6=8C=ED=95=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/backendoori/ootw/config/HttpRequestsConfigurer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/backendoori/ootw/config/HttpRequestsConfigurer.java b/src/main/java/com/backendoori/ootw/config/HttpRequestsConfigurer.java index 31f136b3..8a368aff 100644 --- a/src/main/java/com/backendoori/ootw/config/HttpRequestsConfigurer.java +++ b/src/main/java/com/backendoori/ootw/config/HttpRequestsConfigurer.java @@ -1,5 +1,8 @@ package com.backendoori.ootw.config; +import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; + +import org.springframework.http.HttpMethod; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; @@ -10,6 +13,7 @@ public class HttpRequestsConfigurer implements Customizer.AuthorizationManagerRequestMatcherRegistry> { private static final String AUTH_RESOURCE = "/api/v1/auth/**"; + private static final String POST_RESOURCE = "/api/v1/posts/**"; @Override public void customize( @@ -17,6 +21,8 @@ public void customize( authorizeRequests .requestMatchers(AUTH_RESOURCE) .permitAll() + .requestMatchers(antMatcher(HttpMethod.GET, POST_RESOURCE)) + .permitAll() .anyRequest() .authenticated(); } From 78950376607dd7cf774eb402c7f9fa4c921f66f8 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 16:23:00 +0900 Subject: [PATCH 03/46] =?UTF-8?q?fix:=20dto=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backendoori/ootw/post/controller/PostController.java | 8 +++++--- src/main/java/com/backendoori/ootw/post/domain/Post.java | 5 ++++- .../ootw/post/dto/{ => request}/PostSaveRequest.java | 2 +- .../ootw/post/dto/{ => response}/PostReadResponse.java | 3 +-- .../ootw/post/dto/{ => response}/PostSaveResponse.java | 2 +- .../ootw/post/dto/{ => response}/WriterDto.java | 2 +- .../com/backendoori/ootw/post/service/PostService.java | 8 +++++--- .../backendoori/ootw/post/validation/PostValidator.java | 2 +- .../ootw/like/controller/LikeControllerTest.java | 3 +-- .../java/com/backendoori/ootw/like/domain/LikeTest.java | 2 +- .../backendoori/ootw/like/service/LikeServiceTest.java | 5 +---- .../ootw/post/controller/PostControllerTest.java | 6 +++--- .../java/com/backendoori/ootw/post/domain/PostTest.java | 2 +- .../backendoori/ootw/post/service/PostServiceTest.java | 8 ++++---- 14 files changed, 30 insertions(+), 28 deletions(-) rename src/main/java/com/backendoori/ootw/post/dto/{ => request}/PostSaveRequest.java (94%) rename src/main/java/com/backendoori/ootw/post/dto/{ => response}/PostReadResponse.java (94%) rename src/main/java/com/backendoori/ootw/post/dto/{ => response}/PostSaveResponse.java (94%) rename src/main/java/com/backendoori/ootw/post/dto/{ => response}/WriterDto.java (84%) diff --git a/src/main/java/com/backendoori/ootw/post/controller/PostController.java b/src/main/java/com/backendoori/ootw/post/controller/PostController.java index 5c3ba93a..49bfc0cd 100644 --- a/src/main/java/com/backendoori/ootw/post/controller/PostController.java +++ b/src/main/java/com/backendoori/ootw/post/controller/PostController.java @@ -2,9 +2,11 @@ import java.net.URI; import java.util.List; -import com.backendoori.ootw.post.dto.PostReadResponse; -import com.backendoori.ootw.post.dto.PostSaveRequest; -import com.backendoori.ootw.post.dto.PostSaveResponse; +import com.backendoori.ootw.common.validation.Image; +import com.backendoori.ootw.post.dto.request.PostSaveRequest; +import com.backendoori.ootw.post.dto.request.PostUpdateRequest; +import com.backendoori.ootw.post.dto.response.PostReadResponse; +import com.backendoori.ootw.post.dto.response.PostSaveResponse; import com.backendoori.ootw.post.service.PostService; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/backendoori/ootw/post/domain/Post.java b/src/main/java/com/backendoori/ootw/post/domain/Post.java index 26f61a26..359eaf1e 100644 --- a/src/main/java/com/backendoori/ootw/post/domain/Post.java +++ b/src/main/java/com/backendoori/ootw/post/domain/Post.java @@ -5,7 +5,7 @@ import static com.backendoori.ootw.post.validation.PostValidator.validateUser; import com.backendoori.ootw.common.BaseEntity; -import com.backendoori.ootw.post.dto.PostSaveRequest; +import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.weather.domain.TemperatureArrange; import jakarta.persistence.Column; @@ -21,6 +21,7 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; @Table(name = "posts") @Entity @@ -37,9 +38,11 @@ public class Post extends BaseEntity { @JoinColumn(name = "user_id", nullable = false) private User user; + @Setter @Column(name = "title", nullable = false) private String title; + @Setter @Column(name = "content", nullable = false) private String content; diff --git a/src/main/java/com/backendoori/ootw/post/dto/PostSaveRequest.java b/src/main/java/com/backendoori/ootw/post/dto/request/PostSaveRequest.java similarity index 94% rename from src/main/java/com/backendoori/ootw/post/dto/PostSaveRequest.java rename to src/main/java/com/backendoori/ootw/post/dto/request/PostSaveRequest.java index c19fd1d9..85767b23 100644 --- a/src/main/java/com/backendoori/ootw/post/dto/PostSaveRequest.java +++ b/src/main/java/com/backendoori/ootw/post/dto/request/PostSaveRequest.java @@ -1,4 +1,4 @@ -package com.backendoori.ootw.post.dto; +package com.backendoori.ootw.post.dto.request; import static com.backendoori.ootw.post.validation.Message.BLANK_POST_CONTENT; import static com.backendoori.ootw.post.validation.Message.BLANK_POST_TITLE; diff --git a/src/main/java/com/backendoori/ootw/post/dto/PostReadResponse.java b/src/main/java/com/backendoori/ootw/post/dto/response/PostReadResponse.java similarity index 94% rename from src/main/java/com/backendoori/ootw/post/dto/PostReadResponse.java rename to src/main/java/com/backendoori/ootw/post/dto/response/PostReadResponse.java index 1d0e2f91..2a84809b 100644 --- a/src/main/java/com/backendoori/ootw/post/dto/PostReadResponse.java +++ b/src/main/java/com/backendoori/ootw/post/dto/response/PostReadResponse.java @@ -1,7 +1,6 @@ -package com.backendoori.ootw.post.dto; +package com.backendoori.ootw.post.dto.response; import java.time.LocalDateTime; -import java.util.Objects; import com.backendoori.ootw.post.domain.Post; import com.backendoori.ootw.weather.dto.TemperatureArrangeDto; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/backendoori/ootw/post/dto/PostSaveResponse.java b/src/main/java/com/backendoori/ootw/post/dto/response/PostSaveResponse.java similarity index 94% rename from src/main/java/com/backendoori/ootw/post/dto/PostSaveResponse.java rename to src/main/java/com/backendoori/ootw/post/dto/response/PostSaveResponse.java index 02a9fffe..ba8f40b1 100644 --- a/src/main/java/com/backendoori/ootw/post/dto/PostSaveResponse.java +++ b/src/main/java/com/backendoori/ootw/post/dto/response/PostSaveResponse.java @@ -1,4 +1,4 @@ -package com.backendoori.ootw.post.dto; +package com.backendoori.ootw.post.dto.response; import java.time.LocalDateTime; import com.backendoori.ootw.post.domain.Post; diff --git a/src/main/java/com/backendoori/ootw/post/dto/WriterDto.java b/src/main/java/com/backendoori/ootw/post/dto/response/WriterDto.java similarity index 84% rename from src/main/java/com/backendoori/ootw/post/dto/WriterDto.java rename to src/main/java/com/backendoori/ootw/post/dto/response/WriterDto.java index 1f25d4b0..25f229fc 100644 --- a/src/main/java/com/backendoori/ootw/post/dto/WriterDto.java +++ b/src/main/java/com/backendoori/ootw/post/dto/response/WriterDto.java @@ -1,4 +1,4 @@ -package com.backendoori.ootw.post.dto; +package com.backendoori.ootw.post.dto.response; import com.backendoori.ootw.user.domain.User; diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index e585a79c..48eba423 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -10,9 +10,11 @@ import com.backendoori.ootw.like.domain.Like; import com.backendoori.ootw.like.repository.LikeRepository; import com.backendoori.ootw.post.domain.Post; -import com.backendoori.ootw.post.dto.PostReadResponse; -import com.backendoori.ootw.post.dto.PostSaveRequest; -import com.backendoori.ootw.post.dto.PostSaveResponse; +import com.backendoori.ootw.post.dto.request.PostSaveRequest; +import com.backendoori.ootw.post.dto.request.PostUpdateRequest; +import com.backendoori.ootw.post.dto.response.PostReadResponse; +import com.backendoori.ootw.post.dto.response.PostSaveResponse; +import com.backendoori.ootw.post.exception.NoPostPermissionException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.user.repository.UserRepository; diff --git a/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java b/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java index 96f8a8f2..a5b831e3 100644 --- a/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java +++ b/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java @@ -8,7 +8,7 @@ import static com.backendoori.ootw.post.validation.Message.NULL_TEMPERATURE_ARRANGE; import static com.backendoori.ootw.post.validation.Message.NULL_WRITER; -import com.backendoori.ootw.post.dto.PostSaveRequest; +import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.weather.domain.TemperatureArrange; import org.springframework.util.Assert; diff --git a/src/test/java/com/backendoori/ootw/like/controller/LikeControllerTest.java b/src/test/java/com/backendoori/ootw/like/controller/LikeControllerTest.java index b0581e66..e9b7c6d6 100644 --- a/src/test/java/com/backendoori/ootw/like/controller/LikeControllerTest.java +++ b/src/test/java/com/backendoori/ootw/like/controller/LikeControllerTest.java @@ -14,7 +14,7 @@ import com.backendoori.ootw.like.repository.LikeRepository; import com.backendoori.ootw.post.controller.PostController; import com.backendoori.ootw.post.domain.Post; -import com.backendoori.ootw.post.dto.PostSaveRequest; +import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.post.service.PostService; import com.backendoori.ootw.security.TokenMockMvcTest; @@ -31,7 +31,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/test/java/com/backendoori/ootw/like/domain/LikeTest.java b/src/test/java/com/backendoori/ootw/like/domain/LikeTest.java index faad77b5..20de2a20 100644 --- a/src/test/java/com/backendoori/ootw/like/domain/LikeTest.java +++ b/src/test/java/com/backendoori/ootw/like/domain/LikeTest.java @@ -8,7 +8,7 @@ import java.util.HashMap; import java.util.Map; import com.backendoori.ootw.post.domain.Post; -import com.backendoori.ootw.post.dto.PostSaveRequest; +import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.weather.domain.TemperatureArrange; import com.backendoori.ootw.weather.domain.forecast.ForecastCategory; diff --git a/src/test/java/com/backendoori/ootw/like/service/LikeServiceTest.java b/src/test/java/com/backendoori/ootw/like/service/LikeServiceTest.java index fb852efa..9989f9ad 100644 --- a/src/test/java/com/backendoori/ootw/like/service/LikeServiceTest.java +++ b/src/test/java/com/backendoori/ootw/like/service/LikeServiceTest.java @@ -8,10 +8,7 @@ import java.util.HashMap; import java.util.Map; -import java.util.ArrayList; -import java.util.List; import java.util.NoSuchElementException; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -21,7 +18,7 @@ import com.backendoori.ootw.like.repository.LikeRepository; import com.backendoori.ootw.post.controller.PostController; import com.backendoori.ootw.post.domain.Post; -import com.backendoori.ootw.post.dto.PostSaveRequest; +import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.post.service.PostService; import com.backendoori.ootw.security.TokenMockMvcTest; diff --git a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java index f2043c9a..55eee812 100644 --- a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java +++ b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java @@ -17,9 +17,9 @@ import java.util.List; import java.util.Map; import com.backendoori.ootw.post.domain.Post; -import com.backendoori.ootw.post.dto.PostReadResponse; -import com.backendoori.ootw.post.dto.PostSaveRequest; -import com.backendoori.ootw.post.dto.PostSaveResponse; +import com.backendoori.ootw.post.dto.response.PostReadResponse; +import com.backendoori.ootw.post.dto.request.PostSaveRequest; +import com.backendoori.ootw.post.dto.response.PostSaveResponse; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.post.service.PostService; import com.backendoori.ootw.security.TokenMockMvcTest; diff --git a/src/test/java/com/backendoori/ootw/post/domain/PostTest.java b/src/test/java/com/backendoori/ootw/post/domain/PostTest.java index 53b6b1ee..1c7cd6e2 100644 --- a/src/test/java/com/backendoori/ootw/post/domain/PostTest.java +++ b/src/test/java/com/backendoori/ootw/post/domain/PostTest.java @@ -15,7 +15,7 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; -import com.backendoori.ootw.post.dto.PostSaveRequest; +import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.weather.domain.TemperatureArrange; import com.backendoori.ootw.weather.domain.forecast.ForecastCategory; diff --git a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java index 2bf27af9..8730d0ce 100644 --- a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java +++ b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java @@ -19,10 +19,10 @@ import com.backendoori.ootw.like.repository.LikeRepository; import com.backendoori.ootw.like.service.LikeService; import com.backendoori.ootw.post.domain.Post; -import com.backendoori.ootw.post.dto.PostReadResponse; -import com.backendoori.ootw.post.dto.PostSaveRequest; -import com.backendoori.ootw.post.dto.PostSaveResponse; -import com.backendoori.ootw.post.dto.WriterDto; +import com.backendoori.ootw.post.dto.response.PostReadResponse; +import com.backendoori.ootw.post.dto.request.PostSaveRequest; +import com.backendoori.ootw.post.dto.response.PostSaveResponse; +import com.backendoori.ootw.post.dto.response.WriterDto; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.user.repository.UserRepository; From 32588b22e2a6c8a1111972125fb647cbd5b13a1c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 16:23:13 +0900 Subject: [PATCH 04/46] =?UTF-8?q?style:=20=EC=BD=94=EB=93=9C=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/backendoori/ootw/like/service/LikeService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/like/service/LikeService.java b/src/main/java/com/backendoori/ootw/like/service/LikeService.java index ee83ed32..9114a016 100644 --- a/src/main/java/com/backendoori/ootw/like/service/LikeService.java +++ b/src/main/java/com/backendoori/ootw/like/service/LikeService.java @@ -36,10 +36,10 @@ public LikeResponse requestLike(Long userId, Long postId) { likeRepository.findByUserAndPost(user, post).ifPresentOrElse( like -> { boolean likeStatus = like.updateStatus(); - if(likeStatus){ + if (likeStatus) { post.increaseLikeCnt(); } - if(!likeStatus){ + if (!likeStatus) { post.decreaseLikeCnt(); } }, From 917a102dad8b15050934ced6b82f7d54dfd1bf68 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 16:23:34 +0900 Subject: [PATCH 05/46] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95/=EC=82=AD=EC=A0=9C=20=EA=B6=8C=ED=95=9C=20?= =?UTF-8?q?=EC=97=86=EC=9D=84=20=EB=95=8C=20=EC=98=88=EC=99=B8=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/exception/NoPostPermissionException.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/main/java/com/backendoori/ootw/post/exception/NoPostPermissionException.java diff --git a/src/main/java/com/backendoori/ootw/post/exception/NoPostPermissionException.java b/src/main/java/com/backendoori/ootw/post/exception/NoPostPermissionException.java new file mode 100644 index 00000000..2a83c4d2 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/post/exception/NoPostPermissionException.java @@ -0,0 +1,11 @@ +package com.backendoori.ootw.post.exception; + +public class NoPostPermissionException extends RuntimeException { + + public static final String DEFAULT_MESSAGE = "해당 게시글에 관한 수정/삭제 권한이 없습니다."; + + public NoPostPermissionException() { + super(DEFAULT_MESSAGE); + } + +} From af48f9b588ef1263474e89e8f4c3f0be1148dd3c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 16:23:42 +0900 Subject: [PATCH 06/46] =?UTF-8?q?feat:=20PostControllerAdvice=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/exception/PostControllerAdvice.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java diff --git a/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java b/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java new file mode 100644 index 00000000..1d0ea964 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java @@ -0,0 +1,24 @@ +package com.backendoori.ootw.post.exception; + +import com.backendoori.ootw.exception.ErrorResponse; +import com.backendoori.ootw.post.controller.PostController; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Order(Ordered.HIGHEST_PRECEDENCE) +@RestControllerAdvice(basePackageClasses = PostController.class) +public class PostControllerAdvice { + + @ExceptionHandler(NoPostPermissionException.class) + public ResponseEntity handleNoPostPermissionException(NoPostPermissionException e) { + ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); + + return ResponseEntity.status(HttpStatus.FORBIDDEN) + .body(errorResponse); + } + +} From 479b6a192e495a437d783a513ac45d5b6bca3a55 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 16:23:54 +0900 Subject: [PATCH 07/46] =?UTF-8?q?feat:=20PostUpdateRequest=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/dto/request/PostUpdateRequest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/com/backendoori/ootw/post/dto/request/PostUpdateRequest.java diff --git a/src/main/java/com/backendoori/ootw/post/dto/request/PostUpdateRequest.java b/src/main/java/com/backendoori/ootw/post/dto/request/PostUpdateRequest.java new file mode 100644 index 00000000..035d6244 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/post/dto/request/PostUpdateRequest.java @@ -0,0 +1,21 @@ +package com.backendoori.ootw.post.dto.request; + +import static com.backendoori.ootw.post.validation.Message.BLANK_POST_CONTENT; +import static com.backendoori.ootw.post.validation.Message.BLANK_POST_TITLE; +import static com.backendoori.ootw.post.validation.Message.INVALID_POST_CONTENT; +import static com.backendoori.ootw.post.validation.Message.INVALID_POST_TITLE; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public record PostUpdateRequest( + @NotBlank(message = BLANK_POST_TITLE) + @Size(max = 30, message = INVALID_POST_TITLE) + String title, + + @NotBlank(message = BLANK_POST_CONTENT) + @Size(max = 500, message = INVALID_POST_CONTENT) + String content +) { + +} From 40f0013c7dc041dc95fae53a2de8f358a2bfc3cd Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 16:25:15 +0900 Subject: [PATCH 08/46] =?UTF-8?q?feat:=20post=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/post/controller/PostController.java | 9 +++++++++ .../ootw/post/service/PostService.java | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/main/java/com/backendoori/ootw/post/controller/PostController.java b/src/main/java/com/backendoori/ootw/post/controller/PostController.java index 49bfc0cd..ce527549 100644 --- a/src/main/java/com/backendoori/ootw/post/controller/PostController.java +++ b/src/main/java/com/backendoori/ootw/post/controller/PostController.java @@ -12,6 +12,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -52,4 +53,12 @@ public ResponseEntity> readAll() { .body(postService.getAll()); } + @DeleteMapping("/{postId}") + public ResponseEntity delete(@PathVariable Long postId) { + postService.delete(postId); + + return ResponseEntity.status(HttpStatus.NO_CONTENT) + .build(); + } + } diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index 48eba423..9363de8e 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -24,6 +24,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; import org.springframework.web.multipart.MultipartFile; @Service @@ -94,6 +95,17 @@ public List getAll() { }).toList(); } + @Transactional + public void delete(Long postId) { + Post post = postRepository.findById(postId) + .orElseThrow(() -> new NoSuchElementException(POST_NOT_FOUND)); + + checkUserHasPostPermission(post); + + postRepository.delete(post); + } + + private List getLikedPostId(long userId) { return likeRepository.findByUserAndIsLike(userId, true) .stream().map(like -> like.getPost().getId()) @@ -115,4 +127,10 @@ private boolean isLogin() { .getPrincipal() != ANONYMOUS_USER_PRINCIPLE; } + private void checkUserHasPostPermission(Post post) { + Assert.isTrue(getUserId() == post.getUser().getId(), () -> { + throw new NoPostPermissionException(); + }); + } + } From 7724f951be0a604b33014bacf08fb035d2c7a3eb Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 17:20:16 +0900 Subject: [PATCH 09/46] =?UTF-8?q?refactor:=20Image=20=EC=96=B4=EB=85=B8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EC=85=98=20ignoreCase=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/backendoori/ootw/common/validation/Image.java | 2 ++ .../ootw/common/validation/ImageValidator.java | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/main/java/com/backendoori/ootw/common/validation/Image.java b/src/main/java/com/backendoori/ootw/common/validation/Image.java index 6376e9ce..c49bda09 100644 --- a/src/main/java/com/backendoori/ootw/common/validation/Image.java +++ b/src/main/java/com/backendoori/ootw/common/validation/Image.java @@ -20,4 +20,6 @@ Class[] payload() default {}; + boolean ignoreCase() default false; + } diff --git a/src/main/java/com/backendoori/ootw/common/validation/ImageValidator.java b/src/main/java/com/backendoori/ootw/common/validation/ImageValidator.java index 57f8d59f..60d7c4b1 100644 --- a/src/main/java/com/backendoori/ootw/common/validation/ImageValidator.java +++ b/src/main/java/com/backendoori/ootw/common/validation/ImageValidator.java @@ -6,8 +6,19 @@ public class ImageValidator implements ConstraintValidator { + private Image annotation; + + @Override + public void initialize(Image constraintAnnotation) { + this.annotation = constraintAnnotation; + } + @Override public boolean isValid(MultipartFile img, ConstraintValidatorContext context) { + if (this.annotation.ignoreCase()) { + return true; + } + if (img == null || img.isEmpty()) { return false; } From 6087716d5ae02f855934a59c012e793ab56fb83e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 17:41:42 +0900 Subject: [PATCH 10/46] =?UTF-8?q?feat:=20=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=EB=A6=AC=EC=86=8C=EC=8A=A4=EA=B0=80=20=EC=98=A4=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EC=95=98=EC=9D=84=20=EB=95=8C=20=EB=8D=98=EC=A7=80?= =?UTF-8?q?=EB=8A=94=20=EC=98=88=EC=99=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/post/exception/PostControllerAdvice.java | 8 ++++++++ .../post/exception/ResourceNotExistException.java | 11 +++++++++++ 2 files changed, 19 insertions(+) create mode 100644 src/main/java/com/backendoori/ootw/post/exception/ResourceNotExistException.java diff --git a/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java b/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java index 1d0ea964..691caea0 100644 --- a/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java +++ b/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java @@ -21,4 +21,12 @@ public ResponseEntity handleNoPostPermissionException(NoPostPermi .body(errorResponse); } + @ExceptionHandler(ResourceNotExistException.class) + public ResponseEntity handleNoUpdateResourceException(ResourceNotExistException e) { + ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); + + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(errorResponse); + } + } diff --git a/src/main/java/com/backendoori/ootw/post/exception/ResourceNotExistException.java b/src/main/java/com/backendoori/ootw/post/exception/ResourceNotExistException.java new file mode 100644 index 00000000..b8c497a0 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/post/exception/ResourceNotExistException.java @@ -0,0 +1,11 @@ +package com.backendoori.ootw.post.exception; + +public class ResourceNotExistException extends RuntimeException { + + public static final String DEFAULT_MESSAGE = "해당 게시글을 생성하거나 업데이트할 리소스가 존재하지 않습니다."; + + public ResourceNotExistException() { + super(DEFAULT_MESSAGE); + } + +} From cdbf8a27bc0441b941a2c7b5527cb54fac4b560e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 17:48:39 +0900 Subject: [PATCH 11/46] =?UTF-8?q?refactor:=20=EB=AA=A9=EC=A0=81=EC=97=90?= =?UTF-8?q?=20=EB=A7=9E=EB=8F=84=EB=A1=9D=20dto=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backendoori/ootw/post/controller/PostController.java | 2 +- ...{PostSaveResponse.java => PostSaveUpdateResponse.java} | 6 +++--- .../ootw/post/controller/PostControllerTest.java | 6 +++--- .../backendoori/ootw/post/service/PostServiceTest.java | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) rename src/main/java/com/backendoori/ootw/post/dto/response/{PostSaveResponse.java => PostSaveUpdateResponse.java} (82%) diff --git a/src/main/java/com/backendoori/ootw/post/controller/PostController.java b/src/main/java/com/backendoori/ootw/post/controller/PostController.java index ce527549..c969be48 100644 --- a/src/main/java/com/backendoori/ootw/post/controller/PostController.java +++ b/src/main/java/com/backendoori/ootw/post/controller/PostController.java @@ -6,7 +6,7 @@ import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.post.dto.request.PostUpdateRequest; import com.backendoori.ootw.post.dto.response.PostReadResponse; -import com.backendoori.ootw.post.dto.response.PostSaveResponse; +import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; import com.backendoori.ootw.post.service.PostService; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/backendoori/ootw/post/dto/response/PostSaveResponse.java b/src/main/java/com/backendoori/ootw/post/dto/response/PostSaveUpdateResponse.java similarity index 82% rename from src/main/java/com/backendoori/ootw/post/dto/response/PostSaveResponse.java rename to src/main/java/com/backendoori/ootw/post/dto/response/PostSaveUpdateResponse.java index ba8f40b1..0e0dea09 100644 --- a/src/main/java/com/backendoori/ootw/post/dto/response/PostSaveResponse.java +++ b/src/main/java/com/backendoori/ootw/post/dto/response/PostSaveUpdateResponse.java @@ -4,7 +4,7 @@ import com.backendoori.ootw.post.domain.Post; import com.backendoori.ootw.weather.dto.TemperatureArrangeDto; -public record PostSaveResponse( +public record PostSaveUpdateResponse( Long postId, String title, String content, @@ -14,8 +14,8 @@ public record PostSaveResponse( TemperatureArrangeDto temperatureArrange ) { - public static PostSaveResponse from(Post savedPost) { - return new PostSaveResponse( + public static PostSaveUpdateResponse from(Post savedPost) { + return new PostSaveUpdateResponse( savedPost.getId(), savedPost.getTitle(), savedPost.getContent(), diff --git a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java index 55eee812..0eff2687 100644 --- a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java +++ b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java @@ -19,7 +19,7 @@ import com.backendoori.ootw.post.domain.Post; import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.request.PostSaveRequest; -import com.backendoori.ootw.post.dto.response.PostSaveResponse; +import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.post.service.PostService; import com.backendoori.ootw.security.TokenMockMvcTest; @@ -227,7 +227,7 @@ class GetDetailByPostId { private static final String URL = "http://localhost:8080/api/v1/posts/"; - PostSaveResponse postSaveResponse; + PostSaveUpdateResponse postSaveResponse; @BeforeEach void setUp() { @@ -236,7 +236,7 @@ void setUp() { Post savedPost = postRepository.save( Post.from(user, new PostSaveRequest("Test Title", "Test Content", VALID_COORDINATE), "imgUrl", generateTemperatureArrange())); - postSaveResponse = PostSaveResponse.from(savedPost); + postSaveResponse = PostSaveUpdateResponse.from(savedPost); } @Test diff --git a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java index 8730d0ce..ab002a77 100644 --- a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java +++ b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java @@ -21,7 +21,7 @@ import com.backendoori.ootw.post.domain.Post; import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.request.PostSaveRequest; -import com.backendoori.ootw.post.dto.response.PostSaveResponse; +import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; import com.backendoori.ootw.post.dto.response.WriterDto; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.user.domain.User; @@ -116,7 +116,7 @@ void saveSuccess() { generateTemperatureArrange()); // when - PostSaveResponse postSaveResponse = postService.save(request, postImg); + PostSaveUpdateResponse postSaveResponse = postService.save(request, postImg); //then assertAll( @@ -186,14 +186,14 @@ void saveFailWithInvalidValue(String title, String content) { @DisplayName("게시글 단건 조회하기") class GetDetailByPostId { - PostSaveResponse postSaveResponse; + PostSaveUpdateResponse postSaveResponse; @BeforeEach void setUp() { Post savedPost = postRepository.save( Post.from(user, new PostSaveRequest("Test Title", "Test Content", VALID_COORDINATE), "imgUrl", generateTemperatureArrange())); - postSaveResponse = PostSaveResponse.from(savedPost); + postSaveResponse = PostSaveUpdateResponse.from(savedPost); } @Test From 9ca169595ad0c9943f70886c3499e84967204bac Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 17:49:22 +0900 Subject: [PATCH 12/46] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=EA=B3=BC=20body=EB=A5=BC=20=EC=95=88?= =?UTF-8?q?=EB=B3=B4=EB=82=BC=20=EB=95=8C=20=EB=B0=9C=EC=83=9D=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/exception/GlobalControllerAdvice.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java b/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java index 4e75e2dc..d56fd5ff 100644 --- a/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java +++ b/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java @@ -14,6 +14,8 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.method.annotation.HandlerMethodValidationException; +import org.springframework.web.multipart.MultipartException; +import org.springframework.web.multipart.support.MissingServletRequestPartException; @Slf4j @RestControllerAdvice @@ -21,6 +23,14 @@ public class GlobalControllerAdvice { public static final String DEFAULT_MESSAGE = "유효하지 않은 요청 입니다."; + @ExceptionHandler({MissingServletRequestPartException.class, MultipartException.class}) + public ResponseEntity handleMissingServletRequestPartException(Exception e) { + ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); + + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(errorResponse); + } + @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity handleIllegalArgumentException(IllegalArgumentException e) { ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); From 8c463639ab23aa7c94929c0114ea283692b5f6ca Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 17:49:34 +0900 Subject: [PATCH 13/46] =?UTF-8?q?refactor:=20setter=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/backendoori/ootw/post/domain/Post.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/backendoori/ootw/post/domain/Post.java b/src/main/java/com/backendoori/ootw/post/domain/Post.java index 359eaf1e..588be708 100644 --- a/src/main/java/com/backendoori/ootw/post/domain/Post.java +++ b/src/main/java/com/backendoori/ootw/post/domain/Post.java @@ -46,6 +46,7 @@ public class Post extends BaseEntity { @Column(name = "content", nullable = false) private String content; + @Setter @Column(name = "image") private String image; From 709ad50a254aeb37fec25de3d8de0b96cc3e10e5 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Thu, 11 Jan 2024 17:51:23 +0900 Subject: [PATCH 14/46] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/post/controller/PostController.java | 41 +++++++++++++------ .../ootw/post/service/PostService.java | 36 ++++++++++++++-- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/controller/PostController.java b/src/main/java/com/backendoori/ootw/post/controller/PostController.java index c969be48..cdbea90c 100644 --- a/src/main/java/com/backendoori/ootw/post/controller/PostController.java +++ b/src/main/java/com/backendoori/ootw/post/controller/PostController.java @@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; @@ -28,19 +29,6 @@ public class PostController { private final PostService postService; - @PostMapping - public ResponseEntity save( - @RequestPart MultipartFile postImg, - @RequestPart @Valid PostSaveRequest request) { - PostSaveResponse response = postService.save(request, postImg); - - URI postUri = URI.create("/api/v1/posts/" + response.postId()); - - return ResponseEntity.status(HttpStatus.CREATED) - .location(postUri) - .body(response); - } - @GetMapping("/{postId}") public ResponseEntity readDetailByPostId(@PathVariable Long postId) { return ResponseEntity.status(HttpStatus.OK) @@ -61,4 +49,31 @@ public ResponseEntity delete(@PathVariable Long postId) { .build(); } + @PostMapping + public ResponseEntity save( + @RequestPart(required = false) @Image(ignoreCase = true) MultipartFile postImg, + @RequestPart @Valid PostSaveRequest request) { + PostSaveUpdateResponse response = postService.save(request, postImg); + + return ResponseEntity.status(HttpStatus.CREATED) + .location(getPostUri(response.postId())) + .body(response); + } + + @PutMapping("/{postId}") + public ResponseEntity update( + @PathVariable Long postId, + @RequestPart(required = false) @Image(ignoreCase = true) MultipartFile postImg, + @RequestPart(required = false) @Valid PostUpdateRequest request) { + PostSaveUpdateResponse response = postService.update(postId, postImg, request); + + return ResponseEntity.status(HttpStatus.CREATED) + .location(getPostUri(response.postId())) + .body(response); + } + + private URI getPostUri(Long postId) { + return URI.create("/api/v1/posts/" + postId); + } + } diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index 9363de8e..3dab2e10 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.Optional; import com.backendoori.ootw.common.image.ImageService; import com.backendoori.ootw.exception.UserNotFoundException; @@ -13,8 +14,9 @@ import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.post.dto.request.PostUpdateRequest; import com.backendoori.ootw.post.dto.response.PostReadResponse; -import com.backendoori.ootw.post.dto.response.PostSaveResponse; +import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; import com.backendoori.ootw.post.exception.NoPostPermissionException; +import com.backendoori.ootw.post.exception.ResourceNotExistException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.user.repository.UserRepository; @@ -39,17 +41,20 @@ public class PostService { private final LikeRepository likeRepository; @Transactional - public PostSaveResponse save(PostSaveRequest request, MultipartFile postImg) { + public PostSaveUpdateResponse save(PostSaveRequest request, MultipartFile postImg) { User user = userRepository.findById(getUserId()) .orElseThrow(UserNotFoundException::new); + + // TODO: 이미지가 null인 경우 설정하기 String imgUrl = imageService.uploadImage(postImg); TemperatureArrange temperatureArrange = weatherService.getCurrentTemperatureArrange(request.coordinate()); Post savedPost = postRepository.save(Post.from(user, request, imgUrl, temperatureArrange)); - return PostSaveResponse.from(savedPost); + return PostSaveUpdateResponse.from(savedPost); } + @Transactional(readOnly = true) public PostReadResponse getDetailByPostId(Long postId) { Post post = postRepository.findByIdWithUserEntityGraph(postId) @@ -105,6 +110,29 @@ public void delete(Long postId) { postRepository.delete(post); } + @Transactional + public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpdateRequest request) { + Post post = postRepository.findById(postId) + .orElseThrow(() -> new NoSuchElementException(POST_NOT_FOUND)); + + checkUserHasPostPermission(post); + + Assert.isTrue(Objects.nonNull(request) || Objects.nonNull(postImg), () -> { + throw new ResourceNotExistException(); + }); + + if (Objects.nonNull(request)) { + post.setTitle(request.title()); + post.setContent(request.content()); + } + + if (Objects.nonNull(postImg)) { + // TODO: 기존 저장된 이미지 삭제(원래 null인 경우도 있으니 주의) + post.setImage(imageService.uploadImage(postImg)); + } + + return PostSaveUpdateResponse.from(post); + } private List getLikedPostId(long userId) { return likeRepository.findByUserAndIsLike(userId, true) @@ -120,6 +148,8 @@ private long getUserId() { } //TODO: 이 부분을 .equals 써야하는지 궁금하다. + // 세희) 위에서처럼 정의하면 constant pool에 저장이되고 중복되는 값이 있으면 비슷한 걸로 인식한다고는 들었습니다! + // 다만 실수를 줄이고 더 안전하게 하고 싶다면 equals를 사용하는 것이 나을 수도 있겟네여! private boolean isLogin() { return SecurityContextHolder .getContext() From f257082b77b21c577f2f7b5966cfc59dbfe4e0ef Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 11:41:31 +0900 Subject: [PATCH 15/46] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EB=B3=80=EC=88=98=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/backendoori/ootw/like/service/LikeServiceTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/com/backendoori/ootw/like/service/LikeServiceTest.java b/src/test/java/com/backendoori/ootw/like/service/LikeServiceTest.java index 5f23d62b..90acc3c6 100644 --- a/src/test/java/com/backendoori/ootw/like/service/LikeServiceTest.java +++ b/src/test/java/com/backendoori/ootw/like/service/LikeServiceTest.java @@ -40,8 +40,6 @@ public class LikeServiceTest extends TokenMockMvcTest { static final String POST_NOT_FOUND_MESSAGE = "해당 게시글이 존재하지 않습니다."; static final Faker FAKER = new Faker(); - static final int NX = 55; - static final int NY = 127; User user; From 0d795cbffa0791075aab9c7f3217068bd4b016f0 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 11:41:43 +0900 Subject: [PATCH 16/46] =?UTF-8?q?refactor:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/backendoori/ootw/post/validation/Message.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/backendoori/ootw/post/validation/Message.java b/src/main/java/com/backendoori/ootw/post/validation/Message.java index f5e758a9..2949815b 100644 --- a/src/main/java/com/backendoori/ootw/post/validation/Message.java +++ b/src/main/java/com/backendoori/ootw/post/validation/Message.java @@ -7,7 +7,7 @@ public final class Message { public static final String POST_NOT_FOUND = "해당하는 게시글이 없습니다."; - public static final String NULL_POST = "게시글 생성 요청 정보가 null이어서는 안됩니다."; + public static final String NULL_POST = "게시글 생성/수정 요청 정보가 null이어서는 안됩니다."; public static final String NULL_WRITER = "게시글 생성 요청 사용자가 null이어서는 안됩니다."; From 74b0d47d009c7d5200c93ca19d5ef7fb668d9b1c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 11:42:28 +0900 Subject: [PATCH 17/46] =?UTF-8?q?refactor:=20Post=20setter=EC=97=90=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/backendoori/ootw/post/domain/Post.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/domain/Post.java b/src/main/java/com/backendoori/ootw/post/domain/Post.java index 588be708..78bb6408 100644 --- a/src/main/java/com/backendoori/ootw/post/domain/Post.java +++ b/src/main/java/com/backendoori/ootw/post/domain/Post.java @@ -1,11 +1,13 @@ package com.backendoori.ootw.post.domain; import static com.backendoori.ootw.post.validation.PostValidator.validatePostSaveRequest; +import static com.backendoori.ootw.post.validation.PostValidator.validatePostUpdateRequest; import static com.backendoori.ootw.post.validation.PostValidator.validateTemperatureArrange; import static com.backendoori.ootw.post.validation.PostValidator.validateUser; import com.backendoori.ootw.common.BaseEntity; import com.backendoori.ootw.post.dto.request.PostSaveRequest; +import com.backendoori.ootw.post.dto.request.PostUpdateRequest; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.weather.domain.TemperatureArrange; import jakarta.persistence.Column; @@ -38,11 +40,9 @@ public class Post extends BaseEntity { @JoinColumn(name = "user_id", nullable = false) private User user; - @Setter @Column(name = "title", nullable = false) private String title; - @Setter @Column(name = "content", nullable = false) private String content; @@ -72,6 +72,12 @@ public static Post from(User user, PostSaveRequest request, String imgUrl, Tempe return new Post(user, request, imgUrl, temperatureArrange); } + public void setTitleAndContent(PostUpdateRequest request) { + validatePostUpdateRequest(request); + this.title = request.title(); + this.content = request.content(); + } + public void increaseLikeCnt() { this.likeCnt++; } From 6db9a4b8fe15c2d1182c12b2893ad0ad465654ab Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 11:43:02 +0900 Subject: [PATCH 18/46] =?UTF-8?q?test:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95/=EC=82=AD=EC=A0=9C=20controller=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/controller/PostControllerTest.java | 392 ++++++++++++++++-- 1 file changed, 358 insertions(+), 34 deletions(-) diff --git a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java index 54f98f79..a0d62684 100644 --- a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java +++ b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java @@ -1,11 +1,14 @@ package com.backendoori.ootw.post.controller; +import static com.backendoori.ootw.post.validation.Message.POST_NOT_FOUND; import static com.backendoori.ootw.security.jwt.JwtAuthenticationFilter.TOKEN_HEADER; import static com.backendoori.ootw.security.jwt.JwtAuthenticationFilter.TOKEN_PREFIX; import static com.backendoori.ootw.util.provider.ForecastApiCommonRequestSourceProvider.VALID_COORDINATE; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -17,9 +20,11 @@ import java.util.List; import java.util.Map; import com.backendoori.ootw.post.domain.Post; -import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.request.PostSaveRequest; +import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; +import com.backendoori.ootw.post.exception.NoPostPermissionException; +import com.backendoori.ootw.post.exception.ResourceNotExistException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.post.service.PostService; import com.backendoori.ootw.security.TokenMockMvcTest; @@ -28,7 +33,9 @@ import com.backendoori.ootw.weather.domain.TemperatureArrange; import com.backendoori.ootw.weather.domain.forecast.ForecastCategory; import com.backendoori.ootw.weather.service.WeatherService; +import com.fasterxml.jackson.core.JsonProcessingException; import net.datafaker.Faker; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -44,11 +51,13 @@ import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.test.context.TestSecurityContextHolder; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.request.RequestPostProcessor; @TestInstance(Lifecycle.PER_CLASS) class PostControllerTest extends TokenMockMvcTest { static final Faker FAKER = new Faker(); + public static final String BASE_URL = "http://localhost:8080/api/v1/posts"; User user; @@ -93,8 +102,345 @@ private User generateUser() { .build(); } + @NotNull + private static MockMultipartFile getPostImg() { + return new MockMultipartFile("postImg", "filename.txt", MediaType.MULTIPART_FORM_DATA_VALUE, + "some xml".getBytes()); + } + + @NotNull + private static RequestPostProcessor makeRequestMethodToPut() { + return req -> { + req.setMethod("PUT"); + return req; + }; + } + + @NotNull + private MockMultipartFile getRequestJson(String testTitle) throws JsonProcessingException { + PostSaveRequest postSaveRequest = + new PostSaveRequest(testTitle, "Test Content", VALID_COORDINATE); + + return new MockMultipartFile("request", "request.json", MediaType.APPLICATION_JSON_VALUE, + objectMapper.writeValueAsBytes(postSaveRequest)); + } + + @Nested + @DisplayName("게시글 삭제하기") + class DeleteTest { + + Post userPost; + Post otherPost; + + @BeforeEach + void setup() { + userPost = postRepository.save( + Post.from(user, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + generateTemperatureArrange())); + + User other = userRepository.save(generateUser()); + otherPost = postRepository.save( + Post.from(other, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + generateTemperatureArrange())); + } + + @Test + @DisplayName("게시글 삭제에 성공한다.") + void deleteSuccess() throws Exception { + // given // when + MockHttpServletRequestBuilder requestBuilder = + delete(BASE_URL + "/" + userPost.getId()) + .header(TOKEN_HEADER, TOKEN_PREFIX + token); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isNoContent()) + .andReturn(); + } + + @Test + @DisplayName("로그인을 안한 사용자는 게시글 삭제에 접근이 불가하다.") + void deleteFaildeleteFailWithUnauthorizedUser() throws Exception { + // given // when + MockHttpServletRequestBuilder requestBuilder = + delete(BASE_URL + "/" + userPost.getId()); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isUnauthorized()) + .andReturn(); + } + + @Test + @DisplayName("게시글 주인이 아닌 사용자가 게시글 삭제에 실패한다.") + void deleteFailWithNoPermission() throws Exception { + // given // when + MockHttpServletRequestBuilder requestBuilder = + delete(BASE_URL + "/" + otherPost.getId()) + .header(TOKEN_HEADER, TOKEN_PREFIX + token); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isForbidden()) + .andExpect(jsonPath("$.message", is(NoPostPermissionException.DEFAULT_MESSAGE))) + .andReturn(); + } + + @Test + @DisplayName("존재하지 않는 게시글 삭제에 실패한다.") + void deleteFailWithNonExistPost() throws Exception { + // given // when + MockHttpServletRequestBuilder requestBuilder = + delete(BASE_URL + "/" + otherPost.getId() + 1) + .header(TOKEN_HEADER, TOKEN_PREFIX + token); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.message", is(POST_NOT_FOUND))) + .andReturn(); + } + + } + + @Nested + @DisplayName("게시글 수정하기") + class UpdateTest { + + Post userPost; + Post otherPost; + + @BeforeEach + void setup() { + userPost = postRepository.save( + Post.from(user, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + generateTemperatureArrange())); + + User other = userRepository.save(generateUser()); + otherPost = postRepository.save( + Post.from(other, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + generateTemperatureArrange())); + } + + @Nested + @DisplayName("게시글 수정에 성공한다") + class UpdateSuccess { + + @Test + @DisplayName(" 게시글 정보와 이미지 수정에 성공한다.") + void updateAllSuccess() throws Exception { + // given + MockMultipartFile request = getRequestJson("Test Title"); + MockMultipartFile postImg = getPostImg(); + + // when + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) + .file(request) + .file(postImg) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.MULTIPART_FORM_DATA) + .accept(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .with(makeRequestMethodToPut()); + + // then + MockHttpServletResponse response = mockMvc.perform(requestBuilder) + .andExpect(status().isCreated()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + assertThat(response.getHeader("location")).contains("/api/v1/posts/"); + } + + @Test + @DisplayName("게시글 정보 수정에 성공한다.") + void updatePostUpdateRequestSuccess() throws Exception { + // given + MockMultipartFile request = getRequestJson("Test Title"); + + // when + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) + .file(request) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .accept(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8) + .with(makeRequestMethodToPut()); + + // then + MockHttpServletResponse response = mockMvc.perform(requestBuilder) + .andExpect(status().isCreated()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + assertThat(response.getHeader("location")).contains("/api/v1/posts/"); + } + + @Test + @DisplayName("게시글 이미지 수정에 성공한다.") + void updatePostImageSuccess() throws Exception { + // given + MockMultipartFile postImg = getPostImg(); + + // when + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) + .file(postImg) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.MULTIPART_FORM_DATA) + .characterEncoding(StandardCharsets.UTF_8) + .with(makeRequestMethodToPut()); + + // then + MockHttpServletResponse response = mockMvc.perform(requestBuilder) + .andExpect(status().isCreated()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn() + .getResponse(); + + assertThat(response.getHeader("location")).contains("/api/v1/posts/"); + } + + } + + @Nested + @DisplayName("게시글 수정에 실패한다") + class UpdateFail { + + @Test + @DisplayName("로그인을 안한 사용자는 게시글 수정에 접근이 불가하다.") + void updateFailWithUnauthorizedUser() throws Exception { + // given + MockMultipartFile request = getRequestJson("Test Title"); + MockMultipartFile postImg = getPostImg(); + + // when + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) + .file(request) + .file(postImg) + .contentType(MediaType.MULTIPART_FORM_DATA) + .characterEncoding(StandardCharsets.UTF_8) + .with(makeRequestMethodToPut()); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isUnauthorized()) + .andReturn(); + } + + @Test + @DisplayName("게시글 주인이 아닌 사용자가 게시글 수정에 실패한다.") + void updateFailWithPermission() throws Exception { + // given + MockMultipartFile request = getRequestJson("Test Title"); + MockMultipartFile postImg = getPostImg(); + + // when + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + otherPost.getId()) + .file(request) + .file(postImg) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.MULTIPART_FORM_DATA) + .characterEncoding(StandardCharsets.UTF_8) + .with(makeRequestMethodToPut()); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isForbidden()) + .andExpect(jsonPath("$.message", is(NoPostPermissionException.DEFAULT_MESSAGE))) + .andReturn(); + } + + @Test + @DisplayName("존재하지 않는 게시글 수정에 실패한다.") + void updateFailWithNonExistPost() throws Exception { + // given + MockMultipartFile request = getRequestJson("Test Title"); + MockMultipartFile postImg = getPostImg(); + + // when + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + otherPost.getId() + 1) + .file(request) + .file(postImg) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.MULTIPART_FORM_DATA) + .characterEncoding(StandardCharsets.UTF_8) + .with(makeRequestMethodToPut()); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isNotFound()) + .andExpect(jsonPath("$.message", is(POST_NOT_FOUND))) + .andReturn(); + } + + @Test + @DisplayName("수정할 리소스를 전혀 보내지 않으면 실패한다.") + void updateFailWithNoResource() throws Exception { + // given // when + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.MULTIPART_FORM_DATA) + .characterEncoding(StandardCharsets.UTF_8) + .with(makeRequestMethodToPut()); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.message", is(ResourceNotExistException.DEFAULT_MESSAGE))) + .andReturn(); + } + + @Test + @DisplayName("수정할 이미지만 보냈는데 null이면 수정에 실패한다.") + void updateFailWithNullImage() throws Exception { + // given + MockMultipartFile request = getRequestJson("Test Title"); + MockMultipartFile postImg = getPostImg(); + + // when + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) + .file(request) + .file(postImg) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.MULTIPART_FORM_DATA) + .characterEncoding(StandardCharsets.UTF_8) + .with(makeRequestMethodToPut()); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isCreated()) + .andReturn(); + } + + @Test + @DisplayName("수정할 게시글 정보를 보냈는데 null이면 수정에 실패한다.") + void updateFailWithNullPostUpdateRequest() throws Exception { + // given + MockMultipartFile request = getRequestJson("Test Title"); + MockMultipartFile postImg = getPostImg(); + + // when + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) + .file(request) + .file(postImg) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.MULTIPART_FORM_DATA) + .characterEncoding(StandardCharsets.UTF_8) + .with(makeRequestMethodToPut()); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isCreated()) + .andReturn(); + } + + } + + } + @Nested - @DisplayName("게시글 저장 테스트") + @DisplayName("게시글 저장하기") class SaveTest { @Test @@ -104,14 +450,8 @@ void saveSuccess() throws Exception { given(weatherService.getCurrentTemperatureArrange(VALID_COORDINATE)) .willReturn(generateTemperatureArrange()); - PostSaveRequest postSaveRequest = - new PostSaveRequest("Test Title", "Test Content", VALID_COORDINATE); - MockMultipartFile request = - new MockMultipartFile("request", "request.json", MediaType.APPLICATION_JSON_VALUE, - objectMapper.writeValueAsBytes(postSaveRequest)); - MockMultipartFile postImg = - new MockMultipartFile("postImg", "filename.txt", MediaType.MULTIPART_FORM_DATA_VALUE, - "some xml".getBytes()); + MockMultipartFile request = getRequestJson("Test Title"); + MockMultipartFile postImg = getPostImg(); // when MockHttpServletRequestBuilder requestBuilder = multipart("http://localhost:8080/api/v1/posts") @@ -141,14 +481,8 @@ void saveFailNonSavedUser() throws Exception { given(weatherService.getCurrentTemperatureArrange(VALID_COORDINATE)) .willReturn(generateTemperatureArrange()); - PostSaveRequest postSaveRequest = - new PostSaveRequest("Test Title", "Test Content", VALID_COORDINATE); - MockMultipartFile request = - new MockMultipartFile("request", "request.json", MediaType.APPLICATION_JSON_VALUE, - objectMapper.writeValueAsBytes(postSaveRequest)); - MockMultipartFile postImg = - new MockMultipartFile("postImg", "filename.txt", MediaType.MULTIPART_FORM_DATA_VALUE, - "some xml".getBytes()); + MockMultipartFile request = getRequestJson("Test Title"); + MockMultipartFile postImg = getPostImg(); // when MockHttpServletRequestBuilder requestBuilder = multipart("http://localhost:8080/api/v1/posts") @@ -171,13 +505,8 @@ void saveFailByMethodArgumentNotValidException() throws Exception { given(weatherService.getCurrentTemperatureArrange(VALID_COORDINATE)) .willReturn(generateTemperatureArrange()); - PostSaveRequest postSaveRequest = new PostSaveRequest("", "Test Content", VALID_COORDINATE); - MockMultipartFile request = - new MockMultipartFile("request", "request.json", MediaType.APPLICATION_JSON_VALUE, - objectMapper.writeValueAsBytes(postSaveRequest)); - MockMultipartFile postImg = - new MockMultipartFile("postImg", "filename.txt", MediaType.MULTIPART_FORM_DATA_VALUE, - "some xml".getBytes()); + MockMultipartFile request = getRequestJson(""); + MockMultipartFile postImg = getPostImg(); // when MockHttpServletRequestBuilder requestBuilder = multipart("http://localhost:8080/api/v1/posts") @@ -198,13 +527,8 @@ void saveFailByMethodArgumentNotValidException() throws Exception { @DisplayName("유효하지 않은 요청 값(게시글 제목)이 포함된 게시글 저장에 실패한다.") void saveFailInvalidValueByIllegalArgumentException() throws Exception { // given - PostSaveRequest postSaveRequest = new PostSaveRequest("", "Test Content", VALID_COORDINATE); - MockMultipartFile request = - new MockMultipartFile("request", "request.json", MediaType.APPLICATION_JSON_VALUE, - objectMapper.writeValueAsBytes(postSaveRequest)); - MockMultipartFile postImg = - new MockMultipartFile("postImg", "filename.txt", MediaType.MULTIPART_FORM_DATA_VALUE, - "some xml".getBytes()); + MockMultipartFile request = getRequestJson(""); + MockMultipartFile postImg = getPostImg(); // when MockHttpServletRequestBuilder requestBuilder = multipart("http://localhost:8080/api/v1/posts") @@ -224,7 +548,7 @@ void saveFailInvalidValueByIllegalArgumentException() throws Exception { @Nested @DisplayName("게시글 단건 조회하기") - class GetDetailByPostId { + class GetDetailByPostIdTest { private static final String URL = "http://localhost:8080/api/v1/posts/"; @@ -274,7 +598,7 @@ void getDetailByPostIdSuccess() throws Exception { @Nested @DisplayName("게시글 목록 조회하기") - class GetAll { + class GetAllTest { static final Integer SAVE_COUNT = 10; From 453a25705b26484feaae888fc8b301163e28d53f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 11:43:47 +0900 Subject: [PATCH 19/46] =?UTF-8?q?refactor:=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/backendoori/ootw/post/service/PostService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index 3dab2e10..6b1b8557 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -110,6 +110,7 @@ public void delete(Long postId) { postRepository.delete(post); } + @Transactional public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpdateRequest request) { Post post = postRepository.findById(postId) @@ -122,12 +123,12 @@ public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpd }); if (Objects.nonNull(request)) { - post.setTitle(request.title()); - post.setContent(request.content()); + post.setTitleAndContent(request); } if (Objects.nonNull(postImg)) { // TODO: 기존 저장된 이미지 삭제(원래 null인 경우도 있으니 주의) + // imageService.uploadImage(postImg)가 잘못 저장되어 null 인 경우도 있을까..? post.setImage(imageService.uploadImage(postImg)); } From 8a3d66f846df95f74e46393ac560b90725fc532a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 11:44:06 +0900 Subject: [PATCH 20/46] =?UTF-8?q?refactor:=20PostUpdateRequest=EC=9D=98=20?= =?UTF-8?q?=EB=82=B4=EC=9A=A9=EC=9D=84=20=EA=B2=80=EC=A6=9D=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backendoori/ootw/post/validation/PostValidator.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java b/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java index a5b831e3..98121a91 100644 --- a/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java +++ b/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java @@ -9,6 +9,7 @@ import static com.backendoori.ootw.post.validation.Message.NULL_WRITER; import com.backendoori.ootw.post.dto.request.PostSaveRequest; +import com.backendoori.ootw.post.dto.request.PostUpdateRequest; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.weather.domain.TemperatureArrange; import org.springframework.util.Assert; @@ -28,6 +29,12 @@ public static void validatePostSaveRequest(PostSaveRequest request) { validateContent(request.content()); } + public static void validatePostUpdateRequest(PostUpdateRequest request) { + Assert.notNull(request, NULL_POST); + validateTitle(request.title()); + validateContent(request.content()); + } + public static void validateTemperatureArrange(TemperatureArrange temperatureArrange) { Assert.notNull(temperatureArrange, NULL_TEMPERATURE_ARRANGE); } From 86b497b1ea668af645a1c1bd058aa207d10b2fd9 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 11:44:29 +0900 Subject: [PATCH 21/46] =?UTF-8?q?test:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95/=EC=82=AD=EC=A0=9C=20service=20=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=96=B4=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/post/service/PostServiceTest.java | 232 +++++++++++++++++- 1 file changed, 227 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java index 2f81157f..5bf0d46a 100644 --- a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java +++ b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java @@ -1,10 +1,15 @@ package com.backendoori.ootw.post.service; +import static com.backendoori.ootw.post.validation.Message.BLANK_POST_CONTENT; +import static com.backendoori.ootw.post.validation.Message.BLANK_POST_TITLE; +import static com.backendoori.ootw.post.validation.Message.INVALID_POST_CONTENT; +import static com.backendoori.ootw.post.validation.Message.INVALID_POST_TITLE; import static com.backendoori.ootw.post.validation.Message.POST_NOT_FOUND; import static com.backendoori.ootw.util.provider.ForecastApiCommonRequestSourceProvider.VALID_COORDINATE; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.BDDMockito.given; @@ -19,10 +24,13 @@ import com.backendoori.ootw.like.repository.LikeRepository; import com.backendoori.ootw.like.service.LikeService; import com.backendoori.ootw.post.domain.Post; -import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.request.PostSaveRequest; +import com.backendoori.ootw.post.dto.request.PostUpdateRequest; +import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; import com.backendoori.ootw.post.dto.response.WriterDto; +import com.backendoori.ootw.post.exception.NoPostPermissionException; +import com.backendoori.ootw.post.exception.ResourceNotExistException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.user.repository.UserRepository; @@ -99,8 +107,223 @@ void cleanup() { userRepository.deleteAll(); } + + @Nested + @DisplayName("게시글 삭제하기") + class DeleteTest { + + Post userPost; + Post otherPost; + + @BeforeEach + void setup() { + userPost = postRepository.save( + Post.from(user, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + generateTemperatureArrange())); + + User other = userRepository.save(generateUser()); + otherPost = postRepository.save( + Post.from(other, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + generateTemperatureArrange())); + } + + @Test + @DisplayName("게시글 삭제에 성공한다.") + void deleteSuccess() { + // given // when // then + assertDoesNotThrow(() -> postService.delete(userPost.getId())); + } + + @Test + @DisplayName("게시글 주인이 아닌 사용자가 게시글 삭제에 실패한다.") + void deleteFailWithNoPermission() { + // given // when + ThrowingCallable deletePost = () -> postService.delete(otherPost.getId()); + + // then + assertThatExceptionOfType(NoPostPermissionException.class) + .isThrownBy(deletePost) + .withMessage(NoPostPermissionException.DEFAULT_MESSAGE); + } + + @Test + @DisplayName("존재하지 않는 게시글 삭제에 실패한다.") + void deleteFailWithNonExistPost() { + // given // when + ThrowingCallable deletePost = () -> postService.delete(otherPost.getId() + 1); + + // then + assertThatExceptionOfType(NoSuchElementException.class) + .isThrownBy(deletePost) + .withMessage(POST_NOT_FOUND); + } + + } + @Nested - @DisplayName("게시글 저장 테스트") + @DisplayName("게시글 수정하기") + class UpdateTest { + + Post userPost; + Post otherPost; + + @BeforeEach + void setup() { + userPost = postRepository.save( + Post.from(user, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + generateTemperatureArrange())); + + User other = userRepository.save(generateUser()); + otherPost = postRepository.save( + Post.from(other, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + generateTemperatureArrange())); + } + + @Nested + @DisplayName("게시글 수정에 성공한다") + class UpdateSuccess { + + @Test + @DisplayName(" 게시글 정보와 이미지 수정에 성공한다.") + void updateAllSuccess() { + // given + PostUpdateRequest request = new PostUpdateRequest("Test Title", "Test Content"); + MockMultipartFile postImg = new MockMultipartFile("file", "filename.txt", + "text/plain", "some xml".getBytes()); + + String imgUrl = "imgUrl"; + given(imageService.uploadImage(postImg)).willReturn(imgUrl); + + // when + PostSaveUpdateResponse response = postService.update(userPost.getId(), postImg, request); + + //then + assertAll( + () -> assertThat(response).hasFieldOrPropertyWithValue("title", request.title()), + () -> assertThat(response).hasFieldOrPropertyWithValue("content", request.content()), + () -> assertThat(response).hasFieldOrPropertyWithValue("image", imgUrl) + ); + } + + @Test + @DisplayName("게시글 정보만 수정에 성공한다.") + void updatePostUpdateRequestSuccess() { + // given + PostUpdateRequest request = new PostUpdateRequest("Test Title", "Test Content"); + + // when + PostSaveUpdateResponse response = postService.update(userPost.getId(), null, request); + + //then + assertAll( + () -> assertThat(response).hasFieldOrPropertyWithValue("title", request.title()), + () -> assertThat(response).hasFieldOrPropertyWithValue("content", request.content()) + ); + } + + @Test + @DisplayName("게시글 이미지만 수정에 성공한다.") + void updatePostImageSuccess() { + // given + MockMultipartFile postImg = new MockMultipartFile("file", "filename.txt", + "text/plain", "some xml".getBytes()); + String imgUrl = "imgUrl"; + + given(imageService.uploadImage(postImg)).willReturn(imgUrl); + + // when + PostSaveUpdateResponse response = postService.update(userPost.getId(), postImg, null); + + //then + assertThat(response).hasFieldOrPropertyWithValue("image", imgUrl); + } + + } + + @Nested + @DisplayName("게시글 수정에 실패한다") + class UpdateFail { + + static Stream provideInvalidPostUpdateRequest() { + return Stream.of( + Arguments.of("제목이 null인 경우", new PostUpdateRequest(null, "content"), BLANK_POST_TITLE), + Arguments.of("제목이 공백인 경우", new PostUpdateRequest(" ", "content"), BLANK_POST_TITLE), + Arguments.of("제목이 30자가 넘는 경우", new PostUpdateRequest("t".repeat(31), "content"), + INVALID_POST_TITLE), + Arguments.of("내용이 null인 경우", new PostUpdateRequest("title", null), BLANK_POST_CONTENT), + Arguments.of("내용이 공백인 경우", new PostUpdateRequest("title", " "), BLANK_POST_CONTENT), + Arguments.of("내용이 500자가 넘는 경우", new PostUpdateRequest("title", "t".repeat(501)), + INVALID_POST_CONTENT), + Arguments.of("제목과 내용이 모두 null인 경우", new PostUpdateRequest(null, null), BLANK_POST_TITLE), + Arguments.of("제목과 내용이 모두 공백인 경우", new PostUpdateRequest(" ", " "), BLANK_POST_TITLE) + ); + } + + @Test + @DisplayName("게시글 주인이 아닌 사용자가 게시글 수정에 실패한다.") + void updateFailWithPermission() { + // given + PostUpdateRequest request = new PostUpdateRequest("Test Title", "Test Content"); + MockMultipartFile postImg = new MockMultipartFile("file", "filename.txt", + "text/plain", "some xml".getBytes()); + + // when + ThrowingCallable updatePost = () -> postService.update(otherPost.getId(), postImg, request); + + //then + assertThatExceptionOfType(NoPostPermissionException.class) + .isThrownBy(updatePost) + .withMessage(NoPostPermissionException.DEFAULT_MESSAGE); + } + + @Test + @DisplayName("존재하지 않는 게시글 수정에 실패한다.") + void updateFailWithNonExistPost() { + // given + PostUpdateRequest request = new PostUpdateRequest("Test Title", "Test Content"); + MockMultipartFile postImg = new MockMultipartFile("file", "filename.txt", + "text/plain", "some xml".getBytes()); + + // when + ThrowingCallable updatePost = () -> postService.update(otherPost.getId() + 1, postImg, request); + + //then + assertThatExceptionOfType(NoSuchElementException.class) + .isThrownBy(updatePost) + .withMessage(POST_NOT_FOUND); + } + + @Test + @DisplayName("수정할 리소스를 전혀 보내지 않으면 실패한다.") + void updateFailWithNoResource() { + // given // when + ThrowingCallable updatePost = () -> postService.update(userPost.getId(), null, null); + + //then + assertThatExceptionOfType(ResourceNotExistException.class) + .isThrownBy(updatePost) + .withMessage(ResourceNotExistException.DEFAULT_MESSAGE); + } + + @ParameterizedTest(name = "[{index}] {0}") + @MethodSource("provideInvalidPostUpdateRequest") + @DisplayName("수정할 게시글 정보를 보냈는데 제목이나 내용이 null이거나 공백이면 수정에 실패한다.") + void updateFailWithNullPostUpdateRequest(String testCase, PostUpdateRequest request, String message) { + // given // when + ThrowingCallable updatePost = () -> postService.update(userPost.getId(), null, request); + + //then + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(updatePost) + .withMessage(message); + } + + } + + } + + @Nested + @DisplayName("게시글 저장하기") class SaveTest { @Test @@ -184,7 +407,7 @@ void saveFailWithInvalidValue(String title, String content) { @Nested @DisplayName("게시글 단건 조회하기") - class GetDetailByPostId { + class GetDetailByPostIdTest { PostSaveUpdateResponse postSaveResponse; @@ -281,12 +504,11 @@ void getAllSuccessWithoutLogin() { } - } @Nested @DisplayName("게시글 목록 조회하기") - class GetAll { + class GetAllTest { static final Integer SAVE_COUNT = 10; From 7e990c6a9c28e47e0c10fb6b7e6ecd7051804b41 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 12:05:42 +0900 Subject: [PATCH 22/46] =?UTF-8?q?fix:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=8B=9C=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=EA=B0=80=20null=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=EC=97=90?= =?UTF-8?q?=EB=8F=84=20=EC=83=9D=EC=84=B1=20=EA=B0=80=EB=8A=A5=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/backendoori/ootw/post/service/PostService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index 6b1b8557..5f947b61 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -45,8 +45,11 @@ public PostSaveUpdateResponse save(PostSaveRequest request, MultipartFile postIm User user = userRepository.findById(getUserId()) .orElseThrow(UserNotFoundException::new); - // TODO: 이미지가 null인 경우 설정하기 - String imgUrl = imageService.uploadImage(postImg); + String imgUrl = null; + if (!Objects.isNull(postImg)) { + imgUrl = imageService.uploadImage(postImg); + } + TemperatureArrange temperatureArrange = weatherService.getCurrentTemperatureArrange(request.coordinate()); Post savedPost = postRepository.save(Post.from(user, request, imgUrl, temperatureArrange)); From f62dc5aca506c218d0c5a90a0cbb626fe567c214 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 18:02:10 +0900 Subject: [PATCH 23/46] =?UTF-8?q?refactor:=20AvatarItem=20imageUrl?= =?UTF-8?q?=EB=A1=9C=20=ED=95=84=EB=93=9C=EB=AA=85=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EB=B0=8F=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/backendoori/ootw/avatar/domain/AvatarItem.java | 10 +++++----- .../ootw/avatar/dto/AvatarItemResponse.java | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/avatar/domain/AvatarItem.java b/src/main/java/com/backendoori/ootw/avatar/domain/AvatarItem.java index 473f6084..67b1a625 100644 --- a/src/main/java/com/backendoori/ootw/avatar/domain/AvatarItem.java +++ b/src/main/java/com/backendoori/ootw/avatar/domain/AvatarItem.java @@ -28,8 +28,8 @@ public class AvatarItem { @Column(name = "id") private Long id; - @Column(name = "image", nullable = false) - private String image; + @Column(name = "image_url", nullable = false) + private String imageUrl; @Column(name = "type", nullable = false, columnDefinition = "varchar(30)") @Enumerated(EnumType.STRING) @@ -39,12 +39,12 @@ public class AvatarItem { @Enumerated(EnumType.STRING) private Sex sex; - private AvatarItem(String image, String type, String sex) { - validateImage(image); + private AvatarItem(String imageUrl, String type, String sex) { + validateImage(imageUrl); validateItemType(type); validateSex(sex); - this.image = image; + this.imageUrl = imageUrl; this.itemType = ItemType.valueOf(type); this.sex = Sex.valueOf(sex); } diff --git a/src/main/java/com/backendoori/ootw/avatar/dto/AvatarItemResponse.java b/src/main/java/com/backendoori/ootw/avatar/dto/AvatarItemResponse.java index fd51ad4f..bb0bc156 100644 --- a/src/main/java/com/backendoori/ootw/avatar/dto/AvatarItemResponse.java +++ b/src/main/java/com/backendoori/ootw/avatar/dto/AvatarItemResponse.java @@ -14,7 +14,7 @@ public static AvatarItemResponse from(AvatarItem avatarItem) { avatarItem.getId(), avatarItem.getItemType().name(), avatarItem.getSex().name(), - avatarItem.getImage()); + avatarItem.getImageUrl()); } } From 11d3eca5418b0b54670df034279d6c6c70db318d Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 18:02:53 +0900 Subject: [PATCH 24/46] =?UTF-8?q?refactor:=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=20=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=8A=94=20null=EB=A1=9C=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=ED=95=A0=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/backendoori/ootw/post/domain/Post.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/domain/Post.java b/src/main/java/com/backendoori/ootw/post/domain/Post.java index 549493b4..6786a08f 100644 --- a/src/main/java/com/backendoori/ootw/post/domain/Post.java +++ b/src/main/java/com/backendoori/ootw/post/domain/Post.java @@ -89,8 +89,6 @@ public void updateContent(String content) { } public void updateImageUrl(String imageUrl) { - validateContent(content); this.imageUrl = imageUrl; } - } From da2f23c8ed11c4c8f31c481a8412f70cb8bdbc30 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 18:09:40 +0900 Subject: [PATCH 25/46] =?UTF-8?q?fix:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?-=20=EB=AA=A8=EB=93=A0=20=EA=B2=8C=EC=8B=9C=EA=B8=80=EC=9D=98?= =?UTF-8?q?=20=EC=A0=95=EB=B3=B4(=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=A0=9C?= =?UTF-8?q?=EB=AA=A9,=20=EB=82=B4=EC=9A=A9)=EC=9D=84=20=EB=B3=B4=EB=82=B4?= =?UTF-8?q?=EC=95=BC=ED=95=9C=EB=8B=A4.=20-=20=EB=8B=A8=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=EB=8A=94=20=ED=95=84=EC=88=98=EA=B0=80=20?= =?UTF-8?q?=EC=95=84=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/post/service/PostService.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index 0bac1f38..04e394db 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -1,5 +1,6 @@ package com.backendoori.ootw.post.service; +import static com.backendoori.ootw.post.validation.Message.NULL_POST; import static com.backendoori.ootw.post.validation.Message.POST_NOT_FOUND; import java.util.List; @@ -18,7 +19,6 @@ import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; import com.backendoori.ootw.post.exception.NoPostPermissionException; -import com.backendoori.ootw.post.exception.ResourceNotExistException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.user.repository.UserRepository; @@ -129,29 +129,29 @@ public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpd checkUserHasPostPermission(post); - Assert.isTrue(Objects.nonNull(request) || Objects.nonNull(postImg), () -> { - throw new ResourceNotExistException(); + Assert.isTrue(Objects.nonNull(request), () -> { + throw new IllegalArgumentException(NULL_POST); }); - if (Objects.nonNull(request)) { - post.updateTitle(request.title()); - post.updateContent(request.content()); + post.updateTitle(request.title()); + post.updateContent(request.content()); + + if (Objects.isNull(postImg) || postImg.isEmpty()) { + post.updateImageUrl(null); + return PostSaveUpdateResponse.from(post); } - if (Objects.nonNull(postImg) && !postImg.isEmpty()) { - ImageFile imgFile = imageService.upload(postImg); - try { - // TODO: 기존 저장된 이미지 삭제(원래 null인 경우도 있으니 주의) - // imageService.uploadImage(postImg)가 잘못 저장되어 null 인 경우도 있을까..? - post.setImage(imgFile.url()); - - return PostSaveUpdateResponse.from(post); - } catch (Exception e) { - imageService.delete(imgFile.fileName()); - throw new SaveException(); - } + ImageFile imgFile = imageService.upload(postImg); + try { + // TODO: 기존 저장된 이미지 삭제(원래 null인 경우도 있으니 주의) + // imageService.uploadImage(postImg)가 잘못 저장되어 null 인 경우도 있을까..? + post.updateImageUrl(imgFile.url()); + + return PostSaveUpdateResponse.from(post); + } catch (Exception e) { + imageService.delete(imgFile.fileName()); + throw new SaveException(); } - return PostSaveUpdateResponse.from(post); } private List getLikedPostId(long userId) { From 6b70b2827a87a23bd37a6dbc32f4bacc697dd623 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 18:30:21 +0900 Subject: [PATCH 26/46] =?UTF-8?q?fix:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EC=A0=95=EB=B3=B4=20=EC=97=86=EC=9D=B4=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=EC=9D=84=20=EB=B3=B4=EB=82=BC=20=EB=95=8C=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=8B=A4=EC=8B=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/post/service/PostService.java | 4 +-- .../post/controller/PostControllerTest.java | 25 ------------------- .../ootw/post/domain/PostTest.java | 2 +- .../ootw/post/service/PostServiceTest.java | 17 ------------- 4 files changed, 3 insertions(+), 45 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index 04e394db..874738fa 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -1,6 +1,5 @@ package com.backendoori.ootw.post.service; -import static com.backendoori.ootw.post.validation.Message.NULL_POST; import static com.backendoori.ootw.post.validation.Message.POST_NOT_FOUND; import java.util.List; @@ -19,6 +18,7 @@ import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; import com.backendoori.ootw.post.exception.NoPostPermissionException; +import com.backendoori.ootw.post.exception.ResourceNotExistException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.user.repository.UserRepository; @@ -130,7 +130,7 @@ public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpd checkUserHasPostPermission(post); Assert.isTrue(Objects.nonNull(request), () -> { - throw new IllegalArgumentException(NULL_POST); + throw new ResourceNotExistException(); }); post.updateTitle(request.title()); diff --git a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java index 0c0deb26..2a586803 100644 --- a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java +++ b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java @@ -5,7 +5,6 @@ import static com.backendoori.ootw.security.jwt.JwtAuthenticationFilter.TOKEN_PREFIX; import static com.backendoori.ootw.util.provider.ForecastApiCommonRequestSourceProvider.VALID_COORDINATE; import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.mockito.BDDMockito.given; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; @@ -281,30 +280,6 @@ void updatePostUpdateRequestSuccess() throws Exception { assertThat(response.getHeader("location")).contains("/api/v1/posts/"); } - @Test - @DisplayName("게시글 이미지 수정에 성공한다.") - void updatePostImageSuccess() throws Exception { - // given - MockMultipartFile postImg = getPostImg(); - - // when - MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) - .file(postImg) - .header(TOKEN_HEADER, TOKEN_PREFIX + token) - .contentType(MediaType.MULTIPART_FORM_DATA) - .characterEncoding(StandardCharsets.UTF_8) - .with(makeRequestMethodToPut()); - - // then - MockHttpServletResponse response = mockMvc.perform(requestBuilder) - .andExpect(status().isCreated()) - .andExpect(content().contentType(MediaType.APPLICATION_JSON)) - .andReturn() - .getResponse(); - - assertThat(response.getHeader("location")).contains("/api/v1/posts/"); - } - } @Nested diff --git a/src/test/java/com/backendoori/ootw/post/domain/PostTest.java b/src/test/java/com/backendoori/ootw/post/domain/PostTest.java index 1c7cd6e2..e41a104b 100644 --- a/src/test/java/com/backendoori/ootw/post/domain/PostTest.java +++ b/src/test/java/com/backendoori/ootw/post/domain/PostTest.java @@ -77,7 +77,7 @@ void createPostSuccess() { assertAll(() -> assertThat(createdPost).hasFieldOrPropertyWithValue("user", MOCK_USER), () -> assertThat(createdPost).hasFieldOrPropertyWithValue("title", request.title()), () -> assertThat(createdPost).hasFieldOrPropertyWithValue("content", request.content()), - () -> assertThat(createdPost).hasFieldOrPropertyWithValue("image", IMG_URL), + () -> assertThat(createdPost).hasFieldOrPropertyWithValue("imageUrl", IMG_URL), () -> assertThat(createdPost).hasFieldOrPropertyWithValue("temperatureArrange", generateTemperatureArrange())); } diff --git a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java index c141f50e..cc5246e2 100644 --- a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java +++ b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java @@ -225,23 +225,6 @@ void updatePostUpdateRequestSuccess() { ); } - @Test - @DisplayName("게시글 이미지만 수정에 성공한다.") - void updatePostImageSuccess() { - // given - MockMultipartFile postImg = new MockMultipartFile("file", FILE_NAME, - "text/plain", "some xml".getBytes()); - String IMG_URL = "IMG_URL"; - - given(imageService.upload(postImg)).willReturn(new ImageFile(IMG_URL, FILE_NAME)); - - // when - PostSaveUpdateResponse response = postService.update(userPost.getId(), postImg, null); - - //then - assertThat(response).hasFieldOrPropertyWithValue("image", IMG_URL); - } - } @Nested From 8e9de2142c112f0446f4607b062cb252fa4f1832 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 18:33:24 +0900 Subject: [PATCH 27/46] =?UTF-8?q?fix:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EC=A0=95=EB=B3=B4=EB=8A=94=20=ED=95=84?= =?UTF-8?q?=EC=88=98=EC=A0=81=EC=9C=BC=EB=A1=9C=20=EB=B0=9B=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/backendoori/ootw/post/controller/PostController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/backendoori/ootw/post/controller/PostController.java b/src/main/java/com/backendoori/ootw/post/controller/PostController.java index cdbea90c..746d12db 100644 --- a/src/main/java/com/backendoori/ootw/post/controller/PostController.java +++ b/src/main/java/com/backendoori/ootw/post/controller/PostController.java @@ -64,7 +64,7 @@ public ResponseEntity save( public ResponseEntity update( @PathVariable Long postId, @RequestPart(required = false) @Image(ignoreCase = true) MultipartFile postImg, - @RequestPart(required = false) @Valid PostUpdateRequest request) { + @RequestPart @Valid PostUpdateRequest request) { PostSaveUpdateResponse response = postService.update(postId, postImg, request); return ResponseEntity.status(HttpStatus.CREATED) From aeaa8fb53705ca1ec24239824a06e00dd1ca91a9 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 18:57:42 +0900 Subject: [PATCH 28/46] =?UTF-8?q?feat:=20post=20id=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EB=A1=9C=EC=A7=81=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=EC=97=90=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backendoori/ootw/post/controller/PostController.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/controller/PostController.java b/src/main/java/com/backendoori/ootw/post/controller/PostController.java index 746d12db..91946cb6 100644 --- a/src/main/java/com/backendoori/ootw/post/controller/PostController.java +++ b/src/main/java/com/backendoori/ootw/post/controller/PostController.java @@ -9,6 +9,7 @@ import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; import com.backendoori.ootw.post.service.PostService; import jakarta.validation.Valid; +import jakarta.validation.constraints.Positive; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -30,7 +31,7 @@ public class PostController { private final PostService postService; @GetMapping("/{postId}") - public ResponseEntity readDetailByPostId(@PathVariable Long postId) { + public ResponseEntity readDetailByPostId(@PathVariable @Positive Long postId) { return ResponseEntity.status(HttpStatus.OK) .body(postService.getDetailByPostId(postId)); } @@ -42,7 +43,7 @@ public ResponseEntity> readAll() { } @DeleteMapping("/{postId}") - public ResponseEntity delete(@PathVariable Long postId) { + public ResponseEntity delete(@PathVariable @Positive Long postId) { postService.delete(postId); return ResponseEntity.status(HttpStatus.NO_CONTENT) @@ -62,7 +63,7 @@ public ResponseEntity save( @PutMapping("/{postId}") public ResponseEntity update( - @PathVariable Long postId, + @PathVariable @Positive Long postId, @RequestPart(required = false) @Image(ignoreCase = true) MultipartFile postImg, @RequestPart @Valid PostUpdateRequest request) { PostSaveUpdateResponse response = postService.update(postId, postImg, request); From 3038bf301145db4b86f0d5c7d7443b234a279b1a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 21:34:29 +0900 Subject: [PATCH 29/46] =?UTF-8?q?refactor:NoPostPermissionException?= =?UTF-8?q?=EC=9D=84=20=20PermissionException=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9E=AC=EC=A0=95=EC=9D=98=20=ED=9B=84=20GlobalControllerAdvic?= =?UTF-8?q?e=EB=A1=9C=20=ED=95=B8=EB=93=A4=EB=9F=AC=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/exception/GlobalControllerAdvice.java | 8 ++++++++ .../ootw/exception/PermissionException.java | 13 +++++++++++++ .../post/exception/NoPostPermissionException.java | 11 ----------- .../ootw/post/exception/PostControllerAdvice.java | 12 ++---------- 4 files changed, 23 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/backendoori/ootw/exception/PermissionException.java delete mode 100644 src/main/java/com/backendoori/ootw/post/exception/NoPostPermissionException.java diff --git a/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java b/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java index 861223df..94013331 100644 --- a/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java +++ b/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java @@ -31,6 +31,14 @@ public ResponseEntity handleMissingServletRequestPartException(Ex .body(errorResponse); } + @ExceptionHandler(PermissionException.class) + public ResponseEntity handlePermissionException(PermissionException e) { + ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); + + return ResponseEntity.status(HttpStatus.FORBIDDEN) + .body(errorResponse); + } + @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity handleIllegalArgumentException(IllegalArgumentException e) { ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); diff --git a/src/main/java/com/backendoori/ootw/exception/PermissionException.java b/src/main/java/com/backendoori/ootw/exception/PermissionException.java new file mode 100644 index 00000000..c263ce5d --- /dev/null +++ b/src/main/java/com/backendoori/ootw/exception/PermissionException.java @@ -0,0 +1,13 @@ +package com.backendoori.ootw.exception; + +import org.springframework.security.core.AuthenticationException; + +public class PermissionException extends AuthenticationException { + + public static final String DEFAULT_MESSAGE = "요청에 대한 권한이 없습니다."; + + public PermissionException() { + super(DEFAULT_MESSAGE); + } + +} diff --git a/src/main/java/com/backendoori/ootw/post/exception/NoPostPermissionException.java b/src/main/java/com/backendoori/ootw/post/exception/NoPostPermissionException.java deleted file mode 100644 index 2a83c4d2..00000000 --- a/src/main/java/com/backendoori/ootw/post/exception/NoPostPermissionException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.backendoori.ootw.post.exception; - -public class NoPostPermissionException extends RuntimeException { - - public static final String DEFAULT_MESSAGE = "해당 게시글에 관한 수정/삭제 권한이 없습니다."; - - public NoPostPermissionException() { - super(DEFAULT_MESSAGE); - } - -} diff --git a/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java b/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java index 691caea0..f9b2131d 100644 --- a/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java +++ b/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java @@ -13,16 +13,8 @@ @RestControllerAdvice(basePackageClasses = PostController.class) public class PostControllerAdvice { - @ExceptionHandler(NoPostPermissionException.class) - public ResponseEntity handleNoPostPermissionException(NoPostPermissionException e) { - ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); - - return ResponseEntity.status(HttpStatus.FORBIDDEN) - .body(errorResponse); - } - - @ExceptionHandler(ResourceNotExistException.class) - public ResponseEntity handleNoUpdateResourceException(ResourceNotExistException e) { + @ExceptionHandler(ResourceRequiredException.class) + public ResponseEntity handleNoUpdateResourceException(ResourceRequiredException e) { ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); return ResponseEntity.status(HttpStatus.BAD_REQUEST) From 12be6e27d0963d620fdf4cd7625926dd0005cf4a Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 21:35:11 +0900 Subject: [PATCH 30/46] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EC=9E=AC=EC=A0=95=EC=9D=98=ED=95=9C=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/post/service/PostService.java | 8 ++++---- .../ootw/post/controller/PostControllerTest.java | 10 +++++----- .../ootw/post/service/PostServiceTest.java | 16 ++++++++-------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index 874738fa..e9dcadeb 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -9,6 +9,7 @@ import com.backendoori.ootw.common.image.ImageFile; import com.backendoori.ootw.common.image.ImageService; import com.backendoori.ootw.common.image.exception.SaveException; +import com.backendoori.ootw.exception.PermissionException; import com.backendoori.ootw.exception.UserNotFoundException; import com.backendoori.ootw.like.domain.Like; import com.backendoori.ootw.like.repository.LikeRepository; @@ -17,8 +18,7 @@ import com.backendoori.ootw.post.dto.request.PostUpdateRequest; import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; -import com.backendoori.ootw.post.exception.NoPostPermissionException; -import com.backendoori.ootw.post.exception.ResourceNotExistException; +import com.backendoori.ootw.post.exception.ResourceRequiredException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.user.repository.UserRepository; @@ -130,7 +130,7 @@ public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpd checkUserHasPostPermission(post); Assert.isTrue(Objects.nonNull(request), () -> { - throw new ResourceNotExistException(); + throw new ResourceRequiredException(); }); post.updateTitle(request.title()); @@ -179,7 +179,7 @@ private boolean isLogin() { private void checkUserHasPostPermission(Post post) { Assert.isTrue(getUserId() == post.getUser().getId(), () -> { - throw new NoPostPermissionException(); + throw new PermissionException(); }); } diff --git a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java index 2a586803..474a632f 100644 --- a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java +++ b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java @@ -19,12 +19,12 @@ import java.util.List; import java.util.Map; import java.util.stream.Stream; +import com.backendoori.ootw.exception.PermissionException; import com.backendoori.ootw.post.domain.Post; import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; -import com.backendoori.ootw.post.exception.NoPostPermissionException; -import com.backendoori.ootw.post.exception.ResourceNotExistException; +import com.backendoori.ootw.post.exception.ResourceRequiredException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.post.service.PostService; import com.backendoori.ootw.security.TokenMockMvcTest; @@ -185,7 +185,7 @@ void deleteFailWithNoPermission() throws Exception { // then mockMvc.perform(requestBuilder) .andExpect(status().isForbidden()) - .andExpect(jsonPath("$.message", is(NoPostPermissionException.DEFAULT_MESSAGE))) + .andExpect(jsonPath("$.message", is(PermissionException.DEFAULT_MESSAGE))) .andReturn(); } @@ -326,7 +326,7 @@ void updateFailWithPermission() throws Exception { // then mockMvc.perform(requestBuilder) .andExpect(status().isForbidden()) - .andExpect(jsonPath("$.message", is(NoPostPermissionException.DEFAULT_MESSAGE))) + .andExpect(jsonPath("$.message", is(PermissionException.DEFAULT_MESSAGE))) .andReturn(); } @@ -366,7 +366,7 @@ void updateFailWithNoResource() throws Exception { // then mockMvc.perform(requestBuilder) .andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.message", is(ResourceNotExistException.DEFAULT_MESSAGE))) + .andExpect(jsonPath("$.message", is(ResourceRequiredException.DEFAULT_MESSAGE))) .andReturn(); } diff --git a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java index cc5246e2..16234aae 100644 --- a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java +++ b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java @@ -23,6 +23,7 @@ import com.backendoori.ootw.common.image.ImageFile; import com.backendoori.ootw.common.image.ImageService; import com.backendoori.ootw.common.image.exception.SaveException; +import com.backendoori.ootw.exception.PermissionException; import com.backendoori.ootw.exception.UserNotFoundException; import com.backendoori.ootw.like.repository.LikeRepository; import com.backendoori.ootw.like.service.LikeService; @@ -32,8 +33,7 @@ import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; import com.backendoori.ootw.post.dto.response.WriterDto; -import com.backendoori.ootw.post.exception.NoPostPermissionException; -import com.backendoori.ootw.post.exception.ResourceNotExistException; +import com.backendoori.ootw.post.exception.ResourceRequiredException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.user.repository.UserRepository; @@ -146,9 +146,9 @@ void deleteFailWithNoPermission() { ThrowingCallable deletePost = () -> postService.delete(otherPost.getId()); // then - assertThatExceptionOfType(NoPostPermissionException.class) + assertThatExceptionOfType(PermissionException.class) .isThrownBy(deletePost) - .withMessage(NoPostPermissionException.DEFAULT_MESSAGE); + .withMessage(PermissionException.DEFAULT_MESSAGE); } @Test @@ -258,9 +258,9 @@ void updateFailWithPermission() { ThrowingCallable updatePost = () -> postService.update(otherPost.getId(), postImg, request); //then - assertThatExceptionOfType(NoPostPermissionException.class) + assertThatExceptionOfType(PermissionException.class) .isThrownBy(updatePost) - .withMessage(NoPostPermissionException.DEFAULT_MESSAGE); + .withMessage(PermissionException.DEFAULT_MESSAGE); } @Test @@ -287,9 +287,9 @@ void updateFailWithNoResource() { ThrowingCallable updatePost = () -> postService.update(userPost.getId(), null, null); //then - assertThatExceptionOfType(ResourceNotExistException.class) + assertThatExceptionOfType(ResourceRequiredException.class) .isThrownBy(updatePost) - .withMessage(ResourceNotExistException.DEFAULT_MESSAGE); + .withMessage(ResourceRequiredException.DEFAULT_MESSAGE); } @ParameterizedTest(name = "[{index}] {0}") From 0eca95afdbe817fc776e589b488191c9cd081127 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 21:36:12 +0900 Subject: [PATCH 31/46] =?UTF-8?q?refactor:=20PostValidator=20final=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/backendoori/ootw/post/validation/PostValidator.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java b/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java index cf677ddf..8dd1440a 100644 --- a/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java +++ b/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java @@ -12,8 +12,11 @@ import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.weather.domain.TemperatureArrange; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; -public class PostValidator { +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class PostValidator { private static final Integer MAX_TITLE_LENGTH = 30; private static final Integer MAX_CONTENT_LENGTH = 500; From d3b019ffd4d1f70f1c607eed83acf28db1a33d52 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 21:36:37 +0900 Subject: [PATCH 32/46] =?UTF-8?q?refactor:=20ResourceRequiredException?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/exception/ResourceNotExistException.java | 11 ----------- .../post/exception/ResourceRequiredException.java | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 src/main/java/com/backendoori/ootw/post/exception/ResourceNotExistException.java create mode 100644 src/main/java/com/backendoori/ootw/post/exception/ResourceRequiredException.java diff --git a/src/main/java/com/backendoori/ootw/post/exception/ResourceNotExistException.java b/src/main/java/com/backendoori/ootw/post/exception/ResourceNotExistException.java deleted file mode 100644 index b8c497a0..00000000 --- a/src/main/java/com/backendoori/ootw/post/exception/ResourceNotExistException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.backendoori.ootw.post.exception; - -public class ResourceNotExistException extends RuntimeException { - - public static final String DEFAULT_MESSAGE = "해당 게시글을 생성하거나 업데이트할 리소스가 존재하지 않습니다."; - - public ResourceNotExistException() { - super(DEFAULT_MESSAGE); - } - -} diff --git a/src/main/java/com/backendoori/ootw/post/exception/ResourceRequiredException.java b/src/main/java/com/backendoori/ootw/post/exception/ResourceRequiredException.java new file mode 100644 index 00000000..52a62a55 --- /dev/null +++ b/src/main/java/com/backendoori/ootw/post/exception/ResourceRequiredException.java @@ -0,0 +1,11 @@ +package com.backendoori.ootw.post.exception; + +public class ResourceRequiredException extends RuntimeException { + + public static final String DEFAULT_MESSAGE = "해당 게시글을 생성하거나 업데이트할 리소스가 필요합니다."; + + public ResourceRequiredException() { + super(DEFAULT_MESSAGE); + } + +} From 9847f39e6c57064c58ac4bf987e769d3bd7eda09 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 23:42:44 +0900 Subject: [PATCH 33/46] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=98=88=EC=99=B8=20=EB=B0=8F=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=ED=95=B8=EB=93=A4=EB=9F=AC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/exception/PostControllerAdvice.java | 24 ------------------- .../exception/ResourceRequiredException.java | 11 --------- 2 files changed, 35 deletions(-) delete mode 100644 src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java delete mode 100644 src/main/java/com/backendoori/ootw/post/exception/ResourceRequiredException.java diff --git a/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java b/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java deleted file mode 100644 index f9b2131d..00000000 --- a/src/main/java/com/backendoori/ootw/post/exception/PostControllerAdvice.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.backendoori.ootw.post.exception; - -import com.backendoori.ootw.exception.ErrorResponse; -import com.backendoori.ootw.post.controller.PostController; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -@Order(Ordered.HIGHEST_PRECEDENCE) -@RestControllerAdvice(basePackageClasses = PostController.class) -public class PostControllerAdvice { - - @ExceptionHandler(ResourceRequiredException.class) - public ResponseEntity handleNoUpdateResourceException(ResourceRequiredException e) { - ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); - - return ResponseEntity.status(HttpStatus.BAD_REQUEST) - .body(errorResponse); - } - -} diff --git a/src/main/java/com/backendoori/ootw/post/exception/ResourceRequiredException.java b/src/main/java/com/backendoori/ootw/post/exception/ResourceRequiredException.java deleted file mode 100644 index 52a62a55..00000000 --- a/src/main/java/com/backendoori/ootw/post/exception/ResourceRequiredException.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.backendoori.ootw.post.exception; - -public class ResourceRequiredException extends RuntimeException { - - public static final String DEFAULT_MESSAGE = "해당 게시글을 생성하거나 업데이트할 리소스가 필요합니다."; - - public ResourceRequiredException() { - super(DEFAULT_MESSAGE); - } - -} From f0546f48d2e3dfe2dbb159a3921dac2368b242ea Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 23:51:27 +0900 Subject: [PATCH 34/46] =?UTF-8?q?refactor:=20=EC=9D=B8=EC=A6=9D=EB=B3=B4?= =?UTF-8?q?=EB=8B=A4=EB=8A=94=20=EC=9D=B8=EA=B0=80=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EB=9D=BC=EC=84=9C=20=EC=9A=B0=EC=84=A0=20=EB=9F=B0=ED=83=80?= =?UTF-8?q?=EC=9E=84=20=EC=98=88=EC=99=B8=20=EC=83=81=EC=86=8D=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/backendoori/ootw/exception/PermissionException.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/exception/PermissionException.java b/src/main/java/com/backendoori/ootw/exception/PermissionException.java index c263ce5d..acab05a6 100644 --- a/src/main/java/com/backendoori/ootw/exception/PermissionException.java +++ b/src/main/java/com/backendoori/ootw/exception/PermissionException.java @@ -1,8 +1,6 @@ package com.backendoori.ootw.exception; -import org.springframework.security.core.AuthenticationException; - -public class PermissionException extends AuthenticationException { +public class PermissionException extends RuntimeException { public static final String DEFAULT_MESSAGE = "요청에 대한 권한이 없습니다."; From e5d6b2f620bdc4ae09c8a5c4f5f117d4246a7a3f Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 23:52:16 +0900 Subject: [PATCH 35/46] =?UTF-8?q?refactor:=20PostController=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/controller/PostControllerTest.java | 229 ++++++++++++------ 1 file changed, 161 insertions(+), 68 deletions(-) diff --git a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java index 474a632f..db3ce78f 100644 --- a/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java +++ b/src/test/java/com/backendoori/ootw/post/controller/PostControllerTest.java @@ -24,7 +24,6 @@ import com.backendoori.ootw.post.dto.request.PostSaveRequest; import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; -import com.backendoori.ootw.post.exception.ResourceRequiredException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.post.service.PostService; import com.backendoori.ootw.security.TokenMockMvcTest; @@ -60,7 +59,17 @@ class PostControllerTest extends TokenMockMvcTest { static final Faker FAKER = new Faker(); + public static final String IMG_URL = "imageUrl"; public static final String BASE_URL = "http://localhost:8080/api/v1/posts"; + public static final String ORIGINAL_FILE_NAME = "filename.jpeg"; + public static final String FILE_NAME = "postImg"; + public static final String CONTENT = "CONTENT"; + public static final String TITLE = "TITLE"; + + @NotNull + private static MockMultipartFile getPostImg(String originalFileName, String mediaType) { + return new MockMultipartFile(FILE_NAME, originalFileName, mediaType, "some xml".getBytes()); + } User user; @@ -106,9 +115,12 @@ private User generateUser() { } @NotNull - private static MockMultipartFile getPostImg() { - return new MockMultipartFile("postImg", "filename.jpeg", MediaType.IMAGE_JPEG_VALUE, - "some xml".getBytes()); + private MockMultipartFile getRequestJson(String title, String content) throws JsonProcessingException { + PostSaveRequest postSaveRequest = + new PostSaveRequest(title, content, VALID_COORDINATE); + + return new MockMultipartFile("request", "request.json", MediaType.APPLICATION_JSON_VALUE, + objectMapper.writeValueAsBytes(postSaveRequest)); } @NotNull @@ -119,15 +131,6 @@ private static RequestPostProcessor makeRequestMethodToPut() { }; } - @NotNull - private MockMultipartFile getRequestJson(String testTitle) throws JsonProcessingException { - PostSaveRequest postSaveRequest = - new PostSaveRequest(testTitle, "Test Content", VALID_COORDINATE); - - return new MockMultipartFile("request", "request.json", MediaType.APPLICATION_JSON_VALUE, - objectMapper.writeValueAsBytes(postSaveRequest)); - } - @Nested @DisplayName("게시글 삭제하기") class DeleteTest { @@ -138,12 +141,12 @@ class DeleteTest { @BeforeEach void setup() { userPost = postRepository.save( - Post.from(user, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + Post.from(user, new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE), null, generateTemperatureArrange())); User other = userRepository.save(generateUser()); otherPost = postRepository.save( - Post.from(other, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + Post.from(other, new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE), null, generateTemperatureArrange())); } @@ -216,12 +219,12 @@ class UpdateTest { @BeforeEach void setup() { userPost = postRepository.save( - Post.from(user, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + Post.from(user, new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE), null, generateTemperatureArrange())); User other = userRepository.save(generateUser()); otherPost = postRepository.save( - Post.from(other, new PostSaveRequest("title", "content", VALID_COORDINATE), null, + Post.from(other, new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE), null, generateTemperatureArrange())); } @@ -229,12 +232,21 @@ void setup() { @DisplayName("게시글 수정에 성공한다") class UpdateSuccess { - @Test + static Stream provideImageTypes() { + return Stream.of( + Arguments.of("image.jpeg", MediaType.IMAGE_JPEG_VALUE), + Arguments.of("image.gif", MediaType.IMAGE_GIF_VALUE), + Arguments.of("image.png", MediaType.IMAGE_PNG_VALUE) + ); + } + + @ParameterizedTest(name = "[{index}]: 아이템 타입이 {0}인 경우에 저장에 성공한다.") + @MethodSource("provideImageTypes") @DisplayName(" 게시글 정보와 이미지 수정에 성공한다.") - void updateAllSuccess() throws Exception { + void updateAllSuccess(String originalFileName, String mediaType) throws Exception { // given - MockMultipartFile request = getRequestJson("Test Title"); - MockMultipartFile postImg = getPostImg(); + MockMultipartFile request = getRequestJson(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(originalFileName, mediaType); // when MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) @@ -260,7 +272,7 @@ void updateAllSuccess() throws Exception { @DisplayName("게시글 정보 수정에 성공한다.") void updatePostUpdateRequestSuccess() throws Exception { // given - MockMultipartFile request = getRequestJson("Test Title"); + MockMultipartFile request = getRequestJson(TITLE, CONTENT); // when MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) @@ -286,12 +298,34 @@ void updatePostUpdateRequestSuccess() throws Exception { @DisplayName("게시글 수정에 실패한다") class UpdateFail { + static Stream provideInvalidPostInfo() { + return Stream.of( + Arguments.of(null, CONTENT), + Arguments.of(TITLE, null), + Arguments.of("", CONTENT), + Arguments.of(TITLE, ""), + Arguments.of(" ", CONTENT), + Arguments.of(TITLE, " "), + Arguments.of("a".repeat(40), CONTENT), + Arguments.of(TITLE, "a".repeat(600)) + ); + } + + static Stream provideInvalidFile() { + return Stream.of( + Arguments.of("file.md", MediaType.TEXT_MARKDOWN_VALUE), + Arguments.of("file.html", MediaType.TEXT_HTML_VALUE), + Arguments.of("file.pdf", MediaType.APPLICATION_PDF_VALUE), + Arguments.of("file.txt", MediaType.TEXT_PLAIN_VALUE) + ); + } + @Test @DisplayName("로그인을 안한 사용자는 게시글 수정에 접근이 불가하다.") void updateFailWithUnauthorizedUser() throws Exception { // given - MockMultipartFile request = getRequestJson("Test Title"); - MockMultipartFile postImg = getPostImg(); + MockMultipartFile request = getRequestJson(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); // when MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) @@ -311,8 +345,8 @@ void updateFailWithUnauthorizedUser() throws Exception { @DisplayName("게시글 주인이 아닌 사용자가 게시글 수정에 실패한다.") void updateFailWithPermission() throws Exception { // given - MockMultipartFile request = getRequestJson("Test Title"); - MockMultipartFile postImg = getPostImg(); + MockMultipartFile request = getRequestJson(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); // when MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + otherPost.getId()) @@ -334,8 +368,8 @@ void updateFailWithPermission() throws Exception { @DisplayName("존재하지 않는 게시글 수정에 실패한다.") void updateFailWithNonExistPost() throws Exception { // given - MockMultipartFile request = getRequestJson("Test Title"); - MockMultipartFile postImg = getPostImg(); + MockMultipartFile request = getRequestJson(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); // when MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + otherPost.getId() + 1) @@ -366,16 +400,36 @@ void updateFailWithNoResource() throws Exception { // then mockMvc.perform(requestBuilder) .andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.message", is(ResourceRequiredException.DEFAULT_MESSAGE))) .andReturn(); } @Test - @DisplayName("수정할 이미지만 보냈는데 null이면 수정에 실패한다.") + @DisplayName("수정할 이미지만 보내면 수정에 실패한다.") void updateFailWithNullImage() throws Exception { // given - MockMultipartFile request = getRequestJson("Test Title"); - MockMultipartFile postImg = getPostImg(); + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); + + // when + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) + .file(postImg) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.MULTIPART_FORM_DATA) + .characterEncoding(StandardCharsets.UTF_8) + .with(makeRequestMethodToPut()); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isBadRequest()) + .andReturn(); + } + + @ParameterizedTest(name = "[{index}] 제목이 {0}이고 내용이 {1}인 경우") + @MethodSource("provideInvalidPostInfo") + @DisplayName("수정할 게시글 정보를 보냈는데 유효하지 않으면 수정에 실패한다.") + void updateFailWithInvalidPostUpdateRequest(String title, String content) throws Exception { + // given + MockMultipartFile request = getRequestJson(title, content); + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); // when MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) @@ -388,16 +442,17 @@ void updateFailWithNullImage() throws Exception { // then mockMvc.perform(requestBuilder) - .andExpect(status().isCreated()) + .andExpect(status().isBadRequest()) .andReturn(); } - @Test - @DisplayName("수정할 게시글 정보를 보냈는데 null이면 수정에 실패한다.") - void updateFailWithNullPostUpdateRequest() throws Exception { + @ParameterizedTest(name = "[{index}] 파일 타입이 {1}인 경우") + @MethodSource("provideInvalidFile") + @DisplayName("수정할 게시글 정보와 파일을 보냈는데 파일이 유효하지 않으면 수정에 실패한다.") + void updateFailWithInvalidFileType(String originalFileName, String mediaType) throws Exception { // given - MockMultipartFile request = getRequestJson("Test Title"); - MockMultipartFile postImg = getPostImg(); + MockMultipartFile request = getRequestJson(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(originalFileName, mediaType); // when MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL + "/" + userPost.getId()) @@ -410,7 +465,7 @@ void updateFailWithNullPostUpdateRequest() throws Exception { // then mockMvc.perform(requestBuilder) - .andExpect(status().isCreated()) + .andExpect(status().isBadRequest()) .andReturn(); } @@ -422,18 +477,49 @@ void updateFailWithNullPostUpdateRequest() throws Exception { @DisplayName("게시글 저장하기") class SaveTest { - @Test + static Stream provideInvalidPostInfo() { + return Stream.of( + Arguments.of(null, CONTENT), + Arguments.of(PostControllerTest.TITLE, null), + Arguments.of("", CONTENT), + Arguments.of(PostControllerTest.TITLE, ""), + Arguments.of(" ", CONTENT), + Arguments.of(PostControllerTest.TITLE, " "), + Arguments.of("a".repeat(40), CONTENT), + Arguments.of(PostControllerTest.TITLE, "a".repeat(600)) + ); + } + + static Stream provideImageTypes() { + return Stream.of( + Arguments.of("image.jpeg", MediaType.IMAGE_JPEG_VALUE), + Arguments.of("image.gif", MediaType.IMAGE_GIF_VALUE), + Arguments.of("image.png", MediaType.IMAGE_PNG_VALUE) + ); + } + + static Stream provideInvalidFile() { + return Stream.of( + Arguments.of("file.md", MediaType.TEXT_MARKDOWN_VALUE), + Arguments.of("file.html", MediaType.TEXT_HTML_VALUE), + Arguments.of("file.pdf", MediaType.APPLICATION_PDF_VALUE), + Arguments.of("file.txt", MediaType.TEXT_PLAIN_VALUE) + ); + } + + @ParameterizedTest(name = "[{index}]: 아이템 타입이 {0}인 경우에 저장에 성공한다.") + @MethodSource("provideImageTypes") @DisplayName("게시글 저장에 성공한다.") - void saveSuccess() throws Exception { + void saveSuccess(String originalFileName, String mediaType) throws Exception { // given given(weatherService.getCurrentTemperatureArrange(VALID_COORDINATE)) .willReturn(generateTemperatureArrange()); - MockMultipartFile request = getRequestJson("Test Title"); - MockMultipartFile postImg = getPostImg(); + MockMultipartFile request = getRequestJson(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(originalFileName, mediaType); // when - MockHttpServletRequestBuilder requestBuilder = multipart("http://localhost:8080/api/v1/posts") + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL) .file(request) .file(postImg) .header(TOKEN_HEADER, TOKEN_PREFIX + token) @@ -460,11 +546,11 @@ void saveFailNonSavedUser() throws Exception { given(weatherService.getCurrentTemperatureArrange(VALID_COORDINATE)) .willReturn(generateTemperatureArrange()); - MockMultipartFile request = getRequestJson("Test Title"); - MockMultipartFile postImg = getPostImg(); + MockMultipartFile request = getRequestJson(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); // when - MockHttpServletRequestBuilder requestBuilder = multipart("http://localhost:8080/api/v1/posts") + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL) .file(request) .file(postImg) .header(TOKEN_HEADER, TOKEN_PREFIX + token) @@ -480,13 +566,13 @@ void saveFailNonSavedUser() throws Exception { @ParameterizedTest(name = "[{index}] 제목이 {0}이고 내용이 {1}인 경우") @MethodSource("provideInvalidPostInfo") @DisplayName("유효하지 않은 요청 값이 포함된 게시글 저장에 실패한다.") - void saveFailByMethodArgumentNotValidException(String title, String content) throws Exception { + void saveFailByInvalidPostSaveRequest(String title, String content) throws Exception { // given - MockMultipartFile request = getRequestJson(""); - MockMultipartFile postImg = getPostImg(); + MockMultipartFile request = getRequestJson(title, content); + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); // when - MockHttpServletRequestBuilder requestBuilder = multipart("http://localhost:8080/api/v1/posts") + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL) .file(request) .file(postImg) .header(TOKEN_HEADER, TOKEN_PREFIX + token) @@ -499,19 +585,26 @@ void saveFailByMethodArgumentNotValidException(String title, String content) thr .andExpect(content().contentType(MediaType.APPLICATION_JSON)); } - static Stream provideInvalidPostInfo() { - String validTitle = "title"; - String validContent = "content"; - return Stream.of( - Arguments.of(null, validContent), - Arguments.of(validTitle, null), - Arguments.of("", validContent), - Arguments.of(validTitle, ""), - Arguments.of(" ", validContent), - Arguments.of(validTitle, " "), - Arguments.of("a".repeat(40), validContent), - Arguments.of(validTitle, "a".repeat(600)) - ); + @ParameterizedTest(name = "[{index}] 파일 타입이 {1}인 경우") + @MethodSource("provideInvalidFile") + @DisplayName("게시글 정보와 파일을 보냈는데 파일이 유효하지 않으면 저장에 실패한다.") + void saveFailByInvalidFileType(String originalFileName, String mediaType) throws Exception { + // given + MockMultipartFile request = getRequestJson(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(originalFileName, mediaType); + + // when + MockHttpServletRequestBuilder requestBuilder = multipart(BASE_URL) + .file(request) + .file(postImg) + .header(TOKEN_HEADER, TOKEN_PREFIX + token) + .contentType(MediaType.MULTIPART_FORM_DATA) + .accept(MediaType.APPLICATION_JSON); + + // then + mockMvc.perform(requestBuilder) + .andExpect(status().isBadRequest()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)); } } @@ -528,7 +621,7 @@ void setUp() { TestSecurityContextHolder.setAuthentication(new TestingAuthenticationToken(user.getId(), null)); Post savedPost = postRepository.save( - Post.from(user, new PostSaveRequest("Test Title", "Test Content", VALID_COORDINATE), "imgUrl", + Post.from(user, new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE), IMG_URL, generateTemperatureArrange())); postSaveResponse = PostSaveUpdateResponse.from(savedPost); } @@ -576,8 +669,7 @@ void setUp() { TestSecurityContextHolder.setAuthentication(new TestingAuthenticationToken(user.getId(), null)); for (int i = 0; i < SAVE_COUNT; i++) { - Post savedPost = postRepository.save( - Post.from(user, new PostSaveRequest("Test Title", "Test Content", VALID_COORDINATE), "imgUrl", + postRepository.save(Post.from(user, new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE), IMG_URL, generateTemperatureArrange())); } } @@ -586,7 +678,7 @@ void setUp() { @DisplayName("게시글 목록 조회에 성공한다.") void getAllSuccess() throws Exception { // given // when - MockHttpServletRequestBuilder requestBuilder = get("http://localhost:8080/api/v1/posts") + MockHttpServletRequestBuilder requestBuilder = get(BASE_URL) .header(TOKEN_HEADER, TOKEN_PREFIX + token) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON); @@ -606,6 +698,7 @@ void getAllSuccess() throws Exception { } + private TemperatureArrange generateTemperatureArrange() { Map weatherInfoMap = new HashMap<>(); weatherInfoMap.put(ForecastCategory.TMN, String.valueOf(0.0)); From d6d0b59bcae7207105d4731d3c0ece15e4bb06bc Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 23:53:10 +0900 Subject: [PATCH 36/46] =?UTF-8?q?refactor:=20PostService=20=EC=86=8C?= =?UTF-8?q?=EC=8A=A4=EC=BD=94=EB=93=9C=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20?= =?UTF-8?q?=EA=B2=80=EC=82=AC=20=EB=A1=9C=EC=A7=81=20=EA=B0=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backendoori/ootw/post/service/PostService.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index e9dcadeb..f04c21cf 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -1,5 +1,7 @@ package com.backendoori.ootw.post.service; +import static com.backendoori.ootw.common.validation.ImageValidator.validateImage; +import static com.backendoori.ootw.post.validation.Message.NULL_POST; import static com.backendoori.ootw.post.validation.Message.POST_NOT_FOUND; import java.util.List; @@ -18,7 +20,6 @@ import com.backendoori.ootw.post.dto.request.PostUpdateRequest; import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; -import com.backendoori.ootw.post.exception.ResourceRequiredException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.user.repository.UserRepository; @@ -45,15 +46,20 @@ public class PostService { @Transactional public PostSaveUpdateResponse save(PostSaveRequest request, MultipartFile postImg) { + Assert.isTrue(Objects.nonNull(request), () -> { + throw new IllegalArgumentException(NULL_POST); + }); + User user = userRepository.findById(getUserId()) .orElseThrow(UserNotFoundException::new); TemperatureArrange temperatureArrange = weatherService.getCurrentTemperatureArrange(request.coordinate()); - if (postImg.isEmpty()) { + if (Objects.isNull(postImg) || postImg.isEmpty()) { Post savedPost = postRepository.save(Post.from(user, request, null, temperatureArrange)); return PostSaveUpdateResponse.from(savedPost); } + validateImage(postImg); ImageFile imgFile = imageService.upload(postImg); try { Post savedPost = postRepository.save(Post.from(user, request, imgFile.url(), temperatureArrange)); @@ -130,7 +136,7 @@ public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpd checkUserHasPostPermission(post); Assert.isTrue(Objects.nonNull(request), () -> { - throw new ResourceRequiredException(); + throw new IllegalArgumentException(NULL_POST); }); post.updateTitle(request.title()); @@ -141,6 +147,7 @@ public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpd return PostSaveUpdateResponse.from(post); } + validateImage(postImg); ImageFile imgFile = imageService.upload(postImg); try { // TODO: 기존 저장된 이미지 삭제(원래 null인 경우도 있으니 주의) From 12021afcc824453036f56aa4e7d07863c4f4a5a2 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Fri, 12 Jan 2024 23:53:17 +0900 Subject: [PATCH 37/46] =?UTF-8?q?refactor:=20PostService=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/post/service/PostServiceTest.java | 213 +++++++++++++----- 1 file changed, 158 insertions(+), 55 deletions(-) diff --git a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java index 16234aae..9212ad0f 100644 --- a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java +++ b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java @@ -4,6 +4,7 @@ import static com.backendoori.ootw.post.validation.Message.BLANK_POST_TITLE; import static com.backendoori.ootw.post.validation.Message.INVALID_POST_CONTENT; import static com.backendoori.ootw.post.validation.Message.INVALID_POST_TITLE; +import static com.backendoori.ootw.post.validation.Message.NULL_POST; import static com.backendoori.ootw.post.validation.Message.POST_NOT_FOUND; import static com.backendoori.ootw.util.provider.ForecastApiCommonRequestSourceProvider.VALID_COORDINATE; import static org.assertj.core.api.Assertions.assertThat; @@ -13,7 +14,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.BDDMockito.given; -import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -33,7 +33,6 @@ import com.backendoori.ootw.post.dto.response.PostReadResponse; import com.backendoori.ootw.post.dto.response.PostSaveUpdateResponse; import com.backendoori.ootw.post.dto.response.WriterDto; -import com.backendoori.ootw.post.exception.ResourceRequiredException; import com.backendoori.ootw.post.repository.PostRepository; import com.backendoori.ootw.user.domain.User; import com.backendoori.ootw.user.repository.UserRepository; @@ -43,6 +42,8 @@ import com.backendoori.ootw.weather.service.WeatherService; import net.datafaker.Faker; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -54,9 +55,11 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.NullSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.TestingAuthenticationToken; @@ -69,8 +72,11 @@ class PostServiceTest { static final Faker FAKER = new Faker(); - public static final String IMG_URL = "imageUrl"; - public static final String FILE_NAME = "filename.jpeg"; + public static final String IMG_URL = "http://mock.server.com/filename.jpeg"; + public static final String ORIGINAL_FILE_NAME = "filename.jpeg"; + public static final String FILE_NAME = "filename"; + public static final String TITLE = "TITLE"; + public static final String CONTENT = "CONTENT"; User user; @@ -165,6 +171,11 @@ void deleteFailWithNonExistPost() { } + @NotNull + private static MockMultipartFile getPostImg(String originalFileName, String mediaType) { + return new MockMultipartFile(FILE_NAME, originalFileName, mediaType, "some xml".getBytes()); + } + @Nested @DisplayName("게시글 수정하기") class UpdateTest { @@ -188,15 +199,23 @@ void setup() { @DisplayName("게시글 수정에 성공한다") class UpdateSuccess { - @Test + static Stream provideImageTypes() { + return Stream.of( + Arguments.of("image.jpeg", MediaType.IMAGE_JPEG_VALUE), + Arguments.of("image.gif", MediaType.IMAGE_GIF_VALUE), + Arguments.of("image.png", MediaType.IMAGE_PNG_VALUE) + ); + } + + @ParameterizedTest(name = "[{index}]: 아이템 타입이 {0}인 경우에 저장에 성공한다.") + @MethodSource("provideImageTypes") @DisplayName(" 게시글 정보와 이미지 수정에 성공한다.") - void updateAllSuccess() { + void updateAllSuccess(String originalFileName, String mediaType) { // given - PostUpdateRequest request = new PostUpdateRequest("Test Title", "Test Content"); - MockMultipartFile postImg = new MockMultipartFile("file", FILE_NAME, - "text/plain", "some xml".getBytes()); + PostUpdateRequest request = new PostUpdateRequest(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(originalFileName, mediaType); - given(imageService.upload(postImg)).willReturn(new ImageFile(IMG_URL, FILE_NAME)); + given(imageService.upload(postImg)).willReturn(new ImageFile(IMG_URL, ORIGINAL_FILE_NAME)); // when PostSaveUpdateResponse response = postService.update(userPost.getId(), postImg, request); @@ -213,7 +232,7 @@ void updateAllSuccess() { @DisplayName("게시글 정보만 수정에 성공한다.") void updatePostUpdateRequestSuccess() { // given - PostUpdateRequest request = new PostUpdateRequest("Test Title", "Test Content"); + PostUpdateRequest request = new PostUpdateRequest(TITLE, CONTENT); // when PostSaveUpdateResponse response = postService.update(userPost.getId(), null, request); @@ -231,6 +250,15 @@ void updatePostUpdateRequestSuccess() { @DisplayName("게시글 수정에 실패한다") class UpdateFail { + static Stream provideInvalidFile() { + return Stream.of( + Arguments.of("file.md", MediaType.TEXT_MARKDOWN_VALUE), + Arguments.of("file.html", MediaType.TEXT_HTML_VALUE), + Arguments.of("file.pdf", MediaType.APPLICATION_PDF_VALUE), + Arguments.of("file.txt", MediaType.TEXT_PLAIN_VALUE) + ); + } + static Stream provideInvalidPostUpdateRequest() { return Stream.of( Arguments.of("제목이 null인 경우", new PostUpdateRequest(null, "content"), BLANK_POST_TITLE), @@ -250,9 +278,8 @@ static Stream provideInvalidPostUpdateRequest() { @DisplayName("게시글 주인이 아닌 사용자가 게시글 수정에 실패한다.") void updateFailWithPermission() { // given - PostUpdateRequest request = new PostUpdateRequest("Test Title", "Test Content"); - MockMultipartFile postImg = new MockMultipartFile("file", FILE_NAME, - "text/plain", "some xml".getBytes()); + PostUpdateRequest request = new PostUpdateRequest(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); // when ThrowingCallable updatePost = () -> postService.update(otherPost.getId(), postImg, request); @@ -267,9 +294,8 @@ void updateFailWithPermission() { @DisplayName("존재하지 않는 게시글 수정에 실패한다.") void updateFailWithNonExistPost() { // given - PostUpdateRequest request = new PostUpdateRequest("Test Title", "Test Content"); - MockMultipartFile postImg = new MockMultipartFile("file", FILE_NAME, - "text/plain", "some xml".getBytes()); + PostUpdateRequest request = new PostUpdateRequest(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); // when ThrowingCallable updatePost = () -> postService.update(otherPost.getId() + 1, postImg, request); @@ -287,15 +313,15 @@ void updateFailWithNoResource() { ThrowingCallable updatePost = () -> postService.update(userPost.getId(), null, null); //then - assertThatExceptionOfType(ResourceRequiredException.class) + assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(updatePost) - .withMessage(ResourceRequiredException.DEFAULT_MESSAGE); + .withMessage(NULL_POST); } @ParameterizedTest(name = "[{index}] {0}") @MethodSource("provideInvalidPostUpdateRequest") - @DisplayName("수정할 게시글 정보를 보냈는데 제목이나 내용이 null이거나 공백이면 수정에 실패한다.") - void updateFailWithNullPostUpdateRequest(String testCase, PostUpdateRequest request, String message) { + @DisplayName("수정할 게시글 정보를 보냈는데 제목이나 내용이 유효하지 않으면 수정에 실패한다.") + void updateFailWithInvalidPostUpdateRequest(String testCase, PostUpdateRequest request, String message) { // given // when ThrowingCallable updatePost = () -> postService.update(userPost.getId(), null, request); @@ -305,6 +331,21 @@ void updateFailWithNullPostUpdateRequest(String testCase, PostUpdateRequest requ .withMessage(message); } + @ParameterizedTest(name = "[{index}] 파일 타입이 {1}인 경우") + @MethodSource("provideInvalidFile") + @DisplayName("수정할 이미지를 보냈는데 이미지 파일이 유효하지 않으면 수정에 실패한다.") + void updateFailWithInvalidFileType(String originalFileName, String mediaType) { + // given // when + PostUpdateRequest request = new PostUpdateRequest(TITLE, CONTENT); + MockMultipartFile postImg = getPostImg(originalFileName, mediaType); + + ThrowingCallable updatePost = () -> postService.update(userPost.getId(), postImg, request); + + //then + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(updatePost); + } + } } @@ -313,16 +354,45 @@ void updateFailWithNullPostUpdateRequest(String testCase, PostUpdateRequest requ @DisplayName("게시글 저장하기") class SaveTest { - @Test + static Stream provideImageTypes() { + return Stream.of( + Arguments.of("image.jpeg", MediaType.IMAGE_JPEG_VALUE), + Arguments.of("image.gif", MediaType.IMAGE_GIF_VALUE), + Arguments.of("image.png", MediaType.IMAGE_PNG_VALUE) + ); + } + + static Stream provideInvalidFile() { + return Stream.of( + Arguments.of("file.md", MediaType.TEXT_MARKDOWN_VALUE), + Arguments.of("file.html", MediaType.TEXT_HTML_VALUE), + Arguments.of("file.pdf", MediaType.APPLICATION_PDF_VALUE), + Arguments.of("file.txt", MediaType.TEXT_PLAIN_VALUE) + ); + } + + static Stream provideInvalidPostInfo() { + return Stream.of( + Arguments.of(new PostSaveRequest(null, CONTENT, VALID_COORDINATE)), + Arguments.of(new PostSaveRequest(TITLE, null, VALID_COORDINATE)), + Arguments.of(new PostSaveRequest("", CONTENT, VALID_COORDINATE)), + Arguments.of(new PostSaveRequest(TITLE, "", VALID_COORDINATE)), + Arguments.of(new PostSaveRequest(" ", CONTENT, VALID_COORDINATE)), + Arguments.of(new PostSaveRequest(TITLE, " ", VALID_COORDINATE)), + Arguments.of(new PostSaveRequest("a".repeat(40), CONTENT, VALID_COORDINATE)), + Arguments.of(new PostSaveRequest(TITLE, "a".repeat(600), VALID_COORDINATE)) + ); + } + + @ParameterizedTest(name = "[{index}]: 아이템 타입이 {0}인 경우에 저장에 성공한다.") + @MethodSource("provideImageTypes") @DisplayName("게시글 저장에 성공한다.") - void saveSuccess() throws IOException { + void saveSuccess(String originalFileName, String mediaType) { // given - PostSaveRequest request = new PostSaveRequest("Test Title", "Test Content", VALID_COORDINATE); - MockMultipartFile postImg = new MockMultipartFile("file", FILE_NAME, - "image/jpeg", "some xml".getBytes()); + PostSaveRequest request = new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE); + MockMultipartFile postImg = getPostImg(originalFileName, mediaType); - given(imageService.upload(postImg)).willReturn( - new ImageFile("http://mock.server.com/filename.jpeg", FILE_NAME)); + given(imageService.upload(postImg)).willReturn(new ImageFile(IMG_URL, ORIGINAL_FILE_NAME)); given(weatherService.getCurrentTemperatureArrange(VALID_COORDINATE)).willReturn( generateTemperatureArrange()); @@ -338,15 +408,33 @@ void saveSuccess() throws IOException { TemperatureArrangeDto.from(generateTemperatureArrange())); } + @Test + @DisplayName("게시글 정보만 저장에 성공한다.") + void updatePostUpdateRequestSuccess() { + // given + PostSaveRequest request = new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE); + + given(weatherService.getCurrentTemperatureArrange(VALID_COORDINATE)).willReturn( + generateTemperatureArrange()); + + // when + PostSaveUpdateResponse response = postService.save(request, null); + + //then + assertAll( + () -> assertThat(response).hasFieldOrPropertyWithValue("title", request.title()), + () -> assertThat(response).hasFieldOrPropertyWithValue("content", request.content()) + ); + } + @Test @DisplayName("저장된 유저가 아닌 경우 게시글 저장에 실패한다.") void saveFailUserNotFound() { // given setAuthentication(user.getId() + 1); - PostSaveRequest postSaveRequest = new PostSaveRequest("Test Title", "Test Content", VALID_COORDINATE); - MockMultipartFile postImg = new MockMultipartFile("file", FILE_NAME, - "text/plain", "some xml".getBytes()); + PostSaveRequest postSaveRequest = new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE); + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); // when ThrowingCallable savePost = () -> postService.save(postSaveRequest, postImg); @@ -357,37 +445,52 @@ void saveFailUserNotFound() { .withMessage(UserNotFoundException.DEFAULT_MESSAGE); } - static Stream provideInvalidPostInfo() { - String validTitle = "title"; - String validContent = "content"; - return Stream.of( - Arguments.of(null, validContent), - Arguments.of(validTitle, null), - Arguments.of("", validContent), - Arguments.of(validTitle, ""), - Arguments.of(" ", validContent), - Arguments.of(validTitle, " "), - Arguments.of("a".repeat(40), validContent), - Arguments.of(validTitle, "a".repeat(600)) - ); - } - @ParameterizedTest(name = "[{index}] 제목이 {0}이고 내용이 {1}인 경우") @MethodSource("provideInvalidPostInfo") @DisplayName("유효하지 않은 값(게시글 정보)가 들어갈 경우 게시글 저장에 실패한다.") - void saveFailWithInvalidValue(String title, String content) { + void saveFailWithInvalidValue(@Nullable PostSaveRequest request) { + // given + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); + + given(imageService.upload(postImg)).willReturn(new ImageFile(IMG_URL, ORIGINAL_FILE_NAME)); + given(weatherService.getCurrentTemperatureArrange(VALID_COORDINATE)).willReturn( + generateTemperatureArrange()); + + // when, then + assertThrows(SaveException.class, + () -> postService.save(request, postImg)); + } + + @ParameterizedTest + @NullSource + @DisplayName("게시글 정보가 null로 들어갈 경우 게시글 저장에 실패한다.") + void saveFailWithNullPostSaveRequest(PostSaveRequest request) { // given + MockMultipartFile postImg = getPostImg(ORIGINAL_FILE_NAME, MediaType.IMAGE_JPEG_VALUE); + + given(imageService.upload(postImg)).willReturn(new ImageFile(IMG_URL, ORIGINAL_FILE_NAME)); given(weatherService.getCurrentTemperatureArrange(VALID_COORDINATE)).willReturn( generateTemperatureArrange()); - PostSaveRequest postSaveRequest = new PostSaveRequest(title, content, VALID_COORDINATE); - MockMultipartFile postImg = new MockMultipartFile("file", FILE_NAME, - "image/jpeg", "some xml".getBytes()); - given(imageService.upload(postImg)).willReturn( - new ImageFile("http://mock.server.com/filename.jpeg", FILE_NAME)); + // when, then + assertThrows(IllegalArgumentException.class, + () -> postService.save(request, postImg)); + } + + @ParameterizedTest(name = "[{index}] 파일 타입이 {1}인 경우") + @MethodSource("provideInvalidFile") + @DisplayName("수정할 이미지를 보냈는데 이미지 파일이 유효하지 않으면 수정에 실패한다.") + void updateFailWithInvalidFileType(String originalFileName, String mediaType) { + // given + given(weatherService.getCurrentTemperatureArrange(VALID_COORDINATE)).willReturn( + generateTemperatureArrange()); + + PostSaveRequest postSaveRequest = new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE); + MockMultipartFile postImg = getPostImg(originalFileName, mediaType); + given(imageService.upload(postImg)).willReturn(new ImageFile(IMG_URL, ORIGINAL_FILE_NAME)); // when, then - assertThrows(SaveException.class, + assertThrows(IllegalArgumentException.class, () -> postService.save(postSaveRequest, postImg)); } @@ -402,7 +505,7 @@ class GetDetailByPostIdTest { @BeforeEach void setUp() { Post savedPost = postRepository.save( - Post.from(user, new PostSaveRequest("Test Title", "Test Content", VALID_COORDINATE), "IMG_URL", + Post.from(user, new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE), IMG_URL, generateTemperatureArrange())); postSaveResponse = PostSaveUpdateResponse.from(savedPost); } @@ -504,7 +607,7 @@ class GetAllTest { void setUp() { for (int i = 0; i < SAVE_COUNT; i++) { postRepository.save( - Post.from(user, new PostSaveRequest("Test Title", "Test Content", VALID_COORDINATE), "IMG_URL", + Post.from(user, new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE), IMG_URL, generateTemperatureArrange())); } } From 907f16d40798581edd26e1bb20b15c1da015995e Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 16 Jan 2024 17:48:03 +0900 Subject: [PATCH 38/46] =?UTF-8?q?refactor:=20ExceptionHandler=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/exception/GlobalControllerAdvice.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java b/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java index 94013331..ba402c45 100644 --- a/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java +++ b/src/main/java/com/backendoori/ootw/exception/GlobalControllerAdvice.java @@ -31,14 +31,6 @@ public ResponseEntity handleMissingServletRequestPartException(Ex .body(errorResponse); } - @ExceptionHandler(PermissionException.class) - public ResponseEntity handlePermissionException(PermissionException e) { - ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); - - return ResponseEntity.status(HttpStatus.FORBIDDEN) - .body(errorResponse); - } - @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity handleIllegalArgumentException(IllegalArgumentException e) { ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); @@ -83,6 +75,14 @@ public ResponseEntity handleAuthenticationException(Authenticatio .body(errorResponse); } + @ExceptionHandler(PermissionException.class) + public ResponseEntity handlePermissionException(PermissionException e) { + ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); + + return ResponseEntity.status(HttpStatus.FORBIDDEN) + .body(errorResponse); + } + @ExceptionHandler(NoSuchElementException.class) public ResponseEntity handleNoSuchElementException(NoSuchElementException e) { ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); From 37ce1eb174ed954685bf754f1b2946aeaf6bef71 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 16 Jan 2024 17:51:23 +0900 Subject: [PATCH 39/46] =?UTF-8?q?refactor:=20Assert.notNull=EB=A1=9C=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B0=84=EA=B2=B0=ED=95=98=EA=B2=8C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/backendoori/ootw/post/service/PostService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index f04c21cf..7d4701e5 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -135,7 +135,7 @@ public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpd checkUserHasPostPermission(post); - Assert.isTrue(Objects.nonNull(request), () -> { + Assert.notNull(request, () -> { throw new IllegalArgumentException(NULL_POST); }); From 17835f9f95aa775824846a98d1a5f039093dca65 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 16 Jan 2024 17:55:40 +0900 Subject: [PATCH 40/46] =?UTF-8?q?refactor:=20string=20=EB=B9=84=EA=B5=90?= =?UTF-8?q?=EB=AC=B8=20equals=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/backendoori/ootw/post/service/PostService.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index 7d4701e5..5f11ea62 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -174,14 +174,11 @@ private long getUserId() { .getPrincipal(); } - //TODO: 이 부분을 .equals 써야하는지 궁금하다. - // 세희) 위에서처럼 정의하면 constant pool에 저장이되고 중복되는 값이 있으면 비슷한 걸로 인식한다고는 들었습니다! - // 다만 실수를 줄이고 더 안전하게 하고 싶다면 equals를 사용하는 것이 나을 수도 있겟네여! private boolean isLogin() { - return SecurityContextHolder + return !ANONYMOUS_USER_PRINCIPLE.equals(SecurityContextHolder .getContext() .getAuthentication() - .getPrincipal() != ANONYMOUS_USER_PRINCIPLE; + .getPrincipal()); } private void checkUserHasPostPermission(Post post) { From 8638d895f341bbb794c256fdd8a3d968ae0dc62c Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 16 Jan 2024 18:05:05 +0900 Subject: [PATCH 41/46] =?UTF-8?q?refactor:=20user=EC=97=90=20id=20?= =?UTF-8?q?=EB=B9=84=EA=B5=90=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/backendoori/ootw/post/service/PostService.java | 2 +- src/main/java/com/backendoori/ootw/user/domain/User.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index 5f11ea62..1bb325e3 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -182,7 +182,7 @@ private boolean isLogin() { } private void checkUserHasPostPermission(Post post) { - Assert.isTrue(getUserId() == post.getUser().getId(), () -> { + Assert.isTrue(post.getUser().isSameId(getUserId()), () -> { throw new PermissionException(); }); } diff --git a/src/main/java/com/backendoori/ootw/user/domain/User.java b/src/main/java/com/backendoori/ootw/user/domain/User.java index 1a7792b7..aa4b422f 100644 --- a/src/main/java/com/backendoori/ootw/user/domain/User.java +++ b/src/main/java/com/backendoori/ootw/user/domain/User.java @@ -1,5 +1,6 @@ package com.backendoori.ootw.user.domain; +import java.util.Objects; import com.backendoori.ootw.common.AssertUtil; import com.backendoori.ootw.common.BaseEntity; import com.backendoori.ootw.user.validation.Message; @@ -66,4 +67,8 @@ public boolean matchPassword(PasswordEncoder passwordEncoder, String decrypted) return passwordEncoder.matches(decrypted, password); } + public boolean isSameId(Long id) { + return Objects.equals(this.id, id); + } + } From 2254d5b94a4a53d9b93fb2851d4a4b5f879577d2 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 16 Jan 2024 18:06:03 +0900 Subject: [PATCH 42/46] =?UTF-8?q?refactor:=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=B3=80=EC=88=98=EB=AA=85=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/backendoori/ootw/post/service/PostService.java | 6 +++--- .../java/com/backendoori/ootw/post/validation/Message.java | 2 +- .../com/backendoori/ootw/post/validation/PostValidator.java | 4 ++-- .../com/backendoori/ootw/post/service/PostServiceTest.java | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index 1bb325e3..20918836 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -1,7 +1,7 @@ package com.backendoori.ootw.post.service; import static com.backendoori.ootw.common.validation.ImageValidator.validateImage; -import static com.backendoori.ootw.post.validation.Message.NULL_POST; +import static com.backendoori.ootw.post.validation.Message.NULL_REQUEST; import static com.backendoori.ootw.post.validation.Message.POST_NOT_FOUND; import java.util.List; @@ -47,7 +47,7 @@ public class PostService { @Transactional public PostSaveUpdateResponse save(PostSaveRequest request, MultipartFile postImg) { Assert.isTrue(Objects.nonNull(request), () -> { - throw new IllegalArgumentException(NULL_POST); + throw new IllegalArgumentException(NULL_REQUEST); }); User user = userRepository.findById(getUserId()) @@ -136,7 +136,7 @@ public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpd checkUserHasPostPermission(post); Assert.notNull(request, () -> { - throw new IllegalArgumentException(NULL_POST); + throw new IllegalArgumentException(NULL_REQUEST); }); post.updateTitle(request.title()); diff --git a/src/main/java/com/backendoori/ootw/post/validation/Message.java b/src/main/java/com/backendoori/ootw/post/validation/Message.java index 2949815b..7ed35666 100644 --- a/src/main/java/com/backendoori/ootw/post/validation/Message.java +++ b/src/main/java/com/backendoori/ootw/post/validation/Message.java @@ -7,7 +7,7 @@ public final class Message { public static final String POST_NOT_FOUND = "해당하는 게시글이 없습니다."; - public static final String NULL_POST = "게시글 생성/수정 요청 정보가 null이어서는 안됩니다."; + public static final String NULL_REQUEST = "게시글 생성/수정 요청 정보가 null이어서는 안됩니다."; public static final String NULL_WRITER = "게시글 생성 요청 사용자가 null이어서는 안됩니다."; diff --git a/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java b/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java index 8dd1440a..266195ea 100644 --- a/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java +++ b/src/main/java/com/backendoori/ootw/post/validation/PostValidator.java @@ -4,7 +4,7 @@ import static com.backendoori.ootw.post.validation.Message.BLANK_POST_TITLE; import static com.backendoori.ootw.post.validation.Message.INVALID_POST_CONTENT; import static com.backendoori.ootw.post.validation.Message.INVALID_POST_TITLE; -import static com.backendoori.ootw.post.validation.Message.NULL_POST; +import static com.backendoori.ootw.post.validation.Message.NULL_REQUEST; import static com.backendoori.ootw.post.validation.Message.NULL_TEMPERATURE_ARRANGE; import static com.backendoori.ootw.post.validation.Message.NULL_WRITER; @@ -26,7 +26,7 @@ public static void validateUser(User user) { } public static void validatePostSaveRequest(PostSaveRequest request) { - AssertUtil.notNull(request, NULL_POST); + AssertUtil.notNull(request, NULL_REQUEST); validateTitle(request.title()); validateContent(request.content()); } diff --git a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java index 9212ad0f..749007d7 100644 --- a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java +++ b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java @@ -4,7 +4,7 @@ import static com.backendoori.ootw.post.validation.Message.BLANK_POST_TITLE; import static com.backendoori.ootw.post.validation.Message.INVALID_POST_CONTENT; import static com.backendoori.ootw.post.validation.Message.INVALID_POST_TITLE; -import static com.backendoori.ootw.post.validation.Message.NULL_POST; +import static com.backendoori.ootw.post.validation.Message.NULL_REQUEST; import static com.backendoori.ootw.post.validation.Message.POST_NOT_FOUND; import static com.backendoori.ootw.util.provider.ForecastApiCommonRequestSourceProvider.VALID_COORDINATE; import static org.assertj.core.api.Assertions.assertThat; @@ -315,7 +315,7 @@ void updateFailWithNoResource() { //then assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(updatePost) - .withMessage(NULL_POST); + .withMessage(NULL_REQUEST); } @ParameterizedTest(name = "[{index}] {0}") From c3e4f58a42018e418883a90e63b00bbe41525c39 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 16 Jan 2024 18:48:13 +0900 Subject: [PATCH 43/46] =?UTF-8?q?refactor:=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ootw/post/service/PostService.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/backendoori/ootw/post/service/PostService.java b/src/main/java/com/backendoori/ootw/post/service/PostService.java index 20918836..b16e643c 100644 --- a/src/main/java/com/backendoori/ootw/post/service/PostService.java +++ b/src/main/java/com/backendoori/ootw/post/service/PostService.java @@ -1,6 +1,5 @@ package com.backendoori.ootw.post.service; -import static com.backendoori.ootw.common.validation.ImageValidator.validateImage; import static com.backendoori.ootw.post.validation.Message.NULL_REQUEST; import static com.backendoori.ootw.post.validation.Message.POST_NOT_FOUND; @@ -43,7 +42,6 @@ public class PostService { private final WeatherService weatherService; private final LikeRepository likeRepository; - @Transactional public PostSaveUpdateResponse save(PostSaveRequest request, MultipartFile postImg) { Assert.isTrue(Objects.nonNull(request), () -> { @@ -55,23 +53,18 @@ public PostSaveUpdateResponse save(PostSaveRequest request, MultipartFile postIm TemperatureArrange temperatureArrange = weatherService.getCurrentTemperatureArrange(request.coordinate()); if (Objects.isNull(postImg) || postImg.isEmpty()) { - Post savedPost = postRepository.save(Post.from(user, request, null, temperatureArrange)); - return PostSaveUpdateResponse.from(savedPost); + return savePostWithImageUrl(user, request, null, temperatureArrange); } - validateImage(postImg); ImageFile imgFile = imageService.upload(postImg); try { - Post savedPost = postRepository.save(Post.from(user, request, imgFile.url(), temperatureArrange)); - - return PostSaveUpdateResponse.from(savedPost); + return savePostWithImageUrl(user, request, imgFile.url(), temperatureArrange); } catch (Exception e) { imageService.delete(imgFile.fileName()); throw new SaveException(); } } - @Transactional(readOnly = true) public PostReadResponse getDetailByPostId(Long postId) { Post post = postRepository.findByIdWithUserEntityGraph(postId) @@ -127,7 +120,6 @@ public void delete(Long postId) { postRepository.delete(post); } - @Transactional public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpdateRequest request) { Post post = postRepository.findById(postId) @@ -143,24 +135,32 @@ public PostSaveUpdateResponse update(Long postId, MultipartFile postImg, PostUpd post.updateContent(request.content()); if (Objects.isNull(postImg) || postImg.isEmpty()) { - post.updateImageUrl(null); - return PostSaveUpdateResponse.from(post); + return updatePostWithImageUrl(post, null); } - validateImage(postImg); ImageFile imgFile = imageService.upload(postImg); try { // TODO: 기존 저장된 이미지 삭제(원래 null인 경우도 있으니 주의) - // imageService.uploadImage(postImg)가 잘못 저장되어 null 인 경우도 있을까..? - post.updateImageUrl(imgFile.url()); - - return PostSaveUpdateResponse.from(post); + return updatePostWithImageUrl(post, imgFile.url()); } catch (Exception e) { imageService.delete(imgFile.fileName()); throw new SaveException(); } } + private PostSaveUpdateResponse updatePostWithImageUrl(Post post, String imgFile) { + post.updateImageUrl(imgFile); + + return PostSaveUpdateResponse.from(post); + } + + private PostSaveUpdateResponse savePostWithImageUrl(User user, PostSaveRequest request, String imgFile, + TemperatureArrange temperatureArrange) { + Post savedPost = postRepository.save(Post.from(user, request, imgFile, temperatureArrange)); + + return PostSaveUpdateResponse.from(savedPost); + } + private List getLikedPostId(long userId) { return likeRepository.findByUserAndIsLike(userId, true) .stream().map(like -> like.getPost().getId()) From b6a525b310db93faa55412caf430cfae6e3b44e1 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Tue, 16 Jan 2024 19:02:54 +0900 Subject: [PATCH 44/46] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=ED=98=95=EC=8B=9D=20=EA=B4=80=EB=A0=A8=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EB=8A=94=20imageService=EC=97=90=EC=84=9C=20=EB=B0=9C=EC=83=9D?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/backendoori/ootw/post/service/PostServiceTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java index 749007d7..59f913a5 100644 --- a/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java +++ b/src/test/java/com/backendoori/ootw/post/service/PostServiceTest.java @@ -335,10 +335,12 @@ void updateFailWithInvalidPostUpdateRequest(String testCase, PostUpdateRequest r @MethodSource("provideInvalidFile") @DisplayName("수정할 이미지를 보냈는데 이미지 파일이 유효하지 않으면 수정에 실패한다.") void updateFailWithInvalidFileType(String originalFileName, String mediaType) { - // given // when + // given PostUpdateRequest request = new PostUpdateRequest(TITLE, CONTENT); MockMultipartFile postImg = getPostImg(originalFileName, mediaType); + given(imageService.upload(postImg)).willThrow(IllegalArgumentException.class); + // when ThrowingCallable updatePost = () -> postService.update(userPost.getId(), postImg, request); //then @@ -487,7 +489,7 @@ void updateFailWithInvalidFileType(String originalFileName, String mediaType) { PostSaveRequest postSaveRequest = new PostSaveRequest(TITLE, CONTENT, VALID_COORDINATE); MockMultipartFile postImg = getPostImg(originalFileName, mediaType); - given(imageService.upload(postImg)).willReturn(new ImageFile(IMG_URL, ORIGINAL_FILE_NAME)); + given(imageService.upload(postImg)).willThrow(IllegalArgumentException.class); // when, then assertThrows(IllegalArgumentException.class, From 8fed705699166031ea8537c96d6bb5d3cede1448 Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 17 Jan 2024 09:47:44 +0900 Subject: [PATCH 45/46] =?UTF-8?q?refactor:=20db=20pool=20size=20=ED=99=95?= =?UTF-8?q?=EC=9E=A5=20=EB=B0=8F=20=EC=82=AC=EC=9D=B4=EC=A6=88=20=EB=AA=85?= =?UTF-8?q?=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 11b97e9a..1761e2b0 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -4,6 +4,9 @@ spring: username: ${MAIN_MYSQL_USERNAME} password: ${MAIN_MYSQL_PASSWORD} url: ${MAIN_MYSQL_URL} + hikari: + maximum-pool-size: 100 + minimum-idle: 10 jpa: hibernate: ddl-auto: validate From 14d09b8ca252ac46face5c9636f27502d9abf73b Mon Sep 17 00:00:00 2001 From: Sehee-Lee-01 Date: Wed, 17 Jan 2024 09:48:03 +0900 Subject: [PATCH 46/46] =?UTF-8?q?refactor:=20=EC=95=84=EB=B0=94=ED=83=80?= =?UTF-8?q?=20=EC=95=84=EC=9D=B4=ED=85=9C=20=EC=A1=B0=ED=9A=8C=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EB=AA=A8=EB=91=90=20=ED=97=88=EC=9A=A9=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/backendoori/ootw/config/HttpRequestsConfigurer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/backendoori/ootw/config/HttpRequestsConfigurer.java b/src/main/java/com/backendoori/ootw/config/HttpRequestsConfigurer.java index e0f72122..5ead86ba 100644 --- a/src/main/java/com/backendoori/ootw/config/HttpRequestsConfigurer.java +++ b/src/main/java/com/backendoori/ootw/config/HttpRequestsConfigurer.java @@ -14,6 +14,7 @@ public class HttpRequestsConfigurer private static final String AUTH_RESOURCE = "/api/v1/auth/**"; private static final String POST_RESOURCE = "/api/v1/posts/**"; + private static final String AVATAR_RESOURCE = "/api/v1/avatar-items/**"; @Override public void customize( @@ -23,6 +24,8 @@ public void customize( .permitAll() .requestMatchers(antMatcher(HttpMethod.GET, POST_RESOURCE)) .permitAll() + .requestMatchers(antMatcher(HttpMethod.GET, AVATAR_RESOURCE)) + .permitAll() .anyRequest() .authenticated(); }