From b3519f2866921fd5eb1691c69bacccdb6d4f30b6 Mon Sep 17 00:00:00 2001 From: Balazs Gerlei Date: Fri, 8 Nov 2024 14:53:14 +0100 Subject: [PATCH] Feature/nevisaccessapp 6287 multi user transaction confirmation fixes (#27) - Pass only the filtered (valid) accounts to transaction confirmation and account selector when there are multiple registered accounts - Change the order Account Selection and Transaction Confirmation screens are shown: the former now displayed before the latter - Transaction Confirmation screen now only deals with a single Account as that should be selected before that - Transaction Confirmation message is passed along Account Selection now - Simplified/clarified logic in AccountSelectorImpl - Add TransactionConfirmationResponse and TransactionConfirmationUseCase and its implementation, the former is used by AccountSelectorImpl and the latter is used by SelectAccountViewModel to show transaction confirmation when a message is received --- .../coroutines/dagger/ApplicationModule.kt | 10 ++++ .../domain/interaction/AccountSelectorImpl.kt | 40 ++++++++++------ .../model/response/SelectAccountResponse.kt | 14 +++--- .../TransactionConfirmationResponse.kt | 32 +++++++++++++ .../usecase/TransactionConfirmationUseCase.kt | 26 +++++++++++ .../TransactionConfirmationUseCaseImpl.kt | 29 ++++++++++++ .../ui/base/ResponseObserverFragment.kt | 38 ++++++++------- .../ui/selectAccount/SelectAccountFragment.kt | 7 +-- .../selectAccount/SelectAccountViewModel.kt | 46 ++++++++++++++----- .../SelectAccountNavigationParameter.kt | 9 +++- .../TransactionConfirmationFragment.kt | 9 ++-- .../TransactionConfirmationViewModel.kt | 21 +++------ ...nsactionConfirmationNavigationParameter.kt | 21 +++------ 13 files changed, 210 insertions(+), 92 deletions(-) create mode 100644 app/src/main/java/ch/nevis/exampleapp/coroutines/domain/model/response/TransactionConfirmationResponse.kt create mode 100644 app/src/main/java/ch/nevis/exampleapp/coroutines/domain/usecase/TransactionConfirmationUseCase.kt create mode 100644 app/src/main/java/ch/nevis/exampleapp/coroutines/domain/usecase/TransactionConfirmationUseCaseImpl.kt diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/dagger/ApplicationModule.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/dagger/ApplicationModule.kt index 092be4e..cb7e3dc 100644 --- a/app/src/main/java/ch/nevis/exampleapp/coroutines/dagger/ApplicationModule.kt +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/dagger/ApplicationModule.kt @@ -96,6 +96,8 @@ import ch.nevis.exampleapp.coroutines.domain.usecase.StartChangePasswordUseCase import ch.nevis.exampleapp.coroutines.domain.usecase.StartChangePasswordUseCaseImpl import ch.nevis.exampleapp.coroutines.domain.usecase.StartChangePinUseCase import ch.nevis.exampleapp.coroutines.domain.usecase.StartChangePinUseCaseImpl +import ch.nevis.exampleapp.coroutines.domain.usecase.TransactionConfirmationUseCase +import ch.nevis.exampleapp.coroutines.domain.usecase.TransactionConfirmationUseCaseImpl import ch.nevis.exampleapp.coroutines.domain.usecase.VerifyBiometricUseCase import ch.nevis.exampleapp.coroutines.domain.usecase.VerifyBiometricUseCaseImpl import ch.nevis.exampleapp.coroutines.domain.usecase.VerifyDevicePasscodeUseCase @@ -797,6 +799,14 @@ class ApplicationModule { clientProvider: ClientProvider ): ChangeDeviceInformationUseCase = ChangeDeviceInformationUseCaseImpl(clientProvider) + /** + * Provides use case for transaction confirmation. + * + * @return The use case for transaction confirmation. + */ + @Provides + fun provideTransactionConfirmationUseCase(): TransactionConfirmationUseCase = TransactionConfirmationUseCaseImpl() + /** * Provides use case for starting an in-band authentication operation. * diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/interaction/AccountSelectorImpl.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/interaction/AccountSelectorImpl.kt index 0ce4628..c87b840 100644 --- a/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/interaction/AccountSelectorImpl.kt +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/interaction/AccountSelectorImpl.kt @@ -1,7 +1,7 @@ /** * Nevis Mobile Authentication SDK Example App * - * Copyright © 2022. Nevis Security AG. All rights reserved. + * Copyright © 2022-2024. Nevis Security AG. All rights reserved. */ package ch.nevis.exampleapp.coroutines.domain.interaction @@ -9,6 +9,7 @@ package ch.nevis.exampleapp.coroutines.domain.interaction import ch.nevis.exampleapp.coroutines.domain.model.error.BusinessException import ch.nevis.exampleapp.coroutines.domain.model.response.ErrorResponse import ch.nevis.exampleapp.coroutines.domain.model.response.SelectAccountResponse +import ch.nevis.exampleapp.coroutines.domain.model.response.TransactionConfirmationResponse import ch.nevis.exampleapp.coroutines.domain.model.state.UserInteractionOperationState import ch.nevis.exampleapp.coroutines.domain.repository.OperationStateRepository import ch.nevis.exampleapp.coroutines.timber.sdk @@ -46,24 +47,33 @@ class AccountSelectorImpl( val cancellableContinuation = operationState.cancellableContinuation ?: throw BusinessException.invalidState() - val transactionConfirmationData = + val transactionConfirmationData: ByteArray? = accountSelectionContext.transactionConfirmationData().orElse(null) val accounts = validAccounts(accountSelectionContext) - if (accounts.isEmpty()) { - cancellableContinuation.resume(ErrorResponse(BusinessException.accountsNotFound())) - } else if (transactionConfirmationData == null && accounts.size == 1) { - accountSelectionHandler.username( - accountSelectionContext.accounts().first().username() - ) - } else { - cancellableContinuation.resume( - SelectAccountResponse( - operationState.operation, - accountSelectionContext.accounts(), - transactionConfirmationData + when(accounts.size) { + 0 -> cancellableContinuation.resume(ErrorResponse(BusinessException.accountsNotFound())) + 1 -> { + if (transactionConfirmationData != null) { + cancellableContinuation.resume( + TransactionConfirmationResponse( + account = accounts.first(), + transactionConfirmationMessage = transactionConfirmationData.decodeToString() + ) + ) + } else { + accountSelectionHandler.username(accounts.first().username()) + } + } + else -> { + cancellableContinuation.resume( + SelectAccountResponse( + operation = operationState.operation, + accounts = accounts, + transactionConfirmationMessage = transactionConfirmationData?.decodeToString() + ) ) - ) + } } } //endregion diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/model/response/SelectAccountResponse.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/model/response/SelectAccountResponse.kt index 23fa513..d2c8c33 100644 --- a/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/model/response/SelectAccountResponse.kt +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/model/response/SelectAccountResponse.kt @@ -1,7 +1,7 @@ /** * Nevis Mobile Authentication SDK Example App * - * Copyright © 2022. Nevis Security AG. All rights reserved. + * Copyright © 2022-2024. Nevis Security AG. All rights reserved. */ package ch.nevis.exampleapp.coroutines.domain.model.response @@ -12,14 +12,14 @@ import ch.nevis.mobile.sdk.api.localdata.Account /** * [Response] class that indicates an account selection has to be started. * Typically the received [Account] set is shown to the user and he/she selects one of them. - * After the account selection [ch.nevis.exampleapp.coroutines.domain.usecase.SelectAccountUseCase] is called - * to continue the operation. + * After the account selection [ch.nevis.exampleapp.coroutines.domain.usecase.SelectAccountUseCase] + * is called to continue the operation. * * @constructor Creates a new instance. * @param operation The [Operation] the account selection requested for. * @param accounts The set of enrolled accounts the user has to choose from. - * @param transactionConfirmationData The optional transaction data that might be sent during an - * authentication process. + * @param transactionConfirmationMessage The optional transaction data/message that might be sent + * during an authentication process. */ class SelectAccountResponse( @@ -34,7 +34,7 @@ class SelectAccountResponse( val accounts: Set, /** - * The optional transaction data that might be sent during an authentication process. + * The optional transaction data/message that is sent during an authentication process. */ - val transactionConfirmationData: ByteArray? = null + val transactionConfirmationMessage: String? = null ) : Response diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/model/response/TransactionConfirmationResponse.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/model/response/TransactionConfirmationResponse.kt new file mode 100644 index 0000000..feda529 --- /dev/null +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/model/response/TransactionConfirmationResponse.kt @@ -0,0 +1,32 @@ +/** + * Nevis Mobile Authentication SDK Example App + * + * Copyright © 2024. Nevis Security AG. All rights reserved. + */ + +package ch.nevis.exampleapp.coroutines.domain.model.response + +import ch.nevis.mobile.sdk.api.localdata.Account + +/** + * [Response] class that indicates a transaction confirmation has to be started. + * After the transaction confirmation, [ch.nevis.exampleapp.coroutines.domain.usecase.SelectAccountUseCase] + * should be called with the contained account to continue the operation. + * + * @constructor Creates a new instance. + * @param account The previously selected account. + * @param transactionConfirmationMessage The transaction data/message that is be sent during an + * authentication process. + */ +class TransactionConfirmationResponse ( + + /** + * The previously selected account. + */ + val account: Account, + + /** + * The optional transaction data/message that is sent during an authentication process. + */ + val transactionConfirmationMessage: String +) : Response diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/usecase/TransactionConfirmationUseCase.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/usecase/TransactionConfirmationUseCase.kt new file mode 100644 index 0000000..880c7ce --- /dev/null +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/usecase/TransactionConfirmationUseCase.kt @@ -0,0 +1,26 @@ +/** + * Nevis Mobile Authentication SDK Example App + * + * Copyright © 2024. Nevis Security AG. All rights reserved. + */ + +package ch.nevis.exampleapp.coroutines.domain.usecase + +import ch.nevis.exampleapp.coroutines.domain.model.response.Response +import ch.nevis.mobile.sdk.api.localdata.Account + +/** + * Use-case interface for transaction confirmation. + */ +interface TransactionConfirmationUseCase { + + /** + * Executes the use-case. + * + * @param account The account that is used for the out-of-band authentication. + * @param transactionConfirmationMessage The transaction data/message that is be sent during an + * authentication process. + * @return A [Response] object that indicates the result of the use-case execution. + */ + suspend fun execute(account: Account, transactionConfirmationMessage: String): Response +} diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/usecase/TransactionConfirmationUseCaseImpl.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/usecase/TransactionConfirmationUseCaseImpl.kt new file mode 100644 index 0000000..2bcd3ea --- /dev/null +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/domain/usecase/TransactionConfirmationUseCaseImpl.kt @@ -0,0 +1,29 @@ +/** + * Nevis Mobile Authentication SDK Example App + * + * Copyright © 2024. Nevis Security AG. All rights reserved. + */ + +package ch.nevis.exampleapp.coroutines.domain.usecase + +import ch.nevis.exampleapp.coroutines.domain.model.response.Response +import ch.nevis.exampleapp.coroutines.domain.model.response.TransactionConfirmationResponse +import ch.nevis.mobile.sdk.api.localdata.Account +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlin.coroutines.resume + +class TransactionConfirmationUseCaseImpl : TransactionConfirmationUseCase { + + //region TransactionConfirmationUseCase + override suspend fun execute(account: Account, transactionConfirmationMessage: String): Response { + return suspendCancellableCoroutine { cancellableContinuation -> + cancellableContinuation.resume( + TransactionConfirmationResponse( + account, + transactionConfirmationMessage + ) + ) + } + } + //endregion +} diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/base/ResponseObserverFragment.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/base/ResponseObserverFragment.kt index e63b9a1..a9cc599 100644 --- a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/base/ResponseObserverFragment.kt +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/base/ResponseObserverFragment.kt @@ -23,6 +23,7 @@ import ch.nevis.exampleapp.coroutines.domain.model.response.ErrorResponse import ch.nevis.exampleapp.coroutines.domain.model.response.Response import ch.nevis.exampleapp.coroutines.domain.model.response.SelectAccountResponse import ch.nevis.exampleapp.coroutines.domain.model.response.SelectAuthenticatorResponse +import ch.nevis.exampleapp.coroutines.domain.model.response.TransactionConfirmationResponse import ch.nevis.exampleapp.coroutines.domain.model.response.VerifyBiometricResponse import ch.nevis.exampleapp.coroutines.domain.model.response.VerifyDevicePasscodeResponse import ch.nevis.exampleapp.coroutines.domain.model.response.VerifyFingerprintResponse @@ -93,26 +94,23 @@ abstract class ResponseObserverFragment : Fragment() { } is SelectAccountResponse -> { - response.transactionConfirmationData?.also { - val parameter = TransactionConfirmationNavigationParameter( - response.operation, - response.accounts, - it.decodeToString() - ) - val action = - NavigationGraphDirections.actionGlobalTransactionConfirmationFragment( - parameter - ) - navController.navigate(action) - } ?: run { - val parameter = SelectAccountNavigationParameter( - response.operation, - response.accounts - ) - val action = - NavigationGraphDirections.actionGlobalSelectAccountFragment(parameter) - navController.navigate(action) - } + val navigationParameter = SelectAccountNavigationParameter( + response.operation, + response.accounts, + response.transactionConfirmationMessage + ) + val action = + NavigationGraphDirections.actionGlobalSelectAccountFragment(navigationParameter) + navController.navigate(action) + } + + is TransactionConfirmationResponse -> { + val navigationParameter = TransactionConfirmationNavigationParameter( + response.account, + response.transactionConfirmationMessage + ) + val action = NavigationGraphDirections.actionGlobalTransactionConfirmationFragment(navigationParameter) + navController.navigate(action) } is EnrollPinResponse -> { diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/SelectAccountFragment.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/SelectAccountFragment.kt index b1cf3f3..2735249 100644 --- a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/SelectAccountFragment.kt +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/SelectAccountFragment.kt @@ -1,7 +1,7 @@ /** * Nevis Mobile Authentication SDK Example App * - * Copyright © 2022. Nevis Security AG. All rights reserved. + * Copyright © 2022-2024. Nevis Security AG. All rights reserved. */ package ch.nevis.exampleapp.coroutines.ui.selectAccount @@ -90,8 +90,9 @@ class SelectAccountFragment : ResponseObserverFragment(), //region AccountSelectedListener override fun onAccountSelected(account: Account) { viewModel.selectAccount( - navigationArguments.parameter.operation, - account.username() + operation = navigationArguments.parameter.operation, + account = account, + transactionConfirmationMessage = navigationArguments.parameter.message ) } //endregion diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/SelectAccountViewModel.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/SelectAccountViewModel.kt index c5fa4f8..19b8564 100644 --- a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/SelectAccountViewModel.kt +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/SelectAccountViewModel.kt @@ -1,7 +1,7 @@ /** * Nevis Mobile Authentication SDK Example App * - * Copyright © 2022. Nevis Security AG. All rights reserved. + * Copyright © 2022-2024. Nevis Security AG. All rights reserved. */ package ch.nevis.exampleapp.coroutines.ui.selectAccount @@ -10,8 +10,13 @@ import androidx.lifecycle.viewModelScope import ch.nevis.exampleapp.coroutines.dagger.ApplicationModule import ch.nevis.exampleapp.coroutines.domain.model.error.BusinessException import ch.nevis.exampleapp.coroutines.domain.model.operation.Operation -import ch.nevis.exampleapp.coroutines.domain.usecase.* +import ch.nevis.exampleapp.coroutines.domain.usecase.InBandAuthenticationUseCase +import ch.nevis.exampleapp.coroutines.domain.usecase.SelectAccountUseCase +import ch.nevis.exampleapp.coroutines.domain.usecase.StartChangePasswordUseCase +import ch.nevis.exampleapp.coroutines.domain.usecase.StartChangePinUseCase +import ch.nevis.exampleapp.coroutines.domain.usecase.TransactionConfirmationUseCase import ch.nevis.exampleapp.coroutines.ui.base.CancellableOperationViewModel +import ch.nevis.mobile.sdk.api.localdata.Account import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import javax.inject.Inject @@ -32,6 +37,7 @@ import javax.inject.Named class SelectAccountViewModel @Inject constructor( private val startChangePinUseCase: StartChangePinUseCase, private val startChangePasswordUseCase: StartChangePasswordUseCase, + private val transactionConfirmationUseCase: TransactionConfirmationUseCase, @Named(ApplicationModule.IN_BAND_AUTHENTICATION_USE_CASE_DEFAULT) private val inBandAuthenticationUseCase: InBandAuthenticationUseCase, @Named(ApplicationModule.IN_BAND_AUTHENTICATION_USE_CASE_FOR_DEREGISTRATION) @@ -46,16 +52,23 @@ class SelectAccountViewModel @Inject constructor( * [Operation.CHANGE_PASSWORD] and [Operation.OUT_OF_BAND_AUTHENTICATION]. * * @param operation The operation the account selected for. - * @param username The username assigned to the selected account. + * @param account The selected account. + * @param transactionConfirmationMessage The transaction confirmation message + * that need to be confirmed or cancelled by the user. */ - fun selectAccount(operation: Operation, username: String) { + fun selectAccount(operation: Operation, account: Account, transactionConfirmationMessage: String?) { viewModelScope.launch(errorHandler) { - when (operation) { - Operation.AUTHENTICATION -> inBandAuthentication(username) - Operation.DEREGISTRATION -> inBandAuthenticationForDeregistration(username) - Operation.CHANGE_PIN -> changePin(username) - Operation.CHANGE_PASSWORD -> changePassword(username) - Operation.OUT_OF_BAND_AUTHENTICATION -> outOfBandAuthentication(username) + if (transactionConfirmationMessage != null) { + // Transaction confirmation data is received from the SDK + // Show it to the user for confirmation or cancellation + // The AccountSelectionHandler will be invoked or cancelled there. + confirm(transactionConfirmationMessage, account) + } else when (operation) { + Operation.AUTHENTICATION -> inBandAuthenticate(account.username()) + Operation.DEREGISTRATION -> inBandAuthenticationForDeregistration(account.username()) + Operation.CHANGE_PIN -> changePin(account.username()) + Operation.CHANGE_PASSWORD -> changePassword(account.username()) + Operation.OUT_OF_BAND_AUTHENTICATION -> outOfBandAuthentication(account.username()) else -> throw BusinessException.invalidState() } } @@ -83,12 +96,23 @@ class SelectAccountViewModel @Inject constructor( mutableResponseLiveData.postValue(response) } + /** + * Confirms the transaction. + * + * @param message: The transaction confirmation message that need to be confirmed or cancelled by the user. + * @param account: The current account. + */ + private suspend fun confirm(message: String, account: Account) { + val response = transactionConfirmationUseCase.execute(account, message) + mutableResponseLiveData.postValue(response) + } + /** * Starts an in-band authentication. * * @param username The username that identifies the account the in-band authentication must be started for. */ - private suspend fun inBandAuthentication(username: String) { + private suspend fun inBandAuthenticate(username: String) { val response = inBandAuthenticationUseCase.execute(username) mutableResponseLiveData.postValue(response) } diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/parameter/SelectAccountNavigationParameter.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/parameter/SelectAccountNavigationParameter.kt index 15047f7..668bad7 100644 --- a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/parameter/SelectAccountNavigationParameter.kt +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/selectAccount/parameter/SelectAccountNavigationParameter.kt @@ -1,7 +1,7 @@ /** * Nevis Mobile Authentication SDK Example App * - * Copyright © 2022. Nevis Security AG. All rights reserved. + * Copyright © 2022-2024. Nevis Security AG. All rights reserved. */ package ch.nevis.exampleapp.coroutines.ui.selectAccount.parameter @@ -31,5 +31,10 @@ data class SelectAccountNavigationParameter( * The list of available accounts the user can select from. */ @IgnoredOnParcel - val accounts: Set? = null + val accounts: Set? = null, + + /** + * The message to confirm if there is any. + */ + val message: String? = null ) : Parcelable diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/TransactionConfirmationFragment.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/TransactionConfirmationFragment.kt index 182b357..6ce3f51 100644 --- a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/TransactionConfirmationFragment.kt +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/TransactionConfirmationFragment.kt @@ -1,7 +1,7 @@ /** * Nevis Mobile Authentication SDK Example App * - * Copyright © 2022. Nevis Security AG. All rights reserved. + * Copyright © 2022-2024. Nevis Security AG. All rights reserved. */ package ch.nevis.exampleapp.coroutines.ui.transactionConfirmation @@ -58,10 +58,7 @@ class TransactionConfirmationFragment : ResponseObserverFragment() { super.onViewCreated(view, savedInstanceState) binding.confirmButton.setOnClickListener { - viewModel.confirm( - navigationArguments.parameter.operation, - navigationArguments.parameter.accounts ?: setOf() - ) + viewModel.confirm(navigationArguments.parameter.account) } binding.cancelButton.setOnClickListener { @@ -69,7 +66,7 @@ class TransactionConfirmationFragment : ResponseObserverFragment() { } binding.transactionConfirmationDataTextView.text = - navigationArguments.parameter.transactionConfirmationData + navigationArguments.parameter.transactionConfirmationMessage requireActivity().onBackPressedDispatcher.addCallback( viewLifecycleOwner, diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/TransactionConfirmationViewModel.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/TransactionConfirmationViewModel.kt index ab955bf..45ad3b6 100644 --- a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/TransactionConfirmationViewModel.kt +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/TransactionConfirmationViewModel.kt @@ -1,14 +1,13 @@ /** * Nevis Mobile Authentication SDK Example App * - * Copyright © 2022. Nevis Security AG. All rights reserved. + * Copyright © 2022-2024. Nevis Security AG. All rights reserved. */ package ch.nevis.exampleapp.coroutines.ui.transactionConfirmation import androidx.lifecycle.viewModelScope -import ch.nevis.exampleapp.coroutines.domain.model.operation.Operation -import ch.nevis.exampleapp.coroutines.domain.model.response.SelectAccountResponse +import ch.nevis.exampleapp.coroutines.domain.model.error.BusinessException import ch.nevis.exampleapp.coroutines.domain.usecase.SelectAccountUseCase import ch.nevis.exampleapp.coroutines.ui.base.CancellableOperationViewModel import ch.nevis.mobile.sdk.api.localdata.Account @@ -31,19 +30,13 @@ class TransactionConfirmationViewModel @Inject constructor( /** * Confirms the transaction, the operation will be continued. * - * @param operation The confirmed operation. - * @param accounts The available accounts for the operations. + * @param account The previously selected account. */ - fun confirm(operation: Operation, accounts: Set) { + fun confirm(account: Account?) { + account ?: throw BusinessException.invalidState() + viewModelScope.launch(errorHandler) { - val response = if (accounts.size == 1) { - selectAccountUseCase.execute(accounts.first().username()) - } else { - SelectAccountResponse( - operation, - accounts - ) - } + val response = selectAccountUseCase.execute(account.username()) mutableResponseLiveData.postValue(response) } } diff --git a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/parameter/TransactionConfirmationNavigationParameter.kt b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/parameter/TransactionConfirmationNavigationParameter.kt index 32ee175..3e42cdf 100644 --- a/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/parameter/TransactionConfirmationNavigationParameter.kt +++ b/app/src/main/java/ch/nevis/exampleapp/coroutines/ui/transactionConfirmation/parameter/TransactionConfirmationNavigationParameter.kt @@ -1,13 +1,12 @@ /** * Nevis Mobile Authentication SDK Example App * - * Copyright © 2022. Nevis Security AG. All rights reserved. + * Copyright © 2022-2024. Nevis Security AG. All rights reserved. */ package ch.nevis.exampleapp.coroutines.ui.transactionConfirmation.parameter import android.os.Parcelable -import ch.nevis.exampleapp.coroutines.domain.model.operation.Operation import ch.nevis.mobile.sdk.api.localdata.Account import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize @@ -16,27 +15,21 @@ import kotlinx.parcelize.Parcelize * Navigation parameter class for Transaction Confirmation view. * * @constructor Creates a new instance. - * @param operation The operation the account selection was requested for. - * @param accounts The list of available accounts the user can select from. - * @param transactionConfirmationData The transaction confirmation data/message that should be displayed - * on Transaction Confirmation view. + * @param account The previously selected account. + * @param transactionConfirmationMessage The transaction confirmation data/message that should be displayed + * on Transaction Confirmation view. */ @Parcelize data class TransactionConfirmationNavigationParameter( /** - * The operation type the account was selection requested for. - */ - val operation: Operation, - - /** - * The list of available accounts the user can select from. + * The previously selected account. */ @IgnoredOnParcel - val accounts: Set? = null, + val account: Account? = null, /** * The transaction confirmation data as a [String]. */ - val transactionConfirmationData: String + val transactionConfirmationMessage: String ) : Parcelable