mirror of
https://github.com/bitwarden/android.git
synced 2025-12-10 09:56:45 -06:00
PM-27771: Improve TOTP parsing (#6119)
This commit is contained in:
parent
448ba97ae2
commit
ed47ff4d18
@ -11,6 +11,7 @@ import com.bitwarden.cxf.util.getProviderImportCredentialsRequest
|
|||||||
import com.bitwarden.ui.platform.base.BaseViewModel
|
import com.bitwarden.ui.platform.base.BaseViewModel
|
||||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||||
import com.bitwarden.ui.platform.manager.share.ShareManager
|
import com.bitwarden.ui.platform.manager.share.ShareManager
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||||
import com.bitwarden.vault.CipherView
|
import com.bitwarden.vault.CipherView
|
||||||
import com.x8bit.bitwarden.data.auth.manager.AddTotpItemFromAuthenticatorManager
|
import com.x8bit.bitwarden.data.auth.manager.AddTotpItemFromAuthenticatorManager
|
||||||
@ -46,7 +47,6 @@ import com.x8bit.bitwarden.ui.platform.model.FeatureFlagsState
|
|||||||
import com.x8bit.bitwarden.ui.platform.util.isAccountSecurityShortcut
|
import com.x8bit.bitwarden.ui.platform.util.isAccountSecurityShortcut
|
||||||
import com.x8bit.bitwarden.ui.platform.util.isMyVaultShortcut
|
import com.x8bit.bitwarden.ui.platform.util.isMyVaultShortcut
|
||||||
import com.x8bit.bitwarden.ui.platform.util.isPasswordGeneratorShortcut
|
import com.x8bit.bitwarden.ui.platform.util.isPasswordGeneratorShortcut
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import com.x8bit.bitwarden.ui.vault.util.getTotpDataOrNull
|
import com.x8bit.bitwarden.ui.vault.util.getTotpDataOrNull
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.FlowPreview
|
import kotlinx.coroutines.FlowPreview
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package com.x8bit.bitwarden.data.auth.manager
|
package com.x8bit.bitwarden.data.auth.manager
|
||||||
|
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager for keeping track of requests from the Bitwarden Authenticator app to add a TOTP
|
* Manager for keeping track of requests from the Bitwarden Authenticator app to add a TOTP
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package com.x8bit.bitwarden.data.auth.manager
|
package com.x8bit.bitwarden.data.auth.manager
|
||||||
|
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default in memory implementation for [AddTotpItemFromAuthenticatorManager].
|
* Default in memory implementation for [AddTotpItemFromAuthenticatorManager].
|
||||||
|
|||||||
@ -4,13 +4,13 @@ import android.os.Parcelable
|
|||||||
import androidx.credentials.CredentialManager
|
import androidx.credentials.CredentialManager
|
||||||
import com.bitwarden.cxf.model.ImportCredentialsRequestData
|
import com.bitwarden.cxf.model.ImportCredentialsRequestData
|
||||||
import com.bitwarden.ui.platform.manager.share.model.ShareData
|
import com.bitwarden.ui.platform.manager.share.model.ShareData
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.x8bit.bitwarden.data.autofill.model.AutofillSaveItem
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSaveItem
|
||||||
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
||||||
import com.x8bit.bitwarden.data.credentials.model.CreateCredentialRequest
|
import com.x8bit.bitwarden.data.credentials.model.CreateCredentialRequest
|
||||||
import com.x8bit.bitwarden.data.credentials.model.Fido2CredentialAssertionRequest
|
import com.x8bit.bitwarden.data.credentials.model.Fido2CredentialAssertionRequest
|
||||||
import com.x8bit.bitwarden.data.credentials.model.GetCredentialsRequest
|
import com.x8bit.bitwarden.data.credentials.model.GetCredentialsRequest
|
||||||
import com.x8bit.bitwarden.data.credentials.model.ProviderGetPasswordCredentialRequest
|
import com.x8bit.bitwarden.data.credentials.model.ProviderGetPasswordCredentialRequest
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package com.x8bit.bitwarden.data.platform.manager.util
|
package com.x8bit.bitwarden.data.platform.manager.util
|
||||||
|
|
||||||
import com.bitwarden.cxf.model.ImportCredentialsRequestData
|
import com.bitwarden.cxf.model.ImportCredentialsRequestData
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.x8bit.bitwarden.data.autofill.model.AutofillSaveItem
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSaveItem
|
||||||
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
||||||
import com.x8bit.bitwarden.data.credentials.model.CreateCredentialRequest
|
import com.x8bit.bitwarden.data.credentials.model.CreateCredentialRequest
|
||||||
@ -8,7 +9,6 @@ import com.x8bit.bitwarden.data.credentials.model.Fido2CredentialAssertionReques
|
|||||||
import com.x8bit.bitwarden.data.credentials.model.GetCredentialsRequest
|
import com.x8bit.bitwarden.data.credentials.model.GetCredentialsRequest
|
||||||
import com.x8bit.bitwarden.data.credentials.model.ProviderGetPasswordCredentialRequest
|
import com.x8bit.bitwarden.data.credentials.model.ProviderGetPasswordCredentialRequest
|
||||||
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
|
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns [AutofillSaveItem] when contained in the given [SpecialCircumstance].
|
* Returns [AutofillSaveItem] when contained in the given [SpecialCircumstance].
|
||||||
|
|||||||
@ -17,10 +17,10 @@ import com.bitwarden.authenticatorbridge.util.toFingerprint
|
|||||||
import com.bitwarden.authenticatorbridge.util.toSymmetricEncryptionKeyData
|
import com.bitwarden.authenticatorbridge.util.toSymmetricEncryptionKeyData
|
||||||
import com.bitwarden.core.util.isBuildVersionAtLeast
|
import com.bitwarden.core.util.isBuildVersionAtLeast
|
||||||
import com.bitwarden.data.manager.DispatcherManager
|
import com.bitwarden.data.manager.DispatcherManager
|
||||||
|
import com.bitwarden.ui.platform.util.getTotpDataOrNull
|
||||||
import com.x8bit.bitwarden.data.auth.manager.AddTotpItemFromAuthenticatorManager
|
import com.x8bit.bitwarden.data.auth.manager.AddTotpItemFromAuthenticatorManager
|
||||||
import com.x8bit.bitwarden.data.platform.repository.AuthenticatorBridgeRepository
|
import com.x8bit.bitwarden.data.platform.repository.AuthenticatorBridgeRepository
|
||||||
import com.x8bit.bitwarden.data.platform.util.createAddTotpItemFromAuthenticatorIntent
|
import com.x8bit.bitwarden.data.platform.util.createAddTotpItemFromAuthenticatorIntent
|
||||||
import com.x8bit.bitwarden.ui.vault.util.getTotpDataOrNull
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import com.bitwarden.ui.platform.base.BackgroundEvent
|
|||||||
import com.bitwarden.ui.platform.base.BaseViewModel
|
import com.bitwarden.ui.platform.base.BaseViewModel
|
||||||
import com.bitwarden.ui.platform.components.icon.model.IconData
|
import com.bitwarden.ui.platform.components.icon.model.IconData
|
||||||
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||||
import com.bitwarden.ui.util.Text
|
import com.bitwarden.ui.util.Text
|
||||||
import com.bitwarden.ui.util.asText
|
import com.bitwarden.ui.util.asText
|
||||||
@ -59,7 +60,6 @@ import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
|
|||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.applyRestrictItemTypesPolicy
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.applyRestrictItemTypesPolicy
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toFilteredList
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toFilteredList
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toVaultFilterData
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toVaultFilterData
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
|
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
|
||||||
import com.x8bit.bitwarden.ui.vault.util.toVaultItemCipherType
|
import com.x8bit.bitwarden.ui.vault.util.toVaultItemCipherType
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import com.bitwarden.network.model.PolicyTypeJson
|
|||||||
import com.bitwarden.ui.platform.base.BackgroundEvent
|
import com.bitwarden.ui.platform.base.BackgroundEvent
|
||||||
import com.bitwarden.ui.platform.base.BaseViewModel
|
import com.bitwarden.ui.platform.base.BaseViewModel
|
||||||
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||||
import com.bitwarden.ui.util.Text
|
import com.bitwarden.ui.util.Text
|
||||||
@ -76,7 +77,6 @@ import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.messageResourceId
|
|||||||
import com.x8bit.bitwarden.ui.vault.feature.util.canAssignToCollections
|
import com.x8bit.bitwarden.ui.vault.feature.util.canAssignToCollections
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.util.hasDeletePermissionInAtLeastOneCollection
|
import com.x8bit.bitwarden.ui.vault.feature.util.hasDeletePermissionInAtLeastOneCollection
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toCipherView
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toCipherView
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
|
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultCardBrand
|
import com.x8bit.bitwarden.ui.vault.model.VaultCardBrand
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultCardExpirationMonth
|
import com.x8bit.bitwarden.ui.vault.model.VaultCardExpirationMonth
|
||||||
@ -2320,8 +2320,8 @@ data class VaultAddEditState(
|
|||||||
|
|
||||||
val shouldShowMoveToOrganization: Boolean
|
val shouldShowMoveToOrganization: Boolean
|
||||||
get() = !isAddItemMode &&
|
get() = !isAddItemMode &&
|
||||||
!isCipherInCollection &&
|
!isCipherInCollection &&
|
||||||
hasOrganizations
|
hasOrganizations
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum representing the main type options for the vault, such as LOGIN, CARD, etc.
|
* Enum representing the main type options for the vault, such as LOGIN, CARD, etc.
|
||||||
|
|||||||
@ -5,6 +5,7 @@ package com.x8bit.bitwarden.ui.vault.feature.addedit.util
|
|||||||
import com.bitwarden.collections.CollectionType
|
import com.bitwarden.collections.CollectionType
|
||||||
import com.bitwarden.collections.CollectionView
|
import com.bitwarden.collections.CollectionView
|
||||||
import com.bitwarden.core.data.util.toFormattedDateTimeStyle
|
import com.bitwarden.core.data.util.toFormattedDateTimeStyle
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||||
import com.bitwarden.ui.util.asText
|
import com.bitwarden.ui.util.asText
|
||||||
import com.bitwarden.vault.CipherRepromptType
|
import com.bitwarden.vault.CipherRepromptType
|
||||||
@ -19,7 +20,6 @@ import com.x8bit.bitwarden.data.auth.repository.model.UserState
|
|||||||
import com.x8bit.bitwarden.ui.platform.manager.resource.ResourceManager
|
import com.x8bit.bitwarden.ui.platform.manager.resource.ResourceManager
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditState
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditState
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.UriItem
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.UriItem
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
|
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultCardBrand
|
import com.x8bit.bitwarden.ui.vault.model.VaultCardBrand
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultCardExpirationMonth
|
import com.x8bit.bitwarden.ui.vault.model.VaultCardExpirationMonth
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package com.x8bit.bitwarden.ui.vault.feature.addedit.util
|
package com.x8bit.bitwarden.ui.vault.feature.addedit.util
|
||||||
|
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditState
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditState
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns pre-filled content that may be used for an "add" type
|
* Returns pre-filled content that may be used for an "add" type
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import com.bitwarden.ui.platform.base.util.toHostOrPathOrNull
|
|||||||
import com.bitwarden.ui.platform.components.account.model.AccountSummary
|
import com.bitwarden.ui.platform.components.account.model.AccountSummary
|
||||||
import com.bitwarden.ui.platform.components.icon.model.IconData
|
import com.bitwarden.ui.platform.components.icon.model.IconData
|
||||||
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||||
import com.bitwarden.ui.util.Text
|
import com.bitwarden.ui.util.Text
|
||||||
import com.bitwarden.ui.util.asText
|
import com.bitwarden.ui.util.asText
|
||||||
@ -100,7 +101,6 @@ import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
|
|||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toAccountSummaries
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toAccountSummaries
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toActiveAccountSummary
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toActiveAccountSummary
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toFilteredList
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toFilteredList
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
|
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
|
||||||
import com.x8bit.bitwarden.ui.vault.util.toVaultItemCipherType
|
import com.x8bit.bitwarden.ui.vault.util.toVaultItemCipherType
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import com.bitwarden.send.SendType
|
|||||||
import com.bitwarden.send.SendView
|
import com.bitwarden.send.SendView
|
||||||
import com.bitwarden.ui.platform.base.util.toHostOrPathOrNull
|
import com.bitwarden.ui.platform.base.util.toHostOrPathOrNull
|
||||||
import com.bitwarden.ui.platform.components.icon.model.IconData
|
import com.bitwarden.ui.platform.components.icon.model.IconData
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||||
import com.bitwarden.ui.util.asText
|
import com.bitwarden.ui.util.asText
|
||||||
@ -36,7 +37,6 @@ import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
|
|||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.applyRestrictItemTypesPolicy
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.applyRestrictItemTypesPolicy
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toFilteredList
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toFilteredList
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toLoginIconData
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toLoginIconData
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import com.x8bit.bitwarden.ui.vault.util.toSdkCipherType
|
import com.x8bit.bitwarden.ui.vault.util.toSdkCipherType
|
||||||
import java.time.Clock
|
import java.time.Clock
|
||||||
import java.time.format.FormatStyle
|
import java.time.format.FormatStyle
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
package com.x8bit.bitwarden.ui.vault.util
|
package com.x8bit.bitwarden.ui.vault.util
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
|
import com.bitwarden.ui.platform.util.getTotpDataOrNull
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the given [Intent] contains data for a TOTP. The [TotpData] will be returned when the
|
* Checks if the given [Intent] contains data for a TOTP. The [TotpData] will be returned when the
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
package com.x8bit.bitwarden.ui.vault.util
|
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
|
|
||||||
private const val TOTP_HOST_NAME: String = "totp"
|
|
||||||
private const val TOTP_SCHEME_NAME: String = "otpauth"
|
|
||||||
private const val PARAM_NAME_ALGORITHM: String = "algorithm"
|
|
||||||
private const val PARAM_NAME_DIGITS: String = "digits"
|
|
||||||
private const val PARAM_NAME_ISSUER: String = "issuer"
|
|
||||||
private const val PARAM_NAME_PERIOD: String = "period"
|
|
||||||
private const val PARAM_NAME_SECRET: String = "secret"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the given [Uri] contains valid data for a TOTP. The [TotpData] will be returned when
|
|
||||||
* the correct data is present or `null` if data is invalid or missing.
|
|
||||||
*/
|
|
||||||
fun Uri.getTotpDataOrNull(): TotpData? {
|
|
||||||
// Must be a "otpauth" scheme
|
|
||||||
if (!this.scheme.equals(other = TOTP_SCHEME_NAME, ignoreCase = true)) return null
|
|
||||||
// Must be a "totp" host
|
|
||||||
if (!this.host.equals(other = TOTP_HOST_NAME, ignoreCase = true)) return null
|
|
||||||
// Must contain a "secret"
|
|
||||||
val secret = this.getQueryParameter(PARAM_NAME_SECRET)?.trim() ?: return null
|
|
||||||
val segments = this.pathSegments?.firstOrNull()?.split(":")
|
|
||||||
val segmentCount = segments?.size ?: 0
|
|
||||||
return TotpData(
|
|
||||||
uri = this.toString(),
|
|
||||||
issuer = this.getQueryParameter(PARAM_NAME_ISSUER)
|
|
||||||
?: segments?.firstOrNull()?.trim()?.takeIf { segmentCount > 1 },
|
|
||||||
accountName = if (segmentCount > 1) {
|
|
||||||
segments?.getOrNull(index = 1)?.trim()
|
|
||||||
} else {
|
|
||||||
segments?.firstOrNull()?.trim()
|
|
||||||
},
|
|
||||||
secret = secret,
|
|
||||||
digits = this.getQueryParameter(PARAM_NAME_DIGITS)?.trim()?.toIntOrNull() ?: 6,
|
|
||||||
period = this
|
|
||||||
.getQueryParameter(PARAM_NAME_PERIOD)
|
|
||||||
?.trim()
|
|
||||||
?.toIntOrNull()
|
|
||||||
?.takeUnless { it <= 0 }
|
|
||||||
?: 30,
|
|
||||||
algorithm = TotpData.CryptoHashAlgorithm
|
|
||||||
.parse(value = this.getQueryParameter(PARAM_NAME_ALGORITHM)?.trim())
|
|
||||||
?: TotpData.CryptoHashAlgorithm.SHA_1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -21,6 +21,7 @@ import com.bitwarden.ui.platform.base.BaseViewModelTest
|
|||||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||||
import com.bitwarden.ui.platform.manager.share.ShareManager
|
import com.bitwarden.ui.platform.manager.share.ShareManager
|
||||||
import com.bitwarden.ui.platform.manager.share.model.ShareData
|
import com.bitwarden.ui.platform.manager.share.model.ShareData
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||||
import com.bitwarden.vault.CipherView
|
import com.bitwarden.vault.CipherView
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||||
@ -76,7 +77,6 @@ import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLang
|
|||||||
import com.x8bit.bitwarden.ui.platform.util.isAccountSecurityShortcut
|
import com.x8bit.bitwarden.ui.platform.util.isAccountSecurityShortcut
|
||||||
import com.x8bit.bitwarden.ui.platform.util.isMyVaultShortcut
|
import com.x8bit.bitwarden.ui.platform.util.isMyVaultShortcut
|
||||||
import com.x8bit.bitwarden.ui.platform.util.isPasswordGeneratorShortcut
|
import com.x8bit.bitwarden.ui.platform.util.isPasswordGeneratorShortcut
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import com.x8bit.bitwarden.ui.vault.util.getTotpDataOrNull
|
import com.x8bit.bitwarden.ui.vault.util.getTotpDataOrNull
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package com.x8bit.bitwarden.data.auth.manager
|
package com.x8bit.bitwarden.data.auth.manager
|
||||||
|
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.platform.manager.util
|
|||||||
|
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import com.bitwarden.cxf.model.ImportCredentialsRequestData
|
import com.bitwarden.cxf.model.ImportCredentialsRequestData
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.x8bit.bitwarden.data.autofill.model.AutofillSaveItem
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSaveItem
|
||||||
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
||||||
import com.x8bit.bitwarden.data.credentials.model.CreateCredentialRequest
|
import com.x8bit.bitwarden.data.credentials.model.CreateCredentialRequest
|
||||||
@ -9,7 +10,6 @@ import com.x8bit.bitwarden.data.credentials.model.createMockFido2CredentialAsser
|
|||||||
import com.x8bit.bitwarden.data.credentials.model.createMockGetCredentialsRequest
|
import com.x8bit.bitwarden.data.credentials.model.createMockGetCredentialsRequest
|
||||||
import com.x8bit.bitwarden.data.credentials.model.createMockProviderGetPasswordCredentialRequest
|
import com.x8bit.bitwarden.data.credentials.model.createMockProviderGetPasswordCredentialRequest
|
||||||
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
|
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
import org.junit.jupiter.api.Assertions.assertNull
|
import org.junit.jupiter.api.Assertions.assertNull
|
||||||
|
|||||||
@ -20,11 +20,11 @@ import com.bitwarden.authenticatorbridge.util.toSymmetricEncryptionKeyData
|
|||||||
import com.bitwarden.core.data.util.asSuccess
|
import com.bitwarden.core.data.util.asSuccess
|
||||||
import com.bitwarden.core.util.isBuildVersionAtLeast
|
import com.bitwarden.core.util.isBuildVersionAtLeast
|
||||||
import com.bitwarden.data.datasource.disk.base.FakeDispatcherManager
|
import com.bitwarden.data.datasource.disk.base.FakeDispatcherManager
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
|
import com.bitwarden.ui.platform.util.getTotpDataOrNull
|
||||||
import com.x8bit.bitwarden.data.auth.manager.AddTotpItemFromAuthenticatorManagerImpl
|
import com.x8bit.bitwarden.data.auth.manager.AddTotpItemFromAuthenticatorManagerImpl
|
||||||
import com.x8bit.bitwarden.data.platform.repository.AuthenticatorBridgeRepository
|
import com.x8bit.bitwarden.data.platform.repository.AuthenticatorBridgeRepository
|
||||||
import com.x8bit.bitwarden.data.platform.util.createAddTotpItemFromAuthenticatorIntent
|
import com.x8bit.bitwarden.data.platform.util.createAddTotpItemFromAuthenticatorIntent
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import com.x8bit.bitwarden.ui.vault.util.getTotpDataOrNull
|
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
import io.mockk.coVerify
|
import io.mockk.coVerify
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import com.bitwarden.network.model.SyncResponseJson
|
|||||||
import com.bitwarden.send.SendView
|
import com.bitwarden.send.SendView
|
||||||
import com.bitwarden.ui.platform.base.BaseViewModelTest
|
import com.bitwarden.ui.platform.base.BaseViewModelTest
|
||||||
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||||
import com.bitwarden.ui.util.Text
|
import com.bitwarden.ui.util.Text
|
||||||
@ -87,7 +88,6 @@ import com.x8bit.bitwarden.ui.vault.feature.addedit.model.UriItem
|
|||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.createMockPasskeyAttestationOptions
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.createMockPasskeyAttestationOptions
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toDefaultAddTypeContent
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toDefaultAddTypeContent
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toViewState
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toViewState
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
|
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultCardBrand
|
import com.x8bit.bitwarden.ui.vault.model.VaultCardBrand
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultCardExpirationMonth
|
import com.x8bit.bitwarden.ui.vault.model.VaultCardExpirationMonth
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package com.x8bit.bitwarden.ui.vault.feature.addedit.util
|
package com.x8bit.bitwarden.ui.vault.feature.addedit.util
|
||||||
|
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditState
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditState
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockkStatic
|
import io.mockk.mockkStatic
|
||||||
import io.mockk.unmockkStatic
|
import io.mockk.unmockkStatic
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import com.bitwarden.ui.platform.base.BaseViewModelTest
|
|||||||
import com.bitwarden.ui.platform.components.account.model.AccountSummary
|
import com.bitwarden.ui.platform.components.account.model.AccountSummary
|
||||||
import com.bitwarden.ui.platform.components.icon.model.IconData
|
import com.bitwarden.ui.platform.components.icon.model.IconData
|
||||||
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||||
import com.bitwarden.ui.util.Text
|
import com.bitwarden.ui.util.Text
|
||||||
@ -110,7 +111,6 @@ import com.x8bit.bitwarden.ui.vault.feature.itemlisting.util.createMockDisplayIt
|
|||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
|
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toAccountSummaries
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toAccountSummaries
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toActiveAccountSummary
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toActiveAccountSummary
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
|
import com.x8bit.bitwarden.ui.vault.model.VaultItemCipherType
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType
|
import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType
|
||||||
import io.mockk.Ordering
|
import io.mockk.Ordering
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import com.bitwarden.data.repository.util.baseWebSendUrl
|
|||||||
import com.bitwarden.send.SendType
|
import com.bitwarden.send.SendType
|
||||||
import com.bitwarden.send.SendView
|
import com.bitwarden.send.SendView
|
||||||
import com.bitwarden.ui.platform.components.icon.model.IconData
|
import com.bitwarden.ui.platform.components.icon.model.IconData
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||||
import com.bitwarden.ui.util.asText
|
import com.bitwarden.ui.util.asText
|
||||||
@ -33,7 +34,6 @@ import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockSendView
|
|||||||
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
|
import com.x8bit.bitwarden.data.vault.repository.model.VaultData
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingState
|
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.VaultItemListingState
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
|
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.mockkObject
|
import io.mockk.mockkObject
|
||||||
|
|||||||
@ -2,7 +2,8 @@ package com.x8bit.bitwarden.ui.vault.util
|
|||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
|
import com.bitwarden.ui.platform.util.getTotpDataOrNull
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.mockkStatic
|
import io.mockk.mockkStatic
|
||||||
|
|||||||
@ -242,7 +242,4 @@ fun String.prefixHttpsIfNecessary(): String =
|
|||||||
/**
|
/**
|
||||||
* Checks if a string is using base32 digits.
|
* Checks if a string is using base32 digits.
|
||||||
*/
|
*/
|
||||||
fun String.isBase32(): Boolean {
|
fun String.isBase32(): Boolean = "^[A-Za-z2-7]+=*$".toRegex().matches(this)
|
||||||
val regex = ("^[A-Z2-7]+=*$").toRegex()
|
|
||||||
return regex.matches(this)
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package com.x8bit.bitwarden.ui.vault.model
|
package com.bitwarden.ui.platform.model
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
package com.bitwarden.ui.platform.util
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import com.bitwarden.ui.platform.base.util.isBase32
|
||||||
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
|
|
||||||
|
private const val TOTP_HOST_NAME: String = "totp"
|
||||||
|
private const val TOTP_SCHEME_NAME: String = "otpauth"
|
||||||
|
private const val PARAM_NAME_ALGORITHM: String = "algorithm"
|
||||||
|
private const val PARAM_NAME_DIGITS: String = "digits"
|
||||||
|
private const val PARAM_NAME_ISSUER: String = "issuer"
|
||||||
|
private const val PARAM_NAME_PERIOD: String = "period"
|
||||||
|
private const val PARAM_NAME_SECRET: String = "secret"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given [Uri] contains valid data for a TOTP. The [TotpData] will be returned when
|
||||||
|
* the correct data is present or `null` if data is invalid or missing.
|
||||||
|
*/
|
||||||
|
fun Uri.getTotpDataOrNull(): TotpData? {
|
||||||
|
// Must be a "otpauth" scheme
|
||||||
|
if (!this.scheme.equals(other = TOTP_SCHEME_NAME, ignoreCase = true)) return null
|
||||||
|
// Must be a "totp" host
|
||||||
|
if (!this.host.equals(other = TOTP_HOST_NAME, ignoreCase = true)) return null
|
||||||
|
val secret = this.getSecret() ?: return null
|
||||||
|
val digits = this.getDigits() ?: return null
|
||||||
|
val period = this.getPeriod() ?: return null
|
||||||
|
val algorithm = this.getAlgorithm() ?: return null
|
||||||
|
val segments = this.pathSegments?.firstOrNull()?.split(":")
|
||||||
|
val segmentCount = segments?.size ?: 0
|
||||||
|
return TotpData(
|
||||||
|
uri = this.toString(),
|
||||||
|
issuer = this.getQueryParameter(PARAM_NAME_ISSUER)
|
||||||
|
?: segments?.firstOrNull()?.trim()?.takeIf { segmentCount > 1 },
|
||||||
|
accountName = if (segmentCount > 1) {
|
||||||
|
segments?.getOrNull(index = 1)?.trim()
|
||||||
|
} else {
|
||||||
|
segments?.firstOrNull()?.trim()
|
||||||
|
},
|
||||||
|
secret = secret,
|
||||||
|
digits = digits,
|
||||||
|
period = period,
|
||||||
|
algorithm = algorithm,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to extract the algorithm from the given totp [Uri].
|
||||||
|
*/
|
||||||
|
private fun Uri.getAlgorithm(): TotpData.CryptoHashAlgorithm? {
|
||||||
|
val algorithm = this
|
||||||
|
.getQueryParameter(PARAM_NAME_ALGORITHM)
|
||||||
|
?.trim()
|
||||||
|
?.lowercase()
|
||||||
|
return if (algorithm == null) {
|
||||||
|
// If no value was provided, then we'll default to SHA_1.
|
||||||
|
TotpData.CryptoHashAlgorithm.SHA_1
|
||||||
|
} else {
|
||||||
|
// If the value is unidentifiable, then it's invalid.
|
||||||
|
// If it's identifiable, then we return the valid value.
|
||||||
|
// We specifically do not use a `let` here, since we do not want to map an unidentified
|
||||||
|
// value to the default value.
|
||||||
|
TotpData.CryptoHashAlgorithm.parse(value = algorithm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to extract the digits from the given totp [Uri].
|
||||||
|
*/
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
private fun Uri.getDigits(): Int? {
|
||||||
|
val digits = this.getQueryParameter(PARAM_NAME_DIGITS)?.trim()?.toIntOrNull()
|
||||||
|
return if (digits == null) {
|
||||||
|
// If no value was provided, then we'll default to 6.
|
||||||
|
6
|
||||||
|
} else if (digits < 1 || digits > 10) {
|
||||||
|
// If the value is less than 1 or greater than 10, then it's invalid.
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
// If the value is valid, then we'll return it.
|
||||||
|
digits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to extract the period from the given totp [Uri].
|
||||||
|
*/
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
private fun Uri.getPeriod(): Int? {
|
||||||
|
val period = this.getQueryParameter(PARAM_NAME_PERIOD)?.trim()?.toIntOrNull()
|
||||||
|
return if (period == null) {
|
||||||
|
// If no value was provided, then we'll default to 30.
|
||||||
|
30
|
||||||
|
} else if (period < 1) {
|
||||||
|
// If the value is less than 1, then it's invalid.
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
// If the value is valid, then we'll return it.
|
||||||
|
period
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to extract the secret from the given totp [Uri].
|
||||||
|
*/
|
||||||
|
private fun Uri.getSecret(): String? =
|
||||||
|
this
|
||||||
|
.getQueryParameter(PARAM_NAME_SECRET)
|
||||||
|
?.trim()
|
||||||
|
?.takeIf { it.isNotEmpty() && it.isBase32() }
|
||||||
@ -1,8 +1,7 @@
|
|||||||
package com.x8bit.bitwarden.ui.vault.util
|
package com.bitwarden.ui.platform.util
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData
|
import com.bitwarden.ui.platform.model.TotpData
|
||||||
import com.x8bit.bitwarden.ui.vault.model.TotpData.CryptoHashAlgorithm
|
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
@ -41,6 +40,56 @@ class TotpUriUtilsTest {
|
|||||||
assertNull(uri.getTotpDataOrNull())
|
assertNull(uri.getTotpDataOrNull())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `getTotpDataOrNull with invalid secret returns null`() {
|
||||||
|
val uri = mockk<Uri> {
|
||||||
|
every { scheme } returns "otpauth"
|
||||||
|
every { host } returns "totp"
|
||||||
|
every { getQueryParameter("secret") } returns "1234567890qwertyuiop"
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNull(uri.getTotpDataOrNull())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `getTotpDataOrNull with invalid digits returns null`() {
|
||||||
|
val uri = mockk<Uri> {
|
||||||
|
every { scheme } returns "otpauth"
|
||||||
|
every { host } returns "totp"
|
||||||
|
every { getQueryParameter("secret") } returns "secret"
|
||||||
|
every { getQueryParameter("digits") } returns "11"
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNull(uri.getTotpDataOrNull())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `getTotpDataOrNull with invalid period returns null`() {
|
||||||
|
val uri = mockk<Uri> {
|
||||||
|
every { scheme } returns "otpauth"
|
||||||
|
every { host } returns "totp"
|
||||||
|
every { getQueryParameter("secret") } returns "secret"
|
||||||
|
every { getQueryParameter("digits") } returns "5"
|
||||||
|
every { getQueryParameter("period") } returns "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNull(uri.getTotpDataOrNull())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `getTotpDataOrNull with invalid algorithm returns null`() {
|
||||||
|
val uri = mockk<Uri> {
|
||||||
|
every { scheme } returns "otpauth"
|
||||||
|
every { host } returns "totp"
|
||||||
|
every { getQueryParameter("secret") } returns "secret"
|
||||||
|
every { getQueryParameter("digits") } returns "5"
|
||||||
|
every { getQueryParameter("period") } returns "10"
|
||||||
|
every { getQueryParameter("algorithm") } returns "sha22"
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNull(uri.getTotpDataOrNull())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `getTotpDataOrNull with minimum required values returns TotpData with defaults`() {
|
fun `getTotpDataOrNull with minimum required values returns TotpData with defaults`() {
|
||||||
val secret = "secret"
|
val secret = "secret"
|
||||||
@ -62,7 +111,7 @@ class TotpUriUtilsTest {
|
|||||||
secret = secret,
|
secret = secret,
|
||||||
digits = 6,
|
digits = 6,
|
||||||
period = 30,
|
period = 30,
|
||||||
algorithm = CryptoHashAlgorithm.SHA_1,
|
algorithm = TotpData.CryptoHashAlgorithm.SHA_1,
|
||||||
)
|
)
|
||||||
|
|
||||||
assertEquals(expectedResult, uri.getTotpDataOrNull())
|
assertEquals(expectedResult, uri.getTotpDataOrNull())
|
||||||
@ -93,7 +142,7 @@ class TotpUriUtilsTest {
|
|||||||
secret = secret,
|
secret = secret,
|
||||||
digits = digits,
|
digits = digits,
|
||||||
period = period,
|
period = period,
|
||||||
algorithm = CryptoHashAlgorithm.SHA_256,
|
algorithm = TotpData.CryptoHashAlgorithm.SHA_256,
|
||||||
)
|
)
|
||||||
|
|
||||||
assertEquals(expectedResult, uri.getTotpDataOrNull())
|
assertEquals(expectedResult, uri.getTotpDataOrNull())
|
||||||
Loading…
x
Reference in New Issue
Block a user