From 7715dbbd1caf463b5ecdcb6aa35c4dc713ba74df Mon Sep 17 00:00:00 2001 From: Chanyeong Lim Date: Sun, 6 Oct 2024 09:22:29 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EA=B2=80?= =?UTF-8?q?=EC=82=AC=ED=95=A0=EB=95=8C=20=EB=8C=80=EC=86=8C=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=20=EA=B5=AC=EB=B6=84=20=EC=A0=9C=EA=B1=B0=20(#280)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/users/repository/UserRepository.kt | 4 ++-- .../main/kotlin/users/service/UserService.kt | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/core/src/main/kotlin/users/repository/UserRepository.kt b/core/src/main/kotlin/users/repository/UserRepository.kt index 6310fe9f..19f73d10 100644 --- a/core/src/main/kotlin/users/repository/UserRepository.kt +++ b/core/src/main/kotlin/users/repository/UserRepository.kt @@ -28,9 +28,9 @@ interface UserRepository : CoroutineCrudRepository { suspend fun findAllByIdInAndActiveTrue(ids: List): List - suspend fun existsByEmailAndIsEmailVerifiedTrueAndActiveTrue(email: String): Boolean + suspend fun existsByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(email: String): Boolean - suspend fun findByEmailAndIsEmailVerifiedTrueAndActiveTrue(email: String): User? + suspend fun findByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(email: String): User? suspend fun existsByCredentialFbIdAndActiveTrue(fbId: String): Boolean diff --git a/core/src/main/kotlin/users/service/UserService.kt b/core/src/main/kotlin/users/service/UserService.kt index 39be57ab..ff83d533 100644 --- a/core/src/main/kotlin/users/service/UserService.kt +++ b/core/src/main/kotlin/users/service/UserService.kt @@ -183,7 +183,7 @@ class UserServiceImpl( if (!authService.isValidPassword(password)) throw InvalidPasswordException email?.let { if (!authService.isValidEmail(email)) throw InvalidEmailException - userRepository.findByEmailAndIsEmailVerifiedTrueAndActiveTrue(email)?.let { + userRepository.findByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(email)?.let { throw DuplicateEmailException(getSocialProvider(it)) } } @@ -228,7 +228,7 @@ class UserServiceImpl( val credential = authService.buildFacebookCredential(oauth2UserResponse) if (oauth2UserResponse.email != null) { - userRepository.findByEmailAndIsEmailVerifiedTrueAndActiveTrue(oauth2UserResponse.email)?.let { + userRepository.findByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(oauth2UserResponse.email)?.let { throw DuplicateEmailException(getSocialProvider(it)) } } else { @@ -252,7 +252,7 @@ class UserServiceImpl( } checkNotNull(oauth2UserResponse.email) { "google email is null: $oauth2UserResponse" } - userRepository.findByEmailAndIsEmailVerifiedTrueAndActiveTrue(oauth2UserResponse.email)?.let { + userRepository.findByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(oauth2UserResponse.email)?.let { throw DuplicateEmailException(getSocialProvider(it)) } @@ -275,7 +275,7 @@ class UserServiceImpl( } checkNotNull(oauth2UserResponse.email) { "kakao email is null: $oauth2UserResponse" } - userRepository.findByEmailAndIsEmailVerifiedTrueAndActiveTrue(oauth2UserResponse.email)?.let { + userRepository.findByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(oauth2UserResponse.email)?.let { throw DuplicateEmailException(getSocialProvider(it)) } @@ -343,7 +343,12 @@ class UserServiceImpl( ) { if (user.isEmailVerified == true) throw EmailAlreadyVerifiedException if (!authService.isValidSnuMail(email)) throw InvalidEmailException - if (userRepository.existsByEmailAndIsEmailVerifiedTrueAndActiveTrue(email)) throw DuplicateEmailException(getSocialProvider(user)) + if (userRepository.existsByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue( + email, + ) + ) { + throw DuplicateEmailException(getSocialProvider(user)) + } val key = VERIFICATION_CODE_PREFIX + user.id val code = (Math.random() * 1000000).toInt().toString().padStart(6, '0') saveNewVerificationValue(email, code, key) @@ -396,7 +401,7 @@ class UserServiceImpl( ): TokenResponse { val token = socialLoginRequest.token val oauth2UserResponse = authService.socialLoginWithAccessToken(socialProvider, token) - val presentUser = userRepository.findByEmailAndIsEmailVerifiedTrueAndActiveTrue(oauth2UserResponse.email!!) + val presentUser = userRepository.findByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(oauth2UserResponse.email!!) if (presentUser != null && presentUser.id != user.id) { throw DuplicateEmailException(socialProvider) @@ -489,12 +494,12 @@ class UserServiceImpl( } override suspend fun sendLocalIdToEmail(email: String) { - val user = userRepository.findByEmailAndIsEmailVerifiedTrueAndActiveTrue(email) ?: throw UserNotFoundException + val user = userRepository.findByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(email) ?: throw UserNotFoundException mailService.sendUserMail(type = UserMailType.FIND_ID, to = email, localId = user.credential.localId ?: throw UserNotFoundException) } override suspend fun sendResetPasswordCode(email: String) { - val user = userRepository.findByEmailAndIsEmailVerifiedTrueAndActiveTrue(email) ?: throw UserNotFoundException + val user = userRepository.findByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(email) ?: throw UserNotFoundException val key = RESET_PASSWORD_CODE_PREFIX + user.id val code = Base64.getUrlEncoder().encodeToString(Random.nextBytes(6)) saveNewVerificationValue(email, code, key) From 22bc3ef488a08defed246a426cf01305ff5fe179 Mon Sep 17 00:00:00 2001 From: Chanyeong Lim Date: Sun, 6 Oct 2024 21:43:55 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=EC=86=8C=EC=85=9C=20=EC=97=B0=EB=8F=99?= =?UTF-8?q?=ED=95=A0=EB=95=8C=20email=20null=EC=9D=B8=EA=B1=B0=20=ED=97=88?= =?UTF-8?q?=EC=9A=A9=20(#281)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/src/main/kotlin/users/service/UserService.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/src/main/kotlin/users/service/UserService.kt b/core/src/main/kotlin/users/service/UserService.kt index ff83d533..d7fe36c7 100644 --- a/core/src/main/kotlin/users/service/UserService.kt +++ b/core/src/main/kotlin/users/service/UserService.kt @@ -401,11 +401,13 @@ class UserServiceImpl( ): TokenResponse { val token = socialLoginRequest.token val oauth2UserResponse = authService.socialLoginWithAccessToken(socialProvider, token) - val presentUser = userRepository.findByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(oauth2UserResponse.email!!) - - if (presentUser != null && presentUser.id != user.id) { - throw DuplicateEmailException(socialProvider) + if (oauth2UserResponse.email != null) { + val presentUser = userRepository.findByEmailIgnoreCaseAndIsEmailVerifiedTrueAndActiveTrue(oauth2UserResponse.email) + if (presentUser != null && presentUser.id != user.id) { + throw DuplicateEmailException(socialProvider) + } } + when (socialProvider) { SocialProvider.FACEBOOK -> { if (user.credential.fbId != null) throw AlreadySocialAccountException From 654ec188c63e8d54688e41868fec9f54da50aecb Mon Sep 17 00:00:00 2001 From: Chanyeong Lim Date: Tue, 8 Oct 2024 11:37:52 +0900 Subject: [PATCH 3/6] =?UTF-8?q?Referrer=EB=A5=BC=20Referer=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#282)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/sugangsnu/common/api/SugangSnuLectureApi.kt | 2 +- core/src/main/kotlin/lecturebuildings/api/SnuMapApi.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/batch/src/main/kotlin/sugangsnu/common/api/SugangSnuLectureApi.kt b/batch/src/main/kotlin/sugangsnu/common/api/SugangSnuLectureApi.kt index 625b576c..c1b71635 100644 --- a/batch/src/main/kotlin/sugangsnu/common/api/SugangSnuLectureApi.kt +++ b/batch/src/main/kotlin/sugangsnu/common/api/SugangSnuLectureApi.kt @@ -30,7 +30,7 @@ class SugangSnuApiConfig() { Chrome/86.0.4240.80 Safari/537.36 """.trimIndent().replace("\n", " "), - "Referrer" to "https://sugang.snu.ac.kr/sugang/cc/cc100InterfaceExcel.action", + "Referer" to "https://sugang.snu.ac.kr/sugang/cc/cc100InterfaceExcel.action", ), ) } diff --git a/core/src/main/kotlin/lecturebuildings/api/SnuMapApi.kt b/core/src/main/kotlin/lecturebuildings/api/SnuMapApi.kt index bd88c241..9e7a81be 100644 --- a/core/src/main/kotlin/lecturebuildings/api/SnuMapApi.kt +++ b/core/src/main/kotlin/lecturebuildings/api/SnuMapApi.kt @@ -30,7 +30,7 @@ class SnuMapApiConfig() { Chrome/86.0.4240.80 Safari/537.36 """.trimIndent().replace("\n", " "), - "Referrer" to "https://map.snu.ac.kr/web/main.action", + "Referer" to "https://map.snu.ac.kr/web/main.action", ), ) } From fbcb6eee602efd5d8d7d50b9d78010ce03dbe513 Mon Sep 17 00:00:00 2001 From: SeonghaeJo <87258768+SeonghaeJo@users.noreply.github.com> Date: Wed, 9 Oct 2024 20:52:57 +0900 Subject: [PATCH 4/6] Feature/post feedback migration (#272) --- .../main/kotlin/handler/FeedbackHandler.kt | 32 ++++++++ api/src/main/kotlin/router/MainRouter.kt | 12 +++ .../main/kotlin/router/docs/FeedbackDocs.kt | 41 +++++++++++ .../kotlin/common/github/api/GithubRestApi.kt | 29 ++++++++ .../github/client/GithubRestApiClient.kt | 37 ++++++++++ .../kotlin/common/github/dto/GithubIssue.kt | 7 ++ .../main/kotlin/feedback/dto/FeedbackDto.kt | 22 ++++++ .../feedback/dto/FeedbackPostRequestDto.kt | 6 ++ .../feedback/service/FeedbackService.kt | 73 +++++++++++++++++++ .../src/main/resources/application-common.yml | 7 ++ .../testFixtures/resources/application.yaml | 7 ++ 11 files changed, 273 insertions(+) create mode 100644 api/src/main/kotlin/handler/FeedbackHandler.kt create mode 100644 api/src/main/kotlin/router/docs/FeedbackDocs.kt create mode 100644 core/src/main/kotlin/common/github/api/GithubRestApi.kt create mode 100644 core/src/main/kotlin/common/github/client/GithubRestApiClient.kt create mode 100644 core/src/main/kotlin/common/github/dto/GithubIssue.kt create mode 100644 core/src/main/kotlin/feedback/dto/FeedbackDto.kt create mode 100644 core/src/main/kotlin/feedback/dto/FeedbackPostRequestDto.kt create mode 100644 core/src/main/kotlin/feedback/service/FeedbackService.kt diff --git a/api/src/main/kotlin/handler/FeedbackHandler.kt b/api/src/main/kotlin/handler/FeedbackHandler.kt new file mode 100644 index 00000000..ba167da2 --- /dev/null +++ b/api/src/main/kotlin/handler/FeedbackHandler.kt @@ -0,0 +1,32 @@ +package com.wafflestudio.snu4t.handler + +import com.wafflestudio.snu4t.common.client.AppVersion +import com.wafflestudio.snu4t.common.dto.OkResponse +import com.wafflestudio.snu4t.feedback.dto.FeedbackPostRequestDto +import com.wafflestudio.snu4t.feedback.service.FeedbackService +import com.wafflestudio.snu4t.middleware.SnuttRestApiNoAuthMiddleware +import org.springframework.stereotype.Component +import org.springframework.web.reactive.function.server.ServerRequest +import org.springframework.web.reactive.function.server.ServerResponse +import org.springframework.web.reactive.function.server.awaitBody + +@Component +class FeedbackHandler( + private val feedbackService: FeedbackService, + snuttRestApiNoAuthMiddleware: SnuttRestApiNoAuthMiddleware, +) : ServiceHandler(snuttRestApiNoAuthMiddleware) { + suspend fun postFeedback(req: ServerRequest): ServerResponse = + handle(req) { + val body = req.awaitBody() + val clientInfo = req.clientInfo!! + feedbackService.addGithubIssue( + email = body.email, + message = body.message, + osType = clientInfo.osType, + osVersion = clientInfo.osVersion, + appVersion = clientInfo.appVersion ?: AppVersion("Unknown"), + deviceModel = clientInfo.deviceModel ?: "Unknown", + ) + OkResponse() + } +} diff --git a/api/src/main/kotlin/router/MainRouter.kt b/api/src/main/kotlin/router/MainRouter.kt index 79ab91da..30d4cf51 100644 --- a/api/src/main/kotlin/router/MainRouter.kt +++ b/api/src/main/kotlin/router/MainRouter.kt @@ -8,6 +8,7 @@ import com.wafflestudio.snu4t.handler.ConfigHandler import com.wafflestudio.snu4t.handler.CoursebookHandler import com.wafflestudio.snu4t.handler.DeviceHandler import com.wafflestudio.snu4t.handler.EvHandler +import com.wafflestudio.snu4t.handler.FeedbackHandler import com.wafflestudio.snu4t.handler.FriendHandler import com.wafflestudio.snu4t.handler.FriendTableHandler import com.wafflestudio.snu4t.handler.LectureSearchHandler @@ -27,6 +28,7 @@ import com.wafflestudio.snu4t.router.docs.BuildingsDocs import com.wafflestudio.snu4t.router.docs.ConfigDocs import com.wafflestudio.snu4t.router.docs.CoursebookDocs import com.wafflestudio.snu4t.router.docs.EvDocs +import com.wafflestudio.snu4t.router.docs.FeedbackDocs import com.wafflestudio.snu4t.router.docs.FriendDocs import com.wafflestudio.snu4t.router.docs.LectureSearchDocs import com.wafflestudio.snu4t.router.docs.NotificationDocs @@ -64,6 +66,7 @@ class MainRouter( private val evHandler: EvHandler, private val coursebookHandler: CoursebookHandler, private val tagHandler: TagHandler, + private val feedbackHandler: FeedbackHandler, private val staticPageHandler: StaticPageHandler, ) { @Bean @@ -301,6 +304,15 @@ class MainRouter( } } + @Bean + @FeedbackDocs + fun feedbackRouter() = + v1CoRouter { + "/feedback".nest { + POST("", feedbackHandler::postFeedback) + } + } + private fun v1CoRouter(r: CoRouterFunctionDsl.() -> Unit) = coRouter { path("/v1").or("").nest(r) diff --git a/api/src/main/kotlin/router/docs/FeedbackDocs.kt b/api/src/main/kotlin/router/docs/FeedbackDocs.kt new file mode 100644 index 00000000..e542ac2a --- /dev/null +++ b/api/src/main/kotlin/router/docs/FeedbackDocs.kt @@ -0,0 +1,41 @@ +package com.wafflestudio.snu4t.router.docs + +import com.wafflestudio.snu4t.common.dto.OkResponse +import com.wafflestudio.snu4t.feedback.dto.FeedbackPostRequestDto +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.media.Content +import io.swagger.v3.oas.annotations.media.Schema +import io.swagger.v3.oas.annotations.parameters.RequestBody +import io.swagger.v3.oas.annotations.responses.ApiResponse +import org.springdoc.core.annotations.RouterOperation +import org.springdoc.core.annotations.RouterOperations +import org.springframework.http.MediaType +import org.springframework.web.bind.annotation.RequestMethod + +@RouterOperations( + RouterOperation( + path = "/v1/feedback", + method = [RequestMethod.POST], + produces = [MediaType.APPLICATION_JSON_VALUE], + operation = + Operation( + operationId = "postFeedback", + requestBody = + RequestBody( + content = [ + Content( + schema = Schema(implementation = FeedbackPostRequestDto::class), + mediaType = MediaType.APPLICATION_JSON_VALUE, + ), + ], + ), + responses = [ + ApiResponse( + responseCode = "200", + content = [Content(schema = Schema(implementation = OkResponse::class))], + ), + ], + ), + ), +) +annotation class FeedbackDocs() diff --git a/core/src/main/kotlin/common/github/api/GithubRestApi.kt b/core/src/main/kotlin/common/github/api/GithubRestApi.kt new file mode 100644 index 00000000..72243c5e --- /dev/null +++ b/core/src/main/kotlin/common/github/api/GithubRestApi.kt @@ -0,0 +1,29 @@ +package com.wafflestudio.snu4t.common.github.api + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.http.HttpHeaders.ACCEPT +import org.springframework.http.HttpHeaders.USER_AGENT +import org.springframework.web.reactive.function.client.WebClient + +@Configuration +class GithubRestApiConfig { + companion object { + const val GITHUB_API_BASE_URI = "https://api.github.com" + } + + @Bean + fun githubRestApi(): GithubRestApi = + WebClient.builder().baseUrl(GITHUB_API_BASE_URI) + .defaultHeaders { + it.setAll( + mapOf( + ACCEPT to "application/vnd.github.v3+json", + USER_AGENT to "snutt-timetable", + ), + ) + } + .build().let(::GithubRestApi) +} + +class GithubRestApi(webClient: WebClient) : WebClient by webClient diff --git a/core/src/main/kotlin/common/github/client/GithubRestApiClient.kt b/core/src/main/kotlin/common/github/client/GithubRestApiClient.kt new file mode 100644 index 00000000..15cd6889 --- /dev/null +++ b/core/src/main/kotlin/common/github/client/GithubRestApiClient.kt @@ -0,0 +1,37 @@ +package com.wafflestudio.snu4t.common.github.client + +import com.wafflestudio.snu4t.common.extension.post +import com.wafflestudio.snu4t.common.github.api.GithubRestApi +import com.wafflestudio.snu4t.common.github.dto.GithubIssue +import org.springframework.http.HttpHeaders.AUTHORIZATION +import org.springframework.stereotype.Service + +interface GithubRestApiClient { + suspend fun addRepoIssue( + repoOwner: String, + repoName: String, + token: String, + issue: GithubIssue, + ) +} + +@Service +class GithubRestApiClientImpl( + private val githubRestApi: GithubRestApi, +) : GithubRestApiClient { + override suspend fun addRepoIssue( + repoOwner: String, + repoName: String, + token: String, + issue: GithubIssue, + ) { + githubRestApi.post( + uri = "/repos/$repoOwner/$repoName/issues", + body = issue, + headers = + mapOf( + AUTHORIZATION to "token $token", + ), + ) + } +} diff --git a/core/src/main/kotlin/common/github/dto/GithubIssue.kt b/core/src/main/kotlin/common/github/dto/GithubIssue.kt new file mode 100644 index 00000000..9896c023 --- /dev/null +++ b/core/src/main/kotlin/common/github/dto/GithubIssue.kt @@ -0,0 +1,7 @@ +package com.wafflestudio.snu4t.common.github.dto + +data class GithubIssue( + val title: String, + val body: String, + val labels: List = listOf(), +) diff --git a/core/src/main/kotlin/feedback/dto/FeedbackDto.kt b/core/src/main/kotlin/feedback/dto/FeedbackDto.kt new file mode 100644 index 00000000..2c28db54 --- /dev/null +++ b/core/src/main/kotlin/feedback/dto/FeedbackDto.kt @@ -0,0 +1,22 @@ +package com.wafflestudio.snu4t.feedback.dto + +data class FeedbackDto( + val email: String, + val platform: String, + val appVersion: String, + val deviceModel: String, + val currentSeoulTime: String, + val profileName: String, + val message: String, +) { + fun toGithubIssueBody() = + """ + 이메일: `$email` + 플랫폼/디바이스: $platform / $deviceModel + 버전: $appVersion + 프로필: $profileName + 날짜/시간(UTC+9): $currentSeoulTime + + $message + """.trimIndent() +} diff --git a/core/src/main/kotlin/feedback/dto/FeedbackPostRequestDto.kt b/core/src/main/kotlin/feedback/dto/FeedbackPostRequestDto.kt new file mode 100644 index 00000000..4f7d5197 --- /dev/null +++ b/core/src/main/kotlin/feedback/dto/FeedbackPostRequestDto.kt @@ -0,0 +1,6 @@ +package com.wafflestudio.snu4t.feedback.dto + +data class FeedbackPostRequestDto( + val email: String, + val message: String, +) diff --git a/core/src/main/kotlin/feedback/service/FeedbackService.kt b/core/src/main/kotlin/feedback/service/FeedbackService.kt new file mode 100644 index 00000000..8dca93de --- /dev/null +++ b/core/src/main/kotlin/feedback/service/FeedbackService.kt @@ -0,0 +1,73 @@ +package com.wafflestudio.snu4t.feedback.service + +import com.wafflestudio.snu4t.common.client.AppVersion +import com.wafflestudio.snu4t.common.client.OsType +import com.wafflestudio.snu4t.common.github.client.GithubRestApiClient +import com.wafflestudio.snu4t.common.github.dto.GithubIssue +import com.wafflestudio.snu4t.config.PhaseUtils +import com.wafflestudio.snu4t.feedback.dto.FeedbackDto +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Service +import java.time.Instant +import java.time.ZoneId +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter + +interface FeedbackService { + suspend fun addGithubIssue( + email: String, + message: String, + osType: OsType, + osVersion: String?, + appVersion: AppVersion, + deviceModel: String, + ) +} + +@Service +class FeedbackServiceImpl( + @Value("\${github.feedback.token}") private val token: String, + @Value("\${github.feedback.repo.owner}") private val repoOwner: String, + @Value("\${github.feedback.repo.name}") private val repoName: String, + private val githubRestApiClient: GithubRestApiClient, +) : FeedbackService { + override suspend fun addGithubIssue( + email: String, + message: String, + osType: OsType, + osVersion: String?, + appVersion: AppVersion, + deviceModel: String, + ) { + val osTypeString = osType.toString().lowercase() + val platform = osVersion?.let { "$osTypeString ($osVersion)" } ?: osTypeString + val currentSeoulTime = + DateTimeFormatter.ISO_LOCAL_DATE_TIME.format( + ZonedDateTime.ofInstant( + Instant.now(), + ZoneId.of("Asia/Seoul"), + ), + ) + val profileName = PhaseUtils.getPhase().name.lowercase() + githubRestApiClient.addRepoIssue( + repoOwner = repoOwner, + repoName = repoName, + token = token, + issue = + GithubIssue( + title = message, + body = + FeedbackDto( + email = email, + platform = platform, + appVersion = appVersion.toString(), + deviceModel = deviceModel, + currentSeoulTime = currentSeoulTime, + profileName = profileName, + message = message, + ).toGithubIssueBody(), + labels = listOf(osTypeString), + ), + ) + } +} diff --git a/core/src/main/resources/application-common.yml b/core/src/main/resources/application-common.yml index 2d7b6b1f..d0a64bf8 100644 --- a/core/src/main/resources/application-common.yml +++ b/core/src/main/resources/application-common.yml @@ -27,6 +27,13 @@ google: http: response-timeout: 3s +github: + feedback: + token: + repo: + owner: + name: + api: server: snuttev: diff --git a/core/src/testFixtures/resources/application.yaml b/core/src/testFixtures/resources/application.yaml index f83f9ccf..db637ca4 100644 --- a/core/src/testFixtures/resources/application.yaml +++ b/core/src/testFixtures/resources/application.yaml @@ -23,3 +23,10 @@ google: http: responseTimeout: 3s + +github: + feedback: + token: + repo: + owner: + name: From 6d78254ac716a621f5b6f9aaf5a23e0c48b29fe1 Mon Sep 17 00:00:00 2001 From: Chanyeong Lim Date: Fri, 11 Oct 2024 22:29:27 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=EC=B9=9C=EA=B5=AC=20=EB=A7=81=ED=81=AC=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=84=20?= =?UTF-8?q?=EB=95=8C=20=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#285)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/src/main/kotlin/common/exception/ErrorType.kt | 1 + core/src/main/kotlin/common/exception/Snu4tException.kt | 2 ++ core/src/main/kotlin/friend/service/FriendService.kt | 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/main/kotlin/common/exception/ErrorType.kt b/core/src/main/kotlin/common/exception/ErrorType.kt index 037f2b24..3e4d5885 100644 --- a/core/src/main/kotlin/common/exception/ErrorType.kt +++ b/core/src/main/kotlin/common/exception/ErrorType.kt @@ -64,6 +64,7 @@ enum class ErrorType( THEME_NOT_FOUND(HttpStatus.NOT_FOUND, 40406, "테마를 찾을 수 없습니다.", "테마를 찾을 수 없습니다."), EV_DATA_NOT_FOUND(HttpStatus.NOT_FOUND, 40407, "강의평 데이터를 찾을 수 없습니다.", "강의평 데이터를 찾을 수 없습니다."), TAG_LIST_NOT_FOUND(HttpStatus.NOT_FOUND, 40408, "태그 리스트를 찾을 수 없습니다.", "태그 리스트를 찾을 수 없습니다."), + FRIEND_LINK_NOT_FOUND(HttpStatus.NOT_FOUND, 40409, "친구 링크가 유효하지 않습니다.", "친구 링크가 유효하지 않습니다."), DUPLICATE_VACANCY_NOTIFICATION(HttpStatus.CONFLICT, 40900, "빈자리 알림 중복"), DUPLICATE_EMAIL(HttpStatus.CONFLICT, 40901, "이미 사용 중인 이메일입니다.", "이미 사용 중인 이메일입니다."), diff --git a/core/src/main/kotlin/common/exception/Snu4tException.kt b/core/src/main/kotlin/common/exception/Snu4tException.kt index 3d04c6c9..618f19a0 100644 --- a/core/src/main/kotlin/common/exception/Snu4tException.kt +++ b/core/src/main/kotlin/common/exception/Snu4tException.kt @@ -110,6 +110,8 @@ object ConfigNotFoundException : Snu4tException(ErrorType.CONFIG_NOT_FOUND) object FriendNotFoundException : Snu4tException(ErrorType.FRIEND_NOT_FOUND) +object FriendLinkNotFoundException : Snu4tException(ErrorType.FRIEND_LINK_NOT_FOUND) + object UserNotFoundByNicknameException : Snu4tException(ErrorType.USER_NOT_FOUND_BY_NICKNAME) object ThemeNotFoundException : Snu4tException(ErrorType.THEME_NOT_FOUND) diff --git a/core/src/main/kotlin/friend/service/FriendService.kt b/core/src/main/kotlin/friend/service/FriendService.kt index 76700c43..86cf05ee 100644 --- a/core/src/main/kotlin/friend/service/FriendService.kt +++ b/core/src/main/kotlin/friend/service/FriendService.kt @@ -1,6 +1,7 @@ package com.wafflestudio.snu4t.friend.service import com.wafflestudio.snu4t.common.exception.DuplicateFriendException +import com.wafflestudio.snu4t.common.exception.FriendLinkNotFoundException import com.wafflestudio.snu4t.common.exception.FriendNotFoundException import com.wafflestudio.snu4t.common.exception.InvalidDisplayNameException import com.wafflestudio.snu4t.common.exception.InvalidFriendException @@ -232,7 +233,7 @@ class FriendServiceImpl( ): Pair { val fromUserId = redisTemplate.opsForValue() - .getAndAwait(FRIEND_LINK_REDIS_PREFIX + requestToken) ?: throw FriendNotFoundException + .getAndAwait(FRIEND_LINK_REDIS_PREFIX + requestToken) ?: throw FriendLinkNotFoundException val fromUser = userRepository.findByIdAndActiveTrue(fromUserId) ?: throw UserNotFoundException if (fromUser.id == userId) { throw InvalidFriendException From 381077c68dadfaa077bc13cc64afb854f234dfb4 Mon Sep 17 00:00:00 2001 From: Hankyeol Choi Date: Sat, 12 Oct 2024 22:38:21 +0900 Subject: [PATCH 6/6] =?UTF-8?q?flushCache=20=EC=82=AC=EC=9A=A9=EC=B2=98=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?(#288)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/sugangsnu/job/sync/SugangSnuSyncJobConfig.kt | 1 - .../sugangsnu/job/sync/service/SugangSnuSyncService.kt | 4 ---- core/src/main/kotlin/common/cache/Cache.kt | 7 ------- 3 files changed, 12 deletions(-) diff --git a/batch/src/main/kotlin/sugangsnu/job/sync/SugangSnuSyncJobConfig.kt b/batch/src/main/kotlin/sugangsnu/job/sync/SugangSnuSyncJobConfig.kt index 29e24186..6114f32e 100644 --- a/batch/src/main/kotlin/sugangsnu/job/sync/SugangSnuSyncJobConfig.kt +++ b/batch/src/main/kotlin/sugangsnu/job/sync/SugangSnuSyncJobConfig.kt @@ -48,7 +48,6 @@ class SugangSnuSyncJobConfig { sugangSnuSyncService.addCoursebook(newCoursebook) sugangSnuNotificationService.notifyCoursebookUpdate(newCoursebook) } - sugangSnuSyncService.flushCache() } RepeatStatus.FINISHED }, diff --git a/batch/src/main/kotlin/sugangsnu/job/sync/service/SugangSnuSyncService.kt b/batch/src/main/kotlin/sugangsnu/job/sync/service/SugangSnuSyncService.kt index 1d2ab779..d635b36d 100644 --- a/batch/src/main/kotlin/sugangsnu/job/sync/service/SugangSnuSyncService.kt +++ b/batch/src/main/kotlin/sugangsnu/job/sync/service/SugangSnuSyncService.kt @@ -41,8 +41,6 @@ interface SugangSnuSyncService { suspend fun addCoursebook(coursebook: Coursebook) suspend fun isSyncWithSugangSnu(latestCoursebook: Coursebook): Boolean - - suspend fun flushCache() } @Service @@ -85,8 +83,6 @@ class SugangSnuSyncServiceImpl( return latestCoursebook.isSyncedToSugangSnu(sugangSnuLatestCoursebook) } - override suspend fun flushCache() = cache.flushDatabase() - private fun compareLectures( newLectures: Iterable, oldLectures: Iterable, diff --git a/core/src/main/kotlin/common/cache/Cache.kt b/core/src/main/kotlin/common/cache/Cache.kt index 173640b2..8ca08611 100644 --- a/core/src/main/kotlin/common/cache/Cache.kt +++ b/core/src/main/kotlin/common/cache/Cache.kt @@ -7,7 +7,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch -import kotlinx.coroutines.reactive.awaitSingle import org.slf4j.LoggerFactory import org.springframework.data.redis.core.ReactiveStringRedisTemplate import org.springframework.data.redis.core.deleteAndAwait @@ -33,8 +32,6 @@ interface Cache { suspend fun acquireLock(builtKey: BuiltCacheKey): Boolean suspend fun releaseLock(builtKey: BuiltCacheKey): Boolean - - suspend fun flushDatabase() } @Component @@ -104,10 +101,6 @@ class RedisCache( log.debug("[CACHE DEL] {}", builtKey.key) return redisTemplate.deleteAndAwait(builtKey.key) > 0 } - - override suspend fun flushDatabase() { - redisTemplate.execute { it.serverCommands().flushDb() }.awaitSingle() - } } suspend inline fun Cache.get(