From 293fa239098bd4a44858f5df9b3c5ee36c1a8523 Mon Sep 17 00:00:00 2001 From: dldmsql Date: Mon, 9 Sep 2024 23:37:27 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat(POLABO-130):=204=EC=B0=A8=20mvp=201?= =?UTF-8?q?=EC=B0=A8=20=EA=B0=9C=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/controller/BoardController.kt | 35 +++++--- .../board/repository/BoardJooqRepository.kt | 3 + .../repository/BoardJooqRepositoryImpl.kt | 81 ++++++++++++++++++- .../domain/board/service/BoardService.kt | 15 +++- .../polaroid/controller/PolaroidController.kt | 31 +++++-- .../controller/dto/PolaroidGetResponse.kt | 7 +- .../repository/PolaroidJooqRepository.kt | 1 + .../repository/PolaroidJooqRepositoryImpl.kt | 9 +++ .../polaroid/service/PolaroidService.kt | 25 +++++- .../global/exception/CustomErrorCode.kt | 2 + 10 files changed, 184 insertions(+), 25 deletions(-) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/BoardController.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/BoardController.kt index 3276e1b..770e4dd 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/BoardController.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/BoardController.kt @@ -5,23 +5,19 @@ import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardGetResponse import com.ddd.sonnypolabobe.domain.board.service.BoardService import com.ddd.sonnypolabobe.domain.user.dto.UserDto import com.ddd.sonnypolabobe.global.response.ApplicationResponse -import com.ddd.sonnypolabobe.logger +import com.ddd.sonnypolabobe.global.security.JwtUtil import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.security.core.context.SecurityContextHolder -import org.springframework.web.bind.annotation.GetMapping -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 org.springframework.web.bind.annotation.* import java.util.UUID @Tag(name = "Board API", description = "보드 관련 API") @RestController @RequestMapping("/api/v1/boards") class BoardController( - private val boardService: BoardService + private val boardService: BoardService, + private val jwtUtil: JwtUtil ) { @Operation( summary = "보드 생성", description = """ @@ -40,15 +36,21 @@ class BoardController( return ApplicationResponse.ok(this.boardService.create(request)) } - @Tag(name = "1.1.0") + @Tag(name = "1.2.0") @Operation( summary = "보드 조회", description = """ 보드를 조회합니다. DTO 필드 수정했습니다. 폴라로이드에 닉네임 필드 추가 + """ ) @GetMapping("/{id}") - fun get(@PathVariable id: String) = ApplicationResponse.ok(this.boardService.getById(id)) + fun get(@PathVariable id: String, + @RequestHeader("Authorization") token: String? + ) : ApplicationResponse> { + val user = token?.let { this.jwtUtil.getAuthenticatedMemberFromToken(it) } + return ApplicationResponse.ok(this.boardService.getById(id, user)) + } @Operation( summary = "보드 누적 생성 수 조회", description = """ @@ -65,4 +67,17 @@ class BoardController( ) @GetMapping("/create-available") fun createAvailable() = ApplicationResponse.ok(this.boardService.createAvailable()) + + @Tag(name = "1.2.0") + @Operation( + summary = "보드명 주제 추천", description = """ + 보드명 주제를 추천합니다. + """ + ) + @GetMapping("/recommend-title") + fun recommendTitle() : ApplicationResponse> { + val user = + SecurityContextHolder.getContext().authentication.principal as UserDto.Companion.Res + return ApplicationResponse.ok(this.boardService.recommendTitle(user)) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepository.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepository.kt index fd5da4e..63e2c14 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepository.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepository.kt @@ -2,9 +2,11 @@ package com.ddd.sonnypolabobe.domain.board.repository import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardCreateRequest import com.ddd.sonnypolabobe.domain.board.my.dto.MyBoardDto +import com.ddd.sonnypolabobe.domain.user.dto.GenderType import com.ddd.sonnypolabobe.jooq.polabo.tables.Board import org.jooq.Record6 import org.jooq.Record7 +import java.time.LocalDate import java.time.LocalDateTime import java.util.* @@ -25,4 +27,5 @@ interface BoardJooqRepository { ): List fun selectTotalCountByParticipant(userId: Long): Long + fun selectRecommendTitle(userBirth: LocalDate?, userGender: GenderType): List } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt index a3755cc..ca423e7 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt @@ -3,17 +3,22 @@ package com.ddd.sonnypolabobe.domain.board.repository import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardCreateRequest import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardGetResponse import com.ddd.sonnypolabobe.domain.board.my.dto.MyBoardDto +import com.ddd.sonnypolabobe.domain.user.dto.GenderType import com.ddd.sonnypolabobe.global.util.DateConverter import com.ddd.sonnypolabobe.global.util.UuidConverter import com.ddd.sonnypolabobe.global.util.UuidGenerator +import com.ddd.sonnypolabobe.jooq.polabo.enums.UserGender import com.ddd.sonnypolabobe.jooq.polabo.tables.Board import com.ddd.sonnypolabobe.jooq.polabo.tables.Polaroid -import org.jooq.DSLContext -import org.jooq.Record6 -import org.jooq.Record7 +import com.ddd.sonnypolabobe.jooq.polabo.tables.User +import org.jooq.* import org.jooq.impl.DSL +import org.jooq.impl.DSL.* import org.springframework.stereotype.Repository +import java.sql.Timestamp +import java.time.LocalDate import java.time.LocalDateTime +import java.time.temporal.ChronoUnit import java.util.* @Repository @@ -216,4 +221,74 @@ class BoardJooqRepositoryImpl( .fetchOne(0, Long::class.java) ?: 0L } + + override fun selectRecommendTitle(userBirth: LocalDate?, userGender: GenderType): List { + val jBoard = Board.BOARD + val jUser = User.USER + val jPolaroid = Polaroid.POLAROID + // 현재 날짜 기준으로 연령대를 계산하는 로직 + var userAgeGroup : String = "20-29세" + if (userBirth != null) { + val age = ChronoUnit.YEARS.between(userBirth, LocalDate.now()) + userAgeGroup = if (age < 15) { + "15세 미만" + } else if (age < 20) { + "15-19세" + } else if (age < 30) { + "20-29세" + } else if (age < 40) { + "30-39세" + } else if (age < 50) { + "40-49세" + } else if (age < 60) { + "50-59세" + } else { + "60대 이상" + } + } + + // 기준일 (30일 전) + val thirtyDaysAgo = LocalDateTime.now().minusDays(30) + + // 쿼리 작성 + return this.dslContext.select(jBoard.TITLE) + .from(jBoard) + .join(jUser) + .on(jBoard.USER_ID.eq(jUser.ID)) + .leftJoin( + this.dslContext.select(jPolaroid.BOARD_ID, count().`as`("polaroid_count")) + .from(jPolaroid) + .where(jPolaroid.YN.eq(1) + .and(jPolaroid.ACTIVEYN.eq(1))) + .groupBy(jPolaroid.BOARD_ID) + .asTable("sub_query") + ) + .on(jBoard.ID.eq(field(name("sub_query", "board_id"), jBoard.ID.dataType))) + .where(jBoard.YN.eq(1) + .and(jBoard.ACTIVEYN.eq(1)) + .and(jBoard.CREATED_AT.greaterOrEqual(thirtyDaysAgo)) + .and(genderAndAgeGroupMatch(userGender, userAgeGroup)) + ) + .orderBy(field("sub_query.polaroid_count", Int::class.java).desc(), jBoard.CREATED_AT.desc()) + .limit(8) + .fetchInto(String::class.java) + } + + // 성별 및 연령대 일치 조건을 위한 메서드 + private fun genderAndAgeGroupMatch( userGender : GenderType, userAgeGroup: String?): Condition { + return User.USER.GENDER.eq(UserGender.valueOf(userGender.name)) + .or(User.USER.BIRTH_DT.isNotNull().and(ageGroupCondition(userAgeGroup))) + } + + // 연령대 계산 로직에 따른 조건을 처리하는 메서드 + private fun ageGroupCondition(ageGroup: String?) : Condition{ + return `when`(User.USER.BIRTH_DT.ge(LocalDate.now().minusYears(15)), "15세 미만") + .`when`(User.USER.BIRTH_DT.ge(LocalDate.now().minusYears(19)), "15-19세") + .`when`(User.USER.BIRTH_DT.ge(LocalDate.now().minusYears(29)), "20-29세") + .`when`(User.USER.BIRTH_DT.ge(LocalDate.now().minusYears(39)), "30-39세") + .`when`(User.USER.BIRTH_DT.ge(LocalDate.now().minusYears(49)), "40-49세") + .`when`(User.USER.BIRTH_DT.ge(LocalDate.now().minusYears(59)), "50-59세") + .otherwise("60대 이상").eq(ageGroup); + } + } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt index 9cfcac8..8d4b9e8 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt @@ -4,8 +4,10 @@ import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardCreateRequest import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardGetResponse import com.ddd.sonnypolabobe.domain.board.repository.BoardJooqRepository import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidGetResponse +import com.ddd.sonnypolabobe.domain.user.dto.UserDto import com.ddd.sonnypolabobe.global.exception.ApplicationException import com.ddd.sonnypolabobe.global.exception.CustomErrorCode +import com.ddd.sonnypolabobe.global.security.AuthenticatedMember import com.ddd.sonnypolabobe.global.util.S3Util import com.ddd.sonnypolabobe.global.util.UuidConverter import org.springframework.beans.factory.annotation.Value @@ -23,7 +25,7 @@ class BoardService( this.boardJooqRepository.insertOne(request)?.let { UuidConverter.byteArrayToUUID(it) } ?: throw ApplicationException(CustomErrorCode.BOARD_CREATED_FAILED) - fun getById(id: String): List { + fun getById(id: String, user: AuthenticatedMember?): List { return id.run { val queryResult = boardJooqRepository.selectOneById(UuidConverter.stringToUUID(this@run)) @@ -36,7 +38,10 @@ class BoardService( imageUrl = it.value3()?.let { it1 -> s3Util.getImgUrl(it1) } ?: "", oneLineMessage = it.value4() ?: "폴라보와의 추억 한 줄", userId = it.value6() ?: 0L, - nickname = it.value7() ?: "" + nickname = it.value7() ?: "", + isMine = it.value6() == user?.id?.toLong(), + createdAt = it.value5() + ) }.filter { it.id != 0L } BoardGetResponse(title = title ?: "", items = polaroids) @@ -51,4 +56,10 @@ class BoardService( } } + fun recommendTitle(user: UserDto.Companion.Res): List { + val userBirthYear = user.birthDt + val userGender = user.gender + return this.boardJooqRepository.selectRecommendTitle(userBirth = userBirthYear, userGender) + } + } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/PolaroidController.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/PolaroidController.kt index c1edb01..c94c1b3 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/PolaroidController.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/PolaroidController.kt @@ -1,24 +1,43 @@ package com.ddd.sonnypolabobe.domain.polaroid.controller +import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidGetResponse import com.ddd.sonnypolabobe.domain.polaroid.service.PolaroidService +import com.ddd.sonnypolabobe.domain.user.dto.UserDto import com.ddd.sonnypolabobe.global.response.ApplicationResponse import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.web.bind.annotation.* @RestController @RequestMapping("/api/v1/polaroids") class PolaroidController(private val polaroidService: PolaroidService) { - @Tag(name = "1.1.0") + @Tag(name = "1.2.0") @Operation( summary = "폴라로이드 조회", description = """ 폴라로이드를 조회합니다. + DTO 에 작성자 여부를 추가했습니다. """ ) @GetMapping("/{id}") - fun getById(@PathVariable id: Long) = ApplicationResponse.ok(this.polaroidService.getById(id)) + fun getById(@PathVariable id: Long): ApplicationResponse { + val user = + SecurityContextHolder.getContext().authentication.principal as UserDto.Companion.Res + return ApplicationResponse.ok(this.polaroidService.getById(id, user)) + } + + @Tag(name = "1.2.0") + @Operation( + summary = "폴라로이드 삭제", description = """ + 폴라로이드를 삭제합니다. + """ + ) + @DeleteMapping("/{id}") + fun deleteById(@PathVariable id: Long): ApplicationResponse { + val user = + SecurityContextHolder.getContext().authentication.principal as UserDto.Companion.Res + this.polaroidService.deleteById(id, user) + return ApplicationResponse.ok() + } } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt index 4322274..be7b0a8 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt @@ -1,6 +1,7 @@ package com.ddd.sonnypolabobe.domain.polaroid.controller.dto import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime import java.util.UUID data class PolaroidGetResponse( @@ -13,5 +14,9 @@ data class PolaroidGetResponse( @Schema(description = "작성자 ID", example = "userId") val userId: Long?, @Schema(description = "작성자 닉네임", example = "nickname") - val nickname: String + val nickname: String, + @Schema(description = "작성자인지 여부", example = "true") + val isMine: Boolean, + @Schema(description = "생성일시", example = "2021-01-01T00:00:00") + val createdAt: LocalDateTime? ) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepository.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepository.kt index dd70759..c39ba22 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepository.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepository.kt @@ -8,4 +8,5 @@ interface PolaroidJooqRepository { fun selectOneById(id: Long): PolaroidRecord fun countByBoardId(uuidToByteArray: ByteArray): Int fun insertOne(boardId: ByteArray, request: PolaroidCreateRequest, userId: Long): Long + fun deleteById(id: Long) } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt index b4a5963..105bd08 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt @@ -72,4 +72,13 @@ class PolaroidJooqRepositoryImpl(private val dslContext: DSLContext) : PolaroidJ ) .fetchOne(0, Int::class.java) ?: 0 } + + override fun deleteById(id: Long) { + val jPolaroid = Polaroid.POLAROID + this.dslContext.update(jPolaroid) + .set(jPolaroid.YN, 0) + .set(jPolaroid.ACTIVEYN, 0) + .where(jPolaroid.ID.eq(id)) + .execute() + } } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt index b7721e2..645e020 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt @@ -1,8 +1,10 @@ package com.ddd.sonnypolabobe.domain.polaroid.service +import com.ddd.sonnypolabobe.domain.board.repository.BoardJooqRepository import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidCreateRequest import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidGetResponse import com.ddd.sonnypolabobe.domain.polaroid.repository.PolaroidJooqRepository +import com.ddd.sonnypolabobe.domain.user.dto.UserDto import com.ddd.sonnypolabobe.global.exception.ApplicationException import com.ddd.sonnypolabobe.global.exception.CustomErrorCode import com.ddd.sonnypolabobe.global.util.S3Util @@ -13,6 +15,7 @@ import org.springframework.transaction.annotation.Transactional @Service class PolaroidService( private val polaroidJooqRepository: PolaroidJooqRepository, + private val boardJooqRepository: BoardJooqRepository, private val s3Util: S3Util ) { @Transactional @@ -28,14 +31,20 @@ class PolaroidService( } @Transactional(readOnly = true) - fun getById(id: Long): PolaroidGetResponse { - return this.polaroidJooqRepository.selectOneById(id).let { + fun getById(id: Long, user: UserDto.Companion.Res): PolaroidGetResponse { + val data = this.polaroidJooqRepository.selectOneById(id) + val boardWriter = + this.boardJooqRepository.findById(UuidConverter.byteArrayToUUID(data.boardId!!)) + ?: throw ApplicationException(CustomErrorCode.BOARD_NOT_FOUND) + return data.let { PolaroidGetResponse( id = it.id!!, imageUrl = s3Util.getImgUrl(it.imageKey!!), oneLineMessage = it.oneLineMessage ?: "", userId = it.userId, - nickname = it.nickname ?: "" + nickname = it.nickname ?: "", + isMine = boardWriter.userId == user.id, + createdAt = it.createdAt ) } } @@ -52,4 +61,14 @@ class PolaroidService( userId ) } + + @Transactional + fun deleteById(id: Long, user: UserDto.Companion.Res) { + val data = this.polaroidJooqRepository.selectOneById(id) + val boardWriter = + this.boardJooqRepository.findById(UuidConverter.byteArrayToUUID(data.boardId!!)) + ?: throw ApplicationException(CustomErrorCode.BOARD_NOT_FOUND) + if (boardWriter.userId != user.id) throw ApplicationException(CustomErrorCode.POLAROID_DELETE_FAILED) + this.polaroidJooqRepository.deleteById(id) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/exception/CustomErrorCode.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/exception/CustomErrorCode.kt index 6a519d7..3f71369 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/exception/CustomErrorCode.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/exception/CustomErrorCode.kt @@ -26,4 +26,6 @@ enum class CustomErrorCode( BOARD_CREATED_FAILED(HttpStatus.INTERNAL_SERVER_ERROR, "BOARD001", "보드 생성에 실패했습니다."), BOARD_NOT_FOUND(HttpStatus.NOT_FOUND, "BOARD002", "보드를 찾을 수 없습니다."), + POLAROID_DELETE_FAILED(HttpStatus.UNAUTHORIZED, "POL003", "폴라로이드 삭제할 권한이 없습니다."), + } \ No newline at end of file From c90397b8933313a6b5e51ff698cd37e1c6f904b1 Mon Sep 17 00:00:00 2001 From: dldmsql Date: Sat, 14 Sep 2024 12:58:57 +0900 Subject: [PATCH 2/6] =?UTF-8?q?chore:=20=ED=97=AC=EC=8A=A4=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20=EB=94=94=EC=8A=A4=EC=BD=94=EB=93=9C=20disable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/healthCheck.yml | 48 +++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/healthCheck.yml b/.github/workflows/healthCheck.yml index fd762b1..f56c59b 100644 --- a/.github/workflows/healthCheck.yml +++ b/.github/workflows/healthCheck.yml @@ -1,24 +1,24 @@ -name: "[운영] 헬스체크" - -on: - schedule: - - cron: "0 0 */3 * *" - -jobs: - healthcheck: - runs-on: ubuntu-latest - steps: - - name: API Health Check - id: health_check - uses: jtalk/url-health-check-action@v3 - with: - url: ${{ secrets.BASE_URI_PROD }} - max-attempts: 3 - retry-delay: 1s - - - name: Discord Webhook Action - if: always() - uses: tsickert/discord-webhook@v5.3.0 - with: - webhook-url: ${{ secrets.WEBHOOK_URL }} - content: ${{ job.status }} +#name: "[운영] 헬스체크" +# +#on: +# schedule: +# - cron: "0 0 */3 * *" +# +#jobs: +# healthcheck: +# runs-on: ubuntu-latest +# steps: +# - name: API Health Check +# id: health_check +# uses: jtalk/url-health-check-action@v3 +# with: +# url: ${{ secrets.BASE_URI_PROD }} +# max-attempts: 3 +# retry-delay: 1s +# +# - name: Discord Webhook Action +# if: always() +# uses: tsickert/discord-webhook@v5.3.0 +# with: +# webhook-url: ${{ secrets.WEBHOOK_URL }} +# content: ${{ job.status }} From deb0510b7f4e3137ab489ccf987c6445005163ba Mon Sep 17 00:00:00 2001 From: dldmsql Date: Sat, 14 Sep 2024 18:13:17 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=204=EC=B0=A8=20MVP=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../board/controller/BoardController.kt | 7 +- .../board/controller/dto/BoardGetResponse.kt | 7 +- .../domain/board/entity/BoardEntity.kt | 15 --- .../board/repository/BoardJooqRepository.kt | 3 +- .../repository/BoardJooqRepositoryImpl.kt | 13 +- .../board/repository/vo/BoardGetOneVo.kt | 16 +++ .../domain/board/service/BoardService.kt | 29 ++-- .../controller/BoardStickerController.kt | 40 ++++++ .../board/sticker/dto/StickerCreateRequest.kt | 10 ++ .../board/sticker/dto/StickerGetResponse.kt | 9 ++ .../repository/BoardStickerRepository.kt | 11 ++ .../repository/BoardStickerRepositoryImpl.kt | 65 +++++++++ .../board/sticker/service/StickerService.kt | 20 +++ .../controller/BoardPolaroidV2Controller.kt | 7 +- .../controller/dto/PolaroidCreateRequest.kt | 5 +- .../controller/dto/PolaroidGetResponse.kt | 5 +- .../polaroid/enumerate/PolaroidOption.kt | 7 + .../repository/PolaroidJooqRepositoryImpl.kt | 3 + .../polaroid/service/PolaroidService.kt | 6 +- .../global/config/SecurityConfig.kt | 1 + .../sonnypolabobe/global/entity/BaseEntity.kt | 12 -- .../global/security/LoggingFilter.kt | 125 ------------------ 22 files changed, 238 insertions(+), 178 deletions(-) delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/entity/BoardEntity.kt create mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/vo/BoardGetOneVo.kt create mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/controller/BoardStickerController.kt create mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerCreateRequest.kt create mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerGetResponse.kt create mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepository.kt create mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepositoryImpl.kt create mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/service/StickerService.kt create mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/enumerate/PolaroidOption.kt delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/global/entity/BaseEntity.kt delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/global/security/LoggingFilter.kt diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/BoardController.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/BoardController.kt index 770e4dd..06bc890 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/BoardController.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/BoardController.kt @@ -28,19 +28,18 @@ class BoardController( """ ) @PostMapping - fun create(@RequestBody request: BoardCreateRequest) - : ApplicationResponse { + fun create(@RequestBody request: BoardCreateRequest) : ApplicationResponse { val user = SecurityContextHolder.getContext().authentication.principal as UserDto.Companion.Res request.userId = user.id return ApplicationResponse.ok(this.boardService.create(request)) } - @Tag(name = "1.2.0") + @Tag(name = "1.3.0") @Operation( summary = "보드 조회", description = """ 보드를 조회합니다. - DTO 필드 수정했습니다. 폴라로이드에 닉네임 필드 추가 + DTO 필드 수정했습니다. 스티커 리스트 추가했습니다. """ ) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt index a39545f..787e8c7 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt @@ -1,11 +1,14 @@ package com.ddd.sonnypolabobe.domain.board.controller.dto +import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerGetResponse import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidGetResponse import io.swagger.v3.oas.annotations.media.Schema data class BoardGetResponse( @Schema(description = "제목", example = "쏘니의 보드") val title: String, - @Schema(description = "작성자", example = "작성자입니다.") - val items: List + @Schema(description = "폴라로이드") + val items: List, + @Schema(description = "스티커 리스트") + val stickers : List? ) \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/entity/BoardEntity.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/entity/BoardEntity.kt deleted file mode 100644 index 439bb3f..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/entity/BoardEntity.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.ddd.sonnypolabobe.domain.board.entity - -import com.ddd.sonnypolabobe.global.entity.BaseEntity -import com.ddd.sonnypolabobe.global.util.UuidGenerator -import java.time.LocalDateTime -import java.util.* - -class BoardEntity() : BaseEntity { - override val id: UUID = UuidGenerator.create() - var title: String = "" - var userId : UUID? = null - override var yn: Boolean = true - override val createdAt: LocalDateTime = LocalDateTime.now() - override var updatedAt: LocalDateTime = LocalDateTime.now() -} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepository.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepository.kt index 63e2c14..8774419 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepository.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepository.kt @@ -2,6 +2,7 @@ package com.ddd.sonnypolabobe.domain.board.repository import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardCreateRequest import com.ddd.sonnypolabobe.domain.board.my.dto.MyBoardDto +import com.ddd.sonnypolabobe.domain.board.repository.vo.BoardGetOneVo import com.ddd.sonnypolabobe.domain.user.dto.GenderType import com.ddd.sonnypolabobe.jooq.polabo.tables.Board import org.jooq.Record6 @@ -12,7 +13,7 @@ import java.util.* interface BoardJooqRepository { fun insertOne(request: BoardCreateRequest): ByteArray? - fun selectOneById(id: UUID) : Array> + fun selectOneById(id: UUID) : List fun selectTotalCount(): Long fun selectTodayTotalCount(): Long fun findById(id: UUID): MyBoardDto.Companion.GetOneRes? diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt index ca423e7..c789736 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt @@ -3,12 +3,14 @@ package com.ddd.sonnypolabobe.domain.board.repository import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardCreateRequest import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardGetResponse import com.ddd.sonnypolabobe.domain.board.my.dto.MyBoardDto +import com.ddd.sonnypolabobe.domain.board.repository.vo.BoardGetOneVo import com.ddd.sonnypolabobe.domain.user.dto.GenderType import com.ddd.sonnypolabobe.global.util.DateConverter import com.ddd.sonnypolabobe.global.util.UuidConverter import com.ddd.sonnypolabobe.global.util.UuidGenerator import com.ddd.sonnypolabobe.jooq.polabo.enums.UserGender import com.ddd.sonnypolabobe.jooq.polabo.tables.Board +import com.ddd.sonnypolabobe.jooq.polabo.tables.BoardSticker import com.ddd.sonnypolabobe.jooq.polabo.tables.Polaroid import com.ddd.sonnypolabobe.jooq.polabo.tables.User import org.jooq.* @@ -43,18 +45,21 @@ class BoardJooqRepositoryImpl( return if (result == 1) id else null } - override fun selectOneById(id: UUID): Array> { + override fun selectOneById(id: UUID): List { val jBoard = Board.BOARD val jPolaroid = Polaroid.POLAROID + return this.dslContext .select( + jBoard.ID.convertFrom { it?.let{UuidConverter.byteArrayToUUID(it) } }, jBoard.TITLE, - jPolaroid.ID, + jPolaroid.ID.`as`(BoardGetOneVo::polaroidId.name), jPolaroid.IMAGE_KEY, jPolaroid.ONE_LINE_MESSAGE, jPolaroid.CREATED_AT, jPolaroid.USER_ID, - jPolaroid.NICKNAME + jPolaroid.NICKNAME, + jPolaroid.OPTIONS ) .from(jBoard) .leftJoin(jPolaroid).on( @@ -66,7 +71,7 @@ class BoardJooqRepositoryImpl( .and(jBoard.ACTIVEYN.eq(1)) ) .orderBy(jPolaroid.CREATED_AT.desc()) - .fetchArray() + .fetchInto(BoardGetOneVo::class.java) } diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/vo/BoardGetOneVo.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/vo/BoardGetOneVo.kt new file mode 100644 index 0000000..b178d79 --- /dev/null +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/vo/BoardGetOneVo.kt @@ -0,0 +1,16 @@ +package com.ddd.sonnypolabobe.domain.board.repository.vo + +import java.time.LocalDateTime +import java.util.UUID + +data class BoardGetOneVo( + val id: UUID?, + val title: String?, + val polaroidId : Long?, + val imageKey : String?, + val oneLineMessage: String?, + val createdAt: LocalDateTime?, + val userId : Long?, + val nickName: String?, + val options: String? +) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt index 8d4b9e8..e5f715d 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt @@ -3,20 +3,27 @@ package com.ddd.sonnypolabobe.domain.board.service import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardCreateRequest import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardGetResponse import com.ddd.sonnypolabobe.domain.board.repository.BoardJooqRepository +import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerGetResponse +import com.ddd.sonnypolabobe.domain.board.sticker.repository.BoardStickerRepository import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidGetResponse +import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption import com.ddd.sonnypolabobe.domain.user.dto.UserDto import com.ddd.sonnypolabobe.global.exception.ApplicationException import com.ddd.sonnypolabobe.global.exception.CustomErrorCode import com.ddd.sonnypolabobe.global.security.AuthenticatedMember import com.ddd.sonnypolabobe.global.util.S3Util import com.ddd.sonnypolabobe.global.util.UuidConverter +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.databind.ObjectMapper import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Service import java.util.* +import javax.swing.text.html.HTML.Tag.U @Service class BoardService( private val boardJooqRepository: BoardJooqRepository, + private val boardStickerRepository: BoardStickerRepository, private val s3Util: S3Util, @Value("\${limit.count}") private val limit: Int @@ -29,22 +36,24 @@ class BoardService( return id.run { val queryResult = boardJooqRepository.selectOneById(UuidConverter.stringToUUID(this@run)) - val groupByTitle = queryResult.groupBy { it.value1() } + val stickers = boardStickerRepository.findByBoardId(UuidConverter.stringToUUID(id)) + val groupByTitle = queryResult.groupBy { it.title } groupByTitle.map { entry -> val title = entry.key val polaroids = entry.value.map { PolaroidGetResponse( - id = it.value2() ?: 0L, - imageUrl = it.value3()?.let { it1 -> s3Util.getImgUrl(it1) } ?: "", - oneLineMessage = it.value4() ?: "폴라보와의 추억 한 줄", - userId = it.value6() ?: 0L, - nickname = it.value7() ?: "", - isMine = it.value6() == user?.id?.toLong(), - createdAt = it.value5() + id = it.polaroidId ?: 0L, + imageUrl = it.imageKey?.let { it1 -> s3Util.getImgUrl(it1) } ?: "", + oneLineMessage = it.oneLineMessage ?: "폴라보와의 추억 한 줄", + userId = it.userId ?: 0L, + nickname = it.nickName ?: "", + isMine = it.userId == user?.id?.toLong(), + createdAt = it.createdAt, + options = it.options?.let{ ObjectMapper().readValue(it, object : TypeReference>() {})} ) - }.filter { it.id != 0L } - BoardGetResponse(title = title ?: "", items = polaroids) + }.filter { it.id != 0L }.distinctBy { it.id } + BoardGetResponse(title = title ?: "", items = polaroids, stickers = stickers) } } } diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/controller/BoardStickerController.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/controller/BoardStickerController.kt new file mode 100644 index 0000000..2c7c60c --- /dev/null +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/controller/BoardStickerController.kt @@ -0,0 +1,40 @@ +package com.ddd.sonnypolabobe.domain.board.sticker.controller + +import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerCreateRequest +import com.ddd.sonnypolabobe.domain.board.sticker.service.StickerService +import com.ddd.sonnypolabobe.global.response.ApplicationResponse +import com.ddd.sonnypolabobe.global.security.JwtUtil +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestHeader +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/api/v1/boards/sticker") +class BoardStickerController( + private val jwtUtil: JwtUtil, + private val stickerService: StickerService +) { + + @Tag(name = "1.3.0") + @GetMapping("/recent") + fun getRecentList( @RequestHeader("Authorization") token: String?) + : ApplicationResponse> { + val user = token?.let { this.jwtUtil.getAuthenticatedMemberFromToken(it) } + return ApplicationResponse.ok(this.stickerService.getByUserId(user?.id?.toLong())) + } + + @Tag(name = "1.3.0") + @PostMapping + fun createStickerToBoard( + @RequestHeader("Authorization") token: String?, + @RequestBody req : StickerCreateRequest + ) : ApplicationResponse { + val user = token?.let { this.jwtUtil.getAuthenticatedMemberFromToken(it) } + this.stickerService.create(req, user?.id?.toLong()) + return ApplicationResponse.ok() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerCreateRequest.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerCreateRequest.kt new file mode 100644 index 0000000..21a391d --- /dev/null +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerCreateRequest.kt @@ -0,0 +1,10 @@ +package com.ddd.sonnypolabobe.domain.board.sticker.dto + +data class StickerCreateRequest( + val boardId : String, + val stickerId: String, + val x : String, + val y : String, + val scale: String, + val rotate: String +) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerGetResponse.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerGetResponse.kt new file mode 100644 index 0000000..a753316 --- /dev/null +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerGetResponse.kt @@ -0,0 +1,9 @@ +package com.ddd.sonnypolabobe.domain.board.sticker.dto + +data class StickerGetResponse( + val id : String, + val x : String, + val y : String, + val scale: String, + val rotate : String +) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepository.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepository.kt new file mode 100644 index 0000000..63cc2d5 --- /dev/null +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepository.kt @@ -0,0 +1,11 @@ +package com.ddd.sonnypolabobe.domain.board.sticker.repository + +import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerCreateRequest +import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerGetResponse +import java.util.* + +interface BoardStickerRepository { + fun findByUserId(id: Long) : List + fun insertOne(req: StickerCreateRequest, userId: Long?) + fun findByBoardId(stringToUUID: UUID): List? +} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepositoryImpl.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepositoryImpl.kt new file mode 100644 index 0000000..f04a7b9 --- /dev/null +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepositoryImpl.kt @@ -0,0 +1,65 @@ +package com.ddd.sonnypolabobe.domain.board.sticker.repository + +import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerCreateRequest +import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerGetResponse +import com.ddd.sonnypolabobe.global.util.DateConverter +import com.ddd.sonnypolabobe.global.util.UuidConverter +import com.ddd.sonnypolabobe.jooq.polabo.tables.BoardSticker +import org.jooq.DSLContext +import org.springframework.stereotype.Repository +import java.time.LocalDateTime +import java.util.* + +@Repository +class BoardStickerRepositoryImpl( + private val dslContext: DSLContext +) : BoardStickerRepository { + override fun findByUserId(userId: Long): List { + val jSticker = BoardSticker.BOARD_STICKER + return this.dslContext.selectDistinct(jSticker.STICKER_ID) + .from(jSticker) + .where(jSticker.USER_ID.eq(userId)) + .orderBy(jSticker.CREATED_AT.desc()) + .fetchInto(String::class.java) + } + + override fun insertOne(req: StickerCreateRequest, userId: Long?) { + val jSticker = BoardSticker.BOARD_STICKER + this.dslContext.insertInto(jSticker) + .columns( + jSticker.STICKER_ID, + jSticker.BOARD_ID, + jSticker.USER_ID, + jSticker.X, + jSticker.Y, + jSticker.SCALE, + jSticker.ROTATE, + jSticker.CREATED_AT + ).values( + req.stickerId, + UuidConverter.uuidToByteArray(UuidConverter.stringToUUID(req.boardId)), + userId, + req.x, + req.y, + req.scale, + req.rotate, + DateConverter.convertToKst(LocalDateTime.now()) + ).execute() + } + + override fun findByBoardId(stringToUUID: UUID): List? { + val jSticker = BoardSticker.BOARD_STICKER + return this.dslContext.select( + jSticker.ID, + jSticker.X, + jSticker.Y, + jSticker.SCALE, + jSticker.ROTATE + ) + .from(jSticker) + .where(jSticker.BOARD_ID.eq(UuidConverter.uuidToByteArray(stringToUUID))) + .fetchInto(StickerGetResponse::class.java) + } + + +} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/service/StickerService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/service/StickerService.kt new file mode 100644 index 0000000..4266e3a --- /dev/null +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/service/StickerService.kt @@ -0,0 +1,20 @@ +package com.ddd.sonnypolabobe.domain.board.sticker.service + +import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerCreateRequest +import com.ddd.sonnypolabobe.domain.board.sticker.repository.BoardStickerRepository +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class StickerService( + private val boardStickerRepository: BoardStickerRepository +) { + @Transactional(readOnly = true) + fun getByUserId(id: Long?): List + = id?.let { this.boardStickerRepository.findByUserId(id) } ?: emptyList() + + @Transactional + fun create(req: StickerCreateRequest, userId: Long?) { + this.boardStickerRepository.insertOne(req, userId) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidV2Controller.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidV2Controller.kt index 1ec8d84..65937ae 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidV2Controller.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidV2Controller.kt @@ -1,6 +1,7 @@ package com.ddd.sonnypolabobe.domain.polaroid.controller import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidCreateRequest +import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption import com.ddd.sonnypolabobe.domain.polaroid.service.PolaroidService import com.ddd.sonnypolabobe.global.response.ApplicationResponse import com.ddd.sonnypolabobe.global.security.JwtUtil @@ -9,7 +10,7 @@ import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid import org.springframework.web.bind.annotation.* -@Tag(name = "1.1.0") +@Tag(name = "1.3.0") @RestController @RequestMapping("/api/v2/boards/{boardId}/polaroids") class BoardPolaroidV2Controller( @@ -21,7 +22,9 @@ class BoardPolaroidV2Controller( summary = "폴라로이드 생성", description = """ 폴라로이드를 생성합니다. - 작성자 닉네임이 추가되었습니다. + 옵션을 추가했습니다. + + enum에 따라 옵션을 선택해주세요. """ ) @PostMapping diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidCreateRequest.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidCreateRequest.kt index d9dbe69..bc93322 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidCreateRequest.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidCreateRequest.kt @@ -1,5 +1,6 @@ package com.ddd.sonnypolabobe.domain.polaroid.controller.dto +import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption import io.swagger.v3.oas.annotations.media.Schema import jakarta.validation.constraints.Size @@ -11,5 +12,7 @@ data class PolaroidCreateRequest( @field:Size(max = 20) val oneLineMessage : String, @Schema(description = "작성자 닉네임이 null 이면서 회원가입된 유저라면, 유저의 닉네임을 자동할당합니다.", example = "작성자 닉네임") - var nickname : String? + var nickname : String?, + @Schema(description = "폴라로이드 옵션", examples = ["FONT", "FILTER", "THEMA"]) + val options : Map ) \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt index be7b0a8..c382f82 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt @@ -1,5 +1,6 @@ package com.ddd.sonnypolabobe.domain.polaroid.controller.dto +import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDateTime import java.util.UUID @@ -18,5 +19,7 @@ data class PolaroidGetResponse( @Schema(description = "작성자인지 여부", example = "true") val isMine: Boolean, @Schema(description = "생성일시", example = "2021-01-01T00:00:00") - val createdAt: LocalDateTime? + val createdAt: LocalDateTime?, + @Schema(description = "옵션") + val options: Map? ) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/enumerate/PolaroidOption.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/enumerate/PolaroidOption.kt new file mode 100644 index 0000000..84d18be --- /dev/null +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/enumerate/PolaroidOption.kt @@ -0,0 +1,7 @@ +package com.ddd.sonnypolabobe.domain.polaroid.enumerate + +enum class PolaroidOption(val description: String) { + FONT("폰트"), + FILTER("필터"), + THEMA("테마") +} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt index 105bd08..da7e055 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt @@ -6,6 +6,7 @@ import com.ddd.sonnypolabobe.global.exception.CustomErrorCode import com.ddd.sonnypolabobe.global.util.DateConverter import com.ddd.sonnypolabobe.jooq.polabo.tables.Polaroid import com.ddd.sonnypolabobe.jooq.polabo.tables.records.PolaroidRecord +import com.fasterxml.jackson.databind.ObjectMapper import org.jooq.DSLContext import org.springframework.stereotype.Repository import java.time.LocalDateTime @@ -22,6 +23,7 @@ class PolaroidJooqRepositoryImpl(private val dslContext: DSLContext) : PolaroidJ this.yn = 1 this.activeyn = 1 this.nickname = request.nickname + this.options = ObjectMapper().writeValueAsString(request.options) } return this.dslContext.insertInto(jPolaroid) .set(insertValue) @@ -40,6 +42,7 @@ class PolaroidJooqRepositoryImpl(private val dslContext: DSLContext) : PolaroidJ this.yn = 1 this.activeyn = 1 this.nickname = request.nickname + this.options = ObjectMapper().writeValueAsString(request.options) } return this.dslContext.insertInto(jPolaroid) .set(insertValue) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt index 645e020..3047615 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt @@ -3,12 +3,15 @@ package com.ddd.sonnypolabobe.domain.polaroid.service import com.ddd.sonnypolabobe.domain.board.repository.BoardJooqRepository import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidCreateRequest import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidGetResponse +import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption import com.ddd.sonnypolabobe.domain.polaroid.repository.PolaroidJooqRepository import com.ddd.sonnypolabobe.domain.user.dto.UserDto import com.ddd.sonnypolabobe.global.exception.ApplicationException import com.ddd.sonnypolabobe.global.exception.CustomErrorCode import com.ddd.sonnypolabobe.global.util.S3Util import com.ddd.sonnypolabobe.global.util.UuidConverter +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.databind.ObjectMapper import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -44,7 +47,8 @@ class PolaroidService( userId = it.userId, nickname = it.nickname ?: "", isMine = boardWriter.userId == user.id, - createdAt = it.createdAt + createdAt = it.createdAt, + options = it.options?.let{ ObjectMapper().readValue(it, object : TypeReference>() {})} ) } } diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/config/SecurityConfig.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/config/SecurityConfig.kt index 050687b..500d5e5 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/config/SecurityConfig.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/config/SecurityConfig.kt @@ -38,6 +38,7 @@ class SecurityConfig( "/api/v1/polaroids/{id}", "/api/v1/boards/{boardId}/polaroids", "/api/v2/boards/{boardId}/polaroids", + "/api/v1/boards/stickers/recent" ) } @Bean diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/entity/BaseEntity.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/entity/BaseEntity.kt deleted file mode 100644 index 08c6aa3..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/entity/BaseEntity.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.ddd.sonnypolabobe.global.entity - -import java.time.LocalDateTime -import java.util.UUID - -interface BaseEntity { - val id : UUID - val yn : Boolean - val createdAt : LocalDateTime - val updatedAt : LocalDateTime - -} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/LoggingFilter.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/LoggingFilter.kt deleted file mode 100644 index ccd0de8..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/LoggingFilter.kt +++ /dev/null @@ -1,125 +0,0 @@ -//package com.ddd.sonnypolabobe.global.security -// -//import com.ddd.sonnypolabobe.global.exception.CustomErrorCode -//import com.ddd.sonnypolabobe.global.util.DiscordApiClient -//import com.ddd.sonnypolabobe.global.util.HttpLog -//import com.ddd.sonnypolabobe.logger -//import jakarta.servlet.FilterChain -//import jakarta.servlet.ServletRequest -//import jakarta.servlet.ServletResponse -//import jakarta.servlet.http.HttpServletRequest -//import jakarta.servlet.http.HttpServletResponse -//import org.springframework.stereotype.Component -//import org.springframework.web.filter.GenericFilterBean -//import org.springframework.web.util.ContentCachingRequestWrapper -//import org.springframework.web.util.ContentCachingResponseWrapper -//import org.springframework.web.util.WebUtils -//import java.io.UnsupportedEncodingException -//import java.util.* -// -//@Component -//class LoggingFilter( -// private val discordApiClient: DiscordApiClient -//) : GenericFilterBean() { -// private val excludedUrls = setOf("/actuator", "/swagger-ui", "/v3/api-docs") -// -// override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) { -// val requestWrapper: ContentCachingRequestWrapper = -// ContentCachingRequestWrapper(request as HttpServletRequest) -// val responseWrapper: ContentCachingResponseWrapper = -// ContentCachingResponseWrapper(response as HttpServletResponse) -// if (excludeLogging(request.requestURI)) { -// chain.doFilter(request, response) -// } else { -// val startedAt = System.currentTimeMillis() -// chain.doFilter(requestWrapper, responseWrapper) -// val endedAt = System.currentTimeMillis() -// -// logger().info( -// "\n" + -// "[REQUEST] ${request.method} - ${request.requestURI} ${responseWrapper.status} - ${(endedAt - startedAt) / 10000.0} \n" + -// "Headers : ${getHeaders(request)} \n" + -// "Parameters : ${getRequestParams(request)} \n" + -// "Request body : ${getRequestBody(requestWrapper)} \n" + -// "Response body : ${getResponseBody(responseWrapper)}" -// ) -// -// if(responseWrapper.status >= 400 && getResponseBody(responseWrapper).contains(CustomErrorCode.INTERNAL_SERVER_EXCEPTION.message)) { -// this.discordApiClient.sendErrorLog( -// HttpLog( -// request.method, -// request.requestURI, -// responseWrapper.status, -// (endedAt - startedAt) / 10000.0, -// getHeaders(request), -// getRequestParams(request), -// getRequestBody(requestWrapper), -// getResponseBody(responseWrapper) -// ) -// ) -// } -// } -// } -// -// private fun excludeLogging(requestURI: String): Boolean { -// return excludedUrls.any { requestURI.startsWith(it) } -// } -// -// private fun getResponseBody(response: ContentCachingResponseWrapper): String { -// var payload: String? = null -// response.characterEncoding = "utf-8" -// val wrapper = -// WebUtils.getNativeResponse(response, ContentCachingResponseWrapper::class.java) -// if (wrapper != null) { -// val buf = wrapper.contentAsByteArray -// if (buf.isNotEmpty()) { -// payload = String(buf, 0, buf.size, charset(wrapper.characterEncoding)) -// wrapper.copyBodyToResponse() -// } -// } -// return payload ?: " - " -// } -// -// private fun getRequestBody(request: ContentCachingRequestWrapper): String { -// request.characterEncoding = "utf-8" -// val wrapper = WebUtils.getNativeRequest( -// request, -// ContentCachingRequestWrapper::class.java -// ) -// if (wrapper != null) { -// val buf = wrapper.contentAsByteArray -// if (buf.isNotEmpty()) { -// return try { -// String(buf, 0, buf.size, charset(wrapper.characterEncoding)) -// } catch (e: UnsupportedEncodingException) { -// " - " -// } -// } -// } -// return " - " -// } -// -// private fun getRequestParams(request: HttpServletRequest): Map { -// val parameterMap: MutableMap = HashMap() -// request.characterEncoding = "utf-8" -// val parameterArray: Enumeration<*> = request.parameterNames -// -// while (parameterArray.hasMoreElements()) { -// val parameterName = parameterArray.nextElement() as String -// parameterMap[parameterName] = request.getParameter(parameterName) -// } -// -// return parameterMap -// } -// -// private fun getHeaders(request: HttpServletRequest): Map { -// val headerMap: MutableMap = HashMap() -// -// val headerArray: Enumeration<*> = request.headerNames -// while (headerArray.hasMoreElements()) { -// val headerName = headerArray.nextElement() as String -// headerMap[headerName] = request.getHeader(headerName) -// } -// return headerMap -// } -//} \ No newline at end of file From 104481a74f3779a23d08c0aa5b34072bf78dcdae Mon Sep 17 00:00:00 2001 From: dldmsql Date: Sun, 22 Sep 2024 09:39:26 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=204=EC=B0=A8=20MVP=20=EA=B8=B0?= =?UTF-8?q?=ED=9A=8D=20=EB=B3=80=EA=B2=BD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/dto/BoardCreateRequest.kt | 4 +- .../board/controller/dto/BoardGetResponse.kt | 9 +- .../domain/board/my/dto/MyBoardDto.kt | 11 +++ .../domain/board/service/BoardService.kt | 9 +- .../controller/BoardStickerController.kt | 40 -------- .../board/sticker/dto/StickerCreateRequest.kt | 10 -- .../board/sticker/dto/StickerGetResponse.kt | 9 -- .../repository/BoardStickerRepository.kt | 11 --- .../repository/BoardStickerRepositoryImpl.kt | 65 ------------- .../board/sticker/service/StickerService.kt | 20 ---- .../dto/ImageResignedUrlResponse.kt | 4 + .../domain/oauth/service/OauthService.kt | 97 ++++++++----------- .../controller/BoardPolaroidController.kt | 2 +- .../controller/BoardPolaroidV2Controller.kt | 4 +- .../polaroid/controller/PolaroidController.kt | 2 +- .../controller/dto/PolaroidCreateRequest.kt | 18 ---- .../controller/dto/PolaroidGetResponse.kt | 25 ----- .../polaroid/dto/PolaroidCreateRequest.kt | 18 ++++ .../polaroid/dto/PolaroidGetResponse.kt | 25 +++++ .../repository/PolaroidJooqRepository.kt | 2 +- .../repository/PolaroidJooqRepositoryImpl.kt | 2 +- .../polaroid/service/PolaroidService.kt | 4 +- .../domain/user/controller/UserController.kt | 3 - .../sonnypolabobe/domain/user/dto/UserDto.kt | 22 ++++- .../domain/user/service/UserService.kt | 2 +- .../user/{ => withdraw}/dto/WithdrawType.kt | 2 +- .../repository/WithdrawJooqRepository.kt | 2 +- .../repository/WithdrawJooqRepositoryImpl.kt | 2 +- .../global/HealthCheckController.kt | 4 +- .../global/config/JasyptConfig.kt | 24 ++--- .../global/config/SwaggerConfig.kt | 13 ++- .../sonnypolabobe/global/entity/PageDto.kt | 1 - .../exception/GlobalExceptionHandler.kt | 2 +- .../security/CustomUserDetailsService.kt | 5 +- .../global/security/JwtExceptionFilter.kt | 4 +- .../sonnypolabobe/global/security/JwtUtil.kt | 15 ++- .../sonnypolabobe/global/security/KakaoDto.kt | 43 -------- .../security/RateLimitingInterceptor.kt | 7 +- .../global/security/RateLimitingService.kt | 4 +- .../global/util/DateConverter.kt | 11 +-- .../global/util/DiscordApiClient.kt | 52 ++++------ .../ddd/sonnypolabobe/global/util/HttpLog.kt | 12 --- .../ddd/sonnypolabobe/global/util/S3Util.kt | 15 +-- .../global/util/UuidConverter.kt | 17 ++-- .../global/util/UuidGenerator.kt | 4 +- .../global/util/WebClientUtil.kt | 28 ------ 46 files changed, 210 insertions(+), 475 deletions(-) delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/controller/BoardStickerController.kt delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerCreateRequest.kt delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerGetResponse.kt delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepository.kt delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepositoryImpl.kt delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/service/StickerService.kt delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidCreateRequest.kt delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt create mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/dto/PolaroidCreateRequest.kt create mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/dto/PolaroidGetResponse.kt rename src/main/kotlin/com/ddd/sonnypolabobe/domain/user/{ => withdraw}/dto/WithdrawType.kt (83%) rename src/main/kotlin/com/ddd/sonnypolabobe/domain/user/{ => withdraw}/repository/WithdrawJooqRepository.kt (72%) rename src/main/kotlin/com/ddd/sonnypolabobe/domain/user/{ => withdraw}/repository/WithdrawJooqRepositoryImpl.kt (94%) delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/global/security/KakaoDto.kt delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/global/util/HttpLog.kt delete mode 100644 src/main/kotlin/com/ddd/sonnypolabobe/global/util/WebClientUtil.kt diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardCreateRequest.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardCreateRequest.kt index 422042b..fdb3cf6 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardCreateRequest.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardCreateRequest.kt @@ -6,10 +6,10 @@ import jakarta.validation.constraints.Pattern import java.util.* data class BoardCreateRequest( - @Schema(description = "제목", example = "쏘니의 보드") + @field:Schema(description = "제목", example = "쏘니의 보드") @field:NotBlank @field:Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#$%^&*()_+=-])(?=.*[ㄱ-ㅎㅏ-ㅣ가-힣]).{1,20}$", message = "제목은 국문, 영문, 숫자, 특수문자, 띄어쓰기를 포함한 20자 이내여야 합니다.") val title: String, - @Schema(description = "작성자 아이디", example = "null", required = false) + @field:Schema(description = "작성자 아이디", example = "null", required = false) var userId: Long? = null ) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt index 787e8c7..7c644c1 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt @@ -1,14 +1,11 @@ package com.ddd.sonnypolabobe.domain.board.controller.dto -import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerGetResponse -import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidGetResponse +import com.ddd.sonnypolabobe.domain.polaroid.dto.PolaroidGetResponse import io.swagger.v3.oas.annotations.media.Schema data class BoardGetResponse( - @Schema(description = "제목", example = "쏘니의 보드") + @field:Schema(description = "제목", example = "쏘니의 보드") val title: String, - @Schema(description = "폴라로이드") + @field:Schema(description = "폴라로이드") val items: List, - @Schema(description = "스티커 리스트") - val stickers : List? ) \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/my/dto/MyBoardDto.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/my/dto/MyBoardDto.kt index 9aa647f..82cc0de 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/my/dto/MyBoardDto.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/my/dto/MyBoardDto.kt @@ -1,6 +1,7 @@ package com.ddd.sonnypolabobe.domain.board.my.dto import com.fasterxml.jackson.annotation.JsonProperty +import io.swagger.v3.oas.annotations.media.Schema import org.springframework.format.annotation.DateTimeFormat import java.time.LocalDateTime import java.util.UUID @@ -9,26 +10,36 @@ class MyBoardDto { companion object { data class MBUpdateReq( @JsonProperty("title") + @field:Schema(description = "제목", example = "쏘니의 보드") val title: String ) data class PageListRes( + @field:Schema(description = "보드 아이디", example = "01906259-94b2-74ef-8c13-554385c42943") val id: UUID, + @field:Schema(description = "제목", example = "쏘니의 보드") val title: String, @DateTimeFormat(pattern = "yyyy-MM-dd", iso = DateTimeFormat.ISO.DATE) + @field:Schema(description = "생성일", example = "2021-07-01") val createdAt: LocalDateTime, ) data class GetOneRes( + @field:Schema(description = "보드 아이디", example = "01906259-94b2-74ef-8c13-554385c42943") val id: UUID, + @field:Schema(description = "제목", example = "쏘니의 보드") val title: String, @DateTimeFormat(pattern = "yyyy-MM-dd", iso = DateTimeFormat.ISO.DATE) + @field:Schema(description = "생성일", example = "2021-07-01") val createdAt: LocalDateTime, + @field:Schema(description = "작성자 아이디", example = "null", required = false) val userId: Long? ) data class TotalCountRes( + @field:Schema(description = "총 보드 생성 수", example = "100") val totalCreateCount: Long, + @field:Schema(description = "총 참여자 수", example = "1000") val totalParticipantCount: Long ) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt index e5f715d..eff43dc 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt @@ -3,9 +3,7 @@ package com.ddd.sonnypolabobe.domain.board.service import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardCreateRequest import com.ddd.sonnypolabobe.domain.board.controller.dto.BoardGetResponse import com.ddd.sonnypolabobe.domain.board.repository.BoardJooqRepository -import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerGetResponse -import com.ddd.sonnypolabobe.domain.board.sticker.repository.BoardStickerRepository -import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidGetResponse +import com.ddd.sonnypolabobe.domain.polaroid.dto.PolaroidGetResponse import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption import com.ddd.sonnypolabobe.domain.user.dto.UserDto import com.ddd.sonnypolabobe.global.exception.ApplicationException @@ -18,12 +16,10 @@ import com.fasterxml.jackson.databind.ObjectMapper import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Service import java.util.* -import javax.swing.text.html.HTML.Tag.U @Service class BoardService( private val boardJooqRepository: BoardJooqRepository, - private val boardStickerRepository: BoardStickerRepository, private val s3Util: S3Util, @Value("\${limit.count}") private val limit: Int @@ -36,7 +32,6 @@ class BoardService( return id.run { val queryResult = boardJooqRepository.selectOneById(UuidConverter.stringToUUID(this@run)) - val stickers = boardStickerRepository.findByBoardId(UuidConverter.stringToUUID(id)) val groupByTitle = queryResult.groupBy { it.title } groupByTitle.map { entry -> val title = entry.key @@ -53,7 +48,7 @@ class BoardService( ) }.filter { it.id != 0L }.distinctBy { it.id } - BoardGetResponse(title = title ?: "", items = polaroids, stickers = stickers) + BoardGetResponse(title = title ?: "", items = polaroids) } } } diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/controller/BoardStickerController.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/controller/BoardStickerController.kt deleted file mode 100644 index 2c7c60c..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/controller/BoardStickerController.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.ddd.sonnypolabobe.domain.board.sticker.controller - -import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerCreateRequest -import com.ddd.sonnypolabobe.domain.board.sticker.service.StickerService -import com.ddd.sonnypolabobe.global.response.ApplicationResponse -import com.ddd.sonnypolabobe.global.security.JwtUtil -import io.swagger.v3.oas.annotations.tags.Tag -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestHeader -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController - -@RestController -@RequestMapping("/api/v1/boards/sticker") -class BoardStickerController( - private val jwtUtil: JwtUtil, - private val stickerService: StickerService -) { - - @Tag(name = "1.3.0") - @GetMapping("/recent") - fun getRecentList( @RequestHeader("Authorization") token: String?) - : ApplicationResponse> { - val user = token?.let { this.jwtUtil.getAuthenticatedMemberFromToken(it) } - return ApplicationResponse.ok(this.stickerService.getByUserId(user?.id?.toLong())) - } - - @Tag(name = "1.3.0") - @PostMapping - fun createStickerToBoard( - @RequestHeader("Authorization") token: String?, - @RequestBody req : StickerCreateRequest - ) : ApplicationResponse { - val user = token?.let { this.jwtUtil.getAuthenticatedMemberFromToken(it) } - this.stickerService.create(req, user?.id?.toLong()) - return ApplicationResponse.ok() - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerCreateRequest.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerCreateRequest.kt deleted file mode 100644 index 21a391d..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerCreateRequest.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.ddd.sonnypolabobe.domain.board.sticker.dto - -data class StickerCreateRequest( - val boardId : String, - val stickerId: String, - val x : String, - val y : String, - val scale: String, - val rotate: String -) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerGetResponse.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerGetResponse.kt deleted file mode 100644 index a753316..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/dto/StickerGetResponse.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.ddd.sonnypolabobe.domain.board.sticker.dto - -data class StickerGetResponse( - val id : String, - val x : String, - val y : String, - val scale: String, - val rotate : String -) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepository.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepository.kt deleted file mode 100644 index 63cc2d5..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepository.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.ddd.sonnypolabobe.domain.board.sticker.repository - -import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerCreateRequest -import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerGetResponse -import java.util.* - -interface BoardStickerRepository { - fun findByUserId(id: Long) : List - fun insertOne(req: StickerCreateRequest, userId: Long?) - fun findByBoardId(stringToUUID: UUID): List? -} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepositoryImpl.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepositoryImpl.kt deleted file mode 100644 index f04a7b9..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/repository/BoardStickerRepositoryImpl.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.ddd.sonnypolabobe.domain.board.sticker.repository - -import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerCreateRequest -import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerGetResponse -import com.ddd.sonnypolabobe.global.util.DateConverter -import com.ddd.sonnypolabobe.global.util.UuidConverter -import com.ddd.sonnypolabobe.jooq.polabo.tables.BoardSticker -import org.jooq.DSLContext -import org.springframework.stereotype.Repository -import java.time.LocalDateTime -import java.util.* - -@Repository -class BoardStickerRepositoryImpl( - private val dslContext: DSLContext -) : BoardStickerRepository { - override fun findByUserId(userId: Long): List { - val jSticker = BoardSticker.BOARD_STICKER - return this.dslContext.selectDistinct(jSticker.STICKER_ID) - .from(jSticker) - .where(jSticker.USER_ID.eq(userId)) - .orderBy(jSticker.CREATED_AT.desc()) - .fetchInto(String::class.java) - } - - override fun insertOne(req: StickerCreateRequest, userId: Long?) { - val jSticker = BoardSticker.BOARD_STICKER - this.dslContext.insertInto(jSticker) - .columns( - jSticker.STICKER_ID, - jSticker.BOARD_ID, - jSticker.USER_ID, - jSticker.X, - jSticker.Y, - jSticker.SCALE, - jSticker.ROTATE, - jSticker.CREATED_AT - ).values( - req.stickerId, - UuidConverter.uuidToByteArray(UuidConverter.stringToUUID(req.boardId)), - userId, - req.x, - req.y, - req.scale, - req.rotate, - DateConverter.convertToKst(LocalDateTime.now()) - ).execute() - } - - override fun findByBoardId(stringToUUID: UUID): List? { - val jSticker = BoardSticker.BOARD_STICKER - return this.dslContext.select( - jSticker.ID, - jSticker.X, - jSticker.Y, - jSticker.SCALE, - jSticker.ROTATE - ) - .from(jSticker) - .where(jSticker.BOARD_ID.eq(UuidConverter.uuidToByteArray(stringToUUID))) - .fetchInto(StickerGetResponse::class.java) - } - - -} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/service/StickerService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/service/StickerService.kt deleted file mode 100644 index 4266e3a..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/sticker/service/StickerService.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.ddd.sonnypolabobe.domain.board.sticker.service - -import com.ddd.sonnypolabobe.domain.board.sticker.dto.StickerCreateRequest -import com.ddd.sonnypolabobe.domain.board.sticker.repository.BoardStickerRepository -import org.springframework.stereotype.Service -import org.springframework.transaction.annotation.Transactional - -@Service -class StickerService( - private val boardStickerRepository: BoardStickerRepository -) { - @Transactional(readOnly = true) - fun getByUserId(id: Long?): List - = id?.let { this.boardStickerRepository.findByUserId(id) } ?: emptyList() - - @Transactional - fun create(req: StickerCreateRequest, userId: Long?) { - this.boardStickerRepository.insertOne(req, userId) - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/file/controller/dto/ImageResignedUrlResponse.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/file/controller/dto/ImageResignedUrlResponse.kt index 5ddac9f..31982be 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/file/controller/dto/ImageResignedUrlResponse.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/file/controller/dto/ImageResignedUrlResponse.kt @@ -1,6 +1,10 @@ package com.ddd.sonnypolabobe.domain.file.controller.dto +import io.swagger.v3.oas.annotations.media.Schema + data class ImageResignedUrlResponse( + @field:Schema(description = "S3에 저장될 이미지 키", example = "imageKey") val imageKey : String, + @field:Schema(description = "이미지 업로드를 위한 URL", example = "https://cloudfront.net/imageKey") val url : String ) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/oauth/service/OauthService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/oauth/service/OauthService.kt index dc6ed19..2985484 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/oauth/service/OauthService.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/oauth/service/OauthService.kt @@ -7,35 +7,22 @@ import com.ddd.sonnypolabobe.domain.user.token.dto.UserTokenDto import com.ddd.sonnypolabobe.domain.user.token.repository.UserTokenJooqRepository import com.ddd.sonnypolabobe.global.security.JwtUtil import com.ddd.sonnypolabobe.global.util.DateConverter.dateToLocalDateTime -import com.ddd.sonnypolabobe.logger import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service class OauthService( - private val userRepository : UserJooqRepository, + private val userRepository: UserJooqRepository, + private val userTokenRepository: UserTokenJooqRepository, private val jwtUtil: JwtUtil, - private val userTokenRepository: UserTokenJooqRepository - ) { +) { @Transactional fun signIn(request: UserDto.Companion.CreateReq): UserDto.Companion.TokenRes { this.userRepository.findByEmail(request.email)?.let { - val tokenRequest = UserDto.Companion.CreateTokenReq( - id = it.id, - email = it.email, - nickName = it.nickName - ) - - val tokenRes = this.jwtUtil.generateAccessToken(tokenRequest) - - val userToken = UserTokenDto( - userId = it.id, - accessToken = tokenRes.accessToken, - expiredAt = dateToLocalDateTime(tokenRes.expiredDate), - refreshToken = tokenRes.refreshToken - ) + val tokenRes = generateAccessToken(it) + val userToken = userTokenDto(it.id, tokenRes) this.userTokenRepository.updateByUserId(userToken) return tokenRes.also { _ -> @@ -45,22 +32,8 @@ class OauthService( } } ?: run { val userId = this.userRepository.insertOne(request) - - // 토큰 생성 - val tokenRequest = UserDto.Companion.CreateTokenReq( - id = userId, - email = request.email, - nickName = request.nickName - ) - - val tokenRes = this.jwtUtil.generateAccessToken(tokenRequest) - - val userToken = UserTokenDto( - userId = userId, - accessToken = tokenRes.accessToken, - expiredAt = dateToLocalDateTime(tokenRes.expiredDate), - refreshToken = tokenRes.refreshToken - ) + val tokenRes = generateAccessToken(userId, request) + val userToken = userTokenDto(userId, tokenRes) this.userTokenRepository.insertOne(userToken) return tokenRes.also { _ -> @@ -71,34 +44,50 @@ class OauthService( } } - fun reIssue(token: String?): UserDto.Companion.TokenRes{ - val tokenFromDB = token?.let { - val slicedToken = if(it.startsWith("Bearer ")) it.substring(7) else it - this.jwtUtil.getAuthenticatedMemberFromRefreshToken(slicedToken) - } ?: throw RuntimeException("Token Not Found") - val user = this.userRepository.findById(tokenFromDB.id.toLong()) ?: throw RuntimeException("User Not Found") - - // 토큰 생성 - val tokenRequest = UserDto.Companion.CreateTokenReq( - id = user.id, - email = user.email, - nickName = user.nickName - ) + @Transactional + fun reIssue(token: String?): UserDto.Companion.TokenRes { + val tokenFromDB = token?.let { + val slicedToken = if (it.startsWith("Bearer ")) it.substring(7) else it + this.jwtUtil.getAuthenticatedMemberFromRefreshToken(slicedToken) + } ?: throw RuntimeException("Token Not Found") - val tokenRes = this.jwtUtil.generateAccessToken(tokenRequest) + val user = this.userRepository.findById(tokenFromDB.id.toLong()) + ?: throw RuntimeException("User Not Found") - val userToken = UserTokenDto( - userId = user.id, - accessToken = tokenRes.accessToken, - expiredAt = dateToLocalDateTime(tokenRes.expiredDate), - refreshToken = tokenRes.refreshToken - ) + val tokenRes = generateAccessToken(user) + val userToken = userTokenDto(user.id, tokenRes) this.userTokenRepository.updateByUserId(userToken) return tokenRes } + @Transactional fun signOut(id: Long) { this.userTokenRepository.deleteByUserId(id) } + + private fun userTokenDto( + userId: Long, + tokenRes: UserDto.Companion.TokenRes + ): UserTokenDto = UserTokenDto( + userId = userId, + accessToken = tokenRes.accessToken, + expiredAt = dateToLocalDateTime(tokenRes.expiredDate), + refreshToken = tokenRes.refreshToken + ) + + private fun OauthService.generateAccessToken( + userId: Long, request: UserDto.Companion.CreateReq + ): UserDto.Companion.TokenRes = this.jwtUtil.generateAccessToken( + UserDto.Companion.CreateTokenReq( + id = userId, email = request.email, nickName = request.nickName + ) + ) + + private fun OauthService.generateAccessToken(it: UserDto.Companion.Res): UserDto.Companion.TokenRes = + this.jwtUtil.generateAccessToken( + UserDto.Companion.CreateTokenReq( + id = it.id, email = it.email, nickName = it.nickName + ) + ) } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidController.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidController.kt index c4a94e0..3fe2aa5 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidController.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidController.kt @@ -1,6 +1,6 @@ package com.ddd.sonnypolabobe.domain.polaroid.controller -import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidCreateRequest +import com.ddd.sonnypolabobe.domain.polaroid.dto.PolaroidCreateRequest import com.ddd.sonnypolabobe.domain.polaroid.service.PolaroidService import com.ddd.sonnypolabobe.global.response.ApplicationResponse import io.swagger.v3.oas.annotations.Operation diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidV2Controller.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidV2Controller.kt index 65937ae..d2a66c4 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidV2Controller.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/BoardPolaroidV2Controller.kt @@ -1,6 +1,6 @@ package com.ddd.sonnypolabobe.domain.polaroid.controller -import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidCreateRequest +import com.ddd.sonnypolabobe.domain.polaroid.dto.PolaroidCreateRequest import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption import com.ddd.sonnypolabobe.domain.polaroid.service.PolaroidService import com.ddd.sonnypolabobe.global.response.ApplicationResponse @@ -21,9 +21,7 @@ class BoardPolaroidV2Controller( @Operation( summary = "폴라로이드 생성", description = """ 폴라로이드를 생성합니다. - 옵션을 추가했습니다. - enum에 따라 옵션을 선택해주세요. """ ) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/PolaroidController.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/PolaroidController.kt index c94c1b3..787f0a2 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/PolaroidController.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/PolaroidController.kt @@ -1,6 +1,6 @@ package com.ddd.sonnypolabobe.domain.polaroid.controller -import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidGetResponse +import com.ddd.sonnypolabobe.domain.polaroid.dto.PolaroidGetResponse import com.ddd.sonnypolabobe.domain.polaroid.service.PolaroidService import com.ddd.sonnypolabobe.domain.user.dto.UserDto import com.ddd.sonnypolabobe.global.response.ApplicationResponse diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidCreateRequest.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidCreateRequest.kt deleted file mode 100644 index bc93322..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidCreateRequest.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.ddd.sonnypolabobe.domain.polaroid.controller.dto - -import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption -import io.swagger.v3.oas.annotations.media.Schema -import jakarta.validation.constraints.Size - -@Schema(description = "폴라로이드 생성 요청 v2") -data class PolaroidCreateRequest( - @Schema(description = "이미지 키", example = "imageKey") - val imageKey : String, - @Schema(description = "한 줄 문구", example = "한 줄 메시지입니다. 최대 20자까지 가능합니다.") - @field:Size(max = 20) - val oneLineMessage : String, - @Schema(description = "작성자 닉네임이 null 이면서 회원가입된 유저라면, 유저의 닉네임을 자동할당합니다.", example = "작성자 닉네임") - var nickname : String?, - @Schema(description = "폴라로이드 옵션", examples = ["FONT", "FILTER", "THEMA"]) - val options : Map -) \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt deleted file mode 100644 index c382f82..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/controller/dto/PolaroidGetResponse.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.ddd.sonnypolabobe.domain.polaroid.controller.dto - -import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption -import io.swagger.v3.oas.annotations.media.Schema -import java.time.LocalDateTime -import java.util.UUID - -data class PolaroidGetResponse( - @Schema(description = "폴라로이드 ID", example = "1") - val id: Long, - @Schema(description = "이미지 주소", example = "https://image.com/image.jpg") - val imageUrl: String, - @Schema(description = "한 줄 문구", example = "한 줄 메시지입니다.") - val oneLineMessage: String, - @Schema(description = "작성자 ID", example = "userId") - val userId: Long?, - @Schema(description = "작성자 닉네임", example = "nickname") - val nickname: String, - @Schema(description = "작성자인지 여부", example = "true") - val isMine: Boolean, - @Schema(description = "생성일시", example = "2021-01-01T00:00:00") - val createdAt: LocalDateTime?, - @Schema(description = "옵션") - val options: Map? -) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/dto/PolaroidCreateRequest.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/dto/PolaroidCreateRequest.kt new file mode 100644 index 0000000..03bea72 --- /dev/null +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/dto/PolaroidCreateRequest.kt @@ -0,0 +1,18 @@ +package com.ddd.sonnypolabobe.domain.polaroid.dto + +import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.Size + +@Schema(description = "폴라로이드 생성 요청 v2") +data class PolaroidCreateRequest( + @field:Schema(description = "이미지 키", example = "imageKey") + val imageKey : String, + @field:Schema(description = "한 줄 문구", example = "한 줄 메시지입니다. 최대 20자까지 가능합니다.") + @field:Size(max = 20) + val oneLineMessage : String, + @field:Schema(description = "작성자 닉네임이 null 이면서 회원가입된 유저라면, 유저의 닉네임을 자동할당합니다.", example = "작성자 닉네임") + var nickname : String?, + @field:Schema(description = "폴라로이드 옵션", example = "{\"FONT\":\"value1\",\"FILTER\":\"value2\",\"THEMA\":\"value3\"}") + val options : Map +) \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/dto/PolaroidGetResponse.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/dto/PolaroidGetResponse.kt new file mode 100644 index 0000000..80e8901 --- /dev/null +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/dto/PolaroidGetResponse.kt @@ -0,0 +1,25 @@ +package com.ddd.sonnypolabobe.domain.polaroid.dto + +import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime +import java.util.UUID + +data class PolaroidGetResponse( + @field:Schema(description = "폴라로이드 ID", example = "1") + val id: Long, + @field:Schema(description = "이미지 주소", example = "https://image.com/image.jpg") + val imageUrl: String, + @field:Schema(description = "한 줄 문구", example = "한 줄 메시지입니다.") + val oneLineMessage: String, + @field:Schema(description = "작성자 ID", example = "userId") + val userId: Long?, + @field:Schema(description = "작성자 닉네임", example = "nickname") + val nickname: String, + @field:Schema(description = "작성자인지 여부", example = "true") + val isMine: Boolean, + @field:Schema(description = "생성일시", example = "2021-01-01T00:00:00") + val createdAt: LocalDateTime?, + @field:Schema(description = "옵션") + val options: Map? +) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepository.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepository.kt index c39ba22..2a4bc07 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepository.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepository.kt @@ -1,6 +1,6 @@ package com.ddd.sonnypolabobe.domain.polaroid.repository -import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidCreateRequest +import com.ddd.sonnypolabobe.domain.polaroid.dto.PolaroidCreateRequest import com.ddd.sonnypolabobe.jooq.polabo.tables.records.PolaroidRecord interface PolaroidJooqRepository { diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt index da7e055..e9ce3b9 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/repository/PolaroidJooqRepositoryImpl.kt @@ -1,6 +1,6 @@ package com.ddd.sonnypolabobe.domain.polaroid.repository -import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidCreateRequest +import com.ddd.sonnypolabobe.domain.polaroid.dto.PolaroidCreateRequest import com.ddd.sonnypolabobe.global.exception.ApplicationException import com.ddd.sonnypolabobe.global.exception.CustomErrorCode import com.ddd.sonnypolabobe.global.util.DateConverter diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt index 3047615..49677fd 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/polaroid/service/PolaroidService.kt @@ -1,8 +1,8 @@ package com.ddd.sonnypolabobe.domain.polaroid.service import com.ddd.sonnypolabobe.domain.board.repository.BoardJooqRepository -import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidCreateRequest -import com.ddd.sonnypolabobe.domain.polaroid.controller.dto.PolaroidGetResponse +import com.ddd.sonnypolabobe.domain.polaroid.dto.PolaroidCreateRequest +import com.ddd.sonnypolabobe.domain.polaroid.dto.PolaroidGetResponse import com.ddd.sonnypolabobe.domain.polaroid.enumerate.PolaroidOption import com.ddd.sonnypolabobe.domain.polaroid.repository.PolaroidJooqRepository import com.ddd.sonnypolabobe.domain.user.dto.UserDto diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/controller/UserController.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/controller/UserController.kt index e65d85f..be0b860 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/controller/UserController.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/controller/UserController.kt @@ -3,12 +3,9 @@ package com.ddd.sonnypolabobe.domain.user.controller import com.ddd.sonnypolabobe.domain.user.dto.UserDto import com.ddd.sonnypolabobe.domain.user.service.UserService import com.ddd.sonnypolabobe.global.response.ApplicationResponse -import com.ddd.sonnypolabobe.global.util.DateConverter import io.swagger.v3.oas.annotations.Operation -import org.springframework.security.core.context.SecurityContext import org.springframework.security.core.context.SecurityContextHolder import org.springframework.web.bind.annotation.* -import java.time.LocalDateTime @RestController @RequestMapping("/api/v1/user") diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/dto/UserDto.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/dto/UserDto.kt index 7e626af..3e816e1 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/dto/UserDto.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/dto/UserDto.kt @@ -1,8 +1,9 @@ package com.ddd.sonnypolabobe.domain.user.dto +import com.ddd.sonnypolabobe.domain.user.withdraw.dto.WithdrawType import com.fasterxml.jackson.annotation.JsonProperty +import io.swagger.v3.oas.annotations.media.Schema import jakarta.validation.constraints.Email -import org.intellij.lang.annotations.RegExp import org.springframework.security.core.GrantedAuthority import org.springframework.security.core.authority.SimpleGrantedAuthority import org.springframework.security.core.userdetails.UserDetails @@ -15,17 +16,20 @@ class UserDto { companion object { data class CreateReq( @field:Email + @field:Schema(description = "이메일", example = "test@polabo.com") val email: String, + @field:Schema(description = "닉네임", example = "쏘니") val nickName: String, -// val birthDt : LocalDate?, -// val gender : GenderType? ) data class UpdateReq( @JsonProperty("nickName") + @field:Schema(description = "닉네임", example = "쏘니") val nickName: String, @JsonProperty("birthDt") + @field:Schema(description = "생년월일", example = "1990-01-01") val birthDt: LocalDate?, + @field:Schema(description = "성별", example = "NONE, F, M") val gender: GenderType? ) @@ -62,14 +66,26 @@ class UserDto { } data class ProfileRes( + @field:Schema(description = "아이디", example = "1") val id: Long, + @field:Schema(description = "이메일", example = "test@polabo.com") val email: String, + @field:Schema(description = "닉네임", example = "쏘니") val nickName: String, + @field:Schema(description = "생년월일", example = "1990-01-01") val createdAt: LocalDateTime, ) data class WithdrawReq( + @field:Schema(description = "탈퇴 타입", example = """ + NOT_USE : 사용하지 않음 + WORRY_ABOUT_PERSONAL_INFO : 개인정보 우려 + DROP_MY_DATA : 내 데이터 삭제 + WANT_TO_NEW_ACCOUNT : 새로운 계정을 만들고 싶어요 + OTHER : 기타 + """) val type: WithdrawType, + @field:Schema(description = "탈퇴 사유", example = "탈퇴 사유입니다.") val reason: String? ) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/service/UserService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/service/UserService.kt index de96dc5..17fe370 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/service/UserService.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/service/UserService.kt @@ -2,7 +2,7 @@ package com.ddd.sonnypolabobe.domain.user.service import com.ddd.sonnypolabobe.domain.user.dto.UserDto import com.ddd.sonnypolabobe.domain.user.repository.UserJooqRepository -import com.ddd.sonnypolabobe.domain.user.repository.WithdrawJooqRepository +import com.ddd.sonnypolabobe.domain.user.withdraw.repository.WithdrawJooqRepository import org.springframework.stereotype.Service @Service diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/dto/WithdrawType.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/withdraw/dto/WithdrawType.kt similarity index 83% rename from src/main/kotlin/com/ddd/sonnypolabobe/domain/user/dto/WithdrawType.kt rename to src/main/kotlin/com/ddd/sonnypolabobe/domain/user/withdraw/dto/WithdrawType.kt index 2dbbeca..608c937 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/dto/WithdrawType.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/withdraw/dto/WithdrawType.kt @@ -1,4 +1,4 @@ -package com.ddd.sonnypolabobe.domain.user.dto +package com.ddd.sonnypolabobe.domain.user.withdraw.dto enum class WithdrawType(val description : String) { NOT_USE("더이상 사용하지 않아요"), diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/repository/WithdrawJooqRepository.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/withdraw/repository/WithdrawJooqRepository.kt similarity index 72% rename from src/main/kotlin/com/ddd/sonnypolabobe/domain/user/repository/WithdrawJooqRepository.kt rename to src/main/kotlin/com/ddd/sonnypolabobe/domain/user/withdraw/repository/WithdrawJooqRepository.kt index ec9b0be..c9d1083 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/repository/WithdrawJooqRepository.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/withdraw/repository/WithdrawJooqRepository.kt @@ -1,4 +1,4 @@ -package com.ddd.sonnypolabobe.domain.user.repository +package com.ddd.sonnypolabobe.domain.user.withdraw.repository import com.ddd.sonnypolabobe.domain.user.dto.UserDto diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/repository/WithdrawJooqRepositoryImpl.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/withdraw/repository/WithdrawJooqRepositoryImpl.kt similarity index 94% rename from src/main/kotlin/com/ddd/sonnypolabobe/domain/user/repository/WithdrawJooqRepositoryImpl.kt rename to src/main/kotlin/com/ddd/sonnypolabobe/domain/user/withdraw/repository/WithdrawJooqRepositoryImpl.kt index a5c50d4..d844be6 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/repository/WithdrawJooqRepositoryImpl.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/user/withdraw/repository/WithdrawJooqRepositoryImpl.kt @@ -1,4 +1,4 @@ -package com.ddd.sonnypolabobe.domain.user.repository +package com.ddd.sonnypolabobe.domain.user.withdraw.repository import com.ddd.sonnypolabobe.domain.user.dto.UserDto import com.ddd.sonnypolabobe.global.util.DateConverter diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/HealthCheckController.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/HealthCheckController.kt index b171ce0..3bb0061 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/HealthCheckController.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/HealthCheckController.kt @@ -7,7 +7,5 @@ import org.springframework.web.bind.annotation.RestController class HealthCheckController { @GetMapping("/health") - fun healthCheck(): String { - return "OK" - } + fun healthCheck(): String = "OK" } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/config/JasyptConfig.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/config/JasyptConfig.kt index 1f0dbce..663810f 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/config/JasyptConfig.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/config/JasyptConfig.kt @@ -10,17 +10,17 @@ import org.springframework.context.annotation.Configuration class JasyptConfig { @Bean("jasyptStringEncryptor") - fun stringEncryptor(): StringEncryptor { - val encryptor = PooledPBEStringEncryptor() - val config = SimpleStringPBEConfig() - config.password = System.getenv("JASYPT_ENCRYPTOR_PASSWORD") - config.algorithm = "PBEWithMD5AndDES" - config.setKeyObtentionIterations("1000") - config.setPoolSize("1") - config.stringOutputType = "base64" - config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator") - config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator") - encryptor.setConfig(config) - return encryptor + fun stringEncryptor(): StringEncryptor = PooledPBEStringEncryptor().apply { + this.setConfig( + SimpleStringPBEConfig().apply { + this.password = System.getenv("JASYPT_ENCRYPTOR_PASSWORD") + this.algorithm = "PBEWithMD5AndDES" + this.setKeyObtentionIterations("1000") + this.setPoolSize("1") + this.stringOutputType = "base64" + this.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator") + this.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator") + } + ) } } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/config/SwaggerConfig.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/config/SwaggerConfig.kt index 8b1147d..627e706 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/config/SwaggerConfig.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/config/SwaggerConfig.kt @@ -15,7 +15,7 @@ class SwaggerConfig { @Bean fun openAPI(): OpenAPI { val securityScheme: SecurityScheme = getSecurityScheme() - val securityRequirement: SecurityRequirement = getSecurityRequireMent() + val securityRequirement: SecurityRequirement = getSecurityRequirement() return OpenAPI() .addServersItem(Server().url("/")) @@ -23,12 +23,11 @@ class SwaggerConfig { .security(listOf(securityRequirement)) } - private fun getSecurityScheme(): SecurityScheme { - return SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("Bearer").bearerFormat("JWT") + private fun getSecurityScheme(): SecurityScheme = + SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("Bearer").bearerFormat("JWT") .`in`(SecurityScheme.In.HEADER).name("Authorization") - } - private fun getSecurityRequireMent(): SecurityRequirement { - return SecurityRequirement().addList("bearerAuth") - } + + private fun getSecurityRequirement(): SecurityRequirement = + SecurityRequirement().addList("bearerAuth") } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/entity/PageDto.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/entity/PageDto.kt index 7be6e65..7e50158 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/entity/PageDto.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/entity/PageDto.kt @@ -8,7 +8,6 @@ data class PageDto( val currentPage: Int, val size : Int ) { - constructor( data: List, totalCount: Long, diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/exception/GlobalExceptionHandler.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/exception/GlobalExceptionHandler.kt index d90670f..ad6eaa0 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/exception/GlobalExceptionHandler.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/exception/GlobalExceptionHandler.kt @@ -15,7 +15,7 @@ class GlobalExceptionHandler( @ExceptionHandler(ApplicationException::class) fun applicationException(ex: ApplicationException): ResponseEntity> { logger().error("error : ${ex.error}") - if(ex.error.status.is5xxServerError) { + if (ex.error.status.is5xxServerError) { this.discordApiClient.sendErrorTrace( ex.error.status.toString(), ex.error.message, ex.stackTrace.contentToString() diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/CustomUserDetailsService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/CustomUserDetailsService.kt index 18af849..45fc114 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/CustomUserDetailsService.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/CustomUserDetailsService.kt @@ -11,8 +11,7 @@ import org.springframework.transaction.annotation.Transactional class CustomUserDetailsService( private val userJooqRepository: UserJooqRepository ) : UserDetailsService { - override fun loadUserByUsername(id: String): UserDetails { - return userJooqRepository.findById(id.toLong()) + override fun loadUserByUsername(id: String): UserDetails = + this.userJooqRepository.findById(id.toLong()) ?: throw IllegalArgumentException("해당하는 사용자를 찾을 수 없습니다.") - } } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtExceptionFilter.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtExceptionFilter.kt index 876a7e6..e2aa0db 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtExceptionFilter.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtExceptionFilter.kt @@ -67,9 +67,7 @@ class JwtExceptionFilter( } } - private fun excludeLogging(requestURI: String): Boolean { - return excludedUrls.any { requestURI.startsWith(it) } - } + private fun excludeLogging(requestURI: String): Boolean = excludedUrls.any { requestURI.startsWith(it) } private fun getResponseBody(response: ContentCachingResponseWrapper): String { var payload: String? = null diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtUtil.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtUtil.kt index 7081300..63c232b 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtUtil.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtUtil.kt @@ -9,7 +9,6 @@ import io.jsonwebtoken.security.Keys import jakarta.xml.bind.DatatypeConverter import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component -import java.nio.charset.StandardCharsets import java.security.Key import java.util.* @@ -38,7 +37,13 @@ class JwtUtil( .setExpiration(expiredDate) .signWith(SignatureAlgorithm.HS512, getKeyBytes(accessSecretKey)) .compact() - return UserDto.Companion.TokenRes(accessToken, generateRefreshToken(request), expiredDate, false, request.nickName) + return UserDto.Companion.TokenRes( + accessToken, + generateRefreshToken(request), + expiredDate, + false, + request.nickName + ) } fun generateRefreshToken(request: UserDto.Companion.CreateTokenReq): String { @@ -123,10 +128,4 @@ class JwtUtil( private fun getKeyBytes(secretKey: String): ByteArray { return DatatypeConverter.parseBase64Binary((secretKey)) } - - private fun getKey(secretKey: String): Key { - val keyBytes = Base64.getDecoder().decode(secretKey) - return Keys.hmacShaKeyFor(keyBytes) - } - } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/KakaoDto.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/KakaoDto.kt deleted file mode 100644 index 9ae1626..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/KakaoDto.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.ddd.sonnypolabobe.global.security - -import java.util.* - -class KakaoDto { - - companion object { - data class Token( - val access_token: String, - val refresh_token: String, - val token_type: String, - val expires_in: Int, - val refresh_token_expires_in: Int, - val scope: String - ) - - data class UserInfo( - val id: Long, - val connected_at: String, - val properties: Map, - val kakao_account: KakaoAccount - ) - - data class KakaoAccount( - val profile_nickname_needs_agreement: Boolean, - val profile_image_needs_agreement: Boolean, - val profile: Profile, - val has_email: Boolean, - val email_needs_agreement: Boolean, - val is_email_valid: Boolean, - val is_email_verified: Boolean, - val email: String - ) - - data class Profile( - val nickname: String, - val thumbnail_image_url: String, - val profile_image_url: String, - val is_default_image: Boolean, - val is_default_nickname: Boolean - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/RateLimitingInterceptor.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/RateLimitingInterceptor.kt index 95d96fb..57607ce 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/RateLimitingInterceptor.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/RateLimitingInterceptor.kt @@ -10,8 +10,11 @@ import org.springframework.web.servlet.HandlerInterceptor class RateLimitingInterceptor(private val rateLimitingService: RateLimitingService) : HandlerInterceptor { - override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { - // 특정 URL 패턴을 필터링합니다. + override fun preHandle( + request: HttpServletRequest, + response: HttpServletResponse, + handler: Any + ): Boolean { if (request.requestURI == "/api/v1/boards" && request.method == "POST") { if (!rateLimitingService.incrementRequestCount()) { response.status = HttpStatus.TOO_MANY_REQUESTS.value() diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/RateLimitingService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/RateLimitingService.kt index b7dbfd2..b283e7b 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/RateLimitingService.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/RateLimitingService.kt @@ -29,7 +29,5 @@ class RateLimitingService( } @Scheduled(cron = "0 0 0 * * *", zone = "Asia/Seoul") - fun resetRequestCount() { - requestCounts.clear() - } + fun resetRequestCount() = requestCounts.clear() } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DateConverter.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DateConverter.kt index 7836126..73bb93a 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DateConverter.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DateConverter.kt @@ -2,16 +2,13 @@ package com.ddd.sonnypolabobe.global.util import java.time.LocalDateTime import java.time.ZoneId -import java.util.Date +import java.util.* object DateConverter { - fun convertToKst(date: LocalDateTime): LocalDateTime { - return date.plusHours(9) - } + fun convertToKst(date: LocalDateTime): LocalDateTime = date.plusHours(9) - fun dateToLocalDateTime(date: Date) : LocalDateTime { - return LocalDateTime.ofInstant(date.toInstant(), ZoneId.of("Asia/Seoul")) - } + fun dateToLocalDateTime(date: Date): LocalDateTime = + LocalDateTime.ofInstant(date.toInstant(), ZoneId.of("Asia/Seoul")) } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DiscordApiClient.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DiscordApiClient.kt index 0b8906b..7b237ec 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DiscordApiClient.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DiscordApiClient.kt @@ -23,18 +23,16 @@ class DiscordApiClient( .build() fun sendErrorLog(req: String) { - val embedData: MutableMap = HashMap() - - embedData["title"] = "서버 에러 발생" - - val field1: MutableMap = HashMap() - field1["name"] = "요청" - field1["value"] = req - - embedData["fields"] = listOf>(field1) - - val payload: MutableMap = HashMap() - payload["embeds"] = arrayOf(embedData) + val payload = """ + { + "content": "서버 알림", + "tts": false, + "embeds": [{ + "title": "에러 발생", + "description": "$req" + }] + } + """.trimIndent() sendDiscordComm() .post() @@ -46,26 +44,16 @@ class DiscordApiClient( } fun sendErrorTrace(errorCode: String, message: String?, trace: String) { - val embedData: MutableMap = HashMap() - - embedData["title"] = "서버 에러 발생" - - val field1: MutableMap = HashMap() - field1["name"] = "트레이스" - field1["value"] = trace - - val field2: MutableMap = HashMap() - field2["name"] = "에러 코드" - field2["value"] = errorCode - - val field3: MutableMap = HashMap() - field3["name"] = "메시지" - field3["value"] = message ?: "메시지 없음" - - embedData["fields"] = listOf>(field1, field2, field3) - - val payload: MutableMap = HashMap() - payload["embeds"] = arrayOf(embedData) + val payload = """ + { + "content": "서버 알림", + "tts": false, + "embeds": [{ + "title": "서버 에러 발생", + "description": "에러 코드 : ${errorCode} \n 트레이스 : $trace \n 메세지 : ${message ?: "메시지 없음"}" + }] + } + """.trimIndent() sendDiscordComm() .post() diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/HttpLog.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/HttpLog.kt deleted file mode 100644 index a9cfe8a..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/HttpLog.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.ddd.sonnypolabobe.global.util - -data class HttpLog( - val requestMethod : String, - val requestURI : String, - val responseStatus : Int, - val elapsedTime : Double, - val headers : Map, - val parameters : Map, - val requestBody : String, - val responseBody : String -) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/S3Util.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/S3Util.kt index f09219d..c160551 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/S3Util.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/S3Util.kt @@ -33,16 +33,11 @@ class S3Util( private val cloudfrontDomain: String, ) { - fun awsCredentials(): BasicAWSCredentials { - return BasicAWSCredentials(accessKey, secretKey) - } - - fun amazonS3Client(): AmazonS3 { - return AmazonS3ClientBuilder.standard() - .withCredentials(AWSStaticCredentialsProvider(awsCredentials())) - .withRegion(region) - .build() - } + fun awsCredentials(): BasicAWSCredentials = BasicAWSCredentials(accessKey, secretKey) + fun amazonS3Client(): AmazonS3 = AmazonS3ClientBuilder.standard() + .withCredentials(AWSStaticCredentialsProvider(awsCredentials())) + .withRegion(region) + .build() fun getPreSignedUrl(fileName: String): URL { val path: String = (runningName + File.separator) + fileName diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/UuidConverter.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/UuidConverter.kt index 1abe579..5e32ae2 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/UuidConverter.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/UuidConverter.kt @@ -20,17 +20,12 @@ object UuidConverter { return byteBuffer.array() } - fun stringToUUID(uuid: String): UUID { - return try { - UUID.fromString(uuid) - } catch (e: IllegalArgumentException) { - throw ApplicationException( - CustomErrorCode.BOARD_NOT_FOUND - ) - } + fun stringToUUID(uuid: String): UUID = try { + UUID.fromString(uuid) + } catch (e: IllegalArgumentException) { + throw ApplicationException( + CustomErrorCode.BOARD_NOT_FOUND + ) } - fun uuidToString(uuid: UUID): String { - return uuid.toString() - } } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/UuidGenerator.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/UuidGenerator.kt index 26bb83d..0bf6c46 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/UuidGenerator.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/UuidGenerator.kt @@ -4,7 +4,5 @@ import com.github.f4b6a3.uuid.UuidCreator import java.util.* object UuidGenerator { - fun create(): UUID { - return UuidCreator.getTimeOrderedEpochPlus1() - } + fun create(): UUID = UuidCreator.getTimeOrderedEpochPlus1() } \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/WebClientUtil.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/WebClientUtil.kt deleted file mode 100644 index 9a8709a..0000000 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/WebClientUtil.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.ddd.sonnypolabobe.global.util - -import org.springframework.http.HttpHeaders -import org.springframework.http.MediaType -import org.springframework.http.client.reactive.ReactorClientHttpConnector -import org.springframework.stereotype.Component -import org.springframework.web.reactive.function.client.WebClient -import reactor.netty.http.client.HttpClient -import java.time.Duration - - -@Component -class WebClientUtil() { - - fun create(baseUrl: String): WebClient { - return WebClient.builder() - .baseUrl(baseUrl) - .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .codecs { it.defaultCodecs().enableLoggingRequestDetails(true) } - .clientConnector( - ReactorClientHttpConnector( - HttpClient.create().responseTimeout(Duration.ofMillis(2500)) - ) - ) - .build() - } - -} \ No newline at end of file From 8bf27cf7be0391042b9a3e8b4470bbcaaa9cd544 Mon Sep 17 00:00:00 2001 From: dldmsql Date: Wed, 25 Sep 2024 00:02:52 +0900 Subject: [PATCH 5/6] =?UTF-8?q?fix:=204=EC=B0=A8=20MVP=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/board/controller/dto/BoardGetResponse.kt | 2 ++ .../domain/board/repository/BoardJooqRepositoryImpl.kt | 1 + .../domain/board/repository/vo/BoardGetOneVo.kt | 3 ++- .../ddd/sonnypolabobe/domain/board/service/BoardService.kt | 5 +++-- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt index 7c644c1..000fd5f 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/controller/dto/BoardGetResponse.kt @@ -8,4 +8,6 @@ data class BoardGetResponse( val title: String, @field:Schema(description = "폴라로이드") val items: List, + @field:Schema(description = "작성자 여부", example = "true") + val isMine : Boolean ) \ No newline at end of file diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt index c789736..79ba25e 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt @@ -53,6 +53,7 @@ class BoardJooqRepositoryImpl( .select( jBoard.ID.convertFrom { it?.let{UuidConverter.byteArrayToUUID(it) } }, jBoard.TITLE, + jBoard.USER_ID.`as`(BoardGetOneVo::ownerId.name), jPolaroid.ID.`as`(BoardGetOneVo::polaroidId.name), jPolaroid.IMAGE_KEY, jPolaroid.ONE_LINE_MESSAGE, diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/vo/BoardGetOneVo.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/vo/BoardGetOneVo.kt index b178d79..b414708 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/vo/BoardGetOneVo.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/vo/BoardGetOneVo.kt @@ -6,11 +6,12 @@ import java.util.UUID data class BoardGetOneVo( val id: UUID?, val title: String?, + val ownerId: Long?, val polaroidId : Long?, val imageKey : String?, val oneLineMessage: String?, val createdAt: LocalDateTime?, val userId : Long?, - val nickName: String?, + val nickname: String?, val options: String? ) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt index eff43dc..718dcc6 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/service/BoardService.kt @@ -32,6 +32,7 @@ class BoardService( return id.run { val queryResult = boardJooqRepository.selectOneById(UuidConverter.stringToUUID(this@run)) + if(queryResult.isEmpty()) throw ApplicationException(CustomErrorCode.BOARD_NOT_FOUND) val groupByTitle = queryResult.groupBy { it.title } groupByTitle.map { entry -> val title = entry.key @@ -41,14 +42,14 @@ class BoardService( imageUrl = it.imageKey?.let { it1 -> s3Util.getImgUrl(it1) } ?: "", oneLineMessage = it.oneLineMessage ?: "폴라보와의 추억 한 줄", userId = it.userId ?: 0L, - nickname = it.nickName ?: "", + nickname = it.nickname ?: "", isMine = it.userId == user?.id?.toLong(), createdAt = it.createdAt, options = it.options?.let{ ObjectMapper().readValue(it, object : TypeReference>() {})} ) }.filter { it.id != 0L }.distinctBy { it.id } - BoardGetResponse(title = title ?: "", items = polaroids) + BoardGetResponse(title = title ?: "", items = polaroids, isMine = queryResult.first().ownerId == user?.id?.toLong()) } } } From 2a9dba8edf37780d5dae86b79ed65409e0d698b9 Mon Sep 17 00:00:00 2001 From: dldmsql Date: Wed, 25 Sep 2024 00:26:16 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=204=EC=B0=A8=20MVP=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/board/repository/BoardJooqRepositoryImpl.kt | 2 +- .../sonnypolabobe/global/security/JwtExceptionFilter.kt | 8 ++++---- .../com/ddd/sonnypolabobe/global/util/DiscordApiClient.kt | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt index 79ba25e..130129a 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/domain/board/repository/BoardJooqRepositoryImpl.kt @@ -276,7 +276,7 @@ class BoardJooqRepositoryImpl( .and(genderAndAgeGroupMatch(userGender, userAgeGroup)) ) .orderBy(field("sub_query.polaroid_count", Int::class.java).desc(), jBoard.CREATED_AT.desc()) - .limit(8) + .limit(16) .fetchInto(String::class.java) } diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtExceptionFilter.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtExceptionFilter.kt index e2aa0db..1fe39d8 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtExceptionFilter.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/security/JwtExceptionFilter.kt @@ -43,10 +43,10 @@ class JwtExceptionFilter( val message = "\n" + "[REQUEST] ${request.method} - ${request.requestURI} ${responseWrapper.status} - ${(endedAt - startedAt) / 10000.0} \n" + - "Headers : ${getHeaders(request)} \n" + - "Parameters : ${getRequestParams(request)} \n" + - "Request body : ${getRequestBody(requestWrapper)} \n" + - "Response body : ${getResponseBody(responseWrapper)}" + "Headers - ${getHeaders(request)} \n" + + "Parameters - ${getRequestParams(request)} \n" + + "Request body - ${getRequestBody(requestWrapper)} \n" + + "Response body - ${getResponseBody(responseWrapper)}" logger().error(message) if (responseWrapper.status >= 400 && getResponseBody(responseWrapper).contains( CustomErrorCode.INTERNAL_SERVER_EXCEPTION.message diff --git a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DiscordApiClient.kt b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DiscordApiClient.kt index 7b237ec..e36bd39 100644 --- a/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DiscordApiClient.kt +++ b/src/main/kotlin/com/ddd/sonnypolabobe/global/util/DiscordApiClient.kt @@ -50,7 +50,7 @@ class DiscordApiClient( "tts": false, "embeds": [{ "title": "서버 에러 발생", - "description": "에러 코드 : ${errorCode} \n 트레이스 : $trace \n 메세지 : ${message ?: "메시지 없음"}" + "description": "${message ?: "메시지 없음"}" }] } """.trimIndent()