Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -8,4 +8,9 @@ data class TokenResponse(

@SerializedName("refreshToken")
val refreshToken: String,
)

fun TokenResponse.toDomain() = com.eatssu.android.domain.model.Token(
accessToken = accessToken,
refreshToken = refreshToken,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,22 @@ package com.eatssu.android.data.repository

import com.eatssu.android.data.dto.request.CheckValidTokenRequest
import com.eatssu.android.data.dto.request.LoginWithKakaoRequest
import com.eatssu.android.data.dto.response.BaseResponse
import com.eatssu.android.data.dto.response.TokenResponse
import com.eatssu.android.data.dto.response.toDomain
import com.eatssu.android.data.service.OauthService
import com.eatssu.android.domain.model.Token
import com.eatssu.android.domain.repository.OauthRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import javax.inject.Inject

class OauthRepositoryImpl @Inject constructor(private val oauthService: OauthService) :
OauthRepository {
override suspend fun reissueToken(refreshToken: String): Flow<BaseResponse<TokenResponse>> =
flow {
emit(oauthService.getNewToken(refreshToken))
}
override suspend fun reissueToken(refreshToken: String): Token =
oauthService.getNewToken(refreshToken).result?.toDomain()
?: throw IllegalStateException("Failed to get a new token.")

override suspend fun login(body: LoginWithKakaoRequest): Token =
oauthService.loginWithKakao(body).result?.toDomain()
?: throw IllegalStateException("Failed to login.")

override suspend fun login(body: LoginWithKakaoRequest): Flow<BaseResponse<TokenResponse>> =
flow {
emit(oauthService.loginWithKakao(body))
}

override suspend fun checkValidToken(body: CheckValidTokenRequest): Flow<BaseResponse<Boolean>> =
flow {
emit(oauthService.checkValidToken(body))
}
override suspend fun checkValidToken(body: CheckValidTokenRequest): Boolean =
oauthService.checkValidToken(body).result ?: false
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package com.eatssu.android.di.network

import com.eatssu.android.data.dto.response.BaseResponse
import com.eatssu.android.data.dto.response.TokenResponse
import com.eatssu.android.domain.model.Token
import com.eatssu.android.domain.model.TokenStateManager
import com.eatssu.android.domain.usecase.auth.GetRefreshTokenUseCase
import com.eatssu.android.domain.usecase.auth.LogoutUseCase
import com.eatssu.android.domain.usecase.auth.ReissueTokenUseCase
import com.eatssu.android.domain.usecase.auth.SetAccessTokenUseCase
import com.eatssu.android.domain.usecase.auth.SetRefreshTokenUseCase
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.runBlocking
import okhttp3.Authenticator
import okhttp3.Request
Expand Down Expand Up @@ -49,11 +47,11 @@ class TokenAuthenticator @Inject constructor(
try {
Timber.d("TokenAuthenticator → refreshToken으로 재발급 시도")

val newTokenResponse: BaseResponse<TokenResponse>? = reissueTokenUseCase(expiredRefreshToken).firstOrNull()
val newAccessToken = newTokenResponse?.result?.accessToken
val newRefreshToken = newTokenResponse?.result?.refreshToken
val newToken: Token = reissueTokenUseCase(expiredRefreshToken)
val newAccessToken = newToken.accessToken
val newRefreshToken = newToken.refreshToken

if (newAccessToken != null && newRefreshToken != null) {
if (newAccessToken.isNotEmpty() && newRefreshToken.isNotEmpty()) {
Timber.d("TokenAuthenticator → 새 토큰 발급 성공")
setAccessTokenUseCase(newAccessToken)
setRefreshTokenUseCase(newRefreshToken)
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/com/eatssu/android/domain/model/Token.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.eatssu.android.domain.model

data class Token(
val accessToken: String,
val refreshToken: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@ package com.eatssu.android.domain.repository

import com.eatssu.android.data.dto.request.CheckValidTokenRequest
import com.eatssu.android.data.dto.request.LoginWithKakaoRequest
import com.eatssu.android.data.dto.response.BaseResponse
import com.eatssu.android.data.dto.response.TokenResponse
import kotlinx.coroutines.flow.Flow
import com.eatssu.android.domain.model.Token

interface OauthRepository {
suspend fun reissueToken(
refreshToken: String,
): Flow<BaseResponse<TokenResponse>>
): Token

suspend fun login(body: LoginWithKakaoRequest): Flow<BaseResponse<TokenResponse>>
suspend fun login(body: LoginWithKakaoRequest): Token

suspend fun checkValidToken(body: CheckValidTokenRequest): Flow<BaseResponse<Boolean>>
suspend fun checkValidToken(body: CheckValidTokenRequest): Boolean
}

Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package com.eatssu.android.domain.usecase.auth

import com.eatssu.android.data.dto.request.CheckValidTokenRequest
import com.eatssu.android.data.dto.response.BaseResponse
import com.eatssu.android.domain.repository.OauthRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class GetIsAccessTokenValidUseCase @Inject constructor(
private val oauthRepository: OauthRepository
) {
suspend operator fun invoke(userAccessToken: String): Flow<BaseResponse<Boolean>> =
suspend operator fun invoke(userAccessToken: String): Boolean =
oauthRepository.checkValidToken(CheckValidTokenRequest(userAccessToken))
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package com.eatssu.android.domain.usecase.auth

import com.eatssu.android.data.dto.request.LoginWithKakaoRequest
import com.eatssu.android.data.dto.response.BaseResponse
import com.eatssu.android.data.dto.response.TokenResponse
import com.eatssu.android.domain.model.Token
import com.eatssu.android.domain.repository.OauthRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class LoginUseCase @Inject constructor(
private val oauthRepository: OauthRepository,
) {
suspend operator fun invoke(body: LoginWithKakaoRequest): Flow<BaseResponse<TokenResponse>> =
suspend operator fun invoke(body: LoginWithKakaoRequest): Token =
oauthRepository.login(body)
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package com.eatssu.android.domain.usecase.auth

import com.eatssu.android.data.dto.response.BaseResponse
import com.eatssu.android.data.dto.response.TokenResponse
import com.eatssu.android.domain.model.Token
import com.eatssu.android.domain.repository.OauthRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class ReissueTokenUseCase @Inject constructor(
private val oauthRepository: OauthRepository,
) {
suspend operator fun invoke(refreshToken: String): Flow<BaseResponse<TokenResponse>> =
suspend operator fun invoke(refreshToken: String): Token =
oauthRepository.reissueToken(refreshToken)
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,12 @@ class IntroViewModel @Inject constructor(

private fun checkValid(userAccessToken: String) {
viewModelScope.launch {
getIsAccessTokenValidUseCase(userAccessToken)
.collect {
if (it.result == true) { //토큰이 있고 유효함
_uiState.value = UiState.Success(IntroState.ValidToken)
} else { //토큰이 있어도 유효하지 않음
_uiState.value = UiState.Error
_uiEvent.emit(UiEvent.ShowToast("로그인이 필요합니다"))
}
}
if (getIsAccessTokenValidUseCase(userAccessToken)) { //토큰이 있고 유효함
_uiState.value = UiState.Success(IntroState.ValidToken)
} else { //토큰이 있어도 유효하지 않음
_uiState.value = UiState.Error
_uiEvent.emit(UiEvent.ShowToast("로그인이 필요합니다"))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import com.eatssu.android.presentation.UiEvent
import com.eatssu.android.presentation.UiState
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject


Expand All @@ -42,25 +42,24 @@ class LoginViewModel @Inject constructor(

fun getKakaoLogin(email: String, providerID: String) {
viewModelScope.launch {
loginUseCase(LoginWithKakaoRequest(email, providerID))
.onStart {
_uiState.value = UiState.Loading
_uiState.value = UiState.Loading
runCatching {
withContext(Dispatchers.IO) {
loginUseCase(LoginWithKakaoRequest(email, providerID))
}
.catch { e ->
_uiState.value = UiState.Error
_uiEvent.emit(UiEvent.ShowToast(context.getString(R.string.login_failed)))
}
.collect { result ->
result.result?.let {
setAccessTokenUseCase(it.accessToken)
setRefreshTokenUseCase(it.refreshToken)
setUserEmailUseCase(email)
}.onSuccess {
setAccessTokenUseCase(it.accessToken)
setRefreshTokenUseCase(it.refreshToken)
setUserEmailUseCase(email)

_uiState.value = UiState.Success(LoginState.LoginSuccess)
_uiState.value = UiState.Success(LoginState.LoginSuccess)

TokenStateManager.setTokenValid()
}
}
TokenStateManager.setTokenValid()

}.onFailure {
_uiState.value = UiState.Error
_uiEvent.emit(UiEvent.ShowToast(context.getString(R.string.login_failed)))
}
}
}

Expand Down