Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BLOOM-041] validation 추가, api 마이너 수정 #46 #48

Merged
merged 29 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
79a0583
feat: spring validation 추가
Dompoo Aug 12, 2024
024e56a
feat: spring validation 적용
Dompoo Aug 12, 2024
f30346f
feat: validation 예외 전역 처리 코드 작성
Dompoo Aug 12, 2024
69d22a0
fix: spring validation을 kotlin과 통합하기 위해 수정
Dompoo Aug 12, 2024
305068d
test: validationTest 추가
Dompoo Aug 12, 2024
83577f6
feat: 날짜 관련 필드에도 validation 추가, 기존 service에서 검증하던 것들을 삭제
Dompoo Aug 12, 2024
e6b80bd
test: 기존 미래날짜 관련 테스트를 validation 테스트로 통합
Dompoo Aug 12, 2024
a1734b7
fix: 식물 저장 api에서 scientificName 대신에 plantId를 받도록 수정
Dompoo Aug 12, 2024
64a1021
fix: 내 식물 저장시에 별명값을 필수로 받도록 수정,내 식물 수정시에 별명값을 받지 않아도 되도록 수정
Dompoo Aug 12, 2024
bfbae28
fix: 엔티티들의 PK의 자료형을 Long에서 Long?으로 변경
Dompoo Aug 12, 2024
35d8bdf
feat: 홈화면 api에 imageUrl 추가, 테스트코드 작성
Dompoo Aug 12, 2024
404e276
fix: request 필드 에러의 공통 응답의 json 형식을 변경
Dompoo Aug 13, 2024
9304356
fix: 필드 에러 메시지 순서 변경
Dompoo Aug 13, 2024
807df5a
fix: rebase 오류 해결
Dompoo Aug 13, 2024
c6fdca2
fix: Kotlin의 NotNull이 Spring Validation과 잘 작동하지 않는 문제 해결
Dompoo Aug 13, 2024
17326e0
fix: Nullable 확인을 서비스에서 처리하도록 수정, NotNull 대신에 NotBlank만 사용
Dompoo Aug 13, 2024
fec6956
test: 입력값으로 null이 들어가는 테스트 추가
Dompoo Aug 13, 2024
3ec74b9
test: 통합 테스트 진행 후에 데이터 클리닝
Dompoo Aug 13, 2024
f2e51db
chore: ARGUMENT_ERROR -> BAD_REQUEST 로 예외명 변경
Dompoo Aug 13, 2024
d494c9c
chore: 사용하지 않는 변수 삭제
Dompoo Aug 13, 2024
d11e093
chore: 의존성 정리
Dompoo Aug 13, 2024
cc42121
fix: rebase 오류 해결
Dompoo Aug 13, 2024
6df3600
refactor: 엔티티 생성, 연관관계 매핑을 도메인이 직접 하도록 리팩토링
Dompoo Aug 14, 2024
00396b2
feat: 테스트에 test 프로필 적용
Dompoo Aug 14, 2024
96bebf9
refactor: requestDto -> createDto 변환을 컨트롤러에서 하도록 리팩토링
Dompoo Aug 14, 2024
6915f56
chore: 필요없는 ARGUMENT_ERROR 삭제, 테스트용 코드 삭제
Dompoo Aug 14, 2024
3debc24
refactor: BaseEntity의 값을 외부에서 주입하는 것이 아니라, 직접 생성하도록 리팩터링
Dompoo Aug 14, 2024
40a7cde
fix: BaseEntity의 칼럼을 LocalDate에서 LocalDateTime으로 수정
Dompoo Aug 14, 2024
da1f50b
refactor: 이미지 즐겨찾기 수정시 request를 넘겨주는 것이 아니라, 즐겨찾기 여부만 파라미터로 넘겨주도록 리팩터링
Dompoo Aug 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ dependencies {
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
runtimeOnly("com.mysql:mysql-connector-j")
runtimeOnly("com.h2database:h2")
testImplementation("com.h2database:h2")

// Validation
implementation("org.springframework.boot:spring-boot-starter-validation")

// Configuration
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package dnd11th.blooming.api.controller.image
import dnd11th.blooming.api.dto.image.ImageFavoriteModifyRequest
import dnd11th.blooming.api.dto.image.ImageSaveRequest
import dnd11th.blooming.api.service.image.ImageService
import jakarta.validation.Valid
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.time.LocalDate

@RestController
@RequestMapping("/api/v1/myplants")
Expand All @@ -20,14 +20,16 @@ class ImageController(
@PostMapping("/{myPlantId}/image")
override fun saveImage(
@PathVariable myPlantId: Long,
@RequestBody request: ImageSaveRequest,
) = imageService.saveImage(myPlantId, request, LocalDate.now())
@RequestBody @Valid request: ImageSaveRequest,
) = imageService.saveImage(myPlantId, request.toImageCreateDto())

@PatchMapping("/image/{imageId}")
override fun modifyFavorite(
@PathVariable imageId: Long,
@RequestBody request: ImageFavoriteModifyRequest,
) = imageService.modifyFavorite(imageId, request)
@RequestBody @Valid request: ImageFavoriteModifyRequest,
) {
imageService.modifyFavorite(imageId, request.favorite!!)
}

