From 09e2db8ac9a7ab88635ae801be0271588eca2fdc Mon Sep 17 00:00:00 2001 From: KimDoubleB Date: Sat, 29 Jun 2024 23:25:21 +0900 Subject: [PATCH 1/7] fix: Password to String for 4 digit --- .../main/kotlin/com/piikii/application/domain/room/Room.kt | 5 ++++- .../port/input/room/dto/request/RoomSaveRequestForm.kt | 5 ++++- .../port/input/room/dto/request/RoomUpdateRequestForm.kt | 5 ++++- .../main/kotlin/com/piikii/input/http/controller/RoomApi.kt | 5 +++-- .../persistence/postgresql/persistence/entity/RoomEntity.kt | 5 +++-- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/piikii-application/src/main/kotlin/com/piikii/application/domain/room/Room.kt b/piikii-application/src/main/kotlin/com/piikii/application/domain/room/Room.kt index 9b5cfd9f..47c2b03f 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/domain/room/Room.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/domain/room/Room.kt @@ -10,7 +10,7 @@ data class Room( val address: String, val meetDay: LocalDate, val thumbnailLink: String, - val password: Short, + val password: Password, val voteDeadline: LocalDateTime?, val roomId: UUID, ) { @@ -18,3 +18,6 @@ data class Room( return this.voteDeadline == null || this.voteDeadline.isBefore(LocalDateTime.now()) } } + +@JvmInline +value class Password(val value: String) diff --git a/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/RoomSaveRequestForm.kt b/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/RoomSaveRequestForm.kt index 8098a12e..d6d3f664 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/RoomSaveRequestForm.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/RoomSaveRequestForm.kt @@ -1,8 +1,10 @@ package com.piikii.application.port.input.room.dto.request import com.fasterxml.jackson.annotation.JsonInclude +import com.piikii.application.domain.room.Password import com.piikii.application.domain.room.Room import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.Size import java.time.LocalDate import java.util.UUID @@ -17,7 +19,8 @@ data class RoomSaveRequestForm( @Schema(description = "썸네일 이미지") val thumbnailLink: String, @Schema(description = "모임 비밀번호") - val password: Short, + @Size(max = 4, message = "Data must be 4 characters or less") + val password: Password, @Schema(description = "모임 날짜") val meetDay: LocalDate, ) { diff --git a/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/RoomUpdateRequestForm.kt b/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/RoomUpdateRequestForm.kt index 61570a29..1c2d67ea 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/RoomUpdateRequestForm.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/RoomUpdateRequestForm.kt @@ -1,7 +1,9 @@ package com.piikii.application.port.input.room.dto.request +import com.piikii.application.domain.room.Password import com.piikii.application.domain.room.Room import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.Size import java.time.LocalDate import java.time.LocalDateTime import java.util.UUID @@ -16,7 +18,8 @@ data class RoomUpdateRequestForm( @Schema(description = "썸네일 이미지") val thumbnailLink: String, @Schema(description = "모임 비밀번호") - val password: Short, + @Size(max = 4, message = "Data must be 4 characters or less") + val password: Password, @Schema(description = "모임 날짜") val meetDay: LocalDate, @Schema(description = "투표 마감일") diff --git a/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/RoomApi.kt b/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/RoomApi.kt index 27feeed2..6ca138ec 100644 --- a/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/RoomApi.kt +++ b/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/RoomApi.kt @@ -9,6 +9,7 @@ import com.piikii.input.http.docs.RoomApiDocs import com.piikii.input.http.dto.ResponseForm import com.piikii.input.http.dto.RoomMessage import org.springframework.http.HttpStatus +import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.DeleteMapping import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable @@ -28,7 +29,7 @@ class RoomApi( @ResponseStatus(HttpStatus.CREATED) @PostMapping override fun generate( - @RequestBody request: RoomSaveRequestForm, + @Validated @RequestBody request: RoomSaveRequestForm, ): ResponseForm { return ResponseForm( data = roomUseCase.generate(request), @@ -39,7 +40,7 @@ class RoomApi( @ResponseStatus(HttpStatus.OK) @PutMapping override fun modifyInformation( - @RequestBody request: RoomUpdateRequestForm, + @Validated @RequestBody request: RoomUpdateRequestForm, ): ResponseForm { roomUseCase.modify(request) return ResponseForm( diff --git a/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/RoomEntity.kt b/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/RoomEntity.kt index ffbcfabe..e94e187c 100644 --- a/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/RoomEntity.kt +++ b/piikii-output-persistence/postgresql/src/main/kotlin/com/piikii/output/persistence/postgresql/persistence/entity/RoomEntity.kt @@ -1,5 +1,6 @@ package com.piikii.output.persistence.postgresql.persistence.entity +import com.piikii.application.domain.room.Password import com.piikii.application.domain.room.Room import com.piikii.output.persistence.postgresql.persistence.common.BaseEntity import jakarta.persistence.Column @@ -22,8 +23,8 @@ class RoomEntity( var meetDay: LocalDate, @Column(name = "thumbnail_link", length = 255) var thumbnailLink: String, - @Column(name = "password", nullable = false) - var password: Short, + @Column(name = "password", nullable = false, length = 4) + var password: Password, @Column(name = "vote_deadline") var voteDeadline: LocalDateTime?, @Column(name = "room_id", nullable = false, unique = true) From c4e7cfb0aa46da6f81d221098b4b912347eadeff Mon Sep 17 00:00:00 2001 From: KimDoubleB Date: Sat, 29 Jun 2024 23:26:15 +0900 Subject: [PATCH 2/7] feat: send Password when setting vote deadline --- .../port/input/room/dto/request/VoteDeadlineSetRequest.kt | 5 +++++ .../main/kotlin/com/piikii/input/http/controller/VoteApi.kt | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/VoteDeadlineSetRequest.kt b/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/VoteDeadlineSetRequest.kt index c7c15f97..b05094ce 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/VoteDeadlineSetRequest.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/dto/request/VoteDeadlineSetRequest.kt @@ -1,9 +1,14 @@ package com.piikii.application.port.input.room.dto.request +import com.piikii.application.domain.room.Password import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.Size import java.time.LocalDateTime data class VoteDeadlineSetRequest( @Schema(description = "투표 마감일") val voteDeadline: LocalDateTime, + @Schema(description = "방 패스워드") + @Size(max = 4, message = "Data must be 4 characters or less") + val password: Password, ) diff --git a/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt b/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt index 96cf518c..991a222f 100644 --- a/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt +++ b/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt @@ -8,6 +8,7 @@ import com.piikii.input.http.dto.ResponseForm import com.piikii.input.http.dto.request.VoteRequest import com.piikii.input.http.dto.response.VoteStatusResponse import org.springframework.http.HttpStatus +import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PatchMapping import org.springframework.web.bind.annotation.PathVariable @@ -28,7 +29,7 @@ class VoteApi( @PatchMapping("/deadline") override fun changeVoteDeadline( @PathVariable roomId: UUID, - @RequestBody request: VoteDeadlineSetRequest, + @Validated @RequestBody request: VoteDeadlineSetRequest, ): ResponseForm { roomUseCase.changeVoteDeadline(roomId, request.voteDeadline) return ResponseForm.EMPTY_RESPONSE From d3d5d92807bd267cff175fd1e356a7a887510710 Mon Sep 17 00:00:00 2001 From: KimDoubleB Date: Sat, 29 Jun 2024 23:31:13 +0900 Subject: [PATCH 3/7] feat: added ROOM_PASSWORD_INVALID Exception code --- .../src/main/kotlin/com/piikii/common/exception/ExceptionCode.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/piikii-common/src/main/kotlin/com/piikii/common/exception/ExceptionCode.kt b/piikii-common/src/main/kotlin/com/piikii/common/exception/ExceptionCode.kt index 26a767c3..4cb4081c 100644 --- a/piikii-common/src/main/kotlin/com/piikii/common/exception/ExceptionCode.kt +++ b/piikii-common/src/main/kotlin/com/piikii/common/exception/ExceptionCode.kt @@ -7,6 +7,7 @@ enum class ExceptionCode( // 400 ILLEGAL_ARGUMENT_EXCEPTION(400, "요청 값이 올바르지 않습니다."), UNAUTHORIZED(401, "인증된 토큰으로부터의 요청이 아닙니다."), + ROOM_PASSWORD_INVALID(401, "방 패스워드가 틀립니다."), ACCESS_DENIED(403, "해당 리소스에 접근할 수 없습니다."), NOT_FOUNDED(404, "해당 리소스를 찾을 수 없습니다."), CONFLICT(409, "해당 리소스가 중복됩니다."), From 238862286b10c5ea8675760bf34097b71c094edd Mon Sep 17 00:00:00 2001 From: KimDoubleB Date: Sat, 29 Jun 2024 23:31:23 +0900 Subject: [PATCH 4/7] feat: password valid method for room --- .../main/kotlin/com/piikii/application/domain/room/Room.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/piikii-application/src/main/kotlin/com/piikii/application/domain/room/Room.kt b/piikii-application/src/main/kotlin/com/piikii/application/domain/room/Room.kt index 47c2b03f..601adf2b 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/domain/room/Room.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/domain/room/Room.kt @@ -17,6 +17,10 @@ data class Room( fun isVoteUnavailable(): Boolean { return this.voteDeadline == null || this.voteDeadline.isBefore(LocalDateTime.now()) } + + fun isPasswordValid(password: Password): Boolean { + return this.password == password + } } @JvmInline From c5b079cc93e1b4c29bb63a701baea17fb8b5546a Mon Sep 17 00:00:00 2001 From: KimDoubleB Date: Sat, 29 Jun 2024 23:32:34 +0900 Subject: [PATCH 5/7] feat: password verify method at setting vote deadline --- .../application/domain/room/RoomService.kt | 18 ++++++++++++++++-- .../application/port/input/room/RoomUseCase.kt | 2 ++ .../piikii/input/http/controller/VoteApi.kt | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/piikii-application/src/main/kotlin/com/piikii/application/domain/room/RoomService.kt b/piikii-application/src/main/kotlin/com/piikii/application/domain/room/RoomService.kt index f42c140f..1d4eb47e 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/domain/room/RoomService.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/domain/room/RoomService.kt @@ -7,6 +7,8 @@ import com.piikii.application.port.input.room.dto.response.RoomGetResponseForm import com.piikii.application.port.input.room.dto.response.RoomSaveResponseForm import com.piikii.application.port.output.persistence.RoomCommandPort import com.piikii.application.port.output.persistence.RoomQueryPort +import com.piikii.common.exception.ExceptionCode +import com.piikii.common.exception.PiikiiException import org.springframework.stereotype.Service import java.time.LocalDateTime import java.util.UUID @@ -36,9 +38,21 @@ class RoomService( override fun changeVoteDeadline( roomId: UUID, + password: Password, voteDeadline: LocalDateTime, ) { - val room = roomQueryPort.retrieve(roomId).copy(voteDeadline = voteDeadline) - roomCommandPort.update(room) + roomQueryPort.retrieve(roomId).let { room -> + verifyPassword(room, password) + roomCommandPort.update(room.copy(voteDeadline = voteDeadline)) + } + } + + private fun verifyPassword( + room: Room, + password: Password, + ) { + require(room.isPasswordValid(password)) { + throw PiikiiException(ExceptionCode.ROOM_PASSWORD_INVALID) + } } } diff --git a/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/RoomUseCase.kt b/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/RoomUseCase.kt index f8d0db53..9d01c311 100644 --- a/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/RoomUseCase.kt +++ b/piikii-application/src/main/kotlin/com/piikii/application/port/input/room/RoomUseCase.kt @@ -1,5 +1,6 @@ package com.piikii.application.port.input.room +import com.piikii.application.domain.room.Password import com.piikii.application.port.input.room.dto.request.RoomSaveRequestForm import com.piikii.application.port.input.room.dto.request.RoomUpdateRequestForm import com.piikii.application.port.input.room.dto.response.RoomGetResponseForm @@ -18,6 +19,7 @@ interface RoomUseCase { fun changeVoteDeadline( roomId: UUID, + password: Password, voteDeadline: LocalDateTime, ) } diff --git a/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt b/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt index 991a222f..5424cf75 100644 --- a/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt +++ b/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt @@ -31,7 +31,7 @@ class VoteApi( @PathVariable roomId: UUID, @Validated @RequestBody request: VoteDeadlineSetRequest, ): ResponseForm { - roomUseCase.changeVoteDeadline(roomId, request.voteDeadline) + roomUseCase.changeVoteDeadline(roomId, request.password, request.voteDeadline) return ResponseForm.EMPTY_RESPONSE } From 0eb71398c7839c618238dbbe7e0ec6f7a579cdcf Mon Sep 17 00:00:00 2001 From: KimDoubleB Date: Sat, 29 Jun 2024 23:37:29 +0900 Subject: [PATCH 6/7] feat: Validated, Valid annotations --- .../main/kotlin/com/piikii/input/http/controller/RoomApi.kt | 6 ++++-- .../main/kotlin/com/piikii/input/http/controller/VoteApi.kt | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/RoomApi.kt b/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/RoomApi.kt index 6ca138ec..61936886 100644 --- a/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/RoomApi.kt +++ b/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/RoomApi.kt @@ -8,6 +8,7 @@ import com.piikii.application.port.input.room.dto.response.RoomSaveResponseForm import com.piikii.input.http.docs.RoomApiDocs import com.piikii.input.http.dto.ResponseForm import com.piikii.input.http.dto.RoomMessage +import jakarta.validation.Valid import org.springframework.http.HttpStatus import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.DeleteMapping @@ -21,6 +22,7 @@ import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController import java.util.UUID +@Validated @RestController @RequestMapping("/v1/rooms") class RoomApi( @@ -29,7 +31,7 @@ class RoomApi( @ResponseStatus(HttpStatus.CREATED) @PostMapping override fun generate( - @Validated @RequestBody request: RoomSaveRequestForm, + @Valid @RequestBody request: RoomSaveRequestForm, ): ResponseForm { return ResponseForm( data = roomUseCase.generate(request), @@ -40,7 +42,7 @@ class RoomApi( @ResponseStatus(HttpStatus.OK) @PutMapping override fun modifyInformation( - @Validated @RequestBody request: RoomUpdateRequestForm, + @Valid @RequestBody request: RoomUpdateRequestForm, ): ResponseForm { roomUseCase.modify(request) return ResponseForm( diff --git a/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt b/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt index 5424cf75..f3ae36ca 100644 --- a/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt +++ b/piikii-input-http/src/main/kotlin/com/piikii/input/http/controller/VoteApi.kt @@ -7,6 +7,7 @@ import com.piikii.input.http.docs.VoteApiDocs import com.piikii.input.http.dto.ResponseForm import com.piikii.input.http.dto.request.VoteRequest import com.piikii.input.http.dto.response.VoteStatusResponse +import jakarta.validation.Valid import org.springframework.http.HttpStatus import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.GetMapping @@ -19,6 +20,7 @@ import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController import java.util.UUID +@Validated @RestController @RequestMapping("/room/{roomId}/votes") class VoteApi( @@ -29,7 +31,7 @@ class VoteApi( @PatchMapping("/deadline") override fun changeVoteDeadline( @PathVariable roomId: UUID, - @Validated @RequestBody request: VoteDeadlineSetRequest, + @Valid @RequestBody request: VoteDeadlineSetRequest, ): ResponseForm { roomUseCase.changeVoteDeadline(roomId, request.password, request.voteDeadline) return ResponseForm.EMPTY_RESPONSE From 1e4752c647464ec639fc36c9a0eee4526f242fbd Mon Sep 17 00:00:00 2001 From: KimDoubleB Date: Sat, 29 Jun 2024 23:39:44 +0900 Subject: [PATCH 7/7] feat: handle ConstraintDeclarationException --- .../piikii/input/http/advice/ExceptionAdvice.kt | 17 +++++++++++++++++ .../http/dto/response/ExceptionResponse.kt | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/piikii-input-http/src/main/kotlin/com/piikii/input/http/advice/ExceptionAdvice.kt b/piikii-input-http/src/main/kotlin/com/piikii/input/http/advice/ExceptionAdvice.kt index d46474a3..3e669a53 100644 --- a/piikii-input-http/src/main/kotlin/com/piikii/input/http/advice/ExceptionAdvice.kt +++ b/piikii-input-http/src/main/kotlin/com/piikii/input/http/advice/ExceptionAdvice.kt @@ -3,6 +3,7 @@ package com.piikii.input.http.advice import com.piikii.common.exception.PiikiiException import com.piikii.common.logutil.SystemLogger.logger import com.piikii.input.http.dto.response.ExceptionResponse +import jakarta.validation.ConstraintDeclarationException import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.ExceptionHandler @@ -24,6 +25,22 @@ class ExceptionAdvice { ) } + @ExceptionHandler(ConstraintDeclarationException::class) + fun handleConstraintDeclarationException( + exception: ConstraintDeclarationException, + ): ResponseEntity { + logger.error(exception) { "RequestBody Validation Failure" } + return ResponseEntity + .status(HttpStatus.BAD_REQUEST) + .body( + ExceptionResponse( + message = "요청 형식이 잘못됬습니다 (Request Validation Failure)", + cause = exception.message, + timestamp = System.currentTimeMillis(), + ), + ) + } + @ExceptionHandler(Exception::class) fun handleException(exception: Exception): ResponseEntity { logger.error(exception) { "Occurred Exception" } diff --git a/piikii-input-http/src/main/kotlin/com/piikii/input/http/dto/response/ExceptionResponse.kt b/piikii-input-http/src/main/kotlin/com/piikii/input/http/dto/response/ExceptionResponse.kt index ccd65941..5979d623 100644 --- a/piikii-input-http/src/main/kotlin/com/piikii/input/http/dto/response/ExceptionResponse.kt +++ b/piikii-input-http/src/main/kotlin/com/piikii/input/http/dto/response/ExceptionResponse.kt @@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonInclude @JsonInclude(JsonInclude.Include.NON_NULL) class ExceptionResponse( - val message: String, + val message: String?, val cause: String?, val timestamp: Long, )