-
Notifications
You must be signed in to change notification settings - Fork 1
feat: 독서기록상세조회 기능을 개발합니다 #68
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
Changes from all commits
f85d13e
2ef17c7
ecca676
3332358
0090c28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package org.yapp.apis.readingrecord.exception | ||
|
|
||
| import org.springframework.http.HttpStatus | ||
| import org.yapp.globalutils.exception.BaseErrorCode | ||
|
|
||
| enum class ReadingRecordErrorCode( | ||
| private val status: HttpStatus, | ||
| private val code: String, | ||
| private val message: String | ||
| ) : BaseErrorCode { | ||
| READING_RECORD_NOT_FOUND(HttpStatus.NOT_FOUND, "READING_RECORD_001", "독서 기록을 찾을 수 없습니다."); | ||
|
|
||
| override fun getHttpStatus(): HttpStatus = status | ||
| override fun getCode(): String = code | ||
| override fun getMessage(): String = message | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package org.yapp.apis.readingrecord.exception | ||
|
|
||
| import org.yapp.globalutils.exception.CommonException | ||
|
|
||
| class ReadingRecordNotFoundException( | ||
| errorCode: ReadingRecordErrorCode, | ||
| message: String? = null | ||
| ) : CommonException(errorCode, message) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,9 @@ import org.springframework.stereotype.Service | |
| import org.yapp.apis.book.service.UserBookService | ||
| import org.yapp.apis.readingrecord.dto.request.CreateReadingRecordRequest | ||
| import org.yapp.apis.readingrecord.dto.response.ReadingRecordResponse | ||
| import org.yapp.apis.readingrecord.exception.ReadingRecordErrorCode | ||
| import org.yapp.apis.readingrecord.exception.ReadingRecordNotFoundException | ||
| import org.yapp.domain.book.BookDomainService | ||
| import org.yapp.domain.readingrecord.ReadingRecordDomainService | ||
| import org.yapp.domain.readingrecord.ReadingRecordSortType | ||
| import java.util.* | ||
|
|
@@ -35,6 +38,20 @@ class ReadingRecordService( | |
| return ReadingRecordResponse.from(readingRecordInfoVO) | ||
| } | ||
|
|
||
| fun getReadingRecordDetail( | ||
| userId: UUID, | ||
| readingRecordId: UUID | ||
| ): ReadingRecordResponse { | ||
| val readingRecordInfoVO = readingRecordDomainService.findReadingRecordById(readingRecordId) | ||
| ?: throw ReadingRecordNotFoundException( | ||
| ReadingRecordErrorCode.READING_RECORD_NOT_FOUND, | ||
| "Reading record not found with id: $readingRecordId" | ||
| ) | ||
|
|
||
| userBookService.validateUserBookExists(userId, readingRecordInfoVO.userBookId.value) | ||
|
|
||
| return ReadingRecordResponse.from(readingRecordInfoVO) | ||
| } | ||
|
Comment on lines
+41
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 보안 취약점: 인가되지 않은 사용자에게 정보 누출 가능성이 있습니다. 현재 구현에서는 독서 기록 존재 여부를 먼저 확인한 후 사용자 권한을 검증하는데, 이는 권한이 없는 사용자에게도 특정 ID의 독서 기록 존재 여부를 알려줄 수 있습니다. 다음과 같이 수정하여 보안을 강화하는 것을 권장합니다: fun getReadingRecordDetail(
userId: UUID,
readingRecordId: UUID
): ReadingRecordResponse {
val readingRecordInfoVO = readingRecordDomainService.findReadingRecordById(readingRecordId)
?: throw ReadingRecordNotFoundException(
ReadingRecordErrorCode.READING_RECORD_NOT_FOUND,
"Reading record not found with id: $readingRecordId"
)
- userBookService.validateUserBookExists(userId, readingRecordInfoVO.userBookId.value)
+ // 사용자 권한 검증을 먼저 수행하여 정보 누출 방지
+ try {
+ userBookService.validateUserBookExists(userId, readingRecordInfoVO.userBookId.value)
+ } catch (e: Exception) {
+ // 권한이 없는 경우에도 동일한 예외를 던져 정보 누출 방지
+ throw ReadingRecordNotFoundException(
+ ReadingRecordErrorCode.READING_RECORD_NOT_FOUND,
+ "Reading record not found with id: $readingRecordId"
+ )
+ }
return ReadingRecordResponse.from(readingRecordInfoVO)
}🤖 Prompt for AI Agents |
||
|
|
||
| fun getReadingRecordsByDynamicCondition( | ||
| userBookId: UUID, | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -35,6 +35,18 @@ class ReadingRecordUseCase( | |||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| fun getReadingRecordDetail( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| userId: UUID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| readingRecordId: UUID | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): ReadingRecordResponse { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| userAuthService.validateUserExists(userId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| return readingRecordService.getReadingRecordDetail( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| userId = userId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| readingRecordId = readingRecordId | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+38
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 보안 취약점: 사용자 권한 검증이 누락되었습니다. 현재 구현에서는 사용자 존재 여부만 확인하고 있어, 다른 사용자의 독서기록에 접근할 수 있는 보안 취약점이 있습니다. 독서기록 소유권 검증이 필요합니다. 다음과 같이 수정하여 보안을 강화하세요: fun getReadingRecordDetail(
userId: UUID,
readingRecordId: UUID
): ReadingRecordResponse {
userAuthService.validateUserExists(userId)
+
+ // 독서기록 소유권 검증 추가 필요
+ // readingRecordService에서 userId와 readingRecord의 소유자가 일치하는지 확인
return readingRecordService.getReadingRecordDetail(
userId = userId,
readingRecordId = readingRecordId
)
}또는 service layer에서 소유권 검증이 이루어지고 있는지 확인해주세요. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| fun getReadingRecordsByUserBookId( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| userId: UUID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| userBookId: UUID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
API 경로 구조에 대한 제안사항입니다.
현재
/detail/{readingRecordId}경로는 기능적으로 올바르지만, RESTful 설계 관점에서/{readingRecordId}만으로도 충분할 수 있습니다. 다른 리소스와의 일관성을 고려해보세요.하지만 기존
/userBookId엔드포인트와의 충돌을 피하기 위해 현재 구조가 더 명확할 수 있습니다.📝 Committable suggestion
🤖 Prompt for AI Agents