-
Notifications
You must be signed in to change notification settings - Fork 1
Book 469 feature/#141 #156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1fff654
ae6b5ca
bed59ba
7aa722b
008fa55
71400d5
fc06490
ec049dc
0d5f1ea
fe703f4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,7 +7,8 @@ import org.yapp.apis.auth.exception.AuthErrorCode | |||||||||||||
| import org.yapp.apis.auth.exception.AuthException | ||||||||||||||
| import org.yapp.apis.config.GoogleOauthProperties | ||||||||||||||
| import org.yapp.infra.external.oauth.google.GoogleApi | ||||||||||||||
| import org.yapp.infra.external.oauth.google.response.GoogleUserInfo // Changed to GoogleUserInfo | ||||||||||||||
| import org.yapp.infra.external.oauth.google.response.GoogleTokenResponse | ||||||||||||||
| import org.yapp.infra.external.oauth.google.response.GoogleUserInfo | ||||||||||||||
|
|
||||||||||||||
| @Component | ||||||||||||||
| class GoogleApiManager( | ||||||||||||||
|
|
@@ -16,7 +17,57 @@ class GoogleApiManager( | |||||||||||||
| ) { | ||||||||||||||
| private val log = KotlinLogging.logger {} | ||||||||||||||
|
|
||||||||||||||
| fun getUserInfo(accessToken: String): GoogleUserInfo { // Changed to GoogleUserInfo | ||||||||||||||
| // Note: ID tokens cannot be exchanged for access tokens with Google's token endpoint. | ||||||||||||||
| // The ID token should be validated directly using GoogleIdTokenProcessor. | ||||||||||||||
| // If an access token is needed, use the authorization code flow instead. | ||||||||||||||
|
|
||||||||||||||
| fun exchangeAuthorizationCode(authorizationCode: String): GoogleTokenResponse { | ||||||||||||||
| val tokenUri = googleOauthProperties.url.tokenUri | ||||||||||||||
| ?: throw AuthException( | ||||||||||||||
| AuthErrorCode.OAUTH_SERVER_ERROR, | ||||||||||||||
| "Google token URI is not configured." | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| val redirectUri = googleOauthProperties.redirectUri | ||||||||||||||
| ?: throw AuthException( | ||||||||||||||
| AuthErrorCode.OAUTH_SERVER_ERROR, | ||||||||||||||
| "Google redirect URI is not configured." | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| val clientSecret = googleOauthProperties.clientSecret | ||||||||||||||
| ?: throw AuthException( | ||||||||||||||
| AuthErrorCode.OAUTH_SERVER_ERROR, | ||||||||||||||
| "Google client secret is not configured." | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| return googleApi.exchangeAuthorizationCode( | ||||||||||||||
| code = authorizationCode, | ||||||||||||||
| clientId = googleOauthProperties.clientId, | ||||||||||||||
| clientSecret = clientSecret, | ||||||||||||||
| redirectUri = redirectUri, | ||||||||||||||
| tokenExchangeUrl = tokenUri | ||||||||||||||
| ) | ||||||||||||||
| .onSuccess { tokenResponse -> | ||||||||||||||
| log.info { "Successfully exchanged Google authorization code for tokens" } | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+50
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π§Ή Nitpick | π΅ Trivial
β»οΈ μμ μ μ- .onSuccess { tokenResponse ->
+ .onSuccess { _ ->
log.info { "Successfully exchanged Google authorization code for tokens" }
}λλ νλΌλ―Έν°λ₯Ό μμ ν μλ΅: - .onSuccess { tokenResponse ->
+ .onSuccess {
log.info { "Successfully exchanged Google authorization code for tokens" }
}π Committable suggestion
Suggested change
π€ Prompt for AI Agents |
||||||||||||||
| .getOrElse { exception -> | ||||||||||||||
| log.error(exception) { "Failed to exchange Google authorization code" } | ||||||||||||||
|
|
||||||||||||||
| when (exception) { | ||||||||||||||
| is HttpClientErrorException -> throw AuthException( | ||||||||||||||
| AuthErrorCode.INVALID_OAUTH_TOKEN, | ||||||||||||||
| "Invalid Google Authorization Code.", | ||||||||||||||
| ) | ||||||||||||||
|
|
||||||||||||||
| else -> throw AuthException( | ||||||||||||||
| AuthErrorCode.OAUTH_SERVER_ERROR, | ||||||||||||||
| "Failed to communicate with Google server.", | ||||||||||||||
| ) | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| fun getUserInfo(accessToken: String): GoogleUserInfo { | ||||||||||||||
| return googleApi.fetchUserInfo(accessToken, googleOauthProperties.url.userInfo) | ||||||||||||||
| .onSuccess { userInfo -> | ||||||||||||||
| log.info { "Successfully fetched Google user info for userId: ${userInfo.id}" } | ||||||||||||||
|
|
@@ -42,4 +93,4 @@ class GoogleApiManager( | |||||||||||||
| googleApi.revokeGoogleToken(token) | ||||||||||||||
| .getOrThrow() | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import org.springframework.transaction.annotation.Propagation | |
| import org.springframework.transaction.annotation.Transactional | ||
| import org.yapp.apis.user.dto.request.FindOrCreateUserRequest | ||
| import org.yapp.apis.user.dto.request.SaveAppleRefreshTokenRequest | ||
| import org.yapp.apis.user.dto.request.SaveGoogleRefreshTokenRequest | ||
| import org.yapp.apis.user.dto.response.CreateUserResponse | ||
| import org.yapp.apis.user.service.UserAccountService | ||
| import org.yapp.globalutils.annotation.ApplicationService | ||
|
|
@@ -15,17 +16,32 @@ class UserSignInService( | |
| ) { | ||
| @Transactional(propagation = Propagation.REQUIRES_NEW) | ||
| fun processSignIn( | ||
| @Valid request: FindOrCreateUserRequest, appleRefreshToken: String? | ||
| @Valid request: FindOrCreateUserRequest, | ||
| appleRefreshToken: String?, | ||
| googleRefreshToken: String? | ||
| ): CreateUserResponse { | ||
| val initialUserResponse = userAccountService.findOrCreateUser(request) | ||
|
|
||
| return appleRefreshToken.takeIf { !it.isNullOrBlank() } | ||
| ?.let { token -> | ||
| userAccountService.updateAppleRefreshToken( | ||
| SaveAppleRefreshTokenRequest.of( | ||
| initialUserResponse, token | ||
| ) | ||
| var userResponse = initialUserResponse | ||
|
|
||
| // Update Apple refresh token if provided | ||
| if (!appleRefreshToken.isNullOrBlank()) { | ||
| userResponse = userAccountService.updateAppleRefreshToken( | ||
| SaveAppleRefreshTokenRequest.of( | ||
| userResponse, appleRefreshToken | ||
| ) | ||
| ) | ||
| } | ||
|
|
||
| // Update Google refresh token if provided | ||
| if (!googleRefreshToken.isNullOrBlank()) { | ||
| userResponse = userAccountService.updateGoogleRefreshToken( | ||
| SaveGoogleRefreshTokenRequest.of( | ||
| userResponse, googleRefreshToken | ||
| ) | ||
| } ?: initialUserResponse | ||
| ) | ||
| } | ||
|
Comment on lines
+25
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
νμ¬ μ΄ λμμ΄ μλλ κ²μΈμ§ νμΈνκ±°λ, λ°©μ΄μ μΌλ‘ λ λ€ μ λ¬λ κ²½μ°λ₯Ό μ°¨λ¨νλ κ²μ κ³ λ €ν΄ μ£ΌμΈμ. λ°©μ΄ μ½λ μμ fun processSignIn(
`@Valid` request: FindOrCreateUserRequest,
appleRefreshToken: String?,
googleRefreshToken: String?
): CreateUserResponse {
+ require(!(appleRefreshToken != null && googleRefreshToken != null)) {
+ "Appleκ³Ό Google refresh tokenμ΄ λμμ μ λ¬λ μ μμ΅λλ€."
+ }
val initialUserResponse = userAccountService.findOrCreateUser(request)π€ Prompt for AI Agents |
||
|
|
||
| return userResponse | ||
|
Comment on lines
18
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π§Ή Nitpick | π΅ Trivial νμ₯μ±μ κ³ λ €ν 리ν©ν λ§ μ μ: μμ νλ‘λ°μ΄λ μΆκ° μ νλΌλ―Έν° μ¦κ° λ¬Έμ νμ¬ Apple/Google λ κ° νλ‘λ°μ΄λμ λν΄ κ°κ° nullable νλΌλ―Έν°λ₯Ό μΆκ°νλ λ°©μμ λͺ
ννκ³ λμμ λ¬Έμ κ° μμ΅λλ€. λ€λ§, ν₯ν νλ‘λ°μ΄λκ° μΆκ°λ λλ§λ€ νλ‘λ°μ΄λλ³ refresh tokenμ νλμ sealed class λλ map κΈ°λ° νλΌλ―Έν°λ‘ ν΅ν©νλ©΄ νμ₯ μ μκ·Έλμ² λ³κ²½ μμ΄ λμν μ μμ΅λλ€. μμ: sealed class νμ©sealed class SocialRefreshToken {
data class Apple(val refreshToken: String) : SocialRefreshToken()
data class Google(val refreshToken: String) : SocialRefreshToken()
}
fun processSignIn(
`@Valid` request: FindOrCreateUserRequest,
socialRefreshToken: SocialRefreshToken?
): CreateUserResponse {
val initialUserResponse = userAccountService.findOrCreateUser(request)
return when (socialRefreshToken) {
is SocialRefreshToken.Apple -> userAccountService.updateAppleRefreshToken(
SaveAppleRefreshTokenRequest.of(initialUserResponse, socialRefreshToken.refreshToken)
)
is SocialRefreshToken.Google -> userAccountService.updateGoogleRefreshToken(
SaveGoogleRefreshTokenRequest.of(initialUserResponse, socialRefreshToken.refreshToken)
)
null -> initialUserResponse
}
}π€ Prompt for AI Agents |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -21,9 +21,9 @@ data class AppleAuthCredentials( | |||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| data class GoogleAuthCredentials( | ||||||||||||||||||||||||||||||
| val idToken: String, | ||||||||||||||||||||||||||||||
| val authorizationCode: String, | ||||||||||||||||||||||||||||||
| ) : SignInCredentials() { | ||||||||||||||||||||||||||||||
| override fun getProviderType(): ProviderType { | ||||||||||||||||||||||||||||||
| return ProviderType.GOOGLE | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
Comment on lines
22
to
29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π§Ή Nitpick | π΅ Trivial
β»οΈ μΌκ΄μ±μ μν μμ μ μ data class GoogleAuthCredentials(
val idToken: String,
val authorizationCode: String,
) : SignInCredentials() {
- override fun getProviderType(): ProviderType {
- return ProviderType.GOOGLE
- }
+ override fun getProviderType(): ProviderType = ProviderType.GOOGLE
}π Committable suggestion
Suggested change
π€ Prompt for AI Agents |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,13 +5,15 @@ import org.yapp.apis.auth.dto.request.* | |
| import org.yapp.apis.auth.dto.response.TokenPairResponse | ||
| import org.yapp.apis.auth.service.* | ||
| import org.yapp.apis.auth.strategy.signin.AppleAuthCredentials | ||
| import org.yapp.apis.auth.strategy.signin.GoogleAuthCredentials | ||
| import org.yapp.apis.auth.strategy.signin.SignInCredentials | ||
| import org.yapp.apis.auth.strategy.signin.SignInStrategyResolver | ||
| import org.yapp.apis.auth.strategy.withdraw.WithdrawStrategyResolver | ||
| import org.yapp.apis.user.dto.request.FindOrCreateUserRequest | ||
| import org.yapp.apis.user.dto.request.FindUserIdentityRequest | ||
| import org.yapp.apis.user.service.UserAccountService | ||
| import org.yapp.apis.user.service.UserService | ||
| import org.yapp.apis.auth.manager.GoogleApiManager | ||
| import org.yapp.globalutils.annotation.UseCase | ||
| import java.util.* | ||
|
|
||
|
|
@@ -25,7 +27,8 @@ class AuthUseCase( | |
| private val userWithdrawalService: UserWithdrawalService, | ||
| private val refreshTokenService: RefreshTokenService, | ||
| private val authTokenService: AuthTokenService, | ||
| private val appleAuthService: AppleAuthService | ||
| private val appleAuthService: AppleAuthService, | ||
| private val googleApiManager: GoogleApiManager | ||
| ) { | ||
| // μΆν Redis μ μ₯μ λΉλκΈ°λ‘ μ²λ¦¬νκ³ μ€ν¨ μ μ¬μλ λ‘μ§ λμ | ||
| fun signIn(socialLoginRequest: SocialLoginRequest): TokenPairResponse { | ||
|
|
@@ -34,10 +37,12 @@ class AuthUseCase( | |
| val userCreateInfoResponse = strategy.authenticate(credentials) | ||
|
|
||
| val appleRefreshToken = fetchAppleRefreshTokenIfNeeded(credentials) | ||
| val googleRefreshToken = fetchGoogleRefreshTokenIfNeeded(credentials) | ||
|
|
||
| val createUserResponse = userSignInService.processSignIn( | ||
| FindOrCreateUserRequest.from(userCreateInfoResponse), | ||
| appleRefreshToken | ||
| appleRefreshToken, | ||
| googleRefreshToken | ||
| ) | ||
|
|
||
| return authTokenService.generateTokenPair(GenerateTokenPairRequest.from(createUserResponse)) | ||
|
|
@@ -77,4 +82,13 @@ class AuthUseCase( | |
|
|
||
| return null | ||
| } | ||
|
|
||
| private fun fetchGoogleRefreshTokenIfNeeded(credentials: SignInCredentials): String? { | ||
| if (credentials is GoogleAuthCredentials) { | ||
| val tokenResponse = googleApiManager.exchangeAuthorizationCode(credentials.authorizationCode) | ||
| return tokenResponse.refreshToken | ||
| } | ||
|
|
||
| return null | ||
| } | ||
|
Comment on lines
+86
to
+93
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π§© Analysis chainπ Script executed: #!/bin/bash
# Search for GoogleApiManager implementation
echo "=== Searching for GoogleApiManager.kt ==="
fd "GoogleApiManager.kt" -type f
echo ""
echo "=== Searching for GoogleRestClient.kt ==="
fd "GoogleRestClient.kt" -type f
echo ""
echo "=== Searching for GoogleTokenResponse.kt ==="
fd "GoogleTokenResponse.kt" -type f
echo ""
echo "=== Searching for related API manager files ==="
fd -e ".kt" | grep -i "google.*api\|api.*manager" | head -20Repository: YAPP-Github/Reed-Server Length of output: 1050 π Web query:
π‘ Result: To receive a
Notes:
π Script executed: #!/bin/bash
echo "=== GoogleApiManager.kt ==="
cat "apis/src/main/kotlin/org/yapp/apis/auth/manager/GoogleApiManager.kt"
echo ""
echo "=== GoogleApi.kt ==="
cat "infra/src/main/kotlin/org/yapp/infra/external/oauth/google/GoogleApi.kt"
echo ""
echo "=== Searching for GoogleTokenResponse ==="
fd -e "kt" -path "*/google/*" | xargs grep -l "GoogleTokenResponse\|class.*Token.*Response" 2>/dev/null | head -10Repository: YAPP-Github/Reed-Server Length of output: 5652 π Script executed: #!/bin/bash
# Search for GoogleTokenResponse definition
echo "=== Searching for token response classes ==="
rg "data class|class.*TokenResponse" -A 5 -i --type kt | grep -i google -A 5 | head -40Repository: YAPP-Github/Reed-Server Length of output: 155 π Script executed: #!/bin/bash
echo "=== Searching for GoogleTokenResponse definition ==="
find . -name "*.kt" -path "*/google/*" -exec grep -l "GoogleTokenResponse" {} \;
echo ""
echo "=== Searching for GoogleRestClient ==="
find . -name "*.kt" | xargs grep -l "GoogleRestClient" | head -5Repository: YAPP-Github/Reed-Server Length of output: 562 π Script executed: #!/bin/bash
echo "=== Find all files in google folder ==="
find . -path "*/google/*" -name "*.kt" | head -20
echo ""
echo "=== Search for response classes in google oauth folder ==="
find . -path "*/google/*" -name "*.kt" -exec grep -H "data class\|class.*Response" {} \;Repository: YAPP-Github/Reed-Server Length of output: 824 π Script executed: #!/bin/bash
echo "=== GoogleTokenResponse.kt ==="
cat "./infra/src/main/kotlin/org/yapp/infra/external/oauth/google/response/GoogleTokenResponse.kt"
echo ""
echo "=== GoogleRestClient.kt ==="
cat "./infra/src/main/kotlin/org/yapp/infra/external/oauth/google/GoogleRestClient.kt"Repository: YAPP-Github/Reed-Server Length of output: 2745 π Script executed: #!/bin/bash
echo "=== Searching for GoogleOauthProperties ==="
find . -name "*.kt" | xargs grep -l "GoogleOauthProperties"
echo ""
echo "=== Searching for authorization request construction ==="
find . -name "*.kt" | xargs grep -B 5 -A 5 "access_type\|prompt.*consent" | head -30Repository: YAPP-Github/Reed-Server Length of output: 453 π Script executed: #!/bin/bash
echo "=== GoogleOauthProperties.kt ==="
cat "./apis/src/main/kotlin/org/yapp/apis/config/GoogleOauthProperties.kt"
echo ""
echo "=== Searching for authorization request/login flow ==="
find . -name "*.kt" | xargs grep -l "authorize\|authorization.*url\|oauth.*login" | head -10Repository: YAPP-Github/Reed-Server Length of output: 647 π Script executed: #!/bin/bash
echo "=== Search for Google OAuth authorize endpoint construction ==="
rg -i "authorize|/o/oauth" --max-count 20
echo ""
echo "=== Search for OAuth login controller ==="
find . -name "*Controller.kt" | xargs grep -l "google\|oauth" | head -5Repository: YAPP-Github/Reed-Server Length of output: 1772 π Script executed: #!/bin/bash
echo "=== Search for authentication controller ==="
find . -path "*/auth/*" -name "*Controller.kt" -o -path "*/auth/*" -name "*Endpoint.kt"
echo ""
echo "=== Search for Google authorization URL construction ==="
rg -i "google.*authorize|createAuthorizationRequestUri|getAuthorizationUri" --max-count 20
echo ""
echo "=== Check AuthController ==="
find . -name "*AuthController.kt" -o -name "*LoginController.kt"Repository: YAPP-Github/Reed-Server Length of output: 341 π Script executed: #!/bin/bash
echo "=== Look at auth usecase and controller ==="
find ./apis/src/main/kotlin/org/yapp/apis/auth -name "*.kt" | head -20
echo ""
echo "=== Search for Google OAuth login/authorize endpoint ==="
rg -B 3 -A 10 "fun.*google.*login|fun.*sign.*google" -i --max-count 15Repository: YAPP-Github/Reed-Server Length of output: 4513 π Script executed: #!/bin/bash
echo "=== GoogleSignInStrategy.kt ==="
cat "./apis/src/main/kotlin/org/yapp/apis/auth/strategy/signin/GoogleSignInStrategy.kt"
echo ""
echo "=== AuthController.kt ==="
cat "./apis/src/main/kotlin/org/yapp/apis/auth/controller/AuthController.kt"Repository: YAPP-Github/Reed-Server Length of output: 3874 π Script executed: #!/bin/bash
echo "=== Check SocialLoginRequest to understand credentials ==="
cat "./apis/src/main/kotlin/org/yapp/apis/auth/dto/request/SocialLoginRequest.kt"
echo ""
echo "=== Search for GoogleAuthCredentials ==="
find . -name "*.kt" | xargs grep -l "GoogleAuthCredentials" | head -5Repository: YAPP-Github/Reed-Server Length of output: 3400 π Script executed: #!/bin/bash
echo "=== SignInCredentials.kt and related ==="
cat "./apis/src/main/kotlin/org/yapp/apis/auth/strategy/signin/SignInCredentials.kt"
echo ""
echo "=== Full AuthUseCase.kt to understand context ==="
cat "./apis/src/main/kotlin/org/yapp/apis/auth/usecase/AuthUseCase.kt"Repository: YAPP-Github/Reed-Server Length of output: 5116 Google OAuth ν ν° κ΅ν μ μλ¬ νΈλ€λ§κ³Ό refresh_token κ°λ₯μ± κ²ν νμ νμ¬ μ½λλ
π€ Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package org.yapp.apis.user.dto.request | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema | ||
| import jakarta.validation.constraints.NotBlank | ||
| import jakarta.validation.constraints.NotNull | ||
| import org.yapp.apis.user.dto.response.CreateUserResponse | ||
| import java.util.* | ||
|
|
||
| @Schema( | ||
| name = "SaveGoogleRefreshTokenRequest", | ||
| description = "Request DTO for saving Google refresh token with user ID and authorization code" | ||
| ) | ||
|
Comment on lines
+9
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π§Ή Nitpick | π΅ Trivial λ΄λΆ μ μ© DTOμ μ΄ ν΄λμ€λ API μμ² λ°λλ‘ μ§μ λ
ΈμΆλμ§ μκ³ , π€ Prompt for AI Agents |
||
| data class SaveGoogleRefreshTokenRequest private constructor( | ||
| @field:Schema( | ||
| description = "Unique identifier of the user", | ||
| example = "a1b2c3d4-e5f6-7890-1234-56789abcdef0" | ||
| ) | ||
| @field:NotNull(message = "userId must not be null") | ||
| val userId: UUID? = null, | ||
|
|
||
| @field:Schema( | ||
| description = "Google refresh token, nullable if not issued yet", | ||
| example = "1//0g_xxxxxxxxxxxxxxxxxxxxxx" | ||
| ) | ||
| @field:NotBlank(message = "googleRefreshToken must not be blank") | ||
| val googleRefreshToken: String? = null | ||
|
Comment on lines
+21
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Line 22μ descriptionμλ "nullable if not issued yet"μ΄λΌκ³ λμ΄ μμ§λ§, Line 25μ π description μμ μ μ `@field`:Schema(
- description = "Google refresh token, nullable if not issued yet",
+ description = "Google refresh token",
example = "1//0g_xxxxxxxxxxxxxxxxxxxxxx"
)π€ Prompt for AI Agents |
||
| ) { | ||
| fun validUserId(): UUID = userId!! | ||
| fun validGoogleRefreshToken(): String = googleRefreshToken!! | ||
|
|
||
| companion object { | ||
| fun of( | ||
| userResponse: CreateUserResponse, | ||
| googleRefreshToken: String | ||
| ): SaveGoogleRefreshTokenRequest { | ||
| return SaveGoogleRefreshTokenRequest( | ||
| userId = userResponse.id, | ||
| googleRefreshToken = googleRefreshToken | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package org.yapp.infra.external.oauth.google.response | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty | ||
|
|
||
| data class GoogleTokenResponse( | ||
| @JsonProperty("access_token") | ||
| val accessToken: String, | ||
|
|
||
| @JsonProperty("refresh_token") | ||
| val refreshToken: String?, | ||
|
|
||
| @JsonProperty("expires_in") | ||
| val expiresIn: Int, | ||
|
|
||
| @JsonProperty("token_type") | ||
| val tokenType: String, | ||
|
|
||
| @JsonProperty("scope") | ||
| val scope: String?, | ||
|
|
||
| @JsonProperty("id_token") | ||
| val idToken: String? | ||
| ) |
Uh oh!
There was an error while loading. Please reload this page.