diff --git a/app/src/main/java/com/eatssu/android/data/dto/response/TokenResponse.kt b/app/src/main/java/com/eatssu/android/data/dto/response/TokenResponse.kt index ae2cd78b7..11f689dc7 100644 --- a/app/src/main/java/com/eatssu/android/data/dto/response/TokenResponse.kt +++ b/app/src/main/java/com/eatssu/android/data/dto/response/TokenResponse.kt @@ -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, ) \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/data/repository/OauthRepositoryImpl.kt b/app/src/main/java/com/eatssu/android/data/repository/OauthRepositoryImpl.kt index 285096b1b..e41581aa8 100644 --- a/app/src/main/java/com/eatssu/android/data/repository/OauthRepositoryImpl.kt +++ b/app/src/main/java/com/eatssu/android/data/repository/OauthRepositoryImpl.kt @@ -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> = - 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> = - flow { - emit(oauthService.loginWithKakao(body)) - } - - override suspend fun checkValidToken(body: CheckValidTokenRequest): Flow> = - flow { - emit(oauthService.checkValidToken(body)) - } + override suspend fun checkValidToken(body: CheckValidTokenRequest): Boolean = + oauthService.checkValidToken(body).result ?: false } diff --git a/app/src/main/java/com/eatssu/android/di/network/TokenAuthenticator.kt b/app/src/main/java/com/eatssu/android/di/network/TokenAuthenticator.kt index 38d7db194..a1247df8f 100644 --- a/app/src/main/java/com/eatssu/android/di/network/TokenAuthenticator.kt +++ b/app/src/main/java/com/eatssu/android/di/network/TokenAuthenticator.kt @@ -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 @@ -49,11 +47,11 @@ class TokenAuthenticator @Inject constructor( try { Timber.d("TokenAuthenticator → refreshToken으로 재발급 시도") - val newTokenResponse: BaseResponse? = 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) diff --git a/app/src/main/java/com/eatssu/android/domain/model/Token.kt b/app/src/main/java/com/eatssu/android/domain/model/Token.kt new file mode 100644 index 000000000..dace0bdf3 --- /dev/null +++ b/app/src/main/java/com/eatssu/android/domain/model/Token.kt @@ -0,0 +1,6 @@ +package com.eatssu.android.domain.model + +data class Token( + val accessToken: String, + val refreshToken: String, +) \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/domain/repository/OauthRepository.kt b/app/src/main/java/com/eatssu/android/domain/repository/OauthRepository.kt index d3840908e..ae5766c1d 100644 --- a/app/src/main/java/com/eatssu/android/domain/repository/OauthRepository.kt +++ b/app/src/main/java/com/eatssu/android/domain/repository/OauthRepository.kt @@ -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> + ): Token - suspend fun login(body: LoginWithKakaoRequest): Flow> + suspend fun login(body: LoginWithKakaoRequest): Token - suspend fun checkValidToken(body: CheckValidTokenRequest): Flow> + suspend fun checkValidToken(body: CheckValidTokenRequest): Boolean } diff --git a/app/src/main/java/com/eatssu/android/domain/usecase/auth/GetIsAccessTokenValidUseCase.kt b/app/src/main/java/com/eatssu/android/domain/usecase/auth/GetIsAccessTokenValidUseCase.kt index 29ac52347..6d4a8023e 100644 --- a/app/src/main/java/com/eatssu/android/domain/usecase/auth/GetIsAccessTokenValidUseCase.kt +++ b/app/src/main/java/com/eatssu/android/domain/usecase/auth/GetIsAccessTokenValidUseCase.kt @@ -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> = + suspend operator fun invoke(userAccessToken: String): Boolean = oauthRepository.checkValidToken(CheckValidTokenRequest(userAccessToken)) } \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/domain/usecase/auth/LoginUseCase.kt b/app/src/main/java/com/eatssu/android/domain/usecase/auth/LoginUseCase.kt index e4979ae91..37854e01d 100644 --- a/app/src/main/java/com/eatssu/android/domain/usecase/auth/LoginUseCase.kt +++ b/app/src/main/java/com/eatssu/android/domain/usecase/auth/LoginUseCase.kt @@ -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> = + suspend operator fun invoke(body: LoginWithKakaoRequest): Token = oauthRepository.login(body) } \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/domain/usecase/auth/ReissueTokenUseCase.kt b/app/src/main/java/com/eatssu/android/domain/usecase/auth/ReissueTokenUseCase.kt index e2a4bc35b..2144cadc8 100644 --- a/app/src/main/java/com/eatssu/android/domain/usecase/auth/ReissueTokenUseCase.kt +++ b/app/src/main/java/com/eatssu/android/domain/usecase/auth/ReissueTokenUseCase.kt @@ -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> = + suspend operator fun invoke(refreshToken: String): Token = oauthRepository.reissueToken(refreshToken) } \ No newline at end of file diff --git a/app/src/main/java/com/eatssu/android/presentation/intro/IntroViewModel.kt b/app/src/main/java/com/eatssu/android/presentation/intro/IntroViewModel.kt index 86d9c80a8..f23d63b2b 100644 --- a/app/src/main/java/com/eatssu/android/presentation/intro/IntroViewModel.kt +++ b/app/src/main/java/com/eatssu/android/presentation/intro/IntroViewModel.kt @@ -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("로그인이 필요합니다")) + } } } } diff --git a/app/src/main/java/com/eatssu/android/presentation/login/LoginViewModel.kt b/app/src/main/java/com/eatssu/android/presentation/login/LoginViewModel.kt index 39bac78da..d0753c817 100644 --- a/app/src/main/java/com/eatssu/android/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/com/eatssu/android/presentation/login/LoginViewModel.kt @@ -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 @@ -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))) + } } }