From af0ca43f7c0a31d7218236794e92081053664bc6 Mon Sep 17 00:00:00 2001 From: kshired Date: Sun, 17 Dec 2023 12:39:54 +0900 Subject: [PATCH 1/4] fix test --- backend-config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend-config b/backend-config index 9ced1f3a..9b8d6955 160000 --- a/backend-config +++ b/backend-config @@ -1 +1 @@ -Subproject commit 9ced1f3a71c19a24b60bd3de0e8f34f85369eb44 +Subproject commit 9b8d69552a6259f39fc0606b69f22dc0601ebb66 From fd8030e0046be63473fc88474060c5c50339ffae Mon Sep 17 00:00:00 2001 From: SEONGILKIM Date: Sun, 17 Dec 2023 15:50:23 +0900 Subject: [PATCH 2/4] =?UTF-8?q?fix=20:=20redis=20=EB=9E=AD=ED=82=B9=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=20(#150)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apiserver/common/config/RedisConfig.kt | 19 ++- .../controller/v1/admin/AdminController.kt | 6 + .../repository/common/RedisRepository.kt | 100 ++++++++------ .../apiserver/service/user/UserServiceImpl.kt | 1 - .../repository/common/RedisRepositoryTest.kt | 130 ++++++++++++++++++ 5 files changed, 206 insertions(+), 50 deletions(-) create mode 100644 src/test/kotlin/io/csbroker/apiserver/repository/common/RedisRepositoryTest.kt diff --git a/src/main/kotlin/io/csbroker/apiserver/common/config/RedisConfig.kt b/src/main/kotlin/io/csbroker/apiserver/common/config/RedisConfig.kt index 5393d6ba..ef8db47f 100644 --- a/src/main/kotlin/io/csbroker/apiserver/common/config/RedisConfig.kt +++ b/src/main/kotlin/io/csbroker/apiserver/common/config/RedisConfig.kt @@ -6,8 +6,12 @@ import org.springframework.context.annotation.Configuration import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory import org.springframework.data.redis.core.StringRedisTemplate import org.springframework.data.redis.serializer.StringRedisSerializer +import org.springframework.orm.jpa.JpaTransactionManager +import org.springframework.transaction.PlatformTransactionManager +import org.springframework.transaction.annotation.EnableTransactionManagement @Configuration +@EnableTransactionManagement class RedisConfig( @Value("\${spring.redis.host}") private val host: String, @@ -23,11 +27,16 @@ class RedisConfig( @Bean fun stringRedisTemplate(): StringRedisTemplate { - val redisTemplate = StringRedisTemplate() - redisTemplate.keySerializer = StringRedisSerializer() - redisTemplate.valueSerializer = StringRedisSerializer() - redisTemplate.setConnectionFactory(redisConnectionFactory()) + return StringRedisTemplate().also { + it.keySerializer = StringRedisSerializer() + it.valueSerializer = StringRedisSerializer() + it.connectionFactory = redisConnectionFactory() + it.setEnableTransactionSupport(true) + } + } - return redisTemplate + @Bean + fun transactionManager(): PlatformTransactionManager { + return JpaTransactionManager() } } diff --git a/src/main/kotlin/io/csbroker/apiserver/controller/v1/admin/AdminController.kt b/src/main/kotlin/io/csbroker/apiserver/controller/v1/admin/AdminController.kt index cbea4933..4595fc79 100644 --- a/src/main/kotlin/io/csbroker/apiserver/controller/v1/admin/AdminController.kt +++ b/src/main/kotlin/io/csbroker/apiserver/controller/v1/admin/AdminController.kt @@ -52,4 +52,10 @@ class AdminController( ), ) } + + @PostMapping("/rank/refresh") + fun refreshRank(): ApiResponse { + userService.calculateRank() + return ApiResponse.success() + } } diff --git a/src/main/kotlin/io/csbroker/apiserver/repository/common/RedisRepository.kt b/src/main/kotlin/io/csbroker/apiserver/repository/common/RedisRepository.kt index 0504282e..02aed296 100644 --- a/src/main/kotlin/io/csbroker/apiserver/repository/common/RedisRepository.kt +++ b/src/main/kotlin/io/csbroker/apiserver/repository/common/RedisRepository.kt @@ -3,6 +3,8 @@ package io.csbroker.apiserver.repository.common import io.csbroker.apiserver.common.config.properties.AppProperties import io.csbroker.apiserver.dto.common.RankListDto import io.csbroker.apiserver.dto.user.RankResultDto +import org.springframework.data.redis.core.RedisOperations +import org.springframework.data.redis.core.SessionCallback import org.springframework.data.redis.core.StringRedisTemplate import org.springframework.data.redis.core.ZSetOperations.TypedTuple import org.springframework.stereotype.Repository @@ -22,8 +24,7 @@ class RedisRepository( } fun setRefreshTokenByEmail(email: String, refreshToken: String) { - redisTemplate.opsForValue() - .set(email, refreshToken, appProperties.auth.refreshTokenExpiry, TimeUnit.MILLISECONDS) + redisTemplate.opsForValue().set(email, refreshToken, appProperties.auth.refreshTokenExpiry, TimeUnit.MILLISECONDS) } fun setPasswordVerification(code: String, email: String) { @@ -38,21 +39,31 @@ class RedisRepository( redisTemplate.delete(code) } + @Suppress("UNCHECKED_CAST") fun setRank(scoreMap: Map) { - redisTemplate.opsForZSet().add( - RANKING, - scoreMap.map { TypedTuple.of(it.key, it.value) }.toSet(), + redisTemplate.execute( + object : SessionCallback { + override fun execute(operations: RedisOperations) { + val stringOperations = operations as RedisOperations + stringOperations.multi() + stringOperations.delete(RANKING) + stringOperations.opsForZSet().add( + RANKING, + scoreMap.map { TypedTuple.of(it.key, it.value) }.toSet(), + ) + stringOperations.exec() + } + }, ) } fun getRank(key: String): RankResultDto { - var rank: Long? = null - - val score = redisTemplate.opsForZSet().score(RANKING, key) ?: 0.0 - val rankKey = redisTemplate.opsForZSet().reverseRangeByScore(RANKING, score, score, 0, 1)?.first() + val score = redisTemplate.opsForZSet().score(RANKING, key) + ?: return RankResultDto(null, 0.0) - if (rankKey != null) { - rank = redisTemplate.opsForZSet().reverseRank(RANKING, rankKey)?.plus(1) + val rankKey = redisTemplate.opsForZSet().reverseRangeByScore(RANKING, score, score, 0, 1)?.firstOrNull() + val rank = rankKey?.let { + redisTemplate.opsForZSet().reverseRank(RANKING, it)?.plus(1) } return RankResultDto(rank, score) @@ -60,42 +71,12 @@ class RedisRepository( fun getRanks(size: Long, page: Long): RankListDto { val start = size * page - val end = size * (page + 1) - 1 + val end = start + size - 1 - val keyWithScores = redisTemplate.opsForZSet().reverseRangeWithScores(RANKING, start, end) + val keyWithScores = redisTemplate.opsForZSet().reverseRangeWithScores(RANKING, start, end) ?: emptySet() val totalElements = redisTemplate.opsForZSet().size(RANKING) ?: 0 val totalPage = if (totalElements % size > 0) totalElements / size + 1 else totalElements / size - val result = mutableListOf() - var rank = 1L - var isFirst = true - - keyWithScores?.let { - it.forEach { keyWithScore -> - if (!isFirst && result.last().score != keyWithScore.score) { - isFirst = true - } - - if (isFirst) { - val score = keyWithScore.score!! - val key = redisTemplate.opsForZSet().reverseRangeByScore(RANKING, score, score, 0, 1)!!.first() - rank = redisTemplate.opsForZSet().reverseRank(RANKING, key)!!.plus(1) - isFirst = false - } - - val keys = keyWithScore.value!!.split('@') - val id = UUID.fromString(keys[0]) - val username = keys[1] - - result.add( - RankListDto.RankDetail( - id, - username, - rank, - keyWithScore.score!!, - ), - ) - } - } + val result = getRankDetails(keyWithScores) return RankListDto( size = size, @@ -105,4 +86,35 @@ class RedisRepository( contents = result, ) } + + private fun getRankDetails(keyWithScores: Set>): List { + return keyWithScores.fold(emptyList()) { acc, value -> + val (score, id, username) = value.getRankInfo() + + acc + if (acc.isEmpty() || acc.last().score != score) { + val key = redisTemplate.opsForZSet().reverseRangeByScore(RANKING, score, score, 0, 1)!!.first() + RankListDto.RankDetail( + id, + username, + redisTemplate.opsForZSet().reverseRank(RANKING, key)!!.plus(1), + score, + ) + } else { + RankListDto.RankDetail( + id, + username, + acc.last().rank, + score, + ) + } + } + } + + private fun TypedTuple.getRankInfo(): Triple { + val keys = value!!.split('@') + val id = UUID.fromString(keys[0]) + val username = keys[1] + + return Triple(this.score!!, id, username) + } } diff --git a/src/main/kotlin/io/csbroker/apiserver/service/user/UserServiceImpl.kt b/src/main/kotlin/io/csbroker/apiserver/service/user/UserServiceImpl.kt index ab342c73..4e369d88 100644 --- a/src/main/kotlin/io/csbroker/apiserver/service/user/UserServiceImpl.kt +++ b/src/main/kotlin/io/csbroker/apiserver/service/user/UserServiceImpl.kt @@ -132,7 +132,6 @@ class UserServiceImpl( user.profileImageUrl = imgUrl } - @Transactional @Scheduled(cron = "0 0 * * * *") override fun calculateRank() { val userScoreMap = userRepository.findAll().associate { diff --git a/src/test/kotlin/io/csbroker/apiserver/repository/common/RedisRepositoryTest.kt b/src/test/kotlin/io/csbroker/apiserver/repository/common/RedisRepositoryTest.kt new file mode 100644 index 00000000..99920f10 --- /dev/null +++ b/src/test/kotlin/io/csbroker/apiserver/repository/common/RedisRepositoryTest.kt @@ -0,0 +1,130 @@ +package io.csbroker.apiserver.repository.common + +import io.csbroker.apiserver.common.config.properties.AppProperties +import io.csbroker.apiserver.dto.common.RankListDto +import io.kotest.matchers.shouldBe +import io.mockk.every +import io.mockk.mockk +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.data.redis.core.StringRedisTemplate +import org.springframework.data.redis.core.ZSetOperations.TypedTuple +import java.util.UUID + +class RedisRepositoryTest { + private lateinit var sut: RedisRepository + private lateinit var redisTemplate: StringRedisTemplate + private val appProperties = AppProperties( + auth = AppProperties.Auth( + tokenExpiry = 1, + refreshTokenExpiry = 1, + tokenSecret = "this is secret", + ), + oAuth2 = AppProperties.OAuth2( + authorizedRedirectUris = listOf("http://localhost:3000/oauth2/redirect"), + ), + ) + + @BeforeEach + fun setUp() { + redisTemplate = mockk() + sut = RedisRepository( + redisTemplate = redisTemplate, + appProperties = appProperties, + ) + } + + @Test + fun `랭킹 조회에 성공한다`() { + // given + val randomUUIDs = (0..6).map { UUID.randomUUID() } + every { redisTemplate.opsForZSet().reverseRangeWithScores(RANKING, 0, 8) } returns setOf( + TypedTuple.of("${randomUUIDs[0]}@username1", 5.0), + TypedTuple.of("${randomUUIDs[1]}@username2", 5.0), + TypedTuple.of("${randomUUIDs[2]}@username3", 4.0), + TypedTuple.of("${randomUUIDs[3]}@username4", 4.0), + TypedTuple.of("${randomUUIDs[4]}@username5", 3.0), + TypedTuple.of("${randomUUIDs[5]}@username6", 2.0), + TypedTuple.of("${randomUUIDs[6]}@username7", 1.0), + ) + every { redisTemplate.opsForZSet().size(RANKING) } returns 7 + every { redisTemplate.opsForZSet().reverseRangeByScore(RANKING, 5.0, 5.0, 0, 1) } returns setOf( + "${randomUUIDs[0]}@username1", + "${randomUUIDs[1]}@username2", + ) + every { redisTemplate.opsForZSet().reverseRank(RANKING, "${randomUUIDs[0]}@username1") } returns 0 + every { redisTemplate.opsForZSet().reverseRangeByScore(RANKING, 4.0, 4.0, 0, 1) } returns setOf( + "${randomUUIDs[2]}@username3", + "${randomUUIDs[3]}@username4", + ) + every { redisTemplate.opsForZSet().reverseRank(RANKING, "${randomUUIDs[2]}@username3") } returns 2 + every { redisTemplate.opsForZSet().reverseRangeByScore(RANKING, 3.0, 3.0, 0, 1) } returns setOf( + "${randomUUIDs[4]}@username5", + ) + every { redisTemplate.opsForZSet().reverseRank(RANKING, "${randomUUIDs[4]}@username5") } returns 4 + every { redisTemplate.opsForZSet().reverseRangeByScore(RANKING, 2.0, 2.0, 0, 1) } returns setOf( + "${randomUUIDs[5]}@username6", + ) + every { redisTemplate.opsForZSet().reverseRank(RANKING, "${randomUUIDs[5]}@username6") } returns 5 + every { redisTemplate.opsForZSet().reverseRangeByScore(RANKING, 1.0, 1.0, 0, 1) } returns setOf( + "${randomUUIDs[6]}@username7", + ) + every { redisTemplate.opsForZSet().reverseRank(RANKING, "${randomUUIDs[6]}@username7") } returns 6 + + // when + val result = sut.getRanks( + size = 9, + page = 0, + ) + + // then + result.size shouldBe 9 + result.totalPage shouldBe 1 + result.currentPage shouldBe 0 + result.numberOfElements shouldBe 7 + result.contents shouldBe listOf( + RankListDto.RankDetail( + randomUUIDs[0], + "username1", + 1L, + 5.0, + ), + RankListDto.RankDetail( + randomUUIDs[1], + "username2", + 1L, + 5.0, + ), + RankListDto.RankDetail( + randomUUIDs[2], + "username3", + 3L, + 4.0, + ), + RankListDto.RankDetail( + randomUUIDs[3], + "username4", + 3L, + 4.0, + ), + RankListDto.RankDetail( + randomUUIDs[4], + "username5", + 5L, + 3.0, + ), + RankListDto.RankDetail( + randomUUIDs[5], + "username6", + 6L, + 2.0, + ), + RankListDto.RankDetail( + randomUUIDs[6], + "username7", + 7L, + 1.0, + ), + ) + } +} From 28379081b2e9cf3465a8c6bc3c1fcb90157d7628 Mon Sep 17 00:00:00 2001 From: SEONGILKIM Date: Sun, 17 Dec 2023 15:50:36 +0900 Subject: [PATCH 3/4] refactor : aws client (#164) --- .../common/config/AwsClientConfig.kt | 40 +++++++++++++++ .../repository/user/UserRepository.kt | 3 -- .../apiserver/service/common/MailService.kt | 2 +- .../apiserver/service/common/S3ServiceImpl.kt | 34 ++++--------- .../service/common/SesMailServiceImpl.kt | 49 ++++++------------- 5 files changed, 64 insertions(+), 64 deletions(-) create mode 100644 src/main/kotlin/io/csbroker/apiserver/common/config/AwsClientConfig.kt diff --git a/src/main/kotlin/io/csbroker/apiserver/common/config/AwsClientConfig.kt b/src/main/kotlin/io/csbroker/apiserver/common/config/AwsClientConfig.kt new file mode 100644 index 00000000..6ab4c401 --- /dev/null +++ b/src/main/kotlin/io/csbroker/apiserver/common/config/AwsClientConfig.kt @@ -0,0 +1,40 @@ +package io.csbroker.apiserver.common.config + +import aws.sdk.kotlin.runtime.auth.credentials.StaticCredentialsProvider +import aws.sdk.kotlin.services.s3.S3Client +import aws.sdk.kotlin.services.ses.SesClient +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class AwsClientConfig( + @Value("\${aws.mail-url}") + private val url: String, + @Value("\${aws.access-key}") + private val accessKey: String, + @Value("\${aws.secret-key}") + private val secretKey: String, +) { + @Bean + fun sesClient(): SesClient { + return SesClient { + region = url + credentialsProvider = StaticCredentialsProvider { + accessKeyId = accessKey + secretAccessKey = secretKey + } + } + } + + @Bean + fun s3Client(): S3Client { + return S3Client { + region = url + credentialsProvider = StaticCredentialsProvider { + accessKeyId = accessKey + secretAccessKey = secretKey + } + } + } +} diff --git a/src/main/kotlin/io/csbroker/apiserver/repository/user/UserRepository.kt b/src/main/kotlin/io/csbroker/apiserver/repository/user/UserRepository.kt index 418c88b6..168c88ab 100644 --- a/src/main/kotlin/io/csbroker/apiserver/repository/user/UserRepository.kt +++ b/src/main/kotlin/io/csbroker/apiserver/repository/user/UserRepository.kt @@ -20,9 +20,6 @@ interface UserRepository : JpaRepository { fun findUserByProviderId(providerId: String): User? - @Query("select count(u.id) > 0 from User u where u.email = :email") - fun existsUserByEmail(@Param("email") email: String): Boolean - @Query("select count(u) from User u where u.isDeleted = FALSE") fun countUser(): Long diff --git a/src/main/kotlin/io/csbroker/apiserver/service/common/MailService.kt b/src/main/kotlin/io/csbroker/apiserver/service/common/MailService.kt index 66fa0803..b8cc8279 100644 --- a/src/main/kotlin/io/csbroker/apiserver/service/common/MailService.kt +++ b/src/main/kotlin/io/csbroker/apiserver/service/common/MailService.kt @@ -1,5 +1,5 @@ package io.csbroker.apiserver.service.common interface MailService { - suspend fun sendPasswordChangeMail(to: String) + suspend fun sendPasswordChangeMail(email: String) } diff --git a/src/main/kotlin/io/csbroker/apiserver/service/common/S3ServiceImpl.kt b/src/main/kotlin/io/csbroker/apiserver/service/common/S3ServiceImpl.kt index 898a8bb9..d44142a7 100644 --- a/src/main/kotlin/io/csbroker/apiserver/service/common/S3ServiceImpl.kt +++ b/src/main/kotlin/io/csbroker/apiserver/service/common/S3ServiceImpl.kt @@ -1,6 +1,5 @@ package io.csbroker.apiserver.service.common -import aws.sdk.kotlin.runtime.auth.credentials.StaticCredentialsProvider import aws.sdk.kotlin.services.s3.S3Client import aws.sdk.kotlin.services.s3.model.ObjectCannedAcl import aws.sdk.kotlin.services.s3.model.PutObjectRequest @@ -12,35 +11,20 @@ import java.util.UUID @Service class S3ServiceImpl( - @Value("\${aws.access-key}") - private val accessKey: String, - - @Value("\${aws.secret-key}") - private val secretKey: String, - + private val s3Client: S3Client, @Value("\${aws.s3-bucket}") private val bucketName: String, ) : S3Service { override suspend fun uploadProfileImg(multipartFile: MultipartFile): String { val s3FileName = createS3FileName(multipartFile) - - S3Client { - region = "ap-northeast-2" - credentialsProvider = StaticCredentialsProvider { - accessKeyId = accessKey - secretAccessKey = secretKey - } - }.use { - it.putObject( - PutObjectRequest.invoke { - bucket = bucketName - key = s3FileName - body = ByteStream.fromBytes(multipartFile.bytes) - acl = ObjectCannedAcl.PublicRead - }, - ) - } - + s3Client.putObject( + PutObjectRequest { + bucket = bucketName + key = s3FileName + body = ByteStream.fromBytes(multipartFile.bytes) + acl = ObjectCannedAcl.PublicRead + }, + ) return getFullPath(s3FileName) } diff --git a/src/main/kotlin/io/csbroker/apiserver/service/common/SesMailServiceImpl.kt b/src/main/kotlin/io/csbroker/apiserver/service/common/SesMailServiceImpl.kt index bf41cb8e..e27d0b5a 100644 --- a/src/main/kotlin/io/csbroker/apiserver/service/common/SesMailServiceImpl.kt +++ b/src/main/kotlin/io/csbroker/apiserver/service/common/SesMailServiceImpl.kt @@ -1,17 +1,15 @@ package io.csbroker.apiserver.service.common -import aws.sdk.kotlin.runtime.auth.credentials.StaticCredentialsProvider import aws.sdk.kotlin.services.ses.SesClient import aws.sdk.kotlin.services.ses.model.Body import aws.sdk.kotlin.services.ses.model.Content import aws.sdk.kotlin.services.ses.model.Destination import aws.sdk.kotlin.services.ses.model.Message import aws.sdk.kotlin.services.ses.model.SendEmailRequest +import io.csbroker.apiserver.auth.ProviderType import io.csbroker.apiserver.common.exception.EntityNotFoundException import io.csbroker.apiserver.repository.common.RedisRepository import io.csbroker.apiserver.repository.user.UserRepository -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Service import org.thymeleaf.context.Context @@ -23,51 +21,32 @@ class SesMailServiceImpl( private val templateEngine: SpringTemplateEngine, private val userRepository: UserRepository, private val redisRepository: RedisRepository, - @Value("\${aws.mail-url}") private val url: String, - - @Value("\${aws.access-key}") - private val accessKey: String, - - @Value("\${aws.secret-key}") - private val secretKey: String, + private val sesClient: SesClient, ) : MailService { - override suspend fun sendPasswordChangeMail(to: String) { - checkUserExist(to) + override suspend fun sendPasswordChangeMail(email: String) { + checkUserExist(email) val code = UUID.randomUUID().toString() - val emailRequest = createEmailRequest(code, to) - send(emailRequest) - redisRepository.setPasswordVerification(code, to) + val emailRequest = createEmailRequest(code, email) + sesClient.sendEmail(emailRequest) + redisRepository.setPasswordVerification(code, email) } - private suspend fun checkUserExist(to: String) { - val isExist = withContext(Dispatchers.IO) { - userRepository.existsUserByEmail(to) - } - - if (!isExist) { - throw EntityNotFoundException("$to 메일로 가입한 유저를 찾을 수 없습니다.") - } - } + private fun checkUserExist(email: String) { + val user = userRepository.findByEmail(email) + ?: throw EntityNotFoundException("$email 메일로 가입한 유저를 찾을 수 없습니다.") - private suspend fun send(emailRequest: SendEmailRequest) { - SesClient { - region = "ap-northeast-2" - credentialsProvider = StaticCredentialsProvider { - accessKeyId = accessKey - secretAccessKey = secretKey - } - }.use { - it.sendEmail(emailRequest) + if (user.providerType != ProviderType.LOCAL) { + throw EntityNotFoundException("소셜 로그인 유저는 비밀번호를 변경할 수 없습니다.") } } - private fun createEmailRequest(code: String, to: String): SendEmailRequest { + private fun createEmailRequest(code: String, email: String): SendEmailRequest { return SendEmailRequest { destination = Destination { - toAddresses = listOf(to) + toAddresses = listOf(email) } message = Message { subject = Content { From e1ac17ef6ccf1c3a11d90b0b99cddc5cb54922bc Mon Sep 17 00:00:00 2001 From: Jaewon Min <67869514+ekzm8523@users.noreply.github.com> Date: Sun, 17 Dec 2023 18:34:30 +0900 Subject: [PATCH 4/4] =?UTF-8?q?hotfix:=20=EC=84=9C=EC=88=A0=ED=98=95=20?= =?UTF-8?q?=EC=A0=9C=EC=B6=9C=20=EB=B3=80=EC=88=98=EB=AA=85=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(#165)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 서술형 제출 변수명 변경 * fix config version --------- Co-authored-by: kshired --- .../v2/problem/response/SubmitLongProblemResponseDto.kt | 4 ++-- .../apiserver/service/problem/LongProblemServiceImpl.kt | 4 ++-- .../controller/v1/problem/LongProblemControllerTest.kt | 8 ++++---- .../controller/v1/problem/LongProblemIntegrationTest.kt | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/io/csbroker/apiserver/controller/v2/problem/response/SubmitLongProblemResponseDto.kt b/src/main/kotlin/io/csbroker/apiserver/controller/v2/problem/response/SubmitLongProblemResponseDto.kt index 80608e81..091735d3 100644 --- a/src/main/kotlin/io/csbroker/apiserver/controller/v2/problem/response/SubmitLongProblemResponseDto.kt +++ b/src/main/kotlin/io/csbroker/apiserver/controller/v2/problem/response/SubmitLongProblemResponseDto.kt @@ -4,8 +4,8 @@ data class SubmitLongProblemResponseDto( val title: String, val tags: List, val description: String, - val totalSubmissionCount: Int, - val userSubmissionCount: Int, + val totalSubmission: Int, + val userSubmission: Int, val userAnswer: String, val standardAnswer: String, ) diff --git a/src/main/kotlin/io/csbroker/apiserver/service/problem/LongProblemServiceImpl.kt b/src/main/kotlin/io/csbroker/apiserver/service/problem/LongProblemServiceImpl.kt index 87878dc2..5f0eefc3 100644 --- a/src/main/kotlin/io/csbroker/apiserver/service/problem/LongProblemServiceImpl.kt +++ b/src/main/kotlin/io/csbroker/apiserver/service/problem/LongProblemServiceImpl.kt @@ -178,8 +178,8 @@ class LongProblemServiceImpl( title = problem.title, tags = tags, description = problem.description, - totalSubmissionCount = totalSubmissionCount, - userSubmissionCount = userSubmissionCount, + totalSubmission = totalSubmissionCount, + userSubmission = userSubmissionCount, userAnswer = answer, standardAnswer = standardAnswer, ) diff --git a/src/test/kotlin/io/csbroker/apiserver/controller/v1/problem/LongProblemControllerTest.kt b/src/test/kotlin/io/csbroker/apiserver/controller/v1/problem/LongProblemControllerTest.kt index ee43c53e..c5bfd7c7 100644 --- a/src/test/kotlin/io/csbroker/apiserver/controller/v1/problem/LongProblemControllerTest.kt +++ b/src/test/kotlin/io/csbroker/apiserver/controller/v1/problem/LongProblemControllerTest.kt @@ -216,8 +216,8 @@ class LongProblemControllerTest : RestDocsTest() { title = "title", tags = listOf("tag1", "tag2", "tag3"), description = "description", - totalSubmissionCount = 100, - userSubmissionCount = 10, + totalSubmission = 100, + userSubmission = 10, userAnswer = "user answer", standardAnswer = "standard answer", ) @@ -255,9 +255,9 @@ class LongProblemControllerTest : RestDocsTest() { fieldWithPath("data.title").type(JsonFieldType.STRING).description("문제 제목"), fieldWithPath("data.tags").type(JsonFieldType.ARRAY).description("태그"), fieldWithPath("data.description").type(JsonFieldType.STRING).description("문제 설명"), - fieldWithPath("data.totalSubmissionCount").type(JsonFieldType.NUMBER) + fieldWithPath("data.totalSubmission").type(JsonFieldType.NUMBER) .description("해당 문제에 대해 전체 유저가 제출한 수 (총 제출 수)"), - fieldWithPath("data.userSubmissionCount").type(JsonFieldType.NUMBER) + fieldWithPath("data.userSubmission").type(JsonFieldType.NUMBER) .description("해당 문제에 대해 유저가 제출한 수 "), fieldWithPath("data.userAnswer").type(JsonFieldType.STRING).description("유저의 답변"), fieldWithPath("data.standardAnswer").type(JsonFieldType.STRING).description("모범 답안"), diff --git a/src/test/kotlin/io/csbroker/apiserver/controller/v1/problem/LongProblemIntegrationTest.kt b/src/test/kotlin/io/csbroker/apiserver/controller/v1/problem/LongProblemIntegrationTest.kt index 90bb93e4..37aedf82 100644 --- a/src/test/kotlin/io/csbroker/apiserver/controller/v1/problem/LongProblemIntegrationTest.kt +++ b/src/test/kotlin/io/csbroker/apiserver/controller/v1/problem/LongProblemIntegrationTest.kt @@ -77,8 +77,8 @@ class LongProblemIntegrationTest : IntegrationTest() { val responseDto = objectMapper.readValue(dataAsString) responseDto.title shouldBe problem.title responseDto.description shouldBe problem.description - responseDto.totalSubmissionCount shouldBe preSubmissionCount + 1 // 제출 수가 증가하는지 확인 - responseDto.userSubmissionCount shouldBe preUserSubmissionCount + 1 // 제출 수가 증가하는지 확인 + responseDto.totalSubmission shouldBe preSubmissionCount + 1 // 제출 수가 증가하는지 확인 + responseDto.userSubmission shouldBe preUserSubmissionCount + 1 // 제출 수가 증가하는지 확인 responseDto.userAnswer shouldBe userAnswer standardAnswers.map { sa -> sa.content } shouldContain responseDto.standardAnswer // 모법답안중 하나가 반환되는지 확인 }