Updated on 2026-08-14
This commit is contained in:
parent
113c9cb46e
commit
4192ccab33
34 changed files with 444 additions and 81 deletions
|
|
@ -0,0 +1,54 @@
|
|||
package com.tangem.tap.data
|
||||
|
||||
import android.content.Context
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
||||
import com.tangem.common.services.secure.SecureStorage
|
||||
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
||||
import com.tangem.domain.visa.model.VisaAuthTokens
|
||||
import com.tangem.sdk.storage.AndroidSecureStorage
|
||||
import com.tangem.sdk.storage.createEncryptedSharedPreferences
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
internal class DefaultVisaAuthTokenStorage @Inject constructor(
|
||||
@ApplicationContext applicationContext: Context,
|
||||
private val dispatcherProvider: CoroutineDispatcherProvider,
|
||||
) : VisaAuthTokenStorage {
|
||||
|
||||
private val secureStorage = AndroidSecureStorage(
|
||||
preferences = SecureStorage.createEncryptedSharedPreferences(
|
||||
context = applicationContext,
|
||||
storageName = "visa_auth_storage",
|
||||
),
|
||||
)
|
||||
|
||||
private val moshi = Moshi.Builder()
|
||||
.add(KotlinJsonAdapterFactory())
|
||||
.build()
|
||||
|
||||
private val tokensAdapter = moshi.adapter(VisaAuthTokens::class.java)
|
||||
|
||||
override suspend fun store(tokens: VisaAuthTokens) = withContext(dispatcherProvider.io) {
|
||||
val json = tokensAdapter.toJson(tokens)
|
||||
|
||||
secureStorage.store(
|
||||
json.encodeToByteArray(throwOnInvalidSequence = true),
|
||||
VISA_AUTH_TOKENS_KEY,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun get(): VisaAuthTokens? = withContext(dispatcherProvider.io) {
|
||||
secureStorage.get(VISA_AUTH_TOKENS_KEY)
|
||||
?.decodeToString(throwOnInvalidSequence = true)
|
||||
?.let(tokensAdapter::fromJson)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val VISA_AUTH_TOKENS_KEY = "visa_auth_tokens"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.tap.di.data
|
||||
|
||||
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
||||
import com.tangem.tap.data.DefaultVisaAuthTokenStorage
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface VisaStorageModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindVisaStorage(impl: DefaultVisaAuthTokenStorage): VisaAuthTokenStorage
|
||||
}
|
||||
|
|
@ -7,11 +7,10 @@ import com.tangem.common.core.TangemSdkError
|
|||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
|
||||
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
||||
import com.tangem.domain.common.visa.VisaUtilities
|
||||
import com.tangem.domain.visa.model.VisaActivationInput
|
||||
import com.tangem.domain.visa.model.VisaAuthSignedChallenge
|
||||
import com.tangem.domain.visa.model.VisaCardActivationStatus
|
||||
import com.tangem.domain.visa.model.toSignedChallenge
|
||||
import com.tangem.domain.visa.model.*
|
||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||
import com.tangem.domain.visa.repository.VisaAuthRepository
|
||||
import com.tangem.operations.attestation.AttestCardKeyCommand
|
||||
import com.tangem.operations.attestation.AttestCardKeyResponse
|
||||
|
|
@ -25,6 +24,8 @@ import kotlin.coroutines.resume
|
|||
|
||||
internal class VisaCardScanHandler @Inject constructor(
|
||||
private val visaAuthRepository: VisaAuthRepository,
|
||||
private val visaActivationRepository: VisaActivationRepository,
|
||||
private val visaAuthTokenStorage: VisaAuthTokenStorage,
|
||||
) {
|
||||
|
||||
suspend fun handleVisaCardScan(session: CardSession): CompletionResult<VisaCardActivationStatus> {
|
||||
|
|
@ -153,6 +154,8 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
return handleCardAuthorization(session)
|
||||
}
|
||||
|
||||
visaAuthTokenStorage.store(authorizationTokensResponse)
|
||||
|
||||
Timber.i("Authorized using Wallet public key successfully")
|
||||
|
||||
return CompletionResult.Success(VisaCardActivationStatus.Activated(authorizationTokensResponse))
|
||||
|
|
@ -207,7 +210,33 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
TODO() // implement card activation status handling ([REDACTED_TASK_KEY])
|
||||
visaAuthTokenStorage.store(authorizationTokensResponse)
|
||||
|
||||
val activationRemoteState = visaActivationRepository.getActivationRemoteState()
|
||||
|
||||
val error = when (activationRemoteState) {
|
||||
VisaActivationRemoteState.BlockedForActivation -> VisaActivationError.BlockedForActivation
|
||||
VisaActivationRemoteState.Activated -> VisaActivationError.InvalidActivationState
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
return CompletionResult.Failure(TangemSdkError.Underlying(error.message))
|
||||
}
|
||||
|
||||
val activationInput = VisaActivationInput(
|
||||
cardId = card.cardId,
|
||||
cardPublicKey = card.cardPublicKey,
|
||||
isAccessCodeSet = card.isAccessCodeSet,
|
||||
)
|
||||
|
||||
return CompletionResult.Success(
|
||||
VisaCardActivationStatus.ActivationStarted(
|
||||
activationInput = activationInput,
|
||||
authTokens = authorizationTokensResponse,
|
||||
remoteState = activationRemoteState,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun signChallengeWithWallet(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.tap.network.auth
|
||||
|
||||
import com.tangem.datasource.api.common.visa.TangemVisaAuthProvider
|
||||
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultVisaAuthProvider @Inject constructor(
|
||||
private val authStorage: VisaAuthTokenStorage,
|
||||
) : TangemVisaAuthProvider {
|
||||
|
||||
override suspend fun getAuthHeader(): String {
|
||||
return authStorage.get()?.accessToken?.let { "Bearer $it" } ?: "Error in the app!"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,21 @@
|
|||
package com.tangem.tap.network.auth.di
|
||||
|
||||
import com.tangem.datasource.api.common.AuthProvider
|
||||
import com.tangem.datasource.api.common.visa.TangemVisaAuthProvider
|
||||
import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.lib.auth.ExpressAuthProvider
|
||||
import com.tangem.lib.auth.StakeKitAuthProvider
|
||||
import com.tangem.tap.network.auth.*
|
||||
import com.tangem.tap.network.auth.DefaultAppVersionProvider
|
||||
import com.tangem.tap.network.auth.DefaultAuthProvider
|
||||
import com.tangem.tap.network.auth.DefaultExpressAuthProvider
|
||||
import com.tangem.tap.network.auth.DefaultStakeKitAuthProvider
|
||||
import com.tangem.tap.network.auth.DefaultVisaAuthProvider
|
||||
import com.tangem.utils.version.AppVersionProvider
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
|
@ -20,7 +24,7 @@ import javax.inject.Singleton
|
|||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
class AuthModule {
|
||||
internal class AuthModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
|
|
@ -51,4 +55,13 @@ class AuthModule {
|
|||
fun provideAppVersionProvider(): AppVersionProvider {
|
||||
return DefaultAppVersionProvider()
|
||||
}
|
||||
}
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface AuthBindModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindVisaAuthProvider(authStorage: DefaultVisaAuthProvider): TangemVisaAuthProvider
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue