From 4bd3846e205ed0bbcb360ce91e5560bd0999010f Mon Sep 17 00:00:00 2001 From: ows3090 Date: Mon, 12 Feb 2024 15:23:59 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[build]=20#46=20data=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=EA=B3=BC=20core:network=20=EB=AA=A8=EB=93=88=EC=97=90=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=EB=90=9C=20API=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B3=91=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/network/build.gradle | 1 + .../buddycon/network}/di/InterceptorModule.kt | 6 +-- .../yapp/buddycon/network/di/NetworkModule.kt | 36 +++++++------ .../yapp/buddycon/network/di/ServiceModule.kt | 15 +++++- .../di/qualifiers/InterceptorQualifiers.kt | 2 +- .../di/qualifiers/OkHttpClientQualifiers.kt | 2 +- .../di/qualifiers/RetrofitQualifiers.kt | 2 +- .../network/service/auth/AuthService.kt | 7 +-- .../{LoginRequest.kt => AuthRequest.kt} | 8 +-- .../service/auth/response/AuthResponse.kt | 21 ++++++++ .../service/gifticon}/GiftiConService.kt | 4 +- .../response/AvailableGifticonResponse.kt | 2 +- .../yapp/buddycon/data/di/NetworkModule.kt | 54 ------------------- .../yapp/buddycon/data/di/RepositoryModule.kt | 4 +- .../yapp/buddycon/data/model/request/Dummy.kt | 3 ++ .../buddycon/data/repository/local/Dummy.kt | 1 - .../{ => local}/TokenRepositoryImpl.kt | 2 +- .../{ => remote}/AuthRepositoryImpl.kt | 14 ++--- .../remote/AvailableGifticonRepositoryImpl.kt | 2 +- .../buddycon/domain/model/auth/AuthModel.kt | 7 +++ .../domain/repository/AuthRepository.kt | 9 ++-- .../buddycon/startup/login/LoginScreen.kt | 2 + 22 files changed, 101 insertions(+), 103 deletions(-) rename {data/src/main/java/com/yapp/buddycon/data => core/network/src/main/java/com/yapp/buddycon/network}/di/InterceptorModule.kt (78%) rename {data/src/main/java/com/yapp/buddycon/data => core/network/src/main/java/com/yapp/buddycon/network}/di/qualifiers/InterceptorQualifiers.kt (82%) rename {data/src/main/java/com/yapp/buddycon/data => core/network/src/main/java/com/yapp/buddycon/network}/di/qualifiers/OkHttpClientQualifiers.kt (80%) rename {data/src/main/java/com/yapp/buddycon/data => core/network/src/main/java/com/yapp/buddycon/network}/di/qualifiers/RetrofitQualifiers.kt (80%) rename core/network/src/main/java/com/yapp/buddycon/network/service/auth/request/{LoginRequest.kt => AuthRequest.kt} (55%) create mode 100644 core/network/src/main/java/com/yapp/buddycon/network/service/auth/response/AuthResponse.kt rename {data/src/main/java/com/yapp/buddycon/data/api => core/network/src/main/java/com/yapp/buddycon/network/service/gifticon}/GiftiConService.kt (84%) rename {data/src/main/java/com/yapp/buddycon/data/model => core/network/src/main/java/com/yapp/buddycon/network/service/gifticon}/response/AvailableGifticonResponse.kt (96%) delete mode 100644 data/src/main/java/com/yapp/buddycon/data/di/NetworkModule.kt delete mode 100644 data/src/main/java/com/yapp/buddycon/data/repository/local/Dummy.kt rename data/src/main/java/com/yapp/buddycon/data/repository/{ => local}/TokenRepositoryImpl.kt (96%) rename data/src/main/java/com/yapp/buddycon/data/repository/{ => remote}/AuthRepositoryImpl.kt (72%) create mode 100644 domain/src/main/java/com/yapp/buddycon/domain/model/auth/AuthModel.kt diff --git a/core/network/build.gradle b/core/network/build.gradle index d3de0b3b..9d1bfbeb 100644 --- a/core/network/build.gradle +++ b/core/network/build.gradle @@ -32,6 +32,7 @@ android { } dependencies { + implementation project(":domain") implementation libs.bundles.retrofit implementation libs.hilt.android kapt libs.hilt.compiler diff --git a/data/src/main/java/com/yapp/buddycon/data/di/InterceptorModule.kt b/core/network/src/main/java/com/yapp/buddycon/network/di/InterceptorModule.kt similarity index 78% rename from data/src/main/java/com/yapp/buddycon/data/di/InterceptorModule.kt rename to core/network/src/main/java/com/yapp/buddycon/network/di/InterceptorModule.kt index a12b3e05..f404f4d3 100644 --- a/data/src/main/java/com/yapp/buddycon/data/di/InterceptorModule.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/di/InterceptorModule.kt @@ -1,7 +1,7 @@ -package com.yapp.buddycon.data.di +package com.yapp.buddycon.network.di -import com.yapp.buddycon.data.BuildConfig -import com.yapp.buddycon.data.di.qualifiers.HttpLoggingInterceptorQualifier +import com.yapp.buddycon.network.BuildConfig +import com.yapp.buddycon.network.di.qualifiers.HttpLoggingInterceptorQualifier import dagger.Module import dagger.Provides import dagger.hilt.InstallIn diff --git a/core/network/src/main/java/com/yapp/buddycon/network/di/NetworkModule.kt b/core/network/src/main/java/com/yapp/buddycon/network/di/NetworkModule.kt index 1d9b87ac..6741c460 100644 --- a/core/network/src/main/java/com/yapp/buddycon/network/di/NetworkModule.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/di/NetworkModule.kt @@ -1,11 +1,14 @@ package com.yapp.buddycon.network.di +import com.yapp.buddycon.network.di.qualifiers.BuddyConClient +import com.yapp.buddycon.network.di.qualifiers.BuddyConRetrofit +import com.yapp.buddycon.network.di.qualifiers.HttpLoggingInterceptorQualifier import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import okhttp3.Interceptor import okhttp3.OkHttpClient -import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import javax.inject.Singleton @@ -13,26 +16,29 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) object NetworkModule { - private const val BUDDYCON_BASE_URL = "http://3.37.88.131:8080/" + private const val BUDDYCON_BASE_URL = "http://43.202.14.1:8080/" + @BuddyConClient @Provides @Singleton - fun provideRetrofit( - okHttpClient: OkHttpClient + fun provideBuddyConClient( + @HttpLoggingInterceptorQualifier httpLoggingInterceptor: Interceptor, + // @BuddyConInterceptorQualifier buddyConInterceptor: Interceptor + ): OkHttpClient = + OkHttpClient.Builder() + .addInterceptor(httpLoggingInterceptor) + // .addInterceptor(buddyConInterceptor) + .build() + + @BuddyConRetrofit + @Provides + @Singleton + fun provideBuddyConRetrofit( + @BuddyConClient okHttpClient: OkHttpClient ): Retrofit = Retrofit.Builder() .baseUrl(BUDDYCON_BASE_URL) - .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) + .addConverterFactory(GsonConverterFactory.create()) .build() - - @Provides - @Singleton - fun provideOkHttpClient(): OkHttpClient = - OkHttpClient.Builder() - .addInterceptor( - HttpLoggingInterceptor().apply { - level = HttpLoggingInterceptor.Level.BODY - } - ).build() } diff --git a/core/network/src/main/java/com/yapp/buddycon/network/di/ServiceModule.kt b/core/network/src/main/java/com/yapp/buddycon/network/di/ServiceModule.kt index 65ffdf3f..1ca9c51b 100644 --- a/core/network/src/main/java/com/yapp/buddycon/network/di/ServiceModule.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/di/ServiceModule.kt @@ -1,6 +1,8 @@ package com.yapp.buddycon.network.di +import com.yapp.buddycon.network.di.qualifiers.BuddyConRetrofit import com.yapp.buddycon.network.service.auth.AuthService +import com.yapp.buddycon.network.service.gifticon.GiftiConService import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -16,6 +18,15 @@ object ServiceModule { @Provides @Singleton fun provideAuthService( - retrofit: Retrofit - ): AuthService = retrofit.create() + @BuddyConRetrofit retrofit: Retrofit + ): AuthService = + retrofit.create() + + /** api service */ + @Provides + @Singleton + fun provideGiftiConService( + @BuddyConRetrofit retrofit: Retrofit + ): GiftiConService = + retrofit.create() } diff --git a/data/src/main/java/com/yapp/buddycon/data/di/qualifiers/InterceptorQualifiers.kt b/core/network/src/main/java/com/yapp/buddycon/network/di/qualifiers/InterceptorQualifiers.kt similarity index 82% rename from data/src/main/java/com/yapp/buddycon/data/di/qualifiers/InterceptorQualifiers.kt rename to core/network/src/main/java/com/yapp/buddycon/network/di/qualifiers/InterceptorQualifiers.kt index 0bb8448e..23b431e3 100644 --- a/data/src/main/java/com/yapp/buddycon/data/di/qualifiers/InterceptorQualifiers.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/di/qualifiers/InterceptorQualifiers.kt @@ -1,4 +1,4 @@ -package com.yapp.buddycon.data.di.qualifiers +package com.yapp.buddycon.network.di.qualifiers import javax.inject.Qualifier diff --git a/data/src/main/java/com/yapp/buddycon/data/di/qualifiers/OkHttpClientQualifiers.kt b/core/network/src/main/java/com/yapp/buddycon/network/di/qualifiers/OkHttpClientQualifiers.kt similarity index 80% rename from data/src/main/java/com/yapp/buddycon/data/di/qualifiers/OkHttpClientQualifiers.kt rename to core/network/src/main/java/com/yapp/buddycon/network/di/qualifiers/OkHttpClientQualifiers.kt index b9a078cc..18a0f5c9 100644 --- a/data/src/main/java/com/yapp/buddycon/data/di/qualifiers/OkHttpClientQualifiers.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/di/qualifiers/OkHttpClientQualifiers.kt @@ -1,4 +1,4 @@ -package com.yapp.buddycon.data.di.qualifiers +package com.yapp.buddycon.network.di.qualifiers import javax.inject.Qualifier diff --git a/data/src/main/java/com/yapp/buddycon/data/di/qualifiers/RetrofitQualifiers.kt b/core/network/src/main/java/com/yapp/buddycon/network/di/qualifiers/RetrofitQualifiers.kt similarity index 80% rename from data/src/main/java/com/yapp/buddycon/data/di/qualifiers/RetrofitQualifiers.kt rename to core/network/src/main/java/com/yapp/buddycon/network/di/qualifiers/RetrofitQualifiers.kt index 0e10505d..c8413d3c 100644 --- a/data/src/main/java/com/yapp/buddycon/data/di/qualifiers/RetrofitQualifiers.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/di/qualifiers/RetrofitQualifiers.kt @@ -1,4 +1,4 @@ -package com.yapp.buddycon.data.di.qualifiers +package com.yapp.buddycon.network.di.qualifiers import javax.inject.Qualifier diff --git a/core/network/src/main/java/com/yapp/buddycon/network/service/auth/AuthService.kt b/core/network/src/main/java/com/yapp/buddycon/network/service/auth/AuthService.kt index eda51587..e2a6290e 100644 --- a/core/network/src/main/java/com/yapp/buddycon/network/service/auth/AuthService.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/service/auth/AuthService.kt @@ -1,6 +1,7 @@ package com.yapp.buddycon.network.service.auth -import com.yapp.buddycon.network.service.auth.request.LoginRequest +import com.yapp.buddycon.network.service.auth.request.AuthRequest +import com.yapp.buddycon.network.service.auth.response.AuthResponse import retrofit2.http.Body import retrofit2.http.POST @@ -8,6 +9,6 @@ interface AuthService { @POST("api/v1/auth/login") suspend fun fetchLogin( - @Body loginRequest: LoginRequest - ) + @Body authRequest: AuthRequest + ): AuthResponse } diff --git a/core/network/src/main/java/com/yapp/buddycon/network/service/auth/request/LoginRequest.kt b/core/network/src/main/java/com/yapp/buddycon/network/service/auth/request/AuthRequest.kt similarity index 55% rename from core/network/src/main/java/com/yapp/buddycon/network/service/auth/request/LoginRequest.kt rename to core/network/src/main/java/com/yapp/buddycon/network/service/auth/request/AuthRequest.kt index 01983477..f1b8b8ad 100644 --- a/core/network/src/main/java/com/yapp/buddycon/network/service/auth/request/LoginRequest.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/service/auth/request/AuthRequest.kt @@ -1,9 +1,9 @@ package com.yapp.buddycon.network.service.auth.request -data class LoginRequest( +data class AuthRequest( val oauthAccessToken: String, val nickname: String, - val email: String?, - val gender: String?, - val age: String? + val email: String, + val gender: String, + val age: String ) diff --git a/core/network/src/main/java/com/yapp/buddycon/network/service/auth/response/AuthResponse.kt b/core/network/src/main/java/com/yapp/buddycon/network/service/auth/response/AuthResponse.kt new file mode 100644 index 00000000..9bfbbc21 --- /dev/null +++ b/core/network/src/main/java/com/yapp/buddycon/network/service/auth/response/AuthResponse.kt @@ -0,0 +1,21 @@ +package com.yapp.buddycon.network.service.auth.response + +import com.yapp.buddycon.domain.model.auth.AuthModel + +data class AuthResponse( + val status: Int, + val message: String, + val body: AuthResponseBody +) + +data class AuthResponseBody( + val accessToken: String, + val refreshToken: String, + val accessTokenExpiresIn: Long +) { + fun toModel() = AuthModel( + accessToken = accessToken, + refreshToken = refreshToken, + accessTokenExpiresIn = accessTokenExpiresIn + ) +} diff --git a/data/src/main/java/com/yapp/buddycon/data/api/GiftiConService.kt b/core/network/src/main/java/com/yapp/buddycon/network/service/gifticon/GiftiConService.kt similarity index 84% rename from data/src/main/java/com/yapp/buddycon/data/api/GiftiConService.kt rename to core/network/src/main/java/com/yapp/buddycon/network/service/gifticon/GiftiConService.kt index 0506b613..50d068bc 100644 --- a/data/src/main/java/com/yapp/buddycon/data/api/GiftiConService.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/service/gifticon/GiftiConService.kt @@ -1,6 +1,6 @@ -package com.yapp.buddycon.data.api +package com.yapp.buddycon.network.service.gifticon -import com.yapp.buddycon.data.model.response.AvailableGifticonResponse +import com.yapp.buddycon.network.service.gifticon.response.AvailableGifticonResponse import retrofit2.Response import retrofit2.http.GET import retrofit2.http.Header diff --git a/data/src/main/java/com/yapp/buddycon/data/model/response/AvailableGifticonResponse.kt b/core/network/src/main/java/com/yapp/buddycon/network/service/gifticon/response/AvailableGifticonResponse.kt similarity index 96% rename from data/src/main/java/com/yapp/buddycon/data/model/response/AvailableGifticonResponse.kt rename to core/network/src/main/java/com/yapp/buddycon/network/service/gifticon/response/AvailableGifticonResponse.kt index 54e3908c..0698e558 100644 --- a/data/src/main/java/com/yapp/buddycon/data/model/response/AvailableGifticonResponse.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/service/gifticon/response/AvailableGifticonResponse.kt @@ -1,4 +1,4 @@ -package com.yapp.buddycon.data.model.response +package com.yapp.buddycon.network.service.gifticon.response import com.google.gson.annotations.SerializedName import com.yapp.buddycon.domain.model.gifticon.AvailableGifticon diff --git a/data/src/main/java/com/yapp/buddycon/data/di/NetworkModule.kt b/data/src/main/java/com/yapp/buddycon/data/di/NetworkModule.kt deleted file mode 100644 index bee9ac62..00000000 --- a/data/src/main/java/com/yapp/buddycon/data/di/NetworkModule.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.yapp.buddycon.data.di - -import com.yapp.buddycon.data.api.GiftiConService -import com.yapp.buddycon.data.di.qualifiers.BuddyConClient -import com.yapp.buddycon.data.di.qualifiers.BuddyConRetrofit -import com.yapp.buddycon.data.di.qualifiers.HttpLoggingInterceptorQualifier -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import okhttp3.Interceptor -import okhttp3.OkHttpClient -import retrofit2.Retrofit -import retrofit2.converter.gson.GsonConverterFactory -import retrofit2.create -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -object NetworkModule { - private const val BASE_URL = "http://43.202.14.1:8080/" - - @BuddyConClient - @Provides - @Singleton - fun provideBuddyConClient( - @HttpLoggingInterceptorQualifier httpLoggingInterceptor: Interceptor, - // @BuddyConInterceptorQualifier buddyConInterceptor: Interceptor - ): OkHttpClient = - OkHttpClient.Builder() - .addInterceptor(httpLoggingInterceptor) - // .addInterceptor(buddyConInterceptor) - .build() - - @BuddyConRetrofit - @Provides - @Singleton - fun provideBuddyConRetrofit( - @BuddyConClient okHttpClient: OkHttpClient - ): Retrofit = - Retrofit.Builder() - .baseUrl(BASE_URL) - .client(okHttpClient) - .addConverterFactory(GsonConverterFactory.create()) - .build() - - /** api service */ - @Provides - @Singleton - fun provideGiftiConService( - @BuddyConRetrofit retrofit: Retrofit - ): GiftiConService = - retrofit.create() -} diff --git a/data/src/main/java/com/yapp/buddycon/data/di/RepositoryModule.kt b/data/src/main/java/com/yapp/buddycon/data/di/RepositoryModule.kt index 4623f0a5..7d085288 100644 --- a/data/src/main/java/com/yapp/buddycon/data/di/RepositoryModule.kt +++ b/data/src/main/java/com/yapp/buddycon/data/di/RepositoryModule.kt @@ -1,7 +1,7 @@ package com.yapp.buddycon.data.di -import com.yapp.buddycon.data.repository.AuthRepositoryImpl -import com.yapp.buddycon.data.repository.TokenRepositoryImpl +import com.yapp.buddycon.data.repository.remote.AuthRepositoryImpl +import com.yapp.buddycon.data.repository.local.TokenRepositoryImpl import com.yapp.buddycon.data.repository.remote.AvailableGifticonRepositoryImpl import com.yapp.buddycon.domain.repository.AuthRepository import com.yapp.buddycon.domain.repository.AvailableGifticonRepository diff --git a/data/src/main/java/com/yapp/buddycon/data/model/request/Dummy.kt b/data/src/main/java/com/yapp/buddycon/data/model/request/Dummy.kt index 37bf14b8..751e69e9 100644 --- a/data/src/main/java/com/yapp/buddycon/data/model/request/Dummy.kt +++ b/data/src/main/java/com/yapp/buddycon/data/model/request/Dummy.kt @@ -1 +1,4 @@ package com.yapp.buddycon.data.model.request + +fun dummy() { +} diff --git a/data/src/main/java/com/yapp/buddycon/data/repository/local/Dummy.kt b/data/src/main/java/com/yapp/buddycon/data/repository/local/Dummy.kt deleted file mode 100644 index d759f8c5..00000000 --- a/data/src/main/java/com/yapp/buddycon/data/repository/local/Dummy.kt +++ /dev/null @@ -1 +0,0 @@ -package com.yapp.buddycon.data.repository.local diff --git a/data/src/main/java/com/yapp/buddycon/data/repository/TokenRepositoryImpl.kt b/data/src/main/java/com/yapp/buddycon/data/repository/local/TokenRepositoryImpl.kt similarity index 96% rename from data/src/main/java/com/yapp/buddycon/data/repository/TokenRepositoryImpl.kt rename to data/src/main/java/com/yapp/buddycon/data/repository/local/TokenRepositoryImpl.kt index 59f123d5..8a1c02c6 100644 --- a/data/src/main/java/com/yapp/buddycon/data/repository/TokenRepositoryImpl.kt +++ b/data/src/main/java/com/yapp/buddycon/data/repository/local/TokenRepositoryImpl.kt @@ -1,4 +1,4 @@ -package com.yapp.buddycon.data.repository +package com.yapp.buddycon.data.repository.local import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences diff --git a/data/src/main/java/com/yapp/buddycon/data/repository/AuthRepositoryImpl.kt b/data/src/main/java/com/yapp/buddycon/data/repository/remote/AuthRepositoryImpl.kt similarity index 72% rename from data/src/main/java/com/yapp/buddycon/data/repository/AuthRepositoryImpl.kt rename to data/src/main/java/com/yapp/buddycon/data/repository/remote/AuthRepositoryImpl.kt index e6d1bed1..c920e9b2 100644 --- a/data/src/main/java/com/yapp/buddycon/data/repository/AuthRepositoryImpl.kt +++ b/data/src/main/java/com/yapp/buddycon/data/repository/remote/AuthRepositoryImpl.kt @@ -1,8 +1,8 @@ -package com.yapp.buddycon.data.repository +package com.yapp.buddycon.data.repository.remote import com.yapp.buddycon.domain.repository.AuthRepository import com.yapp.buddycon.network.service.auth.AuthService -import com.yapp.buddycon.network.service.auth.request.LoginRequest +import com.yapp.buddycon.network.service.auth.request.AuthRequest import kotlinx.coroutines.flow.flow import javax.inject.Inject @@ -13,20 +13,20 @@ class AuthRepositoryImpl @Inject constructor( override fun fetchLogin( oauthAccessToken: String, nickname: String, - email: String?, - gender: String?, - age: String? + email: String, + gender: String, + age: String ) = flow { emit( authService.fetchLogin( - loginRequest = LoginRequest( + authRequest = AuthRequest( oauthAccessToken = oauthAccessToken, nickname = nickname, email = email, gender = gender, age = age ) - ) + ).body.toModel() ) } } diff --git a/data/src/main/java/com/yapp/buddycon/data/repository/remote/AvailableGifticonRepositoryImpl.kt b/data/src/main/java/com/yapp/buddycon/data/repository/remote/AvailableGifticonRepositoryImpl.kt index 29c1347a..7646ef32 100644 --- a/data/src/main/java/com/yapp/buddycon/data/repository/remote/AvailableGifticonRepositoryImpl.kt +++ b/data/src/main/java/com/yapp/buddycon/data/repository/remote/AvailableGifticonRepositoryImpl.kt @@ -1,6 +1,6 @@ package com.yapp.buddycon.data.repository.remote -import com.yapp.buddycon.data.api.GiftiConService +import com.yapp.buddycon.network.service.gifticon.GiftiConService import com.yapp.buddycon.domain.repository.AvailableGifticonRepository import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.flow diff --git a/domain/src/main/java/com/yapp/buddycon/domain/model/auth/AuthModel.kt b/domain/src/main/java/com/yapp/buddycon/domain/model/auth/AuthModel.kt new file mode 100644 index 00000000..306eb842 --- /dev/null +++ b/domain/src/main/java/com/yapp/buddycon/domain/model/auth/AuthModel.kt @@ -0,0 +1,7 @@ +package com.yapp.buddycon.domain.model.auth + +data class AuthModel( + val accessToken: String, + val refreshToken: String, + val accessTokenExpiresIn: Long +) diff --git a/domain/src/main/java/com/yapp/buddycon/domain/repository/AuthRepository.kt b/domain/src/main/java/com/yapp/buddycon/domain/repository/AuthRepository.kt index 38e90a90..799ba0e9 100644 --- a/domain/src/main/java/com/yapp/buddycon/domain/repository/AuthRepository.kt +++ b/domain/src/main/java/com/yapp/buddycon/domain/repository/AuthRepository.kt @@ -1,13 +1,14 @@ package com.yapp.buddycon.domain.repository +import com.yapp.buddycon.domain.model.auth.AuthModel import kotlinx.coroutines.flow.Flow interface AuthRepository { fun fetchLogin( oauthAccessToken: String, nickname: String, - email: String? = null, - gender: String? = null, - age: String? = null - ): Flow + email: String, + gender: String, + age: String + ): Flow } diff --git a/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginScreen.kt b/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginScreen.kt index 1ea9a5b1..df5a1eaf 100644 --- a/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginScreen.kt +++ b/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginScreen.kt @@ -29,6 +29,7 @@ import com.yapp.buddycon.designsystem.theme.Paddings import kotlinx.coroutines.CancellableContinuation import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine +import timber.log.Timber import kotlin.coroutines.resume private val LoginBannerDescription = "LoginBanner" @@ -75,6 +76,7 @@ fun LoginScreen( it.kakaoAccount?.profile?.nickname?.let { nickname -> loginViewModel.saveNickname(nickname) } + Timber.d("kakao token: $token") onNavigateToSignUp() } } From 49c8c75234c3947e3c16924078b0a61c594124f1 Mon Sep 17 00:00:00 2001 From: ows3090 Date: Mon, 12 Feb 2024 17:46:51 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[feat]=20#46=20TokenRepository=EC=97=90=20?= =?UTF-8?q?=EC=95=A1=EC=84=B8=EC=8A=A4=ED=86=A0=ED=81=B0,=20=EB=A6=AC?= =?UTF-8?q?=ED=94=84=EB=A0=88=EC=89=AC=ED=86=A0=ED=81=B0=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/local/TokenRepositoryImpl.kt | 40 ++++++++++++++++++- .../domain/repository/TokenRepository.kt | 12 ++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/data/src/main/java/com/yapp/buddycon/data/repository/local/TokenRepositoryImpl.kt b/data/src/main/java/com/yapp/buddycon/data/repository/local/TokenRepositoryImpl.kt index 8a1c02c6..c66a577f 100644 --- a/data/src/main/java/com/yapp/buddycon/data/repository/local/TokenRepositoryImpl.kt +++ b/data/src/main/java/com/yapp/buddycon/data/repository/local/TokenRepositoryImpl.kt @@ -4,8 +4,11 @@ import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.edit import com.yapp.buddycon.domain.repository.TokenRepository +import com.yapp.buddycon.local.PreferenceKeys.ACCESS_TOKEN +import com.yapp.buddycon.local.PreferenceKeys.ACCESS_TOKEN_EXPIRES_IN import com.yapp.buddycon.local.PreferenceKeys.IS_FIRST_INSTALLATION import com.yapp.buddycon.local.PreferenceKeys.NICKNAME +import com.yapp.buddycon.local.PreferenceKeys.REFRESH_TOKEN import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import javax.inject.Inject @@ -15,12 +18,12 @@ class TokenRepositoryImpl @Inject constructor( ) : TokenRepository { override fun isFirstInstallation(): Flow = dataStore.data.map { preference -> - preference[IS_FIRST_INSTALLATION] ?: false + preference[IS_FIRST_INSTALLATION] ?: true } override suspend fun checkFirstInstallation() { dataStore.edit { preference -> - preference[IS_FIRST_INSTALLATION] = true + preference[IS_FIRST_INSTALLATION] = false } } @@ -34,4 +37,37 @@ class TokenRepositoryImpl @Inject constructor( preference[NICKNAME] = nickname } } + + override fun getAccessToken(): Flow = + dataStore.data.map { preference -> + preference[ACCESS_TOKEN] ?: "" + } + + override suspend fun saveAccessToken(accessToken: String) { + dataStore.edit { preference -> + preference[ACCESS_TOKEN] = accessToken + } + } + + override fun getRefreshToken(): Flow = + dataStore.data.map { preference -> + preference[REFRESH_TOKEN] ?: "" + } + + override suspend fun saveRefreshToken(refreshToken: String) { + dataStore.edit { preference -> + preference[REFRESH_TOKEN] = refreshToken + } + } + + override fun getAccessTokenExpiresIn(): Flow = + dataStore.data.map { preference -> + preference[ACCESS_TOKEN_EXPIRES_IN] ?: 0L + } + + override suspend fun saveAccessTokenExpiresIn(expire: Long) { + dataStore.edit { preference -> + preference[ACCESS_TOKEN_EXPIRES_IN] = expire + } + } } diff --git a/domain/src/main/java/com/yapp/buddycon/domain/repository/TokenRepository.kt b/domain/src/main/java/com/yapp/buddycon/domain/repository/TokenRepository.kt index 0aed4d31..edaa9865 100644 --- a/domain/src/main/java/com/yapp/buddycon/domain/repository/TokenRepository.kt +++ b/domain/src/main/java/com/yapp/buddycon/domain/repository/TokenRepository.kt @@ -9,4 +9,16 @@ interface TokenRepository { fun getNickname(): Flow suspend fun saveNickname(nickname: String) + + fun getAccessToken(): Flow + + suspend fun saveAccessToken(accessToken: String) + + fun getRefreshToken(): Flow + + suspend fun saveRefreshToken(refreshToken: String) + + fun getAccessTokenExpiresIn(): Flow + + suspend fun saveAccessTokenExpiresIn(expire: Long) } From 220b2e602e081ae2532d369e5abd422ce5f0e212 Mon Sep 17 00:00:00 2001 From: ows3090 Date: Mon, 12 Feb 2024 17:46:56 +0900 Subject: [PATCH 3/5] =?UTF-8?q?[feat]=20#46=20TokenRepository=EC=97=90=20?= =?UTF-8?q?=EC=95=A1=EC=84=B8=EC=8A=A4=ED=86=A0=ED=81=B0,=20=EB=A6=AC?= =?UTF-8?q?=ED=94=84=EB=A0=88=EC=89=AC=ED=86=A0=ED=81=B0=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/yapp/buddycon/local/PreferenceKeys.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/local/src/main/java/com/yapp/buddycon/local/PreferenceKeys.kt b/core/local/src/main/java/com/yapp/buddycon/local/PreferenceKeys.kt index d9eaa157..73aed9dd 100644 --- a/core/local/src/main/java/com/yapp/buddycon/local/PreferenceKeys.kt +++ b/core/local/src/main/java/com/yapp/buddycon/local/PreferenceKeys.kt @@ -1,9 +1,13 @@ package com.yapp.buddycon.local import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey object PreferenceKeys { val IS_FIRST_INSTALLATION = booleanPreferencesKey("IS_FIRST_INSTALLATION") val NICKNAME = stringPreferencesKey("NICKNAME") + val ACCESS_TOKEN = stringPreferencesKey("ACCESS_TOKEN") + val REFRESH_TOKEN = stringPreferencesKey("REFRESH_TOKEN") + val ACCESS_TOKEN_EXPIRES_IN = longPreferencesKey("ACCESS_TOKEN_EXPIRES_IN") } From d6c892d8bfbaba337c0ff3ac3055e0dc3e3163d1 Mon Sep 17 00:00:00 2001 From: ows3090 Date: Mon, 12 Feb 2024 17:47:48 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[feat]=20#46=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EC=8B=9C=20=ED=86=A0=ED=81=B0=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EB=B0=8F=20=EC=9E=90=EB=8F=99=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 2 +- .../buddycon/navigation/BuddyConNavHost.kt | 7 ++++ .../network/service/auth/AuthService.kt | 14 +++++--- .../{AuthRequest.kt => LoginRequest.kt} | 2 +- .../service/auth/request/ReissueRequest.kt | 6 ++++ .../{AuthResponse.kt => LoginResponse.kt} | 10 +++--- .../repository/remote/AuthRepositoryImpl.kt | 21 ++++++++++-- .../domain/repository/AuthRepository.kt | 9 +++-- .../buddycon/startup/login/LoginScreen.kt | 20 +++++++++-- .../buddycon/startup/login/LoginViewModel.kt | 29 ++++++++++++++++ .../buddycon/startup/splash/SplashScreen.kt | 21 ++++++++++-- .../startup/splash/SplashViewModel.kt | 33 ++++++++++++++++++- 12 files changed, 152 insertions(+), 22 deletions(-) rename core/network/src/main/java/com/yapp/buddycon/network/service/auth/request/{AuthRequest.kt => LoginRequest.kt} (88%) create mode 100644 core/network/src/main/java/com/yapp/buddycon/network/service/auth/request/ReissueRequest.kt rename core/network/src/main/java/com/yapp/buddycon/network/service/auth/response/{AuthResponse.kt => LoginResponse.kt} (65%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2213c29a..a21707fc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,7 +8,7 @@ = flow { + emit( + authService.fetchReissue( + reissueRequest = ReissueRequest( + accessToken = "Bearer $accessToken", + refreshToken = refreshToken + ) + ).body.toModel() + ) + } } diff --git a/domain/src/main/java/com/yapp/buddycon/domain/repository/AuthRepository.kt b/domain/src/main/java/com/yapp/buddycon/domain/repository/AuthRepository.kt index 799ba0e9..44870d7d 100644 --- a/domain/src/main/java/com/yapp/buddycon/domain/repository/AuthRepository.kt +++ b/domain/src/main/java/com/yapp/buddycon/domain/repository/AuthRepository.kt @@ -1,6 +1,6 @@ package com.yapp.buddycon.domain.repository -import com.yapp.buddycon.domain.model.auth.AuthModel +import com.yapp.buddycon.domain.model.auth.LoginModel import kotlinx.coroutines.flow.Flow interface AuthRepository { @@ -10,5 +10,10 @@ interface AuthRepository { email: String, gender: String, age: String - ): Flow + ): Flow + + fun fetchReissue( + accessToken: String, + refreshToken: String + ): Flow } diff --git a/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginScreen.kt b/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginScreen.kt index df5a1eaf..1bc21400 100644 --- a/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginScreen.kt +++ b/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginScreen.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -29,7 +30,7 @@ import com.yapp.buddycon.designsystem.theme.Paddings import kotlinx.coroutines.CancellableContinuation import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine -import timber.log.Timber +import java.util.Calendar import kotlin.coroutines.resume private val LoginBannerDescription = "LoginBanner" @@ -43,6 +44,12 @@ fun LoginScreen( val context = LocalContext.current val coroutineScope = rememberCoroutineScope() + LaunchedEffect(Unit) { + loginViewModel.loginResult.collect { loginResult -> + if (loginResult) onNavigateToSignUp() + } + } + Column( modifier = Modifier .fillMaxSize() @@ -75,9 +82,16 @@ fun LoginScreen( user?.let { it.kakaoAccount?.profile?.nickname?.let { nickname -> loginViewModel.saveNickname(nickname) + loginViewModel.fetchLogin( + oauthAccessToken = token.accessToken, + nickname = nickname, + age = it.kakaoAccount?.birthyear?.let { + (Calendar.getInstance().get(Calendar.YEAR) - it.toInt()).toString() + }, + email = it.kakaoAccount?.email, + gender = it.kakaoAccount?.gender?.name + ) } - Timber.d("kakao token: $token") - onNavigateToSignUp() } } } diff --git a/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginViewModel.kt b/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginViewModel.kt index 66683f74..cc461d80 100644 --- a/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginViewModel.kt +++ b/feature/startup/src/main/java/com/yapp/buddycon/startup/login/LoginViewModel.kt @@ -5,6 +5,10 @@ import androidx.lifecycle.viewModelScope import com.yapp.buddycon.domain.repository.AuthRepository import com.yapp.buddycon.domain.repository.TokenRepository import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import javax.inject.Inject @@ -13,9 +17,34 @@ class LoginViewModel @Inject constructor( private val authRepository: AuthRepository, private val tokenRepository: TokenRepository ) : ViewModel() { + + private val _loginResult = MutableStateFlow(false) + val loginResult = _loginResult.asStateFlow() + fun saveNickname(nickname: String) { viewModelScope.launch { tokenRepository.saveNickname(nickname) } } + + fun fetchLogin( + oauthAccessToken: String, + nickname: String, + email: String?, + gender: String?, + age: String? + ) { + authRepository.fetchLogin( + oauthAccessToken = oauthAccessToken, + nickname = nickname, + email = email ?: "", + gender = gender ?: "", + age = age ?: "" + ).onEach { + tokenRepository.saveAccessToken(it.accessToken) + tokenRepository.saveRefreshToken(it.refreshToken) + tokenRepository.saveAccessTokenExpiresIn(it.accessTokenExpiresIn) + _loginResult.value = true + }.launchIn(viewModelScope) + } } diff --git a/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashScreen.kt b/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashScreen.kt index 34eb5418..a9ecdf17 100644 --- a/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashScreen.kt +++ b/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashScreen.kt @@ -13,6 +13,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.yapp.buddycon.designsystem.theme.BuddyConTheme import kotlinx.coroutines.delay +import timber.log.Timber private const val SplashIconDescription = "SplashIcon" @@ -20,18 +21,32 @@ private const val SplashIconDescription = "SplashIcon" fun SplashScreen( splashViewModel: SplashViewModel = hiltViewModel(), onNavigateToOnBoarding: () -> Unit = {}, - onNavigateToLogin: () -> Unit = {} + onNavigateToLogin: () -> Unit = {}, + onNavigateToGifticon: () -> Unit = {} ) { val systemUiController = rememberSystemUiController() systemUiController.setStatusBarColor(BuddyConTheme.colors.primaryVariant) + LaunchedEffect(Unit) { + splashViewModel.loginToken.collect { + if (System.currentTimeMillis() <= it.accessTokenExpiresIn) { + splashViewModel.fetchReissue() + } + } + } + LaunchedEffect(Unit) { delay(2000) + Timber.d("SplashScreen Token Info : ${splashViewModel.loginToken.value}, currentTime : ${System.currentTimeMillis()}") if (splashViewModel.isFirstInstallation.value) { - onNavigateToLogin() - } else { splashViewModel.checkIsFirstInstallation() onNavigateToOnBoarding() + } else { + if (System.currentTimeMillis() <= splashViewModel.loginToken.value.accessTokenExpiresIn) { + onNavigateToGifticon() + } else { + onNavigateToLogin() + } } } diff --git a/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashViewModel.kt b/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashViewModel.kt index 9f92c4fd..f705caf4 100644 --- a/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashViewModel.kt +++ b/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashViewModel.kt @@ -2,10 +2,13 @@ package com.yapp.buddycon.startup.splash import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.yapp.buddycon.domain.model.auth.LoginModel +import com.yapp.buddycon.domain.repository.AuthRepository import com.yapp.buddycon.domain.repository.TokenRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -13,14 +16,19 @@ import javax.inject.Inject @HiltViewModel class SplashViewModel @Inject constructor( - private val tokenRepository: TokenRepository + private val tokenRepository: TokenRepository, + private val authRepository: AuthRepository ) : ViewModel() { private val _isFirstInstallation = MutableStateFlow(false) val isFirstInstallation = _isFirstInstallation.asStateFlow() + private val _loginToken = MutableStateFlow(LoginModel()) + val loginToken = _loginToken.asStateFlow() + init { getIsFirstInstallation() + getLoginToken() } private fun getIsFirstInstallation() { @@ -34,4 +42,27 @@ class SplashViewModel @Inject constructor( tokenRepository.checkFirstInstallation() } } + + private fun getLoginToken() { + combine( + tokenRepository.getAccessToken(), + tokenRepository.getRefreshToken(), + tokenRepository.getAccessTokenExpiresIn() + ) { accessToken, refreshToken, accessTokenExpiresIn -> + LoginModel( + accessToken = accessToken, + refreshToken = refreshToken, + accessTokenExpiresIn = accessTokenExpiresIn + ) + }.onEach { _loginToken.value = it } + .launchIn(viewModelScope) + } + + fun fetchReissue() { + authRepository.fetchReissue( + accessToken = _loginToken.value.accessToken, + refreshToken = _loginToken.value.refreshToken + ).onEach { _loginToken.value = it } + .launchIn(viewModelScope) + } } From 3009bb513efe7032f22beeb19c7a5451ed3835e2 Mon Sep 17 00:00:00 2001 From: ows3090 Date: Mon, 12 Feb 2024 20:04:21 +0900 Subject: [PATCH 5/5] =?UTF-8?q?[feat]=20#46=20=EC=9E=90=EB=8F=99=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=20=EC=9E=AC=EB=B0=9C=ED=96=89=20=EC=8B=9C?= =?UTF-8?q?=ED=82=A4=EB=8A=94=20interceptor=20=EA=B0=9C=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../buddycon/network/di/InterceptorModule.kt | 13 ++++++ .../yapp/buddycon/network/di/NetworkModule.kt | 29 +++++++++++- .../yapp/buddycon/network/di/ServiceModule.kt | 3 +- .../interceptor/BuddyConInterceptor.kt | 44 +++++++++++++++++++ .../service/gifticon/GiftiConService.kt | 4 -- .../repository/local/TokenRepositoryImpl.kt | 2 +- .../buddycon/domain/model/auth/AuthModel.kt | 7 --- .../buddycon/domain/model/auth/LoginModel.kt | 7 +++ .../buddycon/startup/splash/SplashScreen.kt | 2 +- .../startup/splash/SplashViewModel.kt | 12 +++-- 10 files changed, 103 insertions(+), 20 deletions(-) create mode 100644 core/network/src/main/java/com/yapp/buddycon/network/interceptor/BuddyConInterceptor.kt delete mode 100644 domain/src/main/java/com/yapp/buddycon/domain/model/auth/AuthModel.kt create mode 100644 domain/src/main/java/com/yapp/buddycon/domain/model/auth/LoginModel.kt diff --git a/core/network/src/main/java/com/yapp/buddycon/network/di/InterceptorModule.kt b/core/network/src/main/java/com/yapp/buddycon/network/di/InterceptorModule.kt index f404f4d3..c154b6fe 100644 --- a/core/network/src/main/java/com/yapp/buddycon/network/di/InterceptorModule.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/di/InterceptorModule.kt @@ -1,7 +1,11 @@ package com.yapp.buddycon.network.di +import com.yapp.buddycon.domain.repository.AuthRepository +import com.yapp.buddycon.domain.repository.TokenRepository import com.yapp.buddycon.network.BuildConfig +import com.yapp.buddycon.network.di.qualifiers.BuddyConInterceptorQualifier import com.yapp.buddycon.network.di.qualifiers.HttpLoggingInterceptorQualifier +import com.yapp.buddycon.network.interceptor.BuddyConInterceptor import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -20,4 +24,13 @@ object InterceptorModule { HttpLoggingInterceptor().apply { level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE } + + @BuddyConInterceptorQualifier + @Provides + @Singleton + fun provideBuddyConInterceptor( + authRepository: AuthRepository, + tokenRepository: TokenRepository + ): Interceptor = + BuddyConInterceptor(authRepository, tokenRepository) } diff --git a/core/network/src/main/java/com/yapp/buddycon/network/di/NetworkModule.kt b/core/network/src/main/java/com/yapp/buddycon/network/di/NetworkModule.kt index 6741c460..e3c7c83e 100644 --- a/core/network/src/main/java/com/yapp/buddycon/network/di/NetworkModule.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/di/NetworkModule.kt @@ -1,8 +1,11 @@ package com.yapp.buddycon.network.di import com.yapp.buddycon.network.di.qualifiers.BuddyConClient +import com.yapp.buddycon.network.di.qualifiers.BuddyConInterceptorQualifier import com.yapp.buddycon.network.di.qualifiers.BuddyConRetrofit import com.yapp.buddycon.network.di.qualifiers.HttpLoggingInterceptorQualifier +import com.yapp.buddycon.network.di.qualifiers.LoginClient +import com.yapp.buddycon.network.di.qualifiers.LoginRetrofit import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -18,16 +21,38 @@ import javax.inject.Singleton object NetworkModule { private const val BUDDYCON_BASE_URL = "http://43.202.14.1:8080/" + @LoginClient + @Provides + @Singleton + fun provideLoginClient( + @HttpLoggingInterceptorQualifier httpLoggingInterceptor: Interceptor + ): OkHttpClient = + OkHttpClient.Builder() + .addInterceptor(httpLoggingInterceptor) + .build() + + @LoginRetrofit + @Provides + @Singleton + fun provideLoginRetrofit( + @LoginClient okHttpClient: OkHttpClient + ): Retrofit = + Retrofit.Builder() + .baseUrl(BUDDYCON_BASE_URL) + .client(okHttpClient) + .addConverterFactory(GsonConverterFactory.create()) + .build() + @BuddyConClient @Provides @Singleton fun provideBuddyConClient( @HttpLoggingInterceptorQualifier httpLoggingInterceptor: Interceptor, - // @BuddyConInterceptorQualifier buddyConInterceptor: Interceptor + @BuddyConInterceptorQualifier buddyConInterceptor: Interceptor ): OkHttpClient = OkHttpClient.Builder() .addInterceptor(httpLoggingInterceptor) - // .addInterceptor(buddyConInterceptor) + .addInterceptor(buddyConInterceptor) .build() @BuddyConRetrofit diff --git a/core/network/src/main/java/com/yapp/buddycon/network/di/ServiceModule.kt b/core/network/src/main/java/com/yapp/buddycon/network/di/ServiceModule.kt index 1ca9c51b..60ff270f 100644 --- a/core/network/src/main/java/com/yapp/buddycon/network/di/ServiceModule.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/di/ServiceModule.kt @@ -1,6 +1,7 @@ package com.yapp.buddycon.network.di import com.yapp.buddycon.network.di.qualifiers.BuddyConRetrofit +import com.yapp.buddycon.network.di.qualifiers.LoginRetrofit import com.yapp.buddycon.network.service.auth.AuthService import com.yapp.buddycon.network.service.gifticon.GiftiConService import dagger.Module @@ -18,7 +19,7 @@ object ServiceModule { @Provides @Singleton fun provideAuthService( - @BuddyConRetrofit retrofit: Retrofit + @LoginRetrofit retrofit: Retrofit ): AuthService = retrofit.create() diff --git a/core/network/src/main/java/com/yapp/buddycon/network/interceptor/BuddyConInterceptor.kt b/core/network/src/main/java/com/yapp/buddycon/network/interceptor/BuddyConInterceptor.kt new file mode 100644 index 00000000..5b2f1739 --- /dev/null +++ b/core/network/src/main/java/com/yapp/buddycon/network/interceptor/BuddyConInterceptor.kt @@ -0,0 +1,44 @@ +package com.yapp.buddycon.network.interceptor + +import com.yapp.buddycon.domain.repository.AuthRepository +import com.yapp.buddycon.domain.repository.TokenRepository +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.runBlocking +import okhttp3.Interceptor +import okhttp3.Response +import javax.inject.Inject + +class BuddyConInterceptor @Inject constructor( + private val authRepository: AuthRepository, + private val tokenRepository: TokenRepository +) : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + var accessToken = runBlocking { tokenRepository.getAccessToken().first() } + val refreshToken = runBlocking { tokenRepository.getRefreshToken().first() } + val accessTokenExpiresIn = runBlocking { tokenRepository.getAccessTokenExpiresIn().first() } + val currentTime = System.currentTimeMillis() + + if (accessTokenExpiresIn < currentTime) { + try { + val token = runBlocking { + authRepository.fetchReissue( + accessToken = accessToken, + refreshToken = refreshToken + ).first() + } + accessToken = token.accessToken + runBlocking { + tokenRepository.saveAccessToken(accessToken) + tokenRepository.saveRefreshToken(refreshToken) + tokenRepository.saveAccessTokenExpiresIn(accessTokenExpiresIn) + } + } catch (e: Exception) { + } + } + + val newRequest = chain.request().newBuilder() + .addHeader("Authorization", "Bearer $accessToken") + .build() + return chain.proceed(newRequest) + } +} diff --git a/core/network/src/main/java/com/yapp/buddycon/network/service/gifticon/GiftiConService.kt b/core/network/src/main/java/com/yapp/buddycon/network/service/gifticon/GiftiConService.kt index 50d068bc..3c6bfb04 100644 --- a/core/network/src/main/java/com/yapp/buddycon/network/service/gifticon/GiftiConService.kt +++ b/core/network/src/main/java/com/yapp/buddycon/network/service/gifticon/GiftiConService.kt @@ -3,15 +3,11 @@ package com.yapp.buddycon.network.service.gifticon import com.yapp.buddycon.network.service.gifticon.response.AvailableGifticonResponse import retrofit2.Response import retrofit2.http.GET -import retrofit2.http.Header import retrofit2.http.Query interface GiftiConService { @GET("api/v1/gifticons/available") suspend fun requestGiftiConDetail( - @Header("Authorization") token: String = "Bearer " + - "eyJhbGciOiJIUzUxMiJ9.eyJpZCI6MiwiaWF0IjoxNzAyNzg5NDc2LCJleHAiOjE3MDg4Mzc0NzZ9." + - "8YPrIlLexzGiqHwE1T_n2E-hCYbsNqJA5kUPWwgD0H8GmrGGsMgexme4NnNzBgsiHWG2uGtDLZL9fDCdiyZNUw", @Query("pageNumber") pageNumber: Int, // page @Query("gifticonStoreCategory") gifticonStoreCategory: String?, // 기프티콘 가게 카테고리 @Query("rowCount") rowCount: Int = 20 // page 당 요청 데이터 개수 diff --git a/data/src/main/java/com/yapp/buddycon/data/repository/local/TokenRepositoryImpl.kt b/data/src/main/java/com/yapp/buddycon/data/repository/local/TokenRepositoryImpl.kt index c66a577f..e1d76376 100644 --- a/data/src/main/java/com/yapp/buddycon/data/repository/local/TokenRepositoryImpl.kt +++ b/data/src/main/java/com/yapp/buddycon/data/repository/local/TokenRepositoryImpl.kt @@ -62,7 +62,7 @@ class TokenRepositoryImpl @Inject constructor( override fun getAccessTokenExpiresIn(): Flow = dataStore.data.map { preference -> - preference[ACCESS_TOKEN_EXPIRES_IN] ?: 0L + preference[ACCESS_TOKEN_EXPIRES_IN] ?: Long.MAX_VALUE } override suspend fun saveAccessTokenExpiresIn(expire: Long) { diff --git a/domain/src/main/java/com/yapp/buddycon/domain/model/auth/AuthModel.kt b/domain/src/main/java/com/yapp/buddycon/domain/model/auth/AuthModel.kt deleted file mode 100644 index 306eb842..00000000 --- a/domain/src/main/java/com/yapp/buddycon/domain/model/auth/AuthModel.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.yapp.buddycon.domain.model.auth - -data class AuthModel( - val accessToken: String, - val refreshToken: String, - val accessTokenExpiresIn: Long -) diff --git a/domain/src/main/java/com/yapp/buddycon/domain/model/auth/LoginModel.kt b/domain/src/main/java/com/yapp/buddycon/domain/model/auth/LoginModel.kt new file mode 100644 index 00000000..955a76cb --- /dev/null +++ b/domain/src/main/java/com/yapp/buddycon/domain/model/auth/LoginModel.kt @@ -0,0 +1,7 @@ +package com.yapp.buddycon.domain.model.auth + +data class LoginModel( + val accessToken: String = "", + val refreshToken: String = "", + val accessTokenExpiresIn: Long = Long.MAX_VALUE +) diff --git a/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashScreen.kt b/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashScreen.kt index a9ecdf17..9e74aad4 100644 --- a/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashScreen.kt +++ b/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashScreen.kt @@ -29,7 +29,7 @@ fun SplashScreen( LaunchedEffect(Unit) { splashViewModel.loginToken.collect { - if (System.currentTimeMillis() <= it.accessTokenExpiresIn) { + if (it.accessTokenExpiresIn <= System.currentTimeMillis()) { splashViewModel.fetchReissue() } } diff --git a/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashViewModel.kt b/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashViewModel.kt index f705caf4..0f02a8fb 100644 --- a/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashViewModel.kt +++ b/feature/startup/src/main/java/com/yapp/buddycon/startup/splash/SplashViewModel.kt @@ -16,8 +16,8 @@ import javax.inject.Inject @HiltViewModel class SplashViewModel @Inject constructor( - private val tokenRepository: TokenRepository, - private val authRepository: AuthRepository + private val authRepository: AuthRepository, + private val tokenRepository: TokenRepository ) : ViewModel() { private val _isFirstInstallation = MutableStateFlow(false) @@ -62,7 +62,11 @@ class SplashViewModel @Inject constructor( authRepository.fetchReissue( accessToken = _loginToken.value.accessToken, refreshToken = _loginToken.value.refreshToken - ).onEach { _loginToken.value = it } - .launchIn(viewModelScope) + ).onEach { + _loginToken.value = it + tokenRepository.saveAccessToken(it.accessToken) + tokenRepository.saveRefreshToken(it.refreshToken) + tokenRepository.saveAccessTokenExpiresIn(it.accessTokenExpiresIn) + }.launchIn(viewModelScope) } }