From f3156e40c4ba1451a801818f1ce99f286b83c86f Mon Sep 17 00:00:00 2001 From: squall7011 Date: Wed, 22 Nov 2023 19:31:28 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20::=20=EC=9E=98=EB=AA=BB=EB=90=9C?= =?UTF-8?q?=20Image=20URL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../diary/exception/InvalidImageUrlException.kt | 8 ++++++++ .../onui/domain/diary/service/DiaryServiceImpl.kt | 15 ++++++++++++--- .../onui/domain/img/service/ImageServiceImpl.kt | 7 ++----- .../onui/global/config/error/data/ErrorCode.kt | 1 + .../onui/global/config/jwt/JwtTokenResolver.kt | 2 +- 5 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 src/main/kotlin/com/example/onui/domain/diary/exception/InvalidImageUrlException.kt diff --git a/src/main/kotlin/com/example/onui/domain/diary/exception/InvalidImageUrlException.kt b/src/main/kotlin/com/example/onui/domain/diary/exception/InvalidImageUrlException.kt new file mode 100644 index 0000000..794e68f --- /dev/null +++ b/src/main/kotlin/com/example/onui/domain/diary/exception/InvalidImageUrlException.kt @@ -0,0 +1,8 @@ +package com.example.onui.domain.diary.exception + +import com.example.onui.global.config.error.data.ErrorCode +import com.example.onui.global.config.error.exception.BusinessException + +object InvalidImageUrlException : BusinessException(ErrorCode.INVALID_IMG_URL) { + private fun readResolve(): Any = InvalidImageUrlException +} diff --git a/src/main/kotlin/com/example/onui/domain/diary/service/DiaryServiceImpl.kt b/src/main/kotlin/com/example/onui/domain/diary/service/DiaryServiceImpl.kt index cc4dceb..e1921c9 100644 --- a/src/main/kotlin/com/example/onui/domain/diary/service/DiaryServiceImpl.kt +++ b/src/main/kotlin/com/example/onui/domain/diary/service/DiaryServiceImpl.kt @@ -2,6 +2,7 @@ import com.example.onui.domain.diary.entity.Diary import com.example.onui.domain.diary.exception.DiaryNotFoundException +import com.example.onui.domain.diary.exception.InvalidImageUrlException import com.example.onui.domain.diary.presentation.request.ChattingWithGPTRequest import com.example.onui.domain.diary.presentation.request.CreateDiaryRequest import com.example.onui.domain.diary.presentation.request.UpdateDiaryRequest @@ -12,6 +13,7 @@ import com.example.onui.domain.diary.repository.DiaryRepository import com.example.onui.domain.diary.repository.QDiaryRepository import com.example.onui.global.common.facade.UserFacade import com.example.onui.global.config.error.exception.PermissionDeniedException +import com.example.onui.global.env.S3Property import com.example.onui.infra.feign.gpt.GPTClient import com.example.onui.infra.feign.gpt.dto.request.GPTQueryRequest import com.example.onui.infra.feign.gpt.dto.request.Message @@ -20,6 +22,7 @@ import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalDate import java.time.LocalDateTime +import java.util.regex.Pattern @Service @Transactional(readOnly = true) @@ -27,18 +30,24 @@ class DiaryServiceImpl( private val diaryRepository: DiaryRepository, private val userFacade: UserFacade, private val qDiaryRepository: QDiaryRepository, - private val gptClient: GPTClient + private val gptClient: GPTClient, + private val s3Property: S3Property ) : DiaryService { private companion object { const val M_SET = "너의 이름은 오누이이고 직업은 상담사야.\n아래 리스트는 내가 선택한 감정이야.\n" const val M_SET2 = "\n내 감정을 분석하고 되도록 짧게 존댓말로 솔루션을 제공해줘." + const val REGEX = "https://%s.s3.%s.amazonaws.com/%s([\\w-]+)/([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}).(png|jpg|jpeg|pdf|svg|HEIC)" } @Transactional override fun createDiary(req: CreateDiaryRequest): DiaryDetailResponse { val user = userFacade.getCurrentUser() + + if(req.image != null && !REGEX.format(s3Property.bucket, s3Property.region, s3Property.dir).toRegex().matches(req.image)) + throw InvalidImageUrlException + val now = LocalDateTime.now() val diary = @@ -56,9 +65,9 @@ class DiaryServiceImpl( } override fun getDiaryByMonth(year: Int, month: Int) = DiaryListResponse( - diaryRepository.findAllByUserAndYearAndMonthOrderByCreatedAtAsc(userFacade.getCurrentUser(), year, month)?.map { + diaryRepository.findAllByUserAndYearAndMonthOrderByCreatedAtAsc(userFacade.getCurrentUser(), year, month).map { it.toResponse() - }?.toMutableList() + }.toMutableList() ) override fun getDetailById(date: LocalDate): DiaryDetailResponse? = diaryRepository.findByUserAndYearAndMonthAndDay( diff --git a/src/main/kotlin/com/example/onui/domain/img/service/ImageServiceImpl.kt b/src/main/kotlin/com/example/onui/domain/img/service/ImageServiceImpl.kt index e788022..a1595ba 100644 --- a/src/main/kotlin/com/example/onui/domain/img/service/ImageServiceImpl.kt +++ b/src/main/kotlin/com/example/onui/domain/img/service/ImageServiceImpl.kt @@ -36,10 +36,7 @@ class ImageServiceImpl( this.contentLength = bytes.size.toLong() } - var fileName: String = file.originalFilename ?: file.name - - - val ext = fileName.split('.').last() + val ext = (file.originalFilename ?: file.name).split('.').last() try { FileType.values().first { it.extension == ext } @@ -47,7 +44,7 @@ class ImageServiceImpl( throw InvalidFileExtensionException } - fileName = "${s3Property.dir}$sub/${UUID.randomUUID()}$fileName" + val fileName = "${s3Property.dir}$sub/${UUID.randomUUID()}.$ext" val putObjectRequest = PutObjectRequest( s3Property.bucket, diff --git a/src/main/kotlin/com/example/onui/global/config/error/data/ErrorCode.kt b/src/main/kotlin/com/example/onui/global/config/error/data/ErrorCode.kt index c94ec9c..690a797 100644 --- a/src/main/kotlin/com/example/onui/global/config/error/data/ErrorCode.kt +++ b/src/main/kotlin/com/example/onui/global/config/error/data/ErrorCode.kt @@ -13,6 +13,7 @@ enum class ErrorCode( INVALID_DATE_FORMAT(HttpStatus.BAD_REQUEST, "date가 올비르지 않습니다."), TYPE_COAST_MISS_MATCHED(HttpStatus.BAD_REQUEST, "type이 ASSIGN일 때 반드시 coast를 설정해야합니다."), CAN_NOT_BUY_THEME(HttpStatus.BAD_REQUEST, "쌀이 부족합니다."), + INVALID_IMG_URL(HttpStatus.BAD_REQUEST, "잘못된 이미지 URL입니다."), // 401 INVALID_TOKEN(HttpStatus.UNAUTHORIZED, "유효하지 않은 토큰입니다."), diff --git a/src/main/kotlin/com/example/onui/global/config/jwt/JwtTokenResolver.kt b/src/main/kotlin/com/example/onui/global/config/jwt/JwtTokenResolver.kt index 00587a2..a4a9850 100644 --- a/src/main/kotlin/com/example/onui/global/config/jwt/JwtTokenResolver.kt +++ b/src/main/kotlin/com/example/onui/global/config/jwt/JwtTokenResolver.kt @@ -8,7 +8,7 @@ import javax.servlet.http.HttpServletRequest class JwtTokenResolver { companion object{ - private const val REGEX_BEARER_TOKEN = "Bearer [(a-zA-Z0-9-._~+/=*)]{30,600}" + private const val REGEX_BEARER_TOKEN = "Bearer [(a-zA-Z0-9-e._~+/=*)]{30,600}" } fun resolveToken(httpServletRequest: HttpServletRequest) = parseToken(