From 7da3ecd73d27091e926fa672c3de2b8cf1b3353b Mon Sep 17 00:00:00 2001 From: HashEngineering Date: Fri, 2 Feb 2024 16:53:25 -0500 Subject: [PATCH] fix: Update RemoteDataSource for CTXSpend --- .../exploredash/di/ExploreDashModule.kt | 8 ++- .../exploredash/network/RemoteDataSource.kt | 21 ++++-- .../network/interceptor/HeadersInterceptor.kt | 6 +- .../repository/remote/TokenAuthenticator.kt | 70 +++++++++++++++++++ .../res/layout/dialog_gift_card_details.xml | 2 +- 5 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/remote/TokenAuthenticator.kt diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/di/ExploreDashModule.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/di/ExploreDashModule.kt index 1f9da0e364..80501a4aff 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/di/ExploreDashModule.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/di/ExploreDashModule.kt @@ -37,6 +37,7 @@ import org.dash.wallet.features.exploredash.network.service.DashDirectAuthApi import org.dash.wallet.features.exploredash.network.service.DashDirectServicesApi import org.dash.wallet.features.exploredash.network.service.ctxspend.CTXSpendApi import org.dash.wallet.features.exploredash.network.service.ctxspend.CTXSpendDataSource +import org.dash.wallet.features.exploredash.network.service.ctxspend.CTXSpendTokenApi import org.dash.wallet.features.exploredash.repository.* import org.dash.wallet.features.exploredash.services.UserLocationState import org.dash.wallet.features.exploredash.services.UserLocationStateInt @@ -70,7 +71,7 @@ abstract class ExploreDashModule { return CTXSpendDataSource(userConfiguration, config) } - fun provideRemoteDataSource(config: DashDirectConfig): RemoteDataSource { + fun provideRemoteDataSource(config: CTXSpendConfig): RemoteDataSource { return RemoteDataSource(config) } @@ -87,6 +88,11 @@ abstract class ExploreDashModule { fun provideApi(ctxSpendDataSource: CTXSpendDataSource): CTXSpendApi { return ctxSpendDataSource.buildApi(CTXSpendApi::class.java) } + + @Provides + fun provideCTXAuthApi(remoteDataSource: RemoteDataSource): CTXSpendTokenApi { + return remoteDataSource.buildApi(CTXSpendTokenApi::class.java) + } } @Binds diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/network/RemoteDataSource.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/network/RemoteDataSource.kt index d47006c21c..7a64a363a1 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/network/RemoteDataSource.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/network/RemoteDataSource.kt @@ -20,8 +20,10 @@ import okhttp3.Authenticator import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import org.dash.wallet.features.exploredash.network.interceptor.HeadersInterceptor -import org.dash.wallet.features.exploredash.utils.DashDirectConfig -import org.dash.wallet.features.exploredash.utils.DashDirectConstants +import org.dash.wallet.features.exploredash.network.service.ctxspend.CTXSpendTokenApi +import org.dash.wallet.features.exploredash.repository.remote.TokenAuthenticator +import org.dash.wallet.features.exploredash.utils.CTXSpendConfig +import org.dash.wallet.features.exploredash.utils.CTXSpendConstants import org.slf4j.LoggerFactory import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory @@ -29,20 +31,29 @@ import javax.inject.Inject import kotlin.time.Duration.Companion.seconds import kotlin.time.toJavaDuration -class RemoteDataSource @Inject constructor(private val config: DashDirectConfig) { +class RemoteDataSource @Inject constructor(private val config: CTXSpendConfig) { companion object { private val log = LoggerFactory.getLogger(RemoteDataSource::class.java) } fun buildApi(api: Class): Api { return Retrofit.Builder() - .baseUrl(DashDirectConstants.BASE_URL) - .client(getOkHttpClient()) + .baseUrl(CTXSpendConstants.BASE_URL) + .client(getOkHttpClient(TokenAuthenticator(buildTokenApi(), config))) .addConverterFactory(GsonConverterFactory.create()) .build() .create(api) } + private fun buildTokenApi(): CTXSpendTokenApi { + return Retrofit.Builder() + .baseUrl(CTXSpendConstants.BASE_URL) + .client(getOkHttpClient()) + .addConverterFactory(GsonConverterFactory.create()) + .build() + .create(CTXSpendTokenApi::class.java) + } + private fun getOkHttpClient(authenticator: Authenticator? = null): OkHttpClient { return OkHttpClient.Builder() .addInterceptor(HeadersInterceptor(config)) diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/network/interceptor/HeadersInterceptor.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/network/interceptor/HeadersInterceptor.kt index fdc8b53ce0..8ffb0e6c5e 100644 --- a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/network/interceptor/HeadersInterceptor.kt +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/network/interceptor/HeadersInterceptor.kt @@ -19,11 +19,11 @@ package org.dash.wallet.features.exploredash.network.interceptor import kotlinx.coroutines.runBlocking import okhttp3.Interceptor import okhttp3.Response -import org.dash.wallet.features.exploredash.utils.DashDirectConfig +import org.dash.wallet.features.exploredash.utils.CTXSpendConfig import org.dash.wallet.features.exploredash.utils.DashDirectConstants import javax.inject.Inject -class HeadersInterceptor @Inject constructor(private val config: DashDirectConfig) : Interceptor { +class HeadersInterceptor @Inject constructor(private val config: CTXSpendConfig) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val original = chain.request() @@ -32,7 +32,7 @@ class HeadersInterceptor @Inject constructor(private val config: DashDirectConfi requestBuilder.header(DashDirectConstants.CLIENT_ID_PARAM_NAME, DashDirectConstants.CLIENT_ID) val accessToken = runBlocking { - config.getSecuredData(DashDirectConfig.PREFS_KEY_ACCESS_TOKEN) + config.getSecuredData(CTXSpendConfig.PREFS_KEY_ACCESS_TOKEN) } if (accessToken?.isNotEmpty() == true) { diff --git a/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/remote/TokenAuthenticator.kt b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/remote/TokenAuthenticator.kt new file mode 100644 index 0000000000..c48db19535 --- /dev/null +++ b/features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/remote/TokenAuthenticator.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2021 Dash Core Group. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.dash.wallet.features.exploredash.repository.remote + +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import okhttp3.Authenticator +import okhttp3.Request +import okhttp3.Response +import okhttp3.Route +import org.dash.wallet.common.data.ResponseResource +import org.dash.wallet.common.data.safeApiCall +import org.dash.wallet.features.exploredash.data.ctxspend.model.RefreshTokenResponse +import org.dash.wallet.features.exploredash.network.service.ctxspend.CTXSpendTokenApi +import org.dash.wallet.features.exploredash.utils.CTXSpendConfig +import javax.inject.Inject + +class TokenAuthenticator @Inject constructor( + private val tokenApi: CTXSpendTokenApi, + private val config: CTXSpendConfig +) : Authenticator { + + // For multiple call to refresh token sync + private val tokenMutex = Mutex() + + override fun authenticate(route: Route?, response: Response): Request? { + return runBlocking { + tokenMutex.withLock { + when (val tokenResponse = getUpdatedToken()) { + is ResponseResource.Success -> { + tokenResponse.value?.let { + config.set(CTXSpendConfig.PREFS_KEY_ACCESS_TOKEN, it.accessToken?: "") + config.set(CTXSpendConfig.PREFS_KEY_REFRESH_TOKEN, it.refreshToken?: "") + response.request.newBuilder() + .header("Authorization", "Bearer ${it.accessToken}") + .build() + } + } + + else -> { + config.set(CTXSpendConfig.PREFS_KEY_ACCESS_TOKEN, "") + config.set(CTXSpendConfig.PREFS_KEY_REFRESH_TOKEN, "") + null + } + } + } + } + } + + private suspend fun getUpdatedToken(): ResponseResource { + val accessToken = config.get(CTXSpendConfig.PREFS_KEY_ACCESS_TOKEN) ?: "" + val refreshToken = config.get(CTXSpendConfig.PREFS_KEY_REFRESH_TOKEN) ?: "" + return safeApiCall { tokenApi.refreshToken(refreshToken = refreshToken) } + } +} diff --git a/features/exploredash/src/main/res/layout/dialog_gift_card_details.xml b/features/exploredash/src/main/res/layout/dialog_gift_card_details.xml index edb5042e98..f74b438eda 100644 --- a/features/exploredash/src/main/res/layout/dialog_gift_card_details.xml +++ b/features/exploredash/src/main/res/layout/dialog_gift_card_details.xml @@ -22,7 +22,7 @@ android:layout_height="match_parent" android:orientation="vertical" tools:background="@color/background_primary" - tools:context="org.dash.wallet.features.exploredash.ui.dashdirect.dialogs.GiftCardDetailsDialog"> + tools:context="org.dash.wallet.features.exploredash.ui.ctxspend.dialogs.GiftCardDetailsDialog">