Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
0f70fbf
[BOOK-90] fix: gateway - 화이트리스트를 제외하고, 모든 경로에 인증된 사용자만 접근 가능하도록 수정
move-hoon Aug 8, 2025
36067d8
[BOOK-90] feat: global-utils - Swagger 보안을 비활성화하는 어노테이션 추가
move-hoon Aug 8, 2025
8fc6fa6
[BOOK-90] feat: apis - Swagger 보안 설정을 비활성화하는 OperationCustomizer 추가
move-hoon Aug 8, 2025
6aace86
[BOOK-90] feat: apis - 소셜 로그인 및 토큰 갱신 API에 Swagger 보안 비활성화 어노테이션 추가
move-hoon Aug 8, 2025
9f365f9
[BOOK-90] chore: apis - Book 관련 유틸 클래스 book 패키지로 이동
move-hoon Aug 9, 2025
2bfddf5
[BOOK-90] refactor: apis, global-utils - 코드레빗 리뷰 반영
move-hoon Aug 9, 2025
40c0bbf
[BOOK-90] feat: apis, global-utils - ApplicationService 커스텀 어노테이션 생성 …
move-hoon Aug 9, 2025
90716b2
[BOOK-90] chore: apis - DTO에 스키마 명세 추가
move-hoon Aug 9, 2025
cb2340b
[BOOK-90] chore: apis - 가독성을 위한 반환 방식 리팩토링
move-hoon Aug 9, 2025
76851b7
[BOOK-90] refactor: apis, domain - 애플 리프레쉬 토큰 관련 DTO 내부 로직 변경
move-hoon Aug 9, 2025
ce96fb3
[BOOK-90] fix: apis - item 내부에 있는 link를 전달하도록 수정
move-hoon Aug 9, 2025
558d48b
[BOOK-90] chore: apis - 최소 개수 명세 추가
move-hoon Aug 9, 2025
7c3977e
[BOOK-90] refactor: apis - 애플 refreshToken이 null이나 빈문자열로 올 경우 기존 init…
move-hoon Aug 9, 2025
dc46056
[BOOK-90] refactor: apis - 프로퍼티 위의 @Schema만 @field:Schema로 변경
move-hoon Aug 9, 2025
a6516db
[BOOK-90] chore: apis - categories 프로퍼티의 명세 변경
move-hoon Aug 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ import org.springframework.web.bind.annotation.RequestBody
import org.yapp.apis.auth.dto.request.SocialLoginRequest
import org.yapp.apis.auth.dto.request.TokenRefreshRequest
import org.yapp.apis.auth.dto.response.AuthResponse
import org.yapp.globalutils.annotation.DisableSwaggerSecurity
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

인터페이스에 @DisableSwaggerSecurity 부착은 의도에 부합하지만, 현 Customizer 로직으로는 미감지 위험

  • 본 파일처럼 “인터페이스 메서드”에 어노테이션을 부착하는 패턴은 좋습니다.
  • 다만 현재 SwaggerConfig.securityOperationCustomizer()handlerMethod.getMethodAnnotation(...)로만 검사하면, 구현 클래스의 메서드에 어노테이션이 없을 때(=인터페이스에만 있을 때) 감지가 누락될 수 있습니다.
  • 제안한 대로 AnnotatedElementUtils.findMergedAnnotation 기반 + 인터페이스 메서드 탐색으로 보강하면 안정적으로 동작합니다. 관련 수정 제안은 SwaggerConfig.kt 코멘트를 참고하세요.

빠른 점검:

Also applies to: 25-25, 52-52


🏁 Script executed:

#!/bin/bash
# 인터페이스에만 어노테이션이 달려있는지, 구현체에는 없는지 확인
rg -n "@DisableSwaggerSecurity" -S

Length of output: 240


다음 스크립트를 실행해 SwaggerConfig.ktsecurityOperationCustomizer 구현이 handlerMethod.getMethodAnnotation만 사용하고 있는지 확인해 주세요:


🏁 Script executed:

