From f2acf5369b1fc8ea65a64d5b24d3af5a3c326ec5 Mon Sep 17 00:00:00 2001 From: mmihye Date: Thu, 18 Jan 2024 03:51:20 +0900 Subject: [PATCH 1/6] =?UTF-8?q?[#149]=20fix:=20=EC=9A=B0=EC=84=A0=EC=88=9C?= =?UTF-8?q?=EC=9C=84=20=EB=B3=80=EA=B2=BD=20=ED=95=B4=EB=8B=B9=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=EB=A7=8C=20=EB=B3=80=EA=B2=BD=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../toaster/infrastructure/CategoryRepository.java | 14 ++++++++------ .../toaster/service/category/CategoryService.java | 6 +++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/linkmind/src/main/java/com/app/toaster/infrastructure/CategoryRepository.java b/linkmind/src/main/java/com/app/toaster/infrastructure/CategoryRepository.java index 60655dd..c3cc5f0 100644 --- a/linkmind/src/main/java/com/app/toaster/infrastructure/CategoryRepository.java +++ b/linkmind/src/main/java/com/app/toaster/infrastructure/CategoryRepository.java @@ -33,22 +33,24 @@ public interface CategoryRepository extends JpaRepository { @Modifying @Query("UPDATE Category c SET c.priority = c.priority - 1 " + - "WHERE c.categoryId != :categoryId AND c.priority > :currentPriority AND c.priority <= :newPriority") + "WHERE c.categoryId != :categoryId AND c.user.userId =:userId AND c.priority > :currentPriority AND c.priority <= :newPriority") void decreasePriorityByOne(@Param("categoryId") Long categoryId, @Param("currentPriority") int currentPriority, - @Param("newPriority") int newPriority); + @Param("newPriority") int newPriority, + @Param("userId")Long userId); @Modifying @Query("UPDATE Category c SET c.priority = c.priority + 1 " + - "WHERE c.categoryId != :categoryId AND c.priority >= :newPriority AND c.priority < :currentPriority") + "WHERE c.categoryId != :categoryId AND c.user.userId =:userId AND c.priority >= :newPriority AND c.priority < :currentPriority") void increasePriorityByOne(@Param("categoryId") Long categoryId, @Param("currentPriority") int currentPriority, - @Param("newPriority") int newPriority); + @Param("newPriority") int newPriority, + @Param("userId")Long userId); @Modifying @Query("UPDATE Category c SET c.priority = c.priority - 1 " + - "WHERE c.categoryId != :categoryId AND c.priority > :currentPriority") - void decreasePriorityNextDeleteCategory(@Param("categoryId") Long categoryId, @Param("currentPriority") int currentPriority); + "WHERE c.categoryId != :categoryId AND c.user.userId =:userId AND c.priority > :currentPriority") + void decreasePriorityNextDeleteCategory(@Param("categoryId") Long categoryId, @Param("currentPriority") int currentPriority,@Param("userId")Long userId); @Query("SELECT c FROM Category c WHERE " + "c.user.userId = :userId and " + diff --git a/linkmind/src/main/java/com/app/toaster/service/category/CategoryService.java b/linkmind/src/main/java/com/app/toaster/service/category/CategoryService.java index 1376441..e1636f8 100644 --- a/linkmind/src/main/java/com/app/toaster/service/category/CategoryService.java +++ b/linkmind/src/main/java/com/app/toaster/service/category/CategoryService.java @@ -71,7 +71,7 @@ public void deleteCategory(final DeleteCategoryDto deleteCategoryDto){ Category category = categoryRepository.findById(categoryId) .orElseThrow(() -> new NotFoundException(Error.NOT_FOUND_CATEGORY_EXCEPTION, Error.NOT_FOUND_CATEGORY_EXCEPTION.getMessage())); - categoryRepository.decreasePriorityNextDeleteCategory(categoryId, category.getPriority()); + categoryRepository.decreasePriorityNextDeleteCategory(categoryId, category.getPriority(),category.getUser().getUserId()); Reminder timer = timerRepository.findByCategory_CategoryId(categoryId); if(timer != null) @@ -133,9 +133,9 @@ public void editCategoryPriority(ChangeCateoryPriorityDto changeCateoryPriorityD category.updateCategoryPriority(changeCateoryPriorityDto.newPriority()); if(currentPriority < newPriority) - categoryRepository.decreasePriorityByOne(changeCateoryPriorityDto.categoryId(), currentPriority, newPriority); + categoryRepository.decreasePriorityByOne(changeCateoryPriorityDto.categoryId(), currentPriority, newPriority, category.getUser().getUserId()); else if (currentPriority > newPriority) - categoryRepository.increasePriorityByOne(changeCateoryPriorityDto.categoryId(), currentPriority, newPriority); + categoryRepository.increasePriorityByOne(changeCateoryPriorityDto.categoryId(), currentPriority, newPriority,category.getUser().getUserId()); } From fe0ce200da2b0f3b36e8a31ef51812216f4de60b Mon Sep 17 00:00:00 2001 From: mmihye Date: Thu, 18 Jan 2024 03:53:34 +0900 Subject: [PATCH 2/6] =?UTF-8?q?[#149]=20fix:=20=EB=84=A4=EC=9D=B4=EB=B0=8D?= =?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/app/toaster/controller/CategoryController.java | 2 +- .../java/com/app/toaster/service/category/CategoryService.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java b/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java index 6067a5a..0abd531 100644 --- a/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java +++ b/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java @@ -90,7 +90,7 @@ public ApiResponse searchProducts(@UserId Long userId ,@RequestParam("query") St } @GetMapping("/check") - public ApiResponse checkDuplicatedNickname(@UserId Long userId ,@RequestParam("title") String title){ + public ApiResponse checkDuplicatedCategoryTitle(@UserId Long userId ,@RequestParam("title") String title){ return ApiResponse.success(Success.GET_DUPLICATED_SUCCESS, categoryService.checkDuplicatedTitle(userId,title)); } diff --git a/linkmind/src/main/java/com/app/toaster/service/category/CategoryService.java b/linkmind/src/main/java/com/app/toaster/service/category/CategoryService.java index e1636f8..97cfca6 100644 --- a/linkmind/src/main/java/com/app/toaster/service/category/CategoryService.java +++ b/linkmind/src/main/java/com/app/toaster/service/category/CategoryService.java @@ -169,4 +169,5 @@ public DuplicatedResponse checkDuplicatedTitle(Long userId, String title){ return DuplicatedResponse.of(categoryRepository.existsCategoriesByUserAndTitle(findUser(userId), title)); } + } From fd88f675f4a5b1915b3b48c4e374221f5c2de3fb Mon Sep 17 00:00:00 2001 From: soohyun Date: Thu, 18 Jan 2024 04:11:19 +0900 Subject: [PATCH 3/6] =?UTF-8?q?[#146]=20refactor:=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EB=B0=8F=20=EA=B2=80=EC=83=89=20=EC=8B=9C?= =?UTF-8?q?=20validation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../advice/ControllerExceptionAdvice.java | 37 +++++++++++++++---- .../controller/CategoryController.java | 3 +- .../toaster/service/search/SearchService.java | 6 +++ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/linkmind/src/main/java/com/app/toaster/common/advice/ControllerExceptionAdvice.java b/linkmind/src/main/java/com/app/toaster/common/advice/ControllerExceptionAdvice.java index a9d3dc6..d6de9cc 100644 --- a/linkmind/src/main/java/com/app/toaster/common/advice/ControllerExceptionAdvice.java +++ b/linkmind/src/main/java/com/app/toaster/common/advice/ControllerExceptionAdvice.java @@ -7,12 +7,14 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.stereotype.Component; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.HttpMediaTypeNotSupportedException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -54,29 +56,48 @@ protected ResponseEntity handleConstraintDefinitionException(final } @ExceptionHandler(MalformedURLException.class) - protected ApiResponse handleConstraintDefinitionException(final MalformedURLException e) { + protected ResponseEntity handleConstraintDefinitionException(final MalformedURLException e) { Sentry.captureException(e); - return ApiResponse.error(Error.MALFORMED_URL_EXEPTION, Error.MALFORMED_URL_EXEPTION.getMessage()); + return ResponseEntity.status(Error.MALFORMED_URL_EXEPTION.getErrorCode()) + .body(ApiResponse.error(Error.MALFORMED_URL_EXEPTION, Error.MALFORMED_URL_EXEPTION.getMessage())); } @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(DateTimeParseException.class) - protected ApiResponse handleDateTimeParseException(final DateTimeParseException e) { - return ApiResponse.error(Error.BAD_REQUEST_REMIND_TIME, Error.BAD_REQUEST_REMIND_TIME.getMessage()); + protected ResponseEntity handleDateTimeParseException(final DateTimeParseException e) { + return ResponseEntity.status(Error.BAD_REQUEST_REMIND_TIME.getErrorCode()) + .body(ApiResponse.error(Error.BAD_REQUEST_REMIND_TIME, Error.BAD_REQUEST_REMIND_TIME.getMessage())); } @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - protected ApiResponse handleHttpRequestMethodNotSupportedException(final HttpRequestMethodNotSupportedException e) { - return ApiResponse.error(Error.REQUEST_METHOD_VALIDATION_EXCEPTION, e.getMessage()); + protected ResponseEntity handleHttpRequestMethodNotSupportedException(final HttpRequestMethodNotSupportedException e) { + return ResponseEntity.status(e.getStatusCode()) + .body(ApiResponse.error(Error.REQUEST_METHOD_VALIDATION_EXCEPTION, Error.REQUEST_METHOD_VALIDATION_EXCEPTION.getMessage())); } @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(HttpMediaTypeNotSupportedException.class) - protected ApiResponse handleHttpMediaTypeNotSupportedException(final HttpMediaTypeNotSupportedException e) { - return ApiResponse.error(Error.REQUEST_MEDIA_TYPE_VALIDATION_EXCEPTION, e.getMessage()); + protected ResponseEntity handleHttpMediaTypeNotSupportedException(final HttpMediaTypeNotSupportedException e) { + return ResponseEntity.status(e.getStatusCode()) + .body(ApiResponse.error(Error.REQUEST_MEDIA_TYPE_VALIDATION_EXCEPTION, Error.REQUEST_MEDIA_TYPE_VALIDATION_EXCEPTION.getMessage())); + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(MissingServletRequestParameterException.class) + protected ResponseEntity MissingServletRequestParameterException(final MissingServletRequestParameterException e) { + return ResponseEntity.status(e.getStatusCode()) + .body(ApiResponse.error(Error.BAD_REQUEST_VALIDATION, Error.BAD_REQUEST_VALIDATION.getMessage())); } + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(HttpMessageNotReadableException.class) + protected ResponseEntity MissingServletRequestParameterException(final HttpMessageNotReadableException e) { + return ResponseEntity.status(Error.BAD_REQUEST_VALIDATION.getErrorCode()) + .body(ApiResponse.error(Error.BAD_REQUEST_VALIDATION, Error.BAD_REQUEST_VALIDATION.getMessage())); + } + + /** * 500 Internal Server Error diff --git a/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java b/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java index 92d0194..7ea0824 100644 --- a/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java +++ b/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java @@ -7,6 +7,7 @@ import com.app.toaster.controller.response.toast.ToastFilter; import com.app.toaster.controller.response.category.CategoryResponse; import com.app.toaster.controller.response.category.GetCategoryResponseDto; +import com.app.toaster.controller.valid.TitleValid; import com.app.toaster.exception.Success; import com.app.toaster.service.category.CategoryService; import com.app.toaster.service.search.SearchService; @@ -87,7 +88,7 @@ public ApiResponse getCategory( @GetMapping("/search") - public ApiResponse searchProducts(@UserId Long userId ,@RequestParam("query") String query){ + public ApiResponse searchProducts(@UserId Long userId ,@NotNull @RequestParam("query") String query){ return searchService.searchMain(userId,query); } diff --git a/linkmind/src/main/java/com/app/toaster/service/search/SearchService.java b/linkmind/src/main/java/com/app/toaster/service/search/SearchService.java index 6736d97..228bba1 100644 --- a/linkmind/src/main/java/com/app/toaster/service/search/SearchService.java +++ b/linkmind/src/main/java/com/app/toaster/service/search/SearchService.java @@ -16,6 +16,7 @@ import com.app.toaster.domain.User; import com.app.toaster.exception.Error; import com.app.toaster.exception.Success; +import com.app.toaster.exception.model.BadRequestException; import com.app.toaster.exception.model.CustomException; import com.app.toaster.exception.model.NotFoundException; import com.app.toaster.infrastructure.CategoryRepository; @@ -23,6 +24,7 @@ import com.app.toaster.infrastructure.UserRepository; import com.google.protobuf.Api; +import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; @Service @@ -33,6 +35,10 @@ public class SearchService { private final CategoryRepository categoryRepository; public ApiResponse searchMain(Long userId, String searchParam){ + if(searchParam.isBlank()){ + throw new BadRequestException(Error.BAD_REQUEST_VALIDATION, Error.BAD_REQUEST_URL.getMessage()); + } + User presentUser = userRepository.findByUserId(userId).orElseThrow( ()-> new NotFoundException(Error.NOT_FOUND_USER_EXCEPTION, Error.NOT_FOUND_USER_EXCEPTION.getMessage()) ); From fedeea233b7908c6dccbd42db4a610dff616ec99 Mon Sep 17 00:00:00 2001 From: mmihye Date: Thu, 18 Jan 2024 04:27:51 +0900 Subject: [PATCH 4/6] =?UTF-8?q?[#151]=20fix:=20=EB=8C=80=EA=B8=B0=EC=A4=91?= =?UTF-8?q?=EC=9D=B8=20=ED=83=80=EC=9D=B4=EB=A8=B8=20=EC=95=8C=EB=9E=8C?= =?UTF-8?q?=EC=97=AC=EB=B6=80=EB=8A=94=20updateAt=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EC=95=88=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/app/toaster/domain/Reminder.java | 9 ++++++++- .../java/com/app/toaster/service/timer/TimerService.java | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/linkmind/src/main/java/com/app/toaster/domain/Reminder.java b/linkmind/src/main/java/com/app/toaster/domain/Reminder.java index f66a75d..4f51317 100644 --- a/linkmind/src/main/java/com/app/toaster/domain/Reminder.java +++ b/linkmind/src/main/java/com/app/toaster/domain/Reminder.java @@ -10,6 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.LocalTime; import java.util.ArrayList; import java.util.List; @@ -17,7 +18,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Reminder extends BaseTimeEntity { +public class Reminder{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; @@ -37,6 +38,8 @@ public class Reminder extends BaseTimeEntity { private Boolean isAlarm; + private LocalDateTime updateAt = LocalDateTime.now(); + @Builder public Reminder(User user, Category category, String comment, LocalTime remindTime, ArrayList remindDates, Boolean isAlarm) { this.user = user; @@ -63,4 +66,8 @@ public void changeAlarm(){ this.isAlarm = !isAlarm; } + public void setUpdatedAtNow(){ + this.updateAt = LocalDateTime.now(); + } + } diff --git a/linkmind/src/main/java/com/app/toaster/service/timer/TimerService.java b/linkmind/src/main/java/com/app/toaster/service/timer/TimerService.java index 03bcd4d..8f9f8cb 100644 --- a/linkmind/src/main/java/com/app/toaster/service/timer/TimerService.java +++ b/linkmind/src/main/java/com/app/toaster/service/timer/TimerService.java @@ -112,6 +112,8 @@ public void updateTimerDatetime(Long userId, Long timerId, UpdateTimerDateTimeDt } reminder.updateRemindDates(updateTimerDateTimeDto.remindDates()); reminder.updateRemindTime(updateTimerDateTimeDto.remindTime()); + + reminder.setUpdatedAtNow(); em.flush(); LocalDateTime now = LocalDateTime.now(); @@ -139,6 +141,7 @@ public void updateTimerComment(Long userId, Long timerId, UpdateTimerCommentDto } reminder.updateComment(updateTimerCommentDto.newComment()); + reminder.setUpdatedAtNow(); } From 43a3aa6afffb49424a711f51b74f5fce32101fd2 Mon Sep 17 00:00:00 2001 From: mmihye Date: Thu, 18 Jan 2024 04:57:00 +0900 Subject: [PATCH 5/6] =?UTF-8?q?[#152]=20feat:=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A4=84=EB=9F=AC=EC=97=90=EC=84=9C=20=EC=98=88=EC=95=BD?= =?UTF-8?q?=EB=90=9C=20=EC=9E=91=EC=97=85=20=EB=AA=A8=EB=91=90=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=ED=95=98=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20api?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/app/toaster/exception/Success.java | 1 + .../app/toaster/external/client/fcm/FCMController.java | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/linkmind/src/main/java/com/app/toaster/exception/Success.java b/linkmind/src/main/java/com/app/toaster/exception/Success.java index 8c1676d..8904c51 100644 --- a/linkmind/src/main/java/com/app/toaster/exception/Success.java +++ b/linkmind/src/main/java/com/app/toaster/exception/Success.java @@ -49,6 +49,7 @@ public enum Success { CHANGE_TIMER_ALARM_SUCCESS(HttpStatus.OK, "타이머 알람여부 수정 완료"), PUSH_ALARM_PERIODIC_SUCCESS(HttpStatus.OK, "푸시알림 활성에 성공했습니다."), PUSH_ALARM_SUCCESS(HttpStatus.OK, "푸시알림 전송에 성공했습니다."), + CLEAR_SCHEDULED_TASKS_SUCCESS(HttpStatus.OK, "스케줄러에서 예약된 작업을 제거했습니다."), /** diff --git a/linkmind/src/main/java/com/app/toaster/external/client/fcm/FCMController.java b/linkmind/src/main/java/com/app/toaster/external/client/fcm/FCMController.java index 5b511d9..2367b46 100644 --- a/linkmind/src/main/java/com/app/toaster/external/client/fcm/FCMController.java +++ b/linkmind/src/main/java/com/app/toaster/external/client/fcm/FCMController.java @@ -6,12 +6,15 @@ import com.app.toaster.exception.Success; import com.app.toaster.external.client.fcm.FCMService; import lombok.RequiredArgsConstructor; +import org.checkerframework.checker.units.qual.A; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.io.IOException; +import static com.app.toaster.external.client.fcm.FCMService.clearScheduledTasks; + @RestController @RequestMapping("/alarm") @RequiredArgsConstructor @@ -42,4 +45,11 @@ public ApiResponse sendTopicScheduledTest(@RequestBody FCMPushRequestDto request sqsProducer.sendMessage(request); return ApiResponse.success(Success.PUSH_ALARM_PERIODIC_SUCCESS); } + + @DeleteMapping("/clear") + @ResponseStatus(HttpStatus.OK) + public ApiResponse deleteScheduledTasks(){ + clearScheduledTasks(); + return ApiResponse.success(Success.CLEAR_SCHEDULED_TASKS_SUCCESS); + } } \ No newline at end of file From 70c455cde864f3d8ba5d83a3b77b7d5ecff1fe29 Mon Sep 17 00:00:00 2001 From: soohyun Date: Thu, 18 Jan 2024 05:06:02 +0900 Subject: [PATCH 6/6] =?UTF-8?q?[#146]=20refactor:=20=ED=8A=B9=EC=88=98=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=90=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/advice/ControllerExceptionAdvice.java | 11 +++++++++++ .../app/toaster/controller/CategoryController.java | 4 +++- .../com/app/toaster/controller/MainController.java | 3 ++- .../com/app/toaster/controller/valid/TitleValid.java | 3 ++- .../app/toaster/controller/valid/TitleValidator.java | 8 +++++++- 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/linkmind/src/main/java/com/app/toaster/common/advice/ControllerExceptionAdvice.java b/linkmind/src/main/java/com/app/toaster/common/advice/ControllerExceptionAdvice.java index d6de9cc..dc6e7a5 100644 --- a/linkmind/src/main/java/com/app/toaster/common/advice/ControllerExceptionAdvice.java +++ b/linkmind/src/main/java/com/app/toaster/common/advice/ControllerExceptionAdvice.java @@ -18,6 +18,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.annotation.HandlerMethodValidationException; import com.app.toaster.common.dto.ApiResponse; import com.app.toaster.exception.Error; @@ -27,6 +28,7 @@ import io.sentry.Sentry; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.ConstraintDefinitionException; +import jakarta.validation.ConstraintViolationException; import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; @@ -97,6 +99,15 @@ protected ResponseEntity MissingServletRequestParameterException(fi .body(ApiResponse.error(Error.BAD_REQUEST_VALIDATION, Error.BAD_REQUEST_VALIDATION.getMessage())); } + @ResponseStatus(HttpStatus.BAD_REQUEST) // 커스텀 validation 에러 핸들링. + @ExceptionHandler(HandlerMethodValidationException.class) + protected ResponseEntity ConstraintViolationException(final HandlerMethodValidationException e) { + Sentry.captureException(e); + return ResponseEntity.status(Error.BAD_REQUEST_VALIDATION.getErrorCode()) + .body(ApiResponse.error(Error.BAD_REQUEST_VALIDATION, Error.BAD_REQUEST_VALIDATION.getMessage())); + } + + /** diff --git a/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java b/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java index 7ea0824..af3a2b7 100644 --- a/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java +++ b/linkmind/src/main/java/com/app/toaster/controller/CategoryController.java @@ -7,12 +7,14 @@ import com.app.toaster.controller.response.toast.ToastFilter; import com.app.toaster.controller.response.category.CategoryResponse; import com.app.toaster.controller.response.category.GetCategoryResponseDto; +import com.app.toaster.controller.valid.Severity; import com.app.toaster.controller.valid.TitleValid; import com.app.toaster.exception.Success; import com.app.toaster.service.category.CategoryService; import com.app.toaster.service.search.SearchService; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.validation.annotation.Validated; @@ -88,7 +90,7 @@ public ApiResponse getCategory( @GetMapping("/search") - public ApiResponse searchProducts(@UserId Long userId ,@NotNull @RequestParam("query") String query){ + public ApiResponse searchProducts(@UserId Long userId , @TitleValid(payload = Severity.Error.class) @RequestParam("query") String query){ return searchService.searchMain(userId,query); } diff --git a/linkmind/src/main/java/com/app/toaster/controller/MainController.java b/linkmind/src/main/java/com/app/toaster/controller/MainController.java index 5225a45..5c8fc86 100644 --- a/linkmind/src/main/java/com/app/toaster/controller/MainController.java +++ b/linkmind/src/main/java/com/app/toaster/controller/MainController.java @@ -5,6 +5,7 @@ import com.app.toaster.common.dto.ApiResponse; import com.app.toaster.config.UserId; +import com.app.toaster.controller.valid.TitleValid; import com.app.toaster.service.UserService; import com.app.toaster.service.search.SearchService; import com.app.toaster.service.toast.ToastService; @@ -18,7 +19,7 @@ public class MainController { private final SearchService searchService; @GetMapping("/search") - public ApiResponse searchProducts(@UserId Long userId ,@RequestParam("query") String query){ + public ApiResponse searchProducts(@UserId Long userId ,@TitleValid @RequestParam("query") String query){ return searchService.searchMain(userId,query); } diff --git a/linkmind/src/main/java/com/app/toaster/controller/valid/TitleValid.java b/linkmind/src/main/java/com/app/toaster/controller/valid/TitleValid.java index cf0cacc..43b9ad2 100644 --- a/linkmind/src/main/java/com/app/toaster/controller/valid/TitleValid.java +++ b/linkmind/src/main/java/com/app/toaster/controller/valid/TitleValid.java @@ -1,6 +1,7 @@ package com.app.toaster.controller.valid; import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.ArrayList; @@ -10,7 +11,7 @@ @Documented @Constraint(validatedBy = TitleValidator.class) -@Target({java.lang.annotation.ElementType.FIELD}) +@Target({ElementType.PARAMETER, ElementType.FIELD}) @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public @interface TitleValid { String message() default "Invalid title"; diff --git a/linkmind/src/main/java/com/app/toaster/controller/valid/TitleValidator.java b/linkmind/src/main/java/com/app/toaster/controller/valid/TitleValidator.java index 4424829..f83d5ba 100644 --- a/linkmind/src/main/java/com/app/toaster/controller/valid/TitleValidator.java +++ b/linkmind/src/main/java/com/app/toaster/controller/valid/TitleValidator.java @@ -45,6 +45,12 @@ public boolean isValid(String title, ConstraintValidatorContext context) { return false; } + if(!title.matches("^[\\S][가-힣a-zA-Z0-9\\s]{0,20}$")){ + context.buildConstraintViolationWithTemplate("특수 문자로는 검색할 수 없어요.") + .addConstraintViolation(); + return false; + } + return true; } -} +} \ No newline at end of file