Update SDK to 3.0.0-8671-5d8ae614 (#7320)

Co-authored-by: bw-ghapp[bot] <178206702+bw-ghapp[bot]@users.noreply.github.com>
This commit is contained in:
bw-ghapp[bot] authored and GitHub committed 2026-09-03 19:03:49 +00:00
1 parent b1d6d6b513
commit 6f325dd192
7 files changed
+187 -1

No files matched your search

@@ -431,4 +431,23 @@ interface AuthDiskSource : AppIdProvider {
* Stores the v2 upgrade token for the given [userId].
*/
fun storeV2UpgradeToken(userId: String, v2UpgradeToken: V2UpgradeTokenJson?)
/**
* Gets the start of the v2 encrypted migrations grace period for the given [userId].
*
* This value is retained across logout and lock and is only removed when explicitly stored as
* `null`.
*/
fun getV2EncryptedMigrationsGracePeriodStart(userId: String): Instant?
/**
* Stores the start of the v2 encrypted migrations grace period for the given [userId].
*
* This value is retained across logout and lock and is only removed when explicitly stored as
* `null`.
*/
fun storeV2EncryptedMigrationsGracePeriodStart(
userId: String,
gracePeriodStart: Instant?,
)
}
@@ -62,6 +62,8 @@ private const val LAST_LOCK_TIMESTAMP = "lastLockTimestamp"
private const val PROFILE_ACCOUNT_KEYS_KEY = "profileAccountKeys"
private const val V2_UPGRADE_TOKEN = "v2UpgradeToken"
private const val USER_KEY_ID_KEY = "userKeyId"
private const val V2_ENCRYPTED_MIGRATIONS_GRACE_PERIOD_START =
"v2EncryptedMigrationsGracePeriodStart"
/**
* Primary implementation of [AuthDiskSource].
@@ -208,6 +210,7 @@ class AuthDiskSourceImpl(
// * DeviceKey
// * PendingAuthRequest
// * OnboardingStatus
// * V2EncryptedMigrationsGracePeriodStart
}
override fun getAuthenticatorSyncUnlockKey(userId: String): String? =
@@ -632,6 +635,20 @@ class AuthDiskSourceImpl(
)
}
override fun getV2EncryptedMigrationsGracePeriodStart(userId: String): Instant? =
getLong(key = V2_ENCRYPTED_MIGRATIONS_GRACE_PERIOD_START.appendIdentifier(userId))
?.let { Instant.ofEpochMilli(it) }
override fun storeV2EncryptedMigrationsGracePeriodStart(
userId: String,
gracePeriodStart: Instant?,
) {
putLong(
key = V2_ENCRYPTED_MIGRATIONS_GRACE_PERIOD_START.appendIdentifier(userId),
value = gracePeriodStart?.toEpochMilli(),
)
}
private fun generateAndStoreUniqueAppId(): String =
UUID
.randomUUID()
@@ -17,6 +17,7 @@ import com.x8bit.bitwarden.data.auth.repository.util.updateMasterPasswordUnlock
import com.x8bit.bitwarden.data.vault.repository.util.toSdkMasterPasswordUnlock
import com.x8bit.bitwarden.data.vault.repository.util.toV2UpgradeToken
import com.x8bit.bitwarden.data.vault.repository.util.toV2UpgradeTokenJson
import java.time.Instant
/**
* A user-scoped implementation of a Bitwarden SDK [StateBridgeForeignImpl].
@@ -167,6 +168,23 @@ internal class SdkStateBridge(
)
}
override suspend fun setV2EncryptedMigrationsGracePeriodStart(value: Instant) {
authDiskSource.storeV2EncryptedMigrationsGracePeriodStart(
userId = userId,
gracePeriodStart = value,
)
}
override suspend fun getV2EncryptedMigrationsGracePeriodStart(): Instant? =
authDiskSource.getV2EncryptedMigrationsGracePeriodStart(userId = userId)
override suspend fun clearV2EncryptedMigrationsGracePeriodStart() {
authDiskSource.storeV2EncryptedMigrationsGracePeriodStart(
userId = userId,
gracePeriodStart = null,
)
}
override suspend fun getWebauthnPrfUnlockData(): WebAuthnPrfUnlockData? {
// We do not support unlock with WebAuthn, so we can just return null
return null
@@ -378,6 +378,11 @@ class AuthDiskSourceTest {
),
)
authDiskSource.storeUserKeyId(userId = userId, userKeyId = "userKeyId")
val gracePeriodStart = Instant.parse("2025-01-13T12:00:00Z")
authDiskSource.storeV2EncryptedMigrationsGracePeriodStart(
userId = userId,
gracePeriodStart = gracePeriodStart,
)
authDiskSource.clearData(userId = userId)
@@ -389,6 +394,10 @@ class AuthDiskSourceTest {
OnboardingStatus.AUTOFILL_SETUP,
authDiskSource.getOnboardingStatus(userId = userId),
)
assertEquals(
gracePeriodStart,
authDiskSource.getV2EncryptedMigrationsGracePeriodStart(userId = userId),
)
// These should be cleared
assertNull(authDiskSource.getUserBiometricInitVector(userId = userId))
@@ -1557,6 +1566,61 @@ class AuthDiskSourceTest {
val actual = authDiskSource.getLastLockTimestamp(userId = mockUserId)
assertNull(actual)
}
@Test
fun `getV2EncryptedMigrationsGracePeriodStart should pull from SharedPreferences`() {
val storeKey = "bwPreferencesStorage:v2EncryptedMigrationsGracePeriodStart"
val mockUserId = "mockUserId"
val expectedState = Instant.parse("2025-01-13T12:00:00Z")
fakeSharedPreferences.edit {
putLong("${storeKey}_$mockUserId", expectedState.toEpochMilli())
}
val actual = authDiskSource.getV2EncryptedMigrationsGracePeriodStart(userId = mockUserId)
assertEquals(expectedState, actual)
}
@Test
fun `getV2EncryptedMigrationsGracePeriodStart should pull null when there is no data`() {
val mockUserId = "mockUserId"
val actual = authDiskSource.getV2EncryptedMigrationsGracePeriodStart(userId = mockUserId)
assertNull(actual)
}
@Test
fun `storeV2EncryptedMigrationsGracePeriodStart should update SharedPreferences`() {
val mockUserId = "mockUserId"
val expectedState = Instant.parse("2025-01-13T12:00:00Z")
authDiskSource.storeV2EncryptedMigrationsGracePeriodStart(
userId = mockUserId,
gracePeriodStart = expectedState,
)
assertEquals(
expectedState,
authDiskSource.getV2EncryptedMigrationsGracePeriodStart(userId = mockUserId),
)
}
@Test
fun `storeV2EncryptedMigrationsGracePeriodStart should clear the value when null is passed`() {
val mockUserId = "mockUserId"
authDiskSource.storeV2EncryptedMigrationsGracePeriodStart(
userId = mockUserId,
gracePeriodStart = Instant.parse("2025-01-13T12:00:00Z"),
)
authDiskSource.storeV2EncryptedMigrationsGracePeriodStart(
userId = mockUserId,
gracePeriodStart = null,
)
assertNull(authDiskSource.getV2EncryptedMigrationsGracePeriodStart(userId = mockUserId))
}
}
private const val USER_STATE_JSON = """
@@ -74,6 +74,7 @@ class FakeAuthDiskSource : AuthDiskSource {
mutableMapOf<String, MutableSharedFlow<String?>>()
private val storedV2UpgradeTokens = mutableMapOf<String, V2UpgradeTokenJson?>()
private val storedUserKeyIds = mutableMapOf<String, String?>()
private val storedV2EncryptedMigrationsGracePeriodStarts = mutableMapOf<String, Instant?>()
override var userState: UserStateJson? = null
set(value) {
@@ -109,6 +110,12 @@ class FakeAuthDiskSource : AuthDiskSource {
mutableAccountTokensFlowMap.remove(userId)
mutableEphemeralPinProtectedUserKeyEnvelopesFlowMap.remove(userId)
mutablePersistentPinProtectedUserKeyEnvelopesFlowMap.remove(userId)
// Certain values are never removed as required by the feature requirements:
// * DeviceKey
// * PendingAuthRequest
// * OnboardingStatus
// * V2EncryptedMigrationsGracePeriodStart
}
override fun getShouldUseKeyConnectorFlow(
@@ -178,6 +185,16 @@ class FakeAuthDiskSource : AuthDiskSource {
storedV2UpgradeTokens[userId] = v2UpgradeToken
}
override fun getV2EncryptedMigrationsGracePeriodStart(userId: String): Instant? =
storedV2EncryptedMigrationsGracePeriodStarts[userId]
override fun storeV2EncryptedMigrationsGracePeriodStart(
userId: String,
gracePeriodStart: Instant?,
) {
storedV2EncryptedMigrationsGracePeriodStarts[userId] = gracePeriodStart
}
override fun getTwoFactorToken(email: String): String? = storedTwoFactorTokens[email]
override fun storeTwoFactorToken(email: String, twoFactorToken: String?) {
@@ -471,6 +488,13 @@ class FakeAuthDiskSource : AuthDiskSource {
assertEquals(v2UpgradeToken, storedV2UpgradeTokens[userId])
}
/**
* Assert that the [gracePeriodStart] was stored successfully using the [userId].
*/
fun assertV2EncryptedMigrationsGracePeriodStart(userId: String, gracePeriodStart: Instant?) {
assertEquals(gracePeriodStart, storedV2EncryptedMigrationsGracePeriodStarts[userId])
}
/**
* Assert that the [twoFactorToken] was stored successfully using the [email].
*/
@@ -214,6 +214,48 @@ class SdkStateBridgeTest {
authDiskSource.assertV2UpgradeToken(userId = USER_ID, v2UpgradeToken = null)
}
@Test
fun `setV2EncryptedMigrationsGracePeriodStart should store the grace period start`() = runTest {
stateBridge.setV2EncryptedMigrationsGracePeriodStart(value = GRACE_PERIOD_START)
authDiskSource.assertV2EncryptedMigrationsGracePeriodStart(
userId = USER_ID,
gracePeriodStart = GRACE_PERIOD_START,
)
}
@Test
fun `getV2EncryptedMigrationsGracePeriodStart should return the stored grace period start`() =
runTest {
assertNull(stateBridge.getV2EncryptedMigrationsGracePeriodStart())
authDiskSource.storeV2EncryptedMigrationsGracePeriodStart(
userId = USER_ID,
gracePeriodStart = GRACE_PERIOD_START,
)
assertEquals(
GRACE_PERIOD_START,
stateBridge.getV2EncryptedMigrationsGracePeriodStart(),
)
}
@Test
fun `clearV2EncryptedMigrationsGracePeriodStart should clear the grace period start`() =
runTest {
authDiskSource.storeV2EncryptedMigrationsGracePeriodStart(
userId = USER_ID,
gracePeriodStart = GRACE_PERIOD_START,
)
stateBridge.clearV2EncryptedMigrationsGracePeriodStart()
authDiskSource.assertV2EncryptedMigrationsGracePeriodStart(
userId = USER_ID,
gracePeriodStart = null,
)
}
@Test
fun `setAccountCryptographicState should store the account cryptographic state`() = runTest {
val state = createMockWrappedAccountCryptographicState(number = 1)
@@ -493,6 +535,8 @@ private val V2_UPGRADE_TOKEN_JSON: V2UpgradeTokenJson = V2UpgradeTokenJson(
wrappedUserKey2 = "wrappedUserKey2",
)
private val GRACE_PERIOD_START: Instant = Instant.parse("2024-09-13T01:00:00.00Z")
private val MASTER_PASSWORD_UNLOCK_DATA: MasterPasswordUnlockData = MasterPasswordUnlockData(
kdf = Kdf.Pbkdf2(iterations = 600_000u),
masterKeyWrappedUserKey = "masterKeyWrappedUserKey",
+1 -1
View File
@@ -29,7 +29,7 @@ androidxRoom = "2.8.4"
androidxSecurityCrypto = "1.1.0"
androidxSplash = "1.2.0"
androidxWork = "2.11.2"
bitwardenSdk = "3.0.0-8495-c1b859a9"
bitwardenSdk = "3.0.0-8671-5d8ae614"
crashlytics = "3.0.8"
detekt = "1.23.8"
firebaseBom = "34.18.0"