Compare commits

...

8 Commits

Author SHA1 Message Date
Patrick Honkonen
8077895eb8 Update ZXing library version (#6230) 2025-12-04 19:52:24 +00:00
Patrick Honkonen
33e9313c6c Update SonarQube plugin version (#6231) 2025-12-04 19:19:54 +00:00
Patrick Honkonen
593bfbf8cf [PM-28352] Add logging to Credential Manager and Origin Manager flows (#6229) 2025-12-04 18:22:45 +00:00
Patrick Honkonen
4905358adb [PM-28467] Add revisionDate to policy JSON model (#6228) 2025-12-04 18:22:23 +00:00
renovate[bot]
02733f785b [deps]: Lock file maintenance (#6197)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-04 18:01:23 +00:00
Patrick Honkonen
8baa4bf041 [PM-29096] Update Fastlane and Gemfile dependencies (#6216) 2025-12-04 16:20:21 +00:00
David Perez
4d20453d0f PM-25632: Ensure that we use lowercase email addresses when creating a fingerprint (#6227) 2025-12-04 15:34:17 +00:00
David Perez
4b951a1df2 PM-28634: Update Autofill terms to support other languages better (#6226) 2025-12-04 14:55:23 +00:00
29 changed files with 96 additions and 66 deletions

View File

@@ -44,6 +44,5 @@ runs:
- name: Install Fastlane
shell: bash
run: |
gem install bundler:2.2.27
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3

View File

@@ -98,7 +98,6 @@ jobs:
- name: Install Fastlane
run: |
gem install bundler:2.2.27
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3
@@ -134,7 +133,6 @@ jobs:
- name: Install Fastlane
run: |
gem install bundler:2.2.27
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3

View File

@@ -100,7 +100,6 @@ jobs:
- name: Install Fastlane
run: |
gem install bundler:2.2.27
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3
@@ -143,7 +142,6 @@ jobs:
- name: Install Fastlane
run: |
gem install bundler:2.2.27
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3
@@ -462,7 +460,6 @@ jobs:
- name: Install Fastlane
run: |
gem install bundler:2.2.27
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3

View File

@@ -83,7 +83,6 @@ jobs:
- name: Install Fastlane
run: |
gem install bundler:2.2.27
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3

View File

@@ -65,7 +65,6 @@ jobs:
- name: Install Fastlane
run: |
gem install bundler:2.2.27
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3

View File

@@ -14,5 +14,8 @@ gem 'logger'
gem 'mutex_m'
gem 'csv'
# Since ruby 3.4.1 these are not included in the standard library
gem 'nkf'
# Starting with Ruby 3.5.0, these are not included in the standard library
gem 'ostruct'

View File

@@ -1,18 +1,15 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.7)
base64
nkf
rexml
CFPropertyList (3.0.8)
abbrev (0.1.2)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
addressable (2.8.8)
public_suffix (>= 2.0.2, < 8.0)
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.4.0)
aws-partitions (1.1181.0)
aws-sdk-core (3.236.0)
aws-partitions (1.1190.0)
aws-sdk-core (3.239.2)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
@@ -20,10 +17,10 @@ GEM
bigdecimal
jmespath (~> 1, >= 1.6.1)
logger
aws-sdk-kms (1.117.0)
aws-sdk-core (~> 3, >= 3.234.0)
aws-sdk-kms (1.118.0)
aws-sdk-core (~> 3, >= 3.239.1)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.203.0)
aws-sdk-s3 (1.206.0)
aws-sdk-core (~> 3, >= 3.234.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
@@ -58,9 +55,9 @@ GEM
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7)
faraday-cookie_jar (0.0.8)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
http-cookie (>= 1.0.0)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.1)
faraday-excon (1.1.0)
@@ -75,8 +72,9 @@ GEM
faraday_middleware (1.2.1)
faraday (~> 1.0)
fastimage (2.4.0)
fastlane (2.228.0)
fastlane (2.229.0)
CFPropertyList (>= 2.3, < 4.0.0)
abbrev (~> 0.1.2)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
@@ -84,6 +82,7 @@ GEM
bundler (>= 1.12.0, < 3.0.0)
colored (~> 1.2)
commander (~> 4.6)
csv (~> 3.3)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
@@ -103,6 +102,7 @@ GEM
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
mutex_m (~> 0.3.0)
naturally (~> 2.2)
optparse (>= 0.1.1, < 1.0.0)
plist (>= 3.1.0, < 4.0.0)
@@ -169,13 +169,13 @@ GEM
httpclient (2.9.0)
mutex_m
jmespath (1.6.2)
json (2.16.0)
json (2.17.1)
jwt (2.10.2)
base64
logger (1.7.0)
mini_magick (4.13.2)
mini_mime (1.1.5)
multi_json (1.17.0)
multi_json (1.18.0)
multipart-post (2.4.1)
mutex_m (0.3.0)
nanaimo (0.4.0)
@@ -185,7 +185,7 @@ GEM
os (1.1.4)
ostruct (0.6.3)
plist (3.7.2)
public_suffix (6.0.2)
public_suffix (7.0.0)
rake (13.3.1)
representable (3.2.0)
declarative (< 0.1.0)
@@ -241,6 +241,7 @@ DEPENDENCIES
fastlane-plugin-firebase_app_distribution
logger
mutex_m
nkf
ostruct
time
@@ -248,4 +249,4 @@ RUBY VERSION
ruby 3.4.2p28
BUNDLED WITH
2.6.9
2.6.2

View File

@@ -261,7 +261,7 @@
android:name="com.x8bit.bitwarden.AutofillTileService"
android:exported="true"
android:icon="@drawable/ic_notification"
android:label="@string/autofill_title"
android:label="@string/autofill_verb"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
tools:ignore="MissingClass">
<intent-filter>

View File

@@ -30,7 +30,7 @@ class AuthSdkSourceImpl(
getClient()
.auth()
.newAuthRequest(
email = email,
email = email.lowercase(),
)
}
@@ -42,7 +42,7 @@ class AuthSdkSourceImpl(
.platform()
.fingerprint(
req = FingerprintRequest(
fingerprintMaterial = email,
fingerprintMaterial = email.lowercase(),
publicKey = publicKey,
),
)

View File

@@ -49,6 +49,7 @@ class OriginManagerImpl(
)
.fold(
onSuccess = {
Timber.d("Digital asset link validation result: linked = ${it.linked}")
if (it.linked) {
ValidateOriginResult.Success(null)
} else {
@@ -56,6 +57,7 @@ class OriginManagerImpl(
}
},
onFailure = {
Timber.e("Failed to validate origin for calling app")
ValidateOriginResult.Error.AssetLinkNotFound
},
)
@@ -105,7 +107,7 @@ class OriginManagerImpl(
.fold(
onSuccess = { it },
onFailure = {
Timber.e(it, "Failed to validate privileged app: ${callingAppInfo.packageName}")
Timber.e(it, "Failed to validate calling app is privileged.")
ValidateOriginResult.Error.Unknown
},
)

View File

@@ -37,6 +37,7 @@ import com.x8bit.bitwarden.data.credentials.model.GetCredentialsRequest
import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import timber.log.Timber
import java.time.Clock
import javax.crypto.Cipher
@@ -63,8 +64,10 @@ class CredentialProviderProcessorImpl(
cancellationSignal: CancellationSignal,
callback: OutcomeReceiver<BeginCreateCredentialResponse, CreateCredentialException>,
) {
Timber.d("Create credential request received.")
val userId = authRepository.activeUserId
if (userId == null) {
Timber.w("No active user. Cannot create credential.")
callback.onError(CreateCredentialUnknownException("Active user is required."))
return
}
@@ -72,12 +75,16 @@ class CredentialProviderProcessorImpl(
val createCredentialJob = ioScope.launch {
(handleCreatePasskeyQuery(request) ?: handleCreatePasswordQuery(request))
?.let { callback.onResult(it) }
?: callback.onError(CreateCredentialUnknownException())
?: run {
Timber.w("Unknown create credential request.")
callback.onError(CreateCredentialUnknownException())
}
}
cancellationSignal.setOnCancelListener {
if (createCredentialJob.isActive) {
createCredentialJob.cancel()
}
Timber.d("Create credential request cancelled by system.")
callback.onError(CreateCredentialCancellationException())
}
}
@@ -87,15 +94,18 @@ class CredentialProviderProcessorImpl(
cancellationSignal: CancellationSignal,
callback: OutcomeReceiver<BeginGetCredentialResponse, GetCredentialException>,
) {
Timber.d("Get credential request received.")
// If the user is not logged in, return an error.
val userState = authRepository.userStateFlow.value
if (userState == null) {
Timber.w("No active user. Cannot get credentials.")
callback.onError(GetCredentialUnknownException("Active user is required."))
return
}
// Return an unlock action if the current account is locked.
if (!userState.activeAccount.isVaultUnlocked) {
Timber.d("Vault is locked. Requesting unlock.")
val authenticationAction = AuthenticationAction(
title = context.getString(BitwardenString.unlock),
pendingIntent = pendingIntentManager.createFido2UnlockPendingIntent(
@@ -120,10 +130,17 @@ class CredentialProviderProcessorImpl(
BeginGetCredentialRequest.asBundle(request),
),
)
.onSuccess { callback.onResult(BeginGetCredentialResponse(credentialEntries = it)) }
.onFailure { callback.onError(GetCredentialUnknownException(it.message)) }
.onSuccess {
Timber.d("Credentials retrieved.")
callback.onResult(BeginGetCredentialResponse(credentialEntries = it))
}
.onFailure {
Timber.w("Error getting credentials.")
callback.onError(GetCredentialUnknownException(it.message))
}
}
cancellationSignal.setOnCancelListener {
Timber.d("Get credential request cancelled by system.")
callback.onError(GetCredentialCancellationException())
getCredentialJob.cancel()
}
@@ -135,6 +152,7 @@ class CredentialProviderProcessorImpl(
callback: OutcomeReceiver<Void?, ClearCredentialException>,
) {
// no-op: RFU
Timber.w("Unsupported clear credential state request received.")
callback.onError(ClearCredentialUnsupportedException())
}

View File

@@ -219,7 +219,7 @@ private fun AutofillSelectionDialog(
selectionItems = {
if (AutofillSelectionOption.AUTOFILL in displayItem.autofillSelectionOptions) {
BitwardenBasicDialogRow(
text = stringResource(id = BitwardenString.autofill_title),
text = stringResource(id = BitwardenString.autofill_verb),
onClick = {
selectionCallback(
displayItem,

View File

@@ -241,7 +241,7 @@ enum class Settings(
testTag = "AccountSecuritySettingsButton",
),
AUTO_FILL(
text = BitwardenString.autofill_title.asText(),
text = BitwardenString.autofill_noun.asText(),
vectorIconRes = BitwardenDrawable.ic_check_mark,
testTag = "AutofillSettingsButton",
),

View File

@@ -158,7 +158,7 @@ fun AutoFillScreen(
.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
BitwardenTopAppBar(
title = stringResource(id = BitwardenString.autofill_title),
title = stringResource(id = BitwardenString.autofill_noun),
scrollBehavior = scrollBehavior,
navigationIcon = rememberVectorPainter(id = BitwardenDrawable.ic_back),
navigationIconContentDescription = stringResource(id = BitwardenString.back),
@@ -196,7 +196,7 @@ private fun AutoFillScreenContent(
)
Spacer(modifier = Modifier.height(height = 16.dp))
BitwardenListHeaderText(
label = stringResource(id = BitwardenString.autofill_title),
label = stringResource(id = BitwardenString.autofill_noun),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()

View File

@@ -7,8 +7,8 @@ import com.bitwarden.data.datasource.disk.model.EnvironmentUrlDataJson
import com.bitwarden.network.model.GetTokenResponseJson
import com.bitwarden.network.model.KdfTypeJson
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.network.model.createMockOrganization
import com.bitwarden.network.model.createMockPolicy
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
import com.x8bit.bitwarden.data.auth.datasource.disk.util.FakeAuthDiskSource
@@ -259,7 +259,7 @@ class UserStateManagerTest {
@Test
fun `userStateFlow should update isExportable when getUserPolicies returns policies`() =
runTest {
val policy = SyncResponseJson.Policy(
val policy = createMockPolicy(
id = "policyId",
organizationId = "mockId-1",
type = PolicyTypeJson.DISABLE_PERSONAL_VAULT_EXPORT,

View File

@@ -9,6 +9,7 @@ import com.bitwarden.network.model.OrganizationType
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.network.model.TrustedDeviceUserDecryptionOptionsJson
import com.bitwarden.network.model.createMockPolicy
import com.bitwarden.network.model.UserDecryptionJson
import com.bitwarden.network.model.UserDecryptionOptionsJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
@@ -1586,7 +1587,7 @@ class UserStateJsonExtensionsTest {
firstTimeState = FirstTimeState(showImportLoginsCard = true),
getUserPolicies = { _, _ ->
listOf(
SyncResponseJson.Policy(
createMockPolicy(
id = "policyId",
organizationId = "organizationId",
type = PolicyTypeJson.DISABLE_PERSONAL_VAULT_EXPORT,
@@ -1710,7 +1711,7 @@ class UserStateJsonExtensionsTest {
firstTimeState = FirstTimeState(showImportLoginsCard = true),
getUserPolicies = { _, _ ->
listOf(
SyncResponseJson.Policy(
createMockPolicy(
id = "policyId",
organizationId = "organizationId",
type = PolicyTypeJson.DISABLE_PERSONAL_VAULT_EXPORT,

View File

@@ -4,6 +4,7 @@ import app.cash.turbine.test
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.network.model.createMockPolicy
import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
import io.mockk.every
@@ -81,7 +82,7 @@ class PolicyManagerExtensionsTest {
}
}
private val MASTER_PASSWORD_POLICY = SyncResponseJson.Policy(
private val MASTER_PASSWORD_POLICY = createMockPolicy(
organizationId = "organizationId",
id = "master_password_id",
type = PolicyTypeJson.MASTER_PASSWORD,
@@ -109,7 +110,7 @@ private val MASTER_PASSWORD_POLICY_INFO = PolicyInformation.MasterPassword(
enforceOnLogin = true,
)
private val PASSWORD_GENERATOR_POLICY = SyncResponseJson.Policy(
private val PASSWORD_GENERATOR_POLICY = createMockPolicy(
organizationId = "organizationId",
id = "password_generator_id",
type = PolicyTypeJson.PASSWORD_GENERATOR,

View File

@@ -10,7 +10,7 @@ import com.bitwarden.cxf.model.CredentialExchangeVersion
import com.bitwarden.network.model.ImportCiphersJsonRequest
import com.bitwarden.network.model.ImportCiphersResponseJson
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.network.model.createMockPolicy
import com.bitwarden.network.service.CiphersService
import com.bitwarden.network.util.base64UrlDecodeOrNull
import com.bitwarden.vault.Cipher
@@ -358,7 +358,7 @@ class CredentialExchangeImportManagerTest {
every {
policyManager.getActivePolicies(PolicyTypeJson.RESTRICT_ITEM_TYPES)
} returns listOf(
SyncResponseJson.Policy(
createMockPolicy(
id = "mockId-1",
organizationId = "mockId-1",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,
@@ -448,7 +448,7 @@ class CredentialExchangeImportManagerTest {
every {
policyManager.getActivePolicies(PolicyTypeJson.RESTRICT_ITEM_TYPES)
} returns listOf(
SyncResponseJson.Policy(
createMockPolicy(
id = "mockId-1",
organizationId = "mockId-1",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,
@@ -497,7 +497,7 @@ class CredentialExchangeImportManagerTest {
every {
policyManager.getActivePolicies(PolicyTypeJson.RESTRICT_ITEM_TYPES)
} returns listOf(
SyncResponseJson.Policy(
createMockPolicy(
id = "mockId-1",
organizationId = "mockId-1",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,

View File

@@ -10,6 +10,7 @@ import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.data.repository.model.Environment
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.network.model.createMockPolicy
import com.bitwarden.send.SendType
import com.bitwarden.ui.platform.base.BaseViewModelTest
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
@@ -189,7 +190,7 @@ class SearchViewModelTest : BaseViewModelTest() {
every {
policyManager.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
} returns listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "Test Org",
id = "testId",
type = PolicyTypeJson.PERSONAL_OWNERSHIP,
@@ -1677,7 +1678,7 @@ class SearchViewModelTest : BaseViewModelTest() {
)
mutableActivePoliciesFlow.emit(
listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "Test Organization",
id = "testId",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,

View File

@@ -222,7 +222,7 @@ class GeneratorViewModelTest : BaseViewModelTest() {
"useLower" to JsonPrimitive(true),
)
val policies = listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "organizationId",
id = "id",
type = PolicyTypeJson.PASSWORD_GENERATOR,

View File

@@ -6,7 +6,7 @@ import app.cash.turbine.test
import com.bitwarden.core.data.repository.model.DataState
import com.bitwarden.data.repository.model.Environment
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.network.model.createMockPolicy
import com.bitwarden.send.SendView
import com.bitwarden.ui.platform.base.BaseViewModelTest
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
@@ -127,7 +127,7 @@ class AddEditSendViewModelTest : BaseViewModelTest() {
every {
policyManager.getActivePolicies(type = PolicyTypeJson.SEND_OPTIONS)
} returns listOf(
SyncResponseJson.Policy(
createMockPolicy(
id = "123",
type = PolicyTypeJson.SEND_OPTIONS,
isEnabled = true,

View File

@@ -15,7 +15,7 @@ import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.data.repository.model.Environment
import com.bitwarden.network.model.OrganizationType
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.network.model.createMockPolicy
import com.bitwarden.send.SendView
import com.bitwarden.ui.platform.base.BaseViewModelTest
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
@@ -304,7 +304,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
every {
policyManager.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
} returns listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "Test Org",
id = "testId",
type = PolicyTypeJson.PERSONAL_OWNERSHIP,
@@ -3940,7 +3940,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
every {
policyManager.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
} returns listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "Test Org",
id = "testId",
type = PolicyTypeJson.PERSONAL_OWNERSHIP,

View File

@@ -10,7 +10,7 @@ import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
import com.bitwarden.ui.platform.resource.BitwardenPlurals
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.network.model.createMockPolicy
import com.bitwarden.ui.util.asPluralsText
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.data.platform.manager.PolicyManager
@@ -100,7 +100,7 @@ class ImportItemsViewModelTest : BaseViewModelTest() {
every {
policyManager.getActivePolicies(PolicyTypeJson.RESTRICT_ITEM_TYPES)
} returns listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "org-id",
id = "policy-id",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,

View File

@@ -26,6 +26,7 @@ import com.bitwarden.data.repository.util.baseIconUrl
import com.bitwarden.data.repository.util.baseWebSendUrl
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.network.model.createMockPolicy
import com.bitwarden.send.SendType
import com.bitwarden.ui.platform.base.BaseViewModelTest
import com.bitwarden.ui.platform.components.account.model.AccountSummary
@@ -378,7 +379,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
)
mutableActivePoliciesFlow.emit(
listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "Test Organization",
id = "testId",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,
@@ -1406,7 +1407,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
)
mutableActivePoliciesFlow.emit(
listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "Test Organization",
id = "testId",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,
@@ -1444,7 +1445,7 @@ class VaultItemListingViewModelTest : BaseViewModelTest() {
)
mutableActivePoliciesFlow.emit(
listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "Test Organization",
id = "testId",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,

View File

@@ -9,6 +9,7 @@ import com.bitwarden.data.repository.util.baseIconUrl
import com.bitwarden.network.model.OrganizationType
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.network.model.createMockPolicy
import com.bitwarden.ui.platform.base.BaseViewModelTest
import com.bitwarden.ui.platform.components.account.model.AccountSummary
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
@@ -353,7 +354,7 @@ class VaultViewModelTest : BaseViewModelTest() {
every {
policyManager.getActivePolicies(type = PolicyTypeJson.PERSONAL_OWNERSHIP)
} returns listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "Test Organization",
id = "testId",
type = PolicyTypeJson.PERSONAL_OWNERSHIP,
@@ -446,7 +447,7 @@ class VaultViewModelTest : BaseViewModelTest() {
)
mutableActivePoliciesFlow.emit(
listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "Test Organization",
id = "testId",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,
@@ -2801,7 +2802,7 @@ class VaultViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel()
mutableActivePoliciesFlow.emit(
listOf(
SyncResponseJson.Policy(
createMockPolicy(
organizationId = "Test Organization",
id = "testId",
type = PolicyTypeJson.RESTRICT_ITEM_TYPES,

View File

@@ -53,11 +53,11 @@ mockk = "1.14.6"
okhttp = "5.3.0"
retrofitBom = "3.0.0"
robolectric = "4.16"
sonarqube = "7.0.1.6134"
sonarqube = "7.1.0.6387"
testng = "7.11.0"
timber = "5.0.1"
turbine = "1.2.1"
zxing = "3.5.3"
zxing = "3.5.4"
[libraries]
# Format: <maintainer>-<artifact-name>

View File

@@ -115,6 +115,7 @@ data class SyncResponseJson(
* @property type The type of policy.
* @property isEnabled If the policy is enabled or not.
* @property data Any extra data about the policy, in the form of a JSON string.
* @property revisionDate The revision date of the policy (nullable).
*/
@Serializable
data class Policy(
@@ -132,6 +133,10 @@ data class SyncResponseJson(
@SerialName("data")
val data: JsonObject?,
@SerialName("revisionDate")
@Contextual
val revisionDate: ZonedDateTime?,
)
/**

View File

@@ -1,6 +1,7 @@
package com.bitwarden.network.model
import kotlinx.serialization.json.JsonObject
import java.time.ZonedDateTime
/**
* Create a mock [SyncResponseJson.Policy] with the given [number], [type], and [data].
@@ -13,6 +14,7 @@ fun createMockPolicy(
type: PolicyTypeJson = PolicyTypeJson.MASTER_PASSWORD,
isEnabled: Boolean = false,
data: JsonObject? = null,
revisionDate: ZonedDateTime? = null,
): SyncResponseJson.Policy =
SyncResponseJson.Policy(
organizationId = organizationId,
@@ -20,4 +22,5 @@ fun createMockPolicy(
type = type,
isEnabled = isEnabled,
data = data,
revisionDate = revisionDate,
)

View File

@@ -165,7 +165,8 @@
<string name="search_for_a_login_or_add_a_new_login">Search for a login or add a new login</string>
<string name="disabled">Disabled</string>
<string name="bitwarden_autofill_service_alert2">The easiest way to add new logins to your vault is from the Bitwarden Autofill Service. Learn more about using the Bitwarden Autofill Service by navigating to the “Settings” screen.</string>
<string name="autofill_title">Autofill</string>
<string name="autofill_noun">Autofill</string>
<string name="autofill_verb">Autofill</string>
<string name="autofill_or_view">Do you want to autofill or view this item?</string>
<string name="search">Search</string>
<string name="learn_org">Learn about organizations</string>