#!/bin/bash
# SwaggerConfig 파일 경로 찾기 및 securityOperationCustomizer 내용 확인
file=$(rg -l "class SwaggerConfig" -S)
echo "SwaggerConfig file: $file"
rg -n -A5 -B5 "securityOperationCustomizer" "$file"

Length of output: 784


securityOperationCustomizer 로직 보강 필요: 인터페이스 메서드 어노테이션 감지 누락

현재 SwaggerConfig.ktsecurityOperationCustomizer는 구현 클래스의 메서드에만 붙은 어노테이션을 handlerMethod.getMethodAnnotation(...)로 조회하기 때문에, 인터페이스에만 선언된 @DisableSwaggerSecurity를 놓칠 수 있습니다. 아래 위치를 수정해 주세요.

  • 대상 파일:
    apis/src/main/kotlin/org/yapp/apis/config/SwaggerConfig.kt
  • 메서드:
    fun securityOperationCustomizer (라인 57~63)

현 구현 예시:

val disableSwaggerSecurity: DisableSwaggerSecurity? =
    handlerMethod.getMethodAnnotation(DisableSwaggerSecurity::class.java)

제안된 수정 방법 (인터페이스 메서드까지 탐색):

import org.springframework.core.annotation.AnnotatedElementUtils

val disableSwaggerSecurity: DisableSwaggerSecurity? =
    AnnotatedElementUtils.findMergedAnnotation(
        handlerMethod.method, 
        DisableSwaggerSecurity::class.java
    ) ?: AnnotatedElementUtils.findMergedAnnotation(
        handlerMethod.beanType.getMethod(
            handlerMethod.method.name,
            *handlerMethod.method.parameterTypes
        ),
        DisableSwaggerSecurity::class.java
    )

위와 같이 변경하면 인터페이스에 선언된 @DisableSwaggerSecurity도 안정적으로 감지됩니다.

🤖 Prompt for AI Agents
In apis/src/main/kotlin/org/yapp/apis/config/SwaggerConfig.kt around lines 57 to
63, the current securityOperationCustomizer method only checks for the
@DisableSwaggerSecurity annotation on the implementation method using
handlerMethod.getMethodAnnotation, which misses annotations declared on
interface methods. To fix this, replace the annotation retrieval with
AnnotatedElementUtils.findMergedAnnotation to first check the implementation
method and if not found, check the corresponding interface method by name and
parameter types. This ensures that @DisableSwaggerSecurity annotations declared
on interface methods are also detected correctly.

import org.yapp.globalutils.exception.ErrorResponse
import java.util.*

