mirror of
https://github.com/bitwarden/android.git
synced 2024-11-22 01:16:02 +03:00
[PM-10282] Default to last active account for passkey creation (#3780)
This commit is contained in:
parent
5f46423638
commit
a15b84a5bf
3 changed files with 28 additions and 3 deletions
|
@ -21,6 +21,7 @@ import dagger.hilt.InstallIn
|
|||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.time.Clock
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
|
@ -41,6 +42,7 @@ object Fido2ProviderModule {
|
|||
fido2CredentialManager: Fido2CredentialManager,
|
||||
dispatcherManager: DispatcherManager,
|
||||
intentManager: IntentManager,
|
||||
clock: Clock,
|
||||
): Fido2ProviderProcessor =
|
||||
Fido2ProviderProcessorImpl(
|
||||
context,
|
||||
|
@ -49,6 +51,7 @@ object Fido2ProviderModule {
|
|||
fido2CredentialStore,
|
||||
fido2CredentialManager,
|
||||
intentManager,
|
||||
clock,
|
||||
dispatcherManager,
|
||||
)
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.DecryptFido2CredentialAut
|
|||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.time.Clock
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
private const val CREATE_PASSKEY_INTENT = "com.x8bit.bitwarden.fido2.ACTION_CREATE_PASSKEY"
|
||||
|
@ -57,6 +58,7 @@ class Fido2ProviderProcessorImpl(
|
|||
private val fido2CredentialStore: Fido2CredentialStore,
|
||||
private val fido2CredentialManager: Fido2CredentialManager,
|
||||
private val intentManager: IntentManager,
|
||||
private val clock: Clock,
|
||||
dispatcherManager: DispatcherManager,
|
||||
) : Fido2ProviderProcessor {
|
||||
|
||||
|
@ -111,13 +113,14 @@ class Fido2ProviderProcessorImpl(
|
|||
val userState = authRepository.userStateFlow.value ?: return null
|
||||
|
||||
return BeginCreateCredentialResponse.Builder()
|
||||
.setCreateEntries(userState.accounts.toCreateEntries())
|
||||
.setCreateEntries(userState.accounts.toCreateEntries(userState.activeUserId))
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun List<UserState.Account>.toCreateEntries() = map { it.toCreateEntry() }
|
||||
private fun List<UserState.Account>.toCreateEntries(activeUserId: String) =
|
||||
map { it.toCreateEntry(isActive = activeUserId == it.userId) }
|
||||
|
||||
private fun UserState.Account.toCreateEntry(): CreateEntry {
|
||||
private fun UserState.Account.toCreateEntry(isActive: Boolean): CreateEntry {
|
||||
val accountName = name ?: email
|
||||
return CreateEntry
|
||||
.Builder(
|
||||
|
@ -134,6 +137,9 @@ class Fido2ProviderProcessorImpl(
|
|||
accountName,
|
||||
),
|
||||
)
|
||||
// Set the last used time to "now" so the active account is the default option in the
|
||||
// system prompt.
|
||||
.setLastUsedTime(if (isActive) clock.instant() else null)
|
||||
.build()
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ import kotlinx.serialization.encodeToString
|
|||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
import java.time.ZoneOffset
|
||||
|
||||
class Fido2ProviderProcessorTest {
|
||||
|
||||
|
@ -80,6 +83,7 @@ class Fido2ProviderProcessorTest {
|
|||
private val cancellationSignal: CancellationSignal = mockk()
|
||||
|
||||
private val json = PlatformNetworkModule.providesJson()
|
||||
private val clock = FIXED_CLOCK
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
|
@ -90,6 +94,7 @@ class Fido2ProviderProcessorTest {
|
|||
fido2CredentialStore,
|
||||
fido2CredentialManager,
|
||||
intentManager,
|
||||
clock,
|
||||
dispatcherManager,
|
||||
)
|
||||
}
|
||||
|
@ -244,6 +249,12 @@ class Fido2ProviderProcessorTest {
|
|||
verify(exactly = 0) { callback.onError(any()) }
|
||||
|
||||
assertEquals(DEFAULT_USER_STATE.accounts.size, captureSlot.captured.createEntries.size)
|
||||
|
||||
// Verify only the active account entry has a lastUsedTime
|
||||
assertEquals(
|
||||
1,
|
||||
captureSlot.captured.createEntries.filter { it.lastUsedTime != null }.size,
|
||||
)
|
||||
DEFAULT_USER_STATE.accounts.forEachIndexed { index, mockAccount ->
|
||||
assertEquals(mockAccount.email, captureSlot.captured.createEntries[index].accountName)
|
||||
}
|
||||
|
@ -495,6 +506,11 @@ private val DEFAULT_USER_STATE = UserState(
|
|||
accounts = createMockAccounts(2),
|
||||
)
|
||||
|
||||
private val FIXED_CLOCK: Clock = Clock.fixed(
|
||||
Instant.parse("2023-10-27T12:00:00Z"),
|
||||
ZoneOffset.UTC,
|
||||
)
|
||||
|
||||
private fun createMockAccounts(number: Int): List<UserState.Account> {
|
||||
val accounts = mutableListOf<UserState.Account>()
|
||||
repeat(number) {
|
||||
|
|
Loading…
Reference in a new issue