@DeleteMapping("/image/{imageId}")
override fun deleteImage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import dnd11th.blooming.api.dto.location.LocationResponse
import dnd11th.blooming.api.dto.location.LocationSaveRequest
import dnd11th.blooming.api.dto.location.LocationSaveResponse
import dnd11th.blooming.api.service.location.LocationService
import jakarta.validation.Valid
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
Expand All @@ -21,16 +22,16 @@ class LocationController(
) : LocationApi {
@PostMapping
override fun saveLocation(
@RequestBody request: LocationSaveRequest,
): LocationSaveResponse = locationService.saveLocation(request)
@RequestBody @Valid request: LocationSaveRequest,
): LocationSaveResponse = locationService.saveLocation(request.toLocationCreateDto())

@GetMapping
override fun findAllLocation(): List<LocationResponse> = locationService.findAllLocation()

@PatchMapping("/{locationId}")
override fun modifyLocation(
@PathVariable locationId: Long,
@RequestBody request: LocationModifyRequest,
@RequestBody @Valid request: LocationModifyRequest,
): LocationResponse = locationService.modifyLocation(locationId, request)

@DeleteMapping("/{locationId}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import dnd11th.blooming.api.dto.myplant.MyPlantSaveRequest
import dnd11th.blooming.api.dto.myplant.MyPlantSaveResponse
import dnd11th.blooming.api.dto.myplant.MyPlantSortParam
import dnd11th.blooming.api.service.myplant.MyPlantService
import jakarta.validation.Valid
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
Expand All @@ -29,8 +30,8 @@ class MyPlantController(
) : MyPlantApi {
@PostMapping
override fun saveMyPlant(
@RequestBody request: MyPlantSaveRequest,
): MyPlantSaveResponse = myPlantService.saveMyPlant(request, LocalDate.now())
@RequestBody @Valid request: MyPlantSaveRequest,
): MyPlantSaveResponse = myPlantService.saveMyPlant(request.toMyPlantCreateDto(), request.locationId!!)

@GetMapping
override fun findAllMyPlant(
Expand All @@ -48,7 +49,7 @@ class MyPlantController(
@PatchMapping("/{myPlantId}")
override fun modifyMyPlant(
@PathVariable myPlantId: Long,
@RequestBody request: MyPlantModifyRequest,
@RequestBody @Valid request: MyPlantModifyRequest,
) = myPlantService.modifyMyPlant(myPlantId, request)

@DeleteMapping("/{myPlantId}")
Expand All @@ -69,12 +70,12 @@ class MyPlantController(
@PatchMapping("/{myPlantId}/healthcheck")
override fun modifyMyPlantHealthCheck(
@PathVariable myPlantId: Long,
@RequestBody request: MyPlantHealthCheckRequest,
@RequestBody @Valid request: MyPlantHealthCheckRequest,
) = myPlantService.modifyMyPlantHealthCheck(myPlantId, request)

@PatchMapping("/{myPlantId}/alarm")
override fun modifyMyPlantAlarm(
@PathVariable myPlantId: Long,
@RequestBody request: AlarmModifyRequest,
@RequestBody @Valid request: AlarmModifyRequest,
) = myPlantService.modifyMyPlantAlarm(myPlantId, request)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import dnd11th.blooming.api.dto.user.IdTokenRequest
import dnd11th.blooming.api.dto.user.TokenResponse
import dnd11th.blooming.api.service.user.SocialLoginService
import dnd11th.blooming.domain.entity.user.OauthProvider
import jakarta.validation.Valid
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
Expand All @@ -18,7 +19,7 @@ class UserController(
@PostMapping("/login/{provider}")
fun login(
@PathVariable provider: String,
@RequestBody idTokenRequest: IdTokenRequest,
@RequestBody @Valid idTokenRequest: IdTokenRequest,
): TokenResponse {
return socialLoginService.socialLogin(OauthProvider.from(provider), idTokenRequest.idToken)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ data class HomeResponse(
@field:Schema(description = "내 식물 정보 리스트")
val myPlantInfo: List<MyPlantHomeResponse>,
// TODO : 식물 일러스트 응답 추가 필요
// val illustUrl: String,
) {
companion object {
fun from(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import java.time.LocalDate
)
data class MyPlantHomeResponse(
@field:Schema(description = "내 식물 ID", example = "1")
val myPlantId: Long,
val myPlantId: Long?,
@field:Schema(description = "내 식물 별명", example = "뿡뿡이")
val nickname: String,
@field:Schema(description = "내 식물 학명", example = "몬스테라 델리오사")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package dnd11th.blooming.api.dto.image

data class ImageCreateDto(
val url: String,
)
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package dnd11th.blooming.api.dto.image

import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotNull

@Schema(
name = "Image Favorite Modify Request",
description = "이미지 즐겨찾기 수정 요청",
)
data class ImageFavoriteModifyRequest(
@field:Schema(description = "즐겨찾기 여부", example = "true")
val favorite: Boolean,
@field:NotNull(message = "즐겨찾기 여부는 필수값입니다.")
val favorite: Boolean?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ data class ImageResponse(
ImageResponse(
imageUrl = image.url,
favorite = image.favorite,
createdDate = image.createdDate,
createdDate = image.createdDate.toLocalDate(),
)

fun fromList(images: List<Image>): List<ImageResponse> =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
package dnd11th.blooming.api.dto.image

import dnd11th.blooming.domain.entity.Image
import dnd11th.blooming.domain.entity.MyPlant
import io.swagger.v3.oas.annotations.media.Schema
import java.time.LocalDate
import jakarta.validation.constraints.NotBlank

@Schema(
name = "Image Save Request",
description = "이미지를 저장하는 요청",
)
data class ImageSaveRequest(
@field:Schema(description = "이미지 URL", example = "image.com/17")
val imageUrl: String,
@field:NotBlank(message = "URL은 필수값입니다.")
val imageUrl: String?,
) {
fun toImage(
myPlant: MyPlant,
now: LocalDate,
): Image =
Image(
url = imageUrl,
favorite = false,
currentDate = now,
).also {
it.setMyPlantRelation(myPlant)
}
fun toImageCreateDto(): ImageCreateDto =
ImageCreateDto(
url = imageUrl!!,
)
Dompoo marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package dnd11th.blooming.api.dto.location

data class LocationCreateDto(
val name: String,
)
Dompoo marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package dnd11th.blooming.api.dto.location

import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank

@Schema(
name = "Location Modify Request",
description = "위치 수정 요청",
)
data class LocationModifyRequest(
@field:Schema(description = "수정할 위치 이름", example = "거실")
val name: String,
@field:NotBlank(message = "새로운 위치명은 필수값입니다.")
val name: String?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import io.swagger.v3.oas.annotations.media.Schema
)
data class LocationResponse(
@field:Schema(description = "위치 ID", example = "3")
val id: Long,
val id: Long?,
@field:Schema(description = "위치 이름", example = "베란다")
val name: String,
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package dnd11th.blooming.api.dto.location

import dnd11th.blooming.domain.entity.Location
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank

@Schema(
name = "Location Save Request",
description = "위치 저장 요청",
)
data class LocationSaveRequest(
@field:NotBlank(message = "새로운 위치명은 필수값입니다.")
@field:Schema(description = "새로운 위치 이름", example = "부엌")
val name: String,
val name: String?,
) {
fun toLocation(): Location =
Location(
name = name,
fun toLocationCreateDto(): LocationCreateDto =
LocationCreateDto(
name = name!!,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import io.swagger.v3.oas.annotations.media.Schema
)
class LocationSaveResponse(
@field:Schema(description = "저장된 위치 ID", example = "4")
val id: Long,
val id: Long?,
@field:Schema(description = "위치 이름", example = "부엌")
val name: String,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,33 @@ package dnd11th.blooming.api.dto.myplant

import dnd11th.blooming.domain.entity.Alarm
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotNull

@Schema(
name = "Alarm Modify Request",
description = "알림 수정 요청",
)
data class AlarmModifyRequest(
@field:Schema(description = "물주기 알림 여부", example = "true")
val waterAlarm: Boolean,
@field:NotNull(message = "물주기 알림 여부는 필수값입니다.")
val waterAlarm: Boolean?,
@field:Schema(description = "물주기 알림 주기", example = "4")
val waterPeriod: Int?,
@field:Schema(description = "비료주기 알림 여부", example = "false")
val fertilizerAlarm: Boolean,
@field:NotNull(message = "비료주기 알림 여부는 필수값입니다.")
val fertilizerAlarm: Boolean?,
@field:Schema(description = "비료주기 알림 주기", example = "45")
val fertilizerPeriod: Int?,
@field:Schema(description = "건강확인 알림 여부", example = "true")
val healthCheckAlarm: Boolean,
@field:NotNull(message = "건강확인 알림 여부는 필수값입니다.")
val healthCheckAlarm: Boolean?,
) {
fun toAlarm(): Alarm =
Alarm(
waterAlarm = waterAlarm,
waterAlarm = waterAlarm!!,
waterPeriod = waterPeriod,
fertilizerAlarm = fertilizerAlarm,
fertilizerAlarm = fertilizerAlarm!!,
fertilizerPeriod = fertilizerPeriod,
healthCheckAlarm = healthCheckAlarm,
healthCheckAlarm = healthCheckAlarm!!,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dnd11th.blooming.api.dto.myplant

import java.time.LocalDate

data class MyPlantCreateDto(
val nickname: String,
val startDate: LocalDate,
val lastWateredDate: LocalDate,
val lastFertilizerDate: LocalDate,
val waterAlarm: Boolean,
val waterPeriod: Int?,
val fertilizerAlarm: Boolean,
val fertilizerPeriod: Int?,
val healthCheckAlarm: Boolean,
)
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package dnd11th.blooming.api.dto.myplant

import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotNull

@Schema(
name = "HealthCheck Alarm Modify Request",
description = "건강확인 알림 변경 요청",
)
data class MyPlantHealthCheckRequest(
@field:Schema(description = "건강확인 알림 여부", example = "true")
val healthCheck: Boolean,
@field:NotNull(message = "건강확인 알림 여부는 필수값입니다.")
val healthCheck: Boolean?,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package dnd11th.blooming.api.dto.myplant

data class MyPlantIdWithImageUrl(
val imageUrl: String,
val myPlantId: Long,
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dnd11th.blooming.api.dto.myplant

import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.PastOrPresent
import java.time.LocalDate

@Schema(
Expand All @@ -13,9 +14,12 @@ data class MyPlantModifyRequest(
@field:Schema(description = "변경할 위치 ID", example = "4")
val locationId: Long?,
@field:Schema(description = "변경할 키우기 시작한 날짜", example = "2024-05-17")
@field:PastOrPresent(message = "키우기 시작한 날짜는 미래일 수 없습니다.")
val startDate: LocalDate?,
@field:Schema(description = "변경할 마지막으로 물 준 날짜", example = "2024-05-17")
@field:PastOrPresent(message = "마지막으로 물 준 날짜는 미래일 수 없습니다.")
val lastWateredDate: LocalDate?,
@field:Schema(description = "변경할 마지막으로 비료 준 날짜", example = "2024-05-17")
@field:PastOrPresent(message = "마지막으로 비료 준 날짜는 미래일 수 없습니다.")
val lastFertilizerDate: LocalDate?,
)
Loading
Loading