@Tag(name = "Authentication", description = "인증 관련 API")
interface AuthControllerApi {

@DisableSwaggerSecurity
@Operation(
summary = "소셜 로그인",
description = "카카오 또는 애플 계정으로 로그인합니다. 사용자가 존재하지 않으면 자동으로 회원가입됩니다."
Expand All @@ -47,6 +49,7 @@ interface AuthControllerApi {
@PostMapping("/signin")
fun signIn(@RequestBody @Valid request: SocialLoginRequest): ResponseEntity<AuthResponse>

@DisableSwaggerSecurity
@Operation(
summary = "토큰 갱신",
description = "리프레시 토큰을 사용하여 액세스 토큰을 갱신합니다. 새로운 액세스 토큰과 리프레시 토큰을 반환합니다."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.yapp.apis.auth.dto.response.RefreshTokenResponse
)
data class DeleteTokenRequest private constructor(
@field:NotBlank(message = "Refresh token must not be blank.")
@Schema(description = "Refresh token to be deleted", example = "eyJhbGciOiJIUz...")
@field:Schema(description = "Refresh token to be deleted", example = "eyJhbGciOiJIUz...")
val refreshToken: String? = null
Comment on lines +13 to 14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

String? + @NotBlank 조합

refreshToken 을 nullable 로 두면서 @NotBlank 를 적용하면 스키마 상으로는 null 허용으로 보입니다. 일관성을 위해 non-null 로 선언하거나 validation 어노테이션을 조정해 주세요.

🤖 Prompt for AI Agents
In apis/src/main/kotlin/org/yapp/apis/auth/dto/request/DeleteTokenRequest.kt at
lines 13-14, the refreshToken property is declared as nullable String with
@NotBlank annotation, causing inconsistency between nullability and validation.
To fix this, either change the type to non-nullable String or remove/adjust the
@NotBlank annotation to align with the nullable declaration, ensuring consistent
schema and validation behavior.

) {
fun validRefreshToken() = refreshToken!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import java.util.UUID
description = "Request DTO to generate a new pair of access and refresh tokens"
)
data class GenerateTokenPairRequest private constructor(
@Schema(
@field:Schema(
description = "User ID",
example = "a1b2c3d4-e5f6-7890-1234-56789abcdef0"
)
@field:NotNull(message = "userId must not be null")
val userId: UUID? = null,

Comment on lines +15 to 21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

검증과 문서의 required 불일치

@NotNull로 서버 검증은 필수이지만, Kotlin 타입이 nullable이라 OpenAPI에선 선택(optional)로 보일 수 있습니다. 문서-런타임 불일치를 해소하세요.

다음 중 하나를 권장합니다:

  • 간단: @field:Schema(required = true) 추가
  • 근본: 타입을 nullable → non-null로 전환하고 @NotNull 제거

간단안 적용 diff 예시:

 @Schema(
   name = "GenerateTokenPairRequest",
   description = "Request DTO to generate a new pair of access and refresh tokens"
 )
 data class GenerateTokenPairRequest private constructor(
-    @field:Schema(
+    @field:Schema(
+        required = true,
         description = "User ID",
         example = "a1b2c3d4-e5f6-7890-1234-56789abcdef0"
     )
     @field:NotNull(message = "userId must not be null")
     val userId: UUID? = null,

-    @field:Schema(
+    @field:Schema(
+        required = true,
         description = "User role",
         example = "USER"
     )
     @field:NotNull(message = "role must not be null")
     val role: Role? = null
 )

Also applies to: 22-27

🤖 Prompt for AI Agents
In
apis/src/main/kotlin/org/yapp/apis/auth/dto/request/GenerateTokenPairRequest.kt
around lines 15 to 21 and similarly at lines 22 to 27, the userId field is
annotated with @NotNull but declared as a nullable UUID?, causing a mismatch
between validation and OpenAPI documentation. To fix this, either add
@field:Schema(required = true) to explicitly mark the field as required in the
schema or change the Kotlin type to non-nullable UUID and remove the @NotNull
annotation to align validation and documentation consistently.

@Schema(
@field:Schema(
description = "User role",
example = "USER"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@ import org.yapp.domain.user.ProviderType
description = "DTO for social login requests"
)
data class SocialLoginRequest private constructor(
@Schema(
@field:Schema(
description = "Type of social login provider",
example = "KAKAO",
required = true
)
@field:NotBlank(message = "Provider type is required")
val providerType: String? = null,
Comment on lines +17 to 23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

providerType 값 제약 강화(선택) — 잘못된 값 조기 차단

현재 String 수신 후 enum 변환 실패 시 예외 처리하고 있습니다. 요청 단계에서 허용 값(예: KAKAO|APPLE)만 통과하도록 정규식 검증을 추가하면 불필요한 예외 흐름을 줄일 수 있습니다.

정규식 검증 추가 예시:

 @field:Schema(
   description = "Type of social login provider",
   example = "KAKAO",
   required = true
 )
-@field:NotBlank(message = "Provider type is required")
+@field:NotBlank(message = "Provider type is required")
+@field:jakarta.validation.constraints.Pattern(
+  regexp = "KAKAO|APPLE",
+  message = "Provider type must be one of [KAKAO, APPLE]"
+)
 val providerType: String? = null,

파일 상단 import 추가:

import jakarta.validation.constraints.Pattern
🤖 Prompt for AI Agents
In apis/src/main/kotlin/org/yapp/apis/auth/dto/request/SocialLoginRequest.kt
around lines 17 to 23, the providerType field currently accepts any string and
relies on enum conversion failure to handle invalid values. To strengthen
validation and prevent invalid inputs early, add a @field:Pattern annotation
with a regex that only allows valid provider types like "KAKAO" or "APPLE".
Also, import jakarta.validation.constraints.Pattern at the top of the file. This
change will reduce unnecessary exception handling by validating input format
upfront.


@Schema(
@field:Schema(
description = "OAuth token issued by the social provider",
example = "eyJ...",
required = true
)
@field:NotBlank(message = "OAuth token is required")
val oauthToken: String? = null,
Comment on lines +25 to 31
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

토큰/코드 필드 Swagger 마스킹 및 WRITE_ONLY 권장

요청 DTO에 포함된 oauthToken, authorizationCode는 민감정보입니다. Swagger UI 입력 시 마스킹하고, 문서 상에서도 요청 전용(WRITE_ONLY)으로 표시하는 것을 권장합니다.

해당 라인 범위 내 적용 예시:

 @field:Schema(
   description = "OAuth token issued by the social provider",
   example = "eyJ...",
-  required = true
+  required = true,
+  format = "password",
+  accessMode = io.swagger.v3.oas.annotations.media.Schema.AccessMode.WRITE_ONLY
 )
 @field:NotBlank(message = "OAuth token is required")
 val oauthToken: String? = null,

 @field:Schema(
   description = "Authorization code used to issue Apple access/refresh tokens (required only for Apple login)",
   example = "c322a426...",
-  required = false
+  required = false,
+  format = "password",
+  accessMode = io.swagger.v3.oas.annotations.media.Schema.AccessMode.WRITE_ONLY
 )
 val authorizationCode: String? = null

Also applies to: 33-38

🤖 Prompt for AI Agents
In apis/src/main/kotlin/org/yapp/apis/auth/dto/request/SocialLoginRequest.kt
around lines 25 to 31 and 33 to 38, the fields oauthToken and authorizationCode
contain sensitive information and should be masked in Swagger UI and marked as
WRITE_ONLY in the schema. To fix this, add the property writeOnly = true to the
@field:Schema annotation for these fields and configure Swagger to mask the
input for these fields to protect sensitive data during API documentation and
testing.


@Schema(
@field:Schema(
description = "Authorization code used to issue Apple access/refresh tokens (required only for Apple login)",
example = "c322a426...",
required = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import java.util.*
)
data class TokenGenerateRequest private constructor(
@field:NotNull(message = "userId must not be null")
@Schema(description = "User ID", example = "f6b7d490-1b1a-4b9f-8e8e-27f8e3a5dafa")
@field:Schema(description = "User ID", example = "f6b7d490-1b1a-4b9f-8e8e-27f8e3a5dafa")
val userId: UUID? = null,

@field:NotBlank(message = "refreshToken must not be blank")
@Schema(description = "Generated refresh token", example = "eyJhbGciOiJIUzI1NiIsInR...")
@field:Schema(description = "Generated refresh token", example = "eyJhbGciOiJIUzI1NiIsInR...")
val refreshToken: String? = null,

@field:NotNull(message = "expiration must not be null")
@Schema(description = "Refresh token expiration time (in seconds)", example = "2592000")
@field:Schema(description = "Refresh token expiration time (in seconds)", example = "2592000")
val expiration: Long? = null
Comment on lines 13 to 23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Nullable 선언과 Bean Validation 제약 조건의 불일치

필드가 UUID?, String?, Long? 로 nullable 로 선언되어 있지만 @NotNull/@NotBlank 제약을 걸어 두었습니다.
Swagger UI 와 코틀린 타입 시스템이 전달하는 메시지가 달라져 혼란을 줄 수 있으니, 가능하면 타입을 non-null 로 선언하고 기본 생성자를 별도로 제공하는 방식을 고려해 주세요.

🤖 Prompt for AI Agents
In apis/src/main/kotlin/org/yapp/apis/auth/dto/request/TokenGenerateRequest.kt
around lines 13 to 23, the fields userId, refreshToken, and expiration are
declared as nullable types but have @NotNull/@NotBlank validation annotations,
causing inconsistency. Change these fields to non-nullable types by removing the
'?' and provide a separate default constructor if needed to maintain
compatibility. This aligns Kotlin's type system with the validation constraints
and avoids confusion in Swagger UI.

) {
fun validUserId() = userId!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import jakarta.validation.constraints.NotBlank
description = "DTO for requesting an access token using a refresh token"
)
data class TokenRefreshRequest private constructor(
@Schema(
@field:Schema(
description = "Valid refresh token issued during previous authentication",
example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
required = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,27 @@ import java.util.*
@Schema(description = "회원 탈퇴 처리 시 내부적으로 사용되는 요청 DTO")
data class WithdrawStrategyRequest private constructor(
@field:NotNull(message = "사용자 ID는 필수 값입니다.")
@Schema(
@field:Schema(
description = "사용자 고유 ID",
example = "123e4567-e89b-12d3-a456-426614174000"
)
val userId: UUID,

@field:NotNull(message = "소셜 로그인 제공자 타입은 필수 값입니다.")
@Schema(
@field:Schema(
description = "소셜 로그인 제공자 타입",
example = "KAKAO"
)
val providerType: ProviderType,

@field:NotBlank(message = "소셜 로그인 제공자로부터 발급받은 고유 ID는 필수 값입니다.")
@Schema(
@field:Schema(
description = "소셜 로그인 제공자로부터 발급받은 고유 ID",
example = "21412412412"
)
val providerId: String,

@Schema(
@field:Schema(
description = "Apple 로그인 시 발급받은 리프레시 토큰 (Apple 로그인 회원 탈퇴 시에만 필요)",
example = "r_abc123def456ghi789jkl0mnopqrstu",
required = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import io.swagger.v3.oas.annotations.media.Schema
)
data class AuthResponse private constructor(

@Schema(
@field:Schema(
description = "Access token for authorization",
example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
)
val accessToken: String,

@Schema(
@field:Schema(
description = "Refresh token used to obtain a new access token",
example = "dGhpc2lzYXJlZnJlc2h0b2tlbg=="
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.yapp.domain.token.RefreshToken.Token
description = "Response DTO containing the issued refresh token"
)
data class RefreshTokenResponse(
@Schema(description = "The refresh token string", example = "eyJhbGciOiJIUz...")
@field:Schema(description = "The refresh token string", example = "eyJhbGciOiJIUz...")
val refreshToken: String
) {
companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import io.swagger.v3.oas.annotations.media.Schema
)
data class TokenPairResponse private constructor(

@Schema(
@field:Schema(
description = "Access token for user authorization",
example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
)
val accessToken: String,

@Schema(
@field:Schema(
description = "Refresh token to get new access token",
example = "dGhpc2lzYXJlZnJlc2h0b2tlbg=="
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,32 @@ import org.yapp.domain.user.ProviderType
description = "Response DTO containing user information for newly registered users via social login"
)
data class UserCreateInfoResponse private constructor(
@Schema(
@field:Schema(
description = "사용자 이메일",
example = "[email protected]",
nullable = true
)
val email: String?,

@Schema(
@field:Schema(
description = "사용자 닉네임",
example = "코딩하는곰", nullable = true
)
val nickname: String?,

@Schema(
@field:Schema(
description = "사용자 프로필 이미지 URL",
example = "https://example.com/image.jpg", nullable = true
)
val profileImageUrl: String? = null,

@Schema(
@field:Schema(
description = "소셜 로그인 제공자",
example = "KAKAO")

val providerType: ProviderType,

@Schema(
@field:Schema(
description = "소셜 제공자에서 발급한 식별자",
example = "12345678901234567890"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import java.util.*
description = "Response DTO that contains the user ID extracted from a refresh token"
)
data class UserIdResponse(
@Schema(description = "User ID", example = "a1b2c3d4-e5f6-7890-1234-56789abcdef0")
@field:Schema(description = "User ID", example = "a1b2c3d4-e5f6-7890-1234-56789abcdef0")
val userId: UUID
) {
companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package org.yapp.apis.auth.service

import org.springframework.stereotype.Service
import org.springframework.validation.annotation.Validated
import org.yapp.apis.auth.exception.AuthErrorCode
import org.yapp.apis.auth.exception.AuthException
import org.yapp.apis.auth.manager.AppleApiManager
import org.yapp.globalutils.annotation.ApplicationService
import org.yapp.infra.external.oauth.apple.response.AppleTokenResponse

@Service
@Validated
@ApplicationService
class AppleAuthService(
private val appleApiManager: AppleApiManager,
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package org.yapp.apis.auth.service

import jakarta.validation.Valid
import org.springframework.stereotype.Service
import org.springframework.validation.annotation.Validated
import org.yapp.apis.auth.dto.request.DeleteTokenRequest
import org.yapp.apis.auth.dto.request.GenerateTokenPairRequest
import org.yapp.apis.auth.dto.request.TokenGenerateRequest
import org.yapp.apis.auth.dto.request.TokenRefreshRequest
import org.yapp.apis.auth.dto.response.TokenPairResponse
import org.yapp.apis.auth.dto.response.UserIdResponse
import org.yapp.gateway.jwt.JwtTokenService
import org.yapp.globalutils.annotation.ApplicationService

@Service
@Validated
@ApplicationService
class AuthTokenService(
private val refreshTokenService: RefreshTokenService,
private val jwtTokenService: JwtTokenService
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package org.yapp.apis.auth.service

import jakarta.validation.Valid
import org.springframework.stereotype.Service
import org.springframework.validation.annotation.Validated
import org.yapp.apis.auth.dto.request.TokenGenerateRequest
import org.yapp.apis.auth.dto.request.TokenRefreshRequest
import org.yapp.apis.auth.dto.response.RefreshTokenResponse
import org.yapp.apis.auth.dto.response.UserIdResponse
import org.yapp.domain.token.RefreshTokenDomainService
import org.yapp.globalutils.annotation.ApplicationService
import java.util.*

@Service
@Validated
@ApplicationService
class RefreshTokenService(
private val refreshTokenDomainService: RefreshTokenDomainService,
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
package org.yapp.apis.auth.service

import jakarta.validation.Valid
import org.springframework.stereotype.Service
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.response.CreateUserResponse
import org.yapp.apis.user.service.UserAccountService
import org.yapp.globalutils.annotation.ApplicationService

@Service
@ApplicationService
class UserSignInService(
private val userAccountService: UserAccountService,
) {
@Transactional(propagation = Propagation.REQUIRES_NEW)
fun processSignIn(
@Valid request: FindOrCreateUserRequest,
appleRefreshToken: String?
@Valid request: FindOrCreateUserRequest, appleRefreshToken: String?
): CreateUserResponse {
val createUserResponse = userAccountService.findOrCreateUser(request)
val initialUserResponse = userAccountService.findOrCreateUser(request)

appleRefreshToken?.let {
userAccountService.updateAppleRefreshToken(createUserResponse.id, it)
}

return createUserResponse
return appleRefreshToken.takeIf { !it.isNullOrBlank() }
?.let { token ->
userAccountService.updateAppleRefreshToken(
SaveAppleRefreshTokenRequest.of(
initialUserResponse, token
)
)
} ?: initialUserResponse
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package org.yapp.apis.auth.service

import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional
import org.yapp.apis.user.service.UserAccountService
import org.yapp.globalutils.annotation.ApplicationService
import java.util.*

@Service
@ApplicationService
class UserWithdrawalService(
private val userAccountService: UserAccountService,
private val refreshTokenService: RefreshTokenService
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package org.yapp.apis.auth.strategy.signin

import org.springframework.stereotype.Service
import org.springframework.stereotype.Component
import org.yapp.apis.auth.exception.AuthErrorCode
import org.yapp.apis.auth.exception.AuthException

@Service
@Component
class SignInStrategyResolver(
private val strategies: List<SignInStrategy>
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ class AuthUseCase(

private fun fetchAppleRefreshTokenIfNeeded(credentials: SignInCredentials): String? {
if (credentials is AppleAuthCredentials) {
return appleAuthService.fetchAppleOauthTokens(credentials.authorizationCode).refreshToken
val tokenResponse = appleAuthService.fetchAppleOauthTokens(credentials.authorizationCode)
return tokenResponse.refreshToken
}

return null
}
}
Loading