From 7e0e6e06012d095bc24f5b8a98144f3080109f05 Mon Sep 17 00:00:00 2001 From: soopeach Date: Sun, 10 Sep 2023 11:43:59 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[feat/auto=5Flogin]:=20TokenManager=20->=20?= =?UTF-8?q?TokenRepository=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/src/main/java/org/gdsc/data/di/NetworkModule.kt | 6 +++--- data/src/main/java/org/gdsc/data/di/TokenModule.kt | 8 ++++---- data/src/main/java/org/gdsc/data/network/Interceptors.kt | 6 +++--- .../TokenRepositoryImpl.kt} | 8 ++++---- .../repository/{TokenManager.kt => TokenRepository.kt} | 2 +- .../gdsc/domain/usecase/token/ClearTokenInfoUseCase.kt | 6 +++--- .../usecase/token/GetAccessTokenExpiresInUseCase.kt | 6 +++--- .../gdsc/domain/usecase/token/GetAccessTokenUseCase.kt | 6 +++--- .../org/gdsc/domain/usecase/token/GetGrantTypeUseCase.kt | 6 +++--- .../gdsc/domain/usecase/token/GetRefreshTokenUseCase.kt | 6 +++--- .../org/gdsc/domain/usecase/token/SaveTokenUseCase.kt | 6 +++--- 11 files changed, 33 insertions(+), 33 deletions(-) rename data/src/main/java/org/gdsc/data/{datasource/TokenManagerImpl.kt => repository/TokenRepositoryImpl.kt} (93%) rename domain/src/main/java/org/gdsc/domain/repository/{TokenManager.kt => TokenRepository.kt} (92%) diff --git a/data/src/main/java/org/gdsc/data/di/NetworkModule.kt b/data/src/main/java/org/gdsc/data/di/NetworkModule.kt index ca32e0ee..e30dbd9f 100644 --- a/data/src/main/java/org/gdsc/data/di/NetworkModule.kt +++ b/data/src/main/java/org/gdsc/data/di/NetworkModule.kt @@ -7,7 +7,7 @@ import dagger.hilt.components.SingletonComponent import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import org.gdsc.data.network.AuthInterceptor -import org.gdsc.domain.repository.TokenManager +import org.gdsc.domain.repository.TokenRepository import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import javax.inject.Singleton @@ -33,7 +33,7 @@ class NetworkModule { @AuthClient @Provides @Singleton - fun provideAuthorizedApiClient(tokenManager: TokenManager): Retrofit { + fun provideAuthorizedApiClient(tokenRepository: TokenRepository): Retrofit { return Retrofit .Builder() @@ -41,7 +41,7 @@ class NetworkModule { .addConverterFactory(GsonConverterFactory.create()) .client( baseClientBuilder - .addInterceptor(AuthInterceptor(tokenManager)) + .addInterceptor(AuthInterceptor(tokenRepository)) .build() ) .build() diff --git a/data/src/main/java/org/gdsc/data/di/TokenModule.kt b/data/src/main/java/org/gdsc/data/di/TokenModule.kt index 55dfe077..e63576f8 100644 --- a/data/src/main/java/org/gdsc/data/di/TokenModule.kt +++ b/data/src/main/java/org/gdsc/data/di/TokenModule.kt @@ -9,8 +9,8 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import org.gdsc.data.datasource.TokenManagerImpl -import org.gdsc.domain.repository.TokenManager +import org.gdsc.data.repository.TokenRepositoryImpl +import org.gdsc.domain.repository.TokenRepository import javax.inject.Singleton @Module @@ -23,8 +23,8 @@ class TokenModule { @Provides @Singleton - fun provideTokenManager(@ApplicationContext context: Context): TokenManager { - return TokenManagerImpl(context.dataStore) + fun provideTokenManager(@ApplicationContext context: Context): TokenRepository { + return TokenRepositoryImpl(context.dataStore) } } \ No newline at end of file diff --git a/data/src/main/java/org/gdsc/data/network/Interceptors.kt b/data/src/main/java/org/gdsc/data/network/Interceptors.kt index 1c26b6cf..d0c45d2f 100644 --- a/data/src/main/java/org/gdsc/data/network/Interceptors.kt +++ b/data/src/main/java/org/gdsc/data/network/Interceptors.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.CancellationException import kotlinx.coroutines.runBlocking import okhttp3.Interceptor import okhttp3.Response -import org.gdsc.domain.repository.TokenManager +import org.gdsc.domain.repository.TokenRepository import java.io.IOException import javax.inject.Inject @@ -24,11 +24,11 @@ interface CoroutineInterceptor : Interceptor { } class AuthInterceptor @Inject constructor( - private val tokenManager: TokenManager + private val tokenRepository: TokenRepository ) : CoroutineInterceptor { override suspend fun interceptSuspend(chain: Interceptor.Chain): Response { - val token = "Bearer ${tokenManager.getAccessToken()}" + val token = "Bearer ${tokenRepository.getAccessToken()}" val newRequest = chain.request().newBuilder() .addHeader("Authorization", token) .build() diff --git a/data/src/main/java/org/gdsc/data/datasource/TokenManagerImpl.kt b/data/src/main/java/org/gdsc/data/repository/TokenRepositoryImpl.kt similarity index 93% rename from data/src/main/java/org/gdsc/data/datasource/TokenManagerImpl.kt rename to data/src/main/java/org/gdsc/data/repository/TokenRepositoryImpl.kt index c97b8aa5..42d74af9 100644 --- a/data/src/main/java/org/gdsc/data/datasource/TokenManagerImpl.kt +++ b/data/src/main/java/org/gdsc/data/repository/TokenRepositoryImpl.kt @@ -1,4 +1,4 @@ -package org.gdsc.data.datasource +package org.gdsc.data.repository import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences @@ -9,12 +9,12 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import org.gdsc.domain.Empty import org.gdsc.domain.model.response.TokenResponse -import org.gdsc.domain.repository.TokenManager +import org.gdsc.domain.repository.TokenRepository import javax.inject.Inject -class TokenManagerImpl @Inject constructor( +class TokenRepositoryImpl @Inject constructor( private val dataStore: DataStore -): TokenManager { +): TokenRepository { override suspend fun saveTokenInfo(tokenResponse: TokenResponse) { diff --git a/domain/src/main/java/org/gdsc/domain/repository/TokenManager.kt b/domain/src/main/java/org/gdsc/domain/repository/TokenRepository.kt similarity index 92% rename from domain/src/main/java/org/gdsc/domain/repository/TokenManager.kt rename to domain/src/main/java/org/gdsc/domain/repository/TokenRepository.kt index cc9380f0..77315c16 100644 --- a/domain/src/main/java/org/gdsc/domain/repository/TokenManager.kt +++ b/domain/src/main/java/org/gdsc/domain/repository/TokenRepository.kt @@ -2,7 +2,7 @@ package org.gdsc.domain.repository import org.gdsc.domain.model.response.TokenResponse -interface TokenManager { +interface TokenRepository { suspend fun saveTokenInfo(tokenResponse: TokenResponse) diff --git a/domain/src/main/java/org/gdsc/domain/usecase/token/ClearTokenInfoUseCase.kt b/domain/src/main/java/org/gdsc/domain/usecase/token/ClearTokenInfoUseCase.kt index 0678c8f2..b00279f3 100644 --- a/domain/src/main/java/org/gdsc/domain/usecase/token/ClearTokenInfoUseCase.kt +++ b/domain/src/main/java/org/gdsc/domain/usecase/token/ClearTokenInfoUseCase.kt @@ -1,12 +1,12 @@ package org.gdsc.domain.usecase.token -import org.gdsc.domain.repository.TokenManager +import org.gdsc.domain.repository.TokenRepository import javax.inject.Inject class ClearTokenInfoUseCase @Inject constructor( - private val tokenManager: TokenManager + private val tokenRepository: TokenRepository ) { suspend operator fun invoke() { - tokenManager.clearTokenInfo() + tokenRepository.clearTokenInfo() } } \ No newline at end of file diff --git a/domain/src/main/java/org/gdsc/domain/usecase/token/GetAccessTokenExpiresInUseCase.kt b/domain/src/main/java/org/gdsc/domain/usecase/token/GetAccessTokenExpiresInUseCase.kt index 0c11bd6f..6fb18235 100644 --- a/domain/src/main/java/org/gdsc/domain/usecase/token/GetAccessTokenExpiresInUseCase.kt +++ b/domain/src/main/java/org/gdsc/domain/usecase/token/GetAccessTokenExpiresInUseCase.kt @@ -1,13 +1,13 @@ package org.gdsc.domain.usecase.token -import org.gdsc.domain.repository.TokenManager +import org.gdsc.domain.repository.TokenRepository import javax.inject.Inject class GetAccessTokenExpiresInUseCase @Inject constructor( - private val tokenManager: TokenManager + private val tokenRepository: TokenRepository ) { suspend operator fun invoke(): Long { - return tokenManager.getAccessTokenExpiresIn() + return tokenRepository.getAccessTokenExpiresIn() } } \ No newline at end of file diff --git a/domain/src/main/java/org/gdsc/domain/usecase/token/GetAccessTokenUseCase.kt b/domain/src/main/java/org/gdsc/domain/usecase/token/GetAccessTokenUseCase.kt index 993c1818..e70925ae 100644 --- a/domain/src/main/java/org/gdsc/domain/usecase/token/GetAccessTokenUseCase.kt +++ b/domain/src/main/java/org/gdsc/domain/usecase/token/GetAccessTokenUseCase.kt @@ -1,13 +1,13 @@ package org.gdsc.domain.usecase.token -import org.gdsc.domain.repository.TokenManager +import org.gdsc.domain.repository.TokenRepository import javax.inject.Inject class GetAccessTokenUseCase @Inject constructor( - private val tokenManager: TokenManager + private val tokenRepository: TokenRepository ) { suspend operator fun invoke(): String { - return tokenManager.getAccessToken() + return tokenRepository.getAccessToken() } } \ No newline at end of file diff --git a/domain/src/main/java/org/gdsc/domain/usecase/token/GetGrantTypeUseCase.kt b/domain/src/main/java/org/gdsc/domain/usecase/token/GetGrantTypeUseCase.kt index 6075ab18..d0c683b0 100644 --- a/domain/src/main/java/org/gdsc/domain/usecase/token/GetGrantTypeUseCase.kt +++ b/domain/src/main/java/org/gdsc/domain/usecase/token/GetGrantTypeUseCase.kt @@ -1,13 +1,13 @@ package org.gdsc.domain.usecase.token -import org.gdsc.domain.repository.TokenManager +import org.gdsc.domain.repository.TokenRepository import javax.inject.Inject class GetGrantTypeUseCase @Inject constructor( - private val tokenManager: TokenManager + private val tokenRepository: TokenRepository ) { suspend operator fun invoke(): String { - return tokenManager.getGrantType() + return tokenRepository.getGrantType() } } \ No newline at end of file diff --git a/domain/src/main/java/org/gdsc/domain/usecase/token/GetRefreshTokenUseCase.kt b/domain/src/main/java/org/gdsc/domain/usecase/token/GetRefreshTokenUseCase.kt index 8d847f29..9997a47d 100644 --- a/domain/src/main/java/org/gdsc/domain/usecase/token/GetRefreshTokenUseCase.kt +++ b/domain/src/main/java/org/gdsc/domain/usecase/token/GetRefreshTokenUseCase.kt @@ -1,13 +1,13 @@ package org.gdsc.domain.usecase.token -import org.gdsc.domain.repository.TokenManager +import org.gdsc.domain.repository.TokenRepository import javax.inject.Inject class GetRefreshTokenUseCase @Inject constructor( - private val tokenManager: TokenManager + private val tokenRepository: TokenRepository ) { suspend operator fun invoke(): String { - return tokenManager.getRefreshToken() + return tokenRepository.getRefreshToken() } } \ No newline at end of file diff --git a/domain/src/main/java/org/gdsc/domain/usecase/token/SaveTokenUseCase.kt b/domain/src/main/java/org/gdsc/domain/usecase/token/SaveTokenUseCase.kt index 685c558c..12a154fc 100644 --- a/domain/src/main/java/org/gdsc/domain/usecase/token/SaveTokenUseCase.kt +++ b/domain/src/main/java/org/gdsc/domain/usecase/token/SaveTokenUseCase.kt @@ -1,17 +1,17 @@ package org.gdsc.domain.usecase.token import org.gdsc.domain.model.response.TokenResponse -import org.gdsc.domain.repository.TokenManager +import org.gdsc.domain.repository.TokenRepository import javax.inject.Inject class SaveTokenUseCase @Inject constructor( - private val tokenManager: TokenManager, + private val tokenRepository: TokenRepository, ){ suspend operator fun invoke( response: TokenResponse ) { - tokenManager.saveTokenInfo(response) + tokenRepository.saveTokenInfo(response) } } \ No newline at end of file From 77cccbc317f50a99c871ae1c6c48c70e6de9cd28 Mon Sep 17 00:00:00 2001 From: soopeach Date: Sun, 10 Sep 2023 16:20:37 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[feat/auto=5Flogin]:=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=20refresh=20UseCase=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gdsc/data/datasource/TokenDataSource.kt | 9 +++++++++ .../data/datasource/TokenDataSourceImpl.kt | 15 +++++++++++++++ .../main/java/org/gdsc/data/di/ApiModule.kt | 7 +++++++ .../java/org/gdsc/data/di/NetworkModule.kt | 7 ++++--- .../main/java/org/gdsc/data/di/TokenModule.kt | 18 +++++++++++++----- .../org/gdsc/data/network/Interceptors.kt | 17 ++++++++++++++--- .../java/org/gdsc/data/network/TokenAPI.kt | 14 ++++++++++++++ .../data/repository/TokenRepositoryImpl.kt | 19 +++++++++++++++++-- .../model/request/RefreshTokenRequest.kt | 5 +++++ .../gdsc/domain/repository/TokenRepository.kt | 2 ++ .../usecase/token/PostRefreshTokenUseCase.kt | 13 +++++++++++++ 11 files changed, 113 insertions(+), 13 deletions(-) create mode 100644 data/src/main/java/org/gdsc/data/datasource/TokenDataSource.kt create mode 100644 data/src/main/java/org/gdsc/data/datasource/TokenDataSourceImpl.kt create mode 100644 data/src/main/java/org/gdsc/data/network/TokenAPI.kt create mode 100644 domain/src/main/java/org/gdsc/domain/model/request/RefreshTokenRequest.kt create mode 100644 domain/src/main/java/org/gdsc/domain/usecase/token/PostRefreshTokenUseCase.kt diff --git a/data/src/main/java/org/gdsc/data/datasource/TokenDataSource.kt b/data/src/main/java/org/gdsc/data/datasource/TokenDataSource.kt new file mode 100644 index 00000000..a5e89e17 --- /dev/null +++ b/data/src/main/java/org/gdsc/data/datasource/TokenDataSource.kt @@ -0,0 +1,9 @@ +package org.gdsc.data.datasource + +import org.gdsc.data.model.Response +import org.gdsc.domain.model.response.TokenResponse + +interface TokenDataSource { + + suspend fun postRefreshToken(refreshToken: String): Response +} \ No newline at end of file diff --git a/data/src/main/java/org/gdsc/data/datasource/TokenDataSourceImpl.kt b/data/src/main/java/org/gdsc/data/datasource/TokenDataSourceImpl.kt new file mode 100644 index 00000000..7db78f0f --- /dev/null +++ b/data/src/main/java/org/gdsc/data/datasource/TokenDataSourceImpl.kt @@ -0,0 +1,15 @@ +package org.gdsc.data.datasource + +import org.gdsc.data.model.Response +import org.gdsc.data.network.TokenAPI +import org.gdsc.domain.model.request.RefreshTokenRequest +import org.gdsc.domain.model.response.TokenResponse +import javax.inject.Inject + +class TokenDataSourceImpl @Inject constructor( + private val tokenAPI: TokenAPI +): TokenDataSource { + override suspend fun postRefreshToken(refreshToken: String): Response { + return tokenAPI.refreshToken(RefreshTokenRequest(refreshToken)) + } +} \ No newline at end of file diff --git a/data/src/main/java/org/gdsc/data/di/ApiModule.kt b/data/src/main/java/org/gdsc/data/di/ApiModule.kt index dd40d410..598998be 100644 --- a/data/src/main/java/org/gdsc/data/di/ApiModule.kt +++ b/data/src/main/java/org/gdsc/data/di/ApiModule.kt @@ -6,6 +6,7 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import org.gdsc.data.network.LoginAPI import org.gdsc.data.network.RestaurantAPI +import org.gdsc.data.network.TokenAPI import org.gdsc.data.network.UserAPI import retrofit2.Retrofit import javax.inject.Singleton @@ -32,4 +33,10 @@ class ApiModule { return retrofit.create(UserAPI::class.java) } + @Provides + @Singleton + fun provideTokenApi(@AuthClient retrofit: Retrofit): TokenAPI { + return retrofit.create(TokenAPI::class.java) + } + } \ No newline at end of file diff --git a/data/src/main/java/org/gdsc/data/di/NetworkModule.kt b/data/src/main/java/org/gdsc/data/di/NetworkModule.kt index e30dbd9f..da0c560e 100644 --- a/data/src/main/java/org/gdsc/data/di/NetworkModule.kt +++ b/data/src/main/java/org/gdsc/data/di/NetworkModule.kt @@ -1,13 +1,14 @@ package org.gdsc.data.di +import android.content.Context import dagger.Module import dagger.Provides import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import org.gdsc.data.network.AuthInterceptor -import org.gdsc.domain.repository.TokenRepository import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import javax.inject.Singleton @@ -33,7 +34,7 @@ class NetworkModule { @AuthClient @Provides @Singleton - fun provideAuthorizedApiClient(tokenRepository: TokenRepository): Retrofit { + fun provideAuthorizedApiClient(@ApplicationContext context: Context): Retrofit { return Retrofit .Builder() @@ -41,7 +42,7 @@ class NetworkModule { .addConverterFactory(GsonConverterFactory.create()) .client( baseClientBuilder - .addInterceptor(AuthInterceptor(tokenRepository)) + .addInterceptor(AuthInterceptor(context.tokenDataStore)) .build() ) .build() diff --git a/data/src/main/java/org/gdsc/data/di/TokenModule.kt b/data/src/main/java/org/gdsc/data/di/TokenModule.kt index e63576f8..50bc25fe 100644 --- a/data/src/main/java/org/gdsc/data/di/TokenModule.kt +++ b/data/src/main/java/org/gdsc/data/di/TokenModule.kt @@ -9,22 +9,30 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import org.gdsc.data.datasource.TokenDataSource +import org.gdsc.data.datasource.TokenDataSourceImpl +import org.gdsc.data.network.TokenAPI import org.gdsc.data.repository.TokenRepositoryImpl import org.gdsc.domain.repository.TokenRepository import javax.inject.Singleton +val TOKEN_INFO_STORAGE = "token_info_storage" +val Context.tokenDataStore: DataStore by preferencesDataStore(name = TOKEN_INFO_STORAGE) + @Module @InstallIn(SingletonComponent::class) class TokenModule { - private val TOKEN_INFO_STORAGE = "token_info_storage" - - private val Context.dataStore: DataStore by preferencesDataStore(name = TOKEN_INFO_STORAGE) + @Provides + @Singleton + fun provideTokenDataSource(tokenAPI: TokenAPI): TokenDataSource { + return TokenDataSourceImpl(tokenAPI) + } @Provides @Singleton - fun provideTokenManager(@ApplicationContext context: Context): TokenRepository { - return TokenRepositoryImpl(context.dataStore) + fun provideTokenRepository(@ApplicationContext context: Context, tokenDataSource: TokenDataSource): TokenRepository { + return TokenRepositoryImpl(context.tokenDataStore, tokenDataSource) } } \ No newline at end of file diff --git a/data/src/main/java/org/gdsc/data/network/Interceptors.kt b/data/src/main/java/org/gdsc/data/network/Interceptors.kt index d0c45d2f..feecd614 100644 --- a/data/src/main/java/org/gdsc/data/network/Interceptors.kt +++ b/data/src/main/java/org/gdsc/data/network/Interceptors.kt @@ -1,10 +1,15 @@ package org.gdsc.data.network +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.stringPreferencesKey import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map import kotlinx.coroutines.runBlocking import okhttp3.Interceptor import okhttp3.Response -import org.gdsc.domain.repository.TokenRepository +import org.gdsc.domain.Empty import java.io.IOException import javax.inject.Inject @@ -20,15 +25,21 @@ interface CoroutineInterceptor : Interceptor { } } } + suspend fun interceptSuspend(chain: Interceptor.Chain): Response } class AuthInterceptor @Inject constructor( - private val tokenRepository: TokenRepository + private val dataStore: DataStore, ) : CoroutineInterceptor { override suspend fun interceptSuspend(chain: Interceptor.Chain): Response { - val token = "Bearer ${tokenRepository.getAccessToken()}" + + val accessToken = dataStore.data.map { preferences -> + preferences[stringPreferencesKey("accessToken")] + }.first() ?: String.Empty + + val token = "Bearer $accessToken" val newRequest = chain.request().newBuilder() .addHeader("Authorization", token) .build() diff --git a/data/src/main/java/org/gdsc/data/network/TokenAPI.kt b/data/src/main/java/org/gdsc/data/network/TokenAPI.kt new file mode 100644 index 00000000..6ec7e01a --- /dev/null +++ b/data/src/main/java/org/gdsc/data/network/TokenAPI.kt @@ -0,0 +1,14 @@ +package org.gdsc.data.network + +import org.gdsc.data.model.Response +import org.gdsc.domain.model.request.RefreshTokenRequest +import org.gdsc.domain.model.response.TokenResponse +import retrofit2.http.Body +import retrofit2.http.POST + +interface TokenAPI { + @POST("api/v1/token") + suspend fun refreshToken( + @Body request: RefreshTokenRequest + ): Response +} \ No newline at end of file diff --git a/data/src/main/java/org/gdsc/data/repository/TokenRepositoryImpl.kt b/data/src/main/java/org/gdsc/data/repository/TokenRepositoryImpl.kt index 42d74af9..47e8dd52 100644 --- a/data/src/main/java/org/gdsc/data/repository/TokenRepositoryImpl.kt +++ b/data/src/main/java/org/gdsc/data/repository/TokenRepositoryImpl.kt @@ -7,14 +7,16 @@ import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map +import org.gdsc.data.datasource.TokenDataSource import org.gdsc.domain.Empty import org.gdsc.domain.model.response.TokenResponse import org.gdsc.domain.repository.TokenRepository import javax.inject.Inject class TokenRepositoryImpl @Inject constructor( - private val dataStore: DataStore -): TokenRepository { + private val dataStore: DataStore, + private val tokenDataSource: TokenDataSource +) : TokenRepository { override suspend fun saveTokenInfo(tokenResponse: TokenResponse) { @@ -59,6 +61,19 @@ class TokenRepositoryImpl @Inject constructor( } } + // check success or not + override suspend fun requestRefreshToken(refreshToken: String): Boolean { + + try { + val newTokenInfo = tokenDataSource.postRefreshToken(refreshToken).data + saveTokenInfo(newTokenInfo) + } catch (e: Exception) { + return false + } + + return true + } + companion object { private val ACCESS_TOKEN = stringPreferencesKey("accessToken") private val ACCESS_TOKEN_EXPIRES_IN = longPreferencesKey("accessTokenExpiresIn") diff --git a/domain/src/main/java/org/gdsc/domain/model/request/RefreshTokenRequest.kt b/domain/src/main/java/org/gdsc/domain/model/request/RefreshTokenRequest.kt new file mode 100644 index 00000000..38a83d67 --- /dev/null +++ b/domain/src/main/java/org/gdsc/domain/model/request/RefreshTokenRequest.kt @@ -0,0 +1,5 @@ +package org.gdsc.domain.model.request + +data class RefreshTokenRequest( + val refreshToken: String +) diff --git a/domain/src/main/java/org/gdsc/domain/repository/TokenRepository.kt b/domain/src/main/java/org/gdsc/domain/repository/TokenRepository.kt index 77315c16..b359d066 100644 --- a/domain/src/main/java/org/gdsc/domain/repository/TokenRepository.kt +++ b/domain/src/main/java/org/gdsc/domain/repository/TokenRepository.kt @@ -15,5 +15,7 @@ interface TokenRepository { suspend fun getRefreshToken(): String suspend fun clearTokenInfo() + + suspend fun requestRefreshToken(refreshToken: String): Boolean } \ No newline at end of file diff --git a/domain/src/main/java/org/gdsc/domain/usecase/token/PostRefreshTokenUseCase.kt b/domain/src/main/java/org/gdsc/domain/usecase/token/PostRefreshTokenUseCase.kt new file mode 100644 index 00000000..508913cf --- /dev/null +++ b/domain/src/main/java/org/gdsc/domain/usecase/token/PostRefreshTokenUseCase.kt @@ -0,0 +1,13 @@ +package org.gdsc.domain.usecase.token + +import org.gdsc.domain.repository.TokenRepository +import javax.inject.Inject + +class PostRefreshTokenUseCase@Inject constructor( + private val tokenRepository: TokenRepository +) { + + suspend operator fun invoke(refreshToken: String): Boolean { + return tokenRepository.requestRefreshToken(refreshToken) + } +} \ No newline at end of file From 6de9c9624267d54e930ecb7753385bb78a1593fd Mon Sep 17 00:00:00 2001 From: soopeach Date: Sun, 10 Sep 2023 16:32:47 +0900 Subject: [PATCH 3/5] =?UTF-8?q?[feat/auto=5Flogin]:=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84(Splash=EC=97=90=EC=84=9C=20=ED=99=95=EC=9D=B8=20?= =?UTF-8?q?=ED=9B=84=20=EC=B2=98=EB=A6=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gdsc/presentation/login/SplashActivity.kt | 54 +++++++++++++++++-- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt b/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt index 4215a506..cd968d1c 100644 --- a/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt +++ b/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt @@ -5,24 +5,67 @@ import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.Handler import android.os.Looper -import androidx.core.view.WindowCompat +import androidx.lifecycle.lifecycleScope +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch +import org.gdsc.domain.usecase.token.GetRefreshTokenUseCase +import org.gdsc.domain.usecase.token.PostRefreshTokenUseCase +import org.gdsc.domain.usecase.token.VerifyAccessTokenUseCase import org.gdsc.presentation.R +import org.gdsc.presentation.view.MainActivity +import javax.inject.Inject +@AndroidEntryPoint class SplashActivity : AppCompatActivity() { val handle: Handler = Handler(Looper.getMainLooper()) + @Inject + lateinit var verifyAccessTokenUseCase: VerifyAccessTokenUseCase + + @Inject + lateinit var postRefreshTokenUseCase: PostRefreshTokenUseCase + + @Inject + lateinit var getRefreshTokenUseCase: GetRefreshTokenUseCase + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_splash) setToFullPage() handle.postDelayed({ - Intent(this, LoginActivity::class.java).apply { - startActivity(this) + + lifecycleScope.launch { + val isAccessTokenValid = verifyAccessTokenUseCase.invoke() + + // 정상이면 그냥 리프레쉬 + if (isAccessTokenValid) { + postRefreshTokenUseCase.invoke(getRefreshTokenUseCase.invoke()) + val intent = Intent(applicationContext, MainActivity::class.java) + startActivity(intent) + finish() + + // access Token이 만료되었다면 + } else { + // refresh 시도 + val isRefreshSuccess = postRefreshTokenUseCase.invoke(getRefreshTokenUseCase.invoke()) + + // refresh 성공했다면 + if (isRefreshSuccess) { + val intent = Intent(applicationContext, MainActivity::class.java) + startActivity(intent) + finish() + // refresh 실패했다면 + } else { + val intent = Intent(applicationContext, LoginActivity::class.java) + startActivity(intent) + finish() + } + + } } - finish() }, 2000) } @@ -30,6 +73,7 @@ class SplashActivity : AppCompatActivity() { val window = window window.setFlags( android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, - android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) + android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS + ) } } \ No newline at end of file From b6d9629a557dfe649306b56de86722ba6373dfcb Mon Sep 17 00:00:00 2001 From: DOGDDUDDY Date: Sun, 10 Sep 2023 19:19:44 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[feat/auto=5Flogin]:=20Splash=EC=99=80=20To?= =?UTF-8?q?ken=20=EB=B9=84=EB=8F=99=EA=B8=B0=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gdsc/presentation/login/SplashActivity.kt | 76 ++++++++++--------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt b/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt index cd968d1c..e63245ad 100644 --- a/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt +++ b/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt @@ -3,10 +3,10 @@ package org.gdsc.presentation.login import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle -import android.os.Handler -import android.os.Looper import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.gdsc.domain.usecase.token.GetRefreshTokenUseCase import org.gdsc.domain.usecase.token.PostRefreshTokenUseCase @@ -18,8 +18,6 @@ import javax.inject.Inject @AndroidEntryPoint class SplashActivity : AppCompatActivity() { - val handle: Handler = Handler(Looper.getMainLooper()) - @Inject lateinit var verifyAccessTokenUseCase: VerifyAccessTokenUseCase @@ -29,44 +27,48 @@ class SplashActivity : AppCompatActivity() { @Inject lateinit var getRefreshTokenUseCase: GetRefreshTokenUseCase + private val DELAY_TIME = 2000L + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_splash) setToFullPage() - handle.postDelayed({ - - lifecycleScope.launch { - val isAccessTokenValid = verifyAccessTokenUseCase.invoke() - - // 정상이면 그냥 리프레쉬 - if (isAccessTokenValid) { - postRefreshTokenUseCase.invoke(getRefreshTokenUseCase.invoke()) - val intent = Intent(applicationContext, MainActivity::class.java) - startActivity(intent) - finish() - - // access Token이 만료되었다면 - } else { - // refresh 시도 - val isRefreshSuccess = postRefreshTokenUseCase.invoke(getRefreshTokenUseCase.invoke()) - - // refresh 성공했다면 - if (isRefreshSuccess) { - val intent = Intent(applicationContext, MainActivity::class.java) - startActivity(intent) - finish() - // refresh 실패했다면 - } else { - val intent = Intent(applicationContext, LoginActivity::class.java) - startActivity(intent) - finish() - } - - } - } - - }, 2000) + lifecycleScope.launch(Dispatchers.Main) { + + val validateTokenJob = validateToken() + + delay(DELAY_TIME) + + if(validateTokenJob) + moveToMain() + else + moveToLogin() + } + } + + private fun moveToMain() { + startActivity(Intent(applicationContext,MainActivity::class.java)) + finish() + } + + private fun moveToLogin() { + startActivity(Intent(applicationContext,LoginActivity::class.java)) + finish() + } + + private suspend fun validateToken(): Boolean { + val isAccessTokenValid = verifyAccessTokenUseCase.invoke() + + + return if (isAccessTokenValid) { // 정상이면 그냥 리프레쉬 + postRefreshTokenUseCase.invoke(getRefreshTokenUseCase.invoke()) + true + } else { + // refresh 시도 + val isRefreshSuccess = postRefreshTokenUseCase.invoke(getRefreshTokenUseCase.invoke()) + isRefreshSuccess + } } private fun setToFullPage() { From 5c6ad89e37a9f72230f91d3e01fc819d01f5b776 Mon Sep 17 00:00:00 2001 From: DOGDDUDDY Date: Sun, 10 Sep 2023 20:18:46 +0900 Subject: [PATCH 5/5] =?UTF-8?q?[feat/auto=5Flogin]:=20=EB=B3=80=EC=88=98?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/gdsc/presentation/login/SplashActivity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt b/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt index e63245ad..a34e3fb5 100644 --- a/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt +++ b/presentation/src/main/java/org/gdsc/presentation/login/SplashActivity.kt @@ -36,11 +36,11 @@ class SplashActivity : AppCompatActivity() { lifecycleScope.launch(Dispatchers.Main) { - val validateTokenJob = validateToken() + val accessible = validateToken() delay(DELAY_TIME) - if(validateTokenJob) + if(accessible) moveToMain() else moveToLogin()