mirror of
https://github.com/bitwarden/android.git
synced 2026-08-01 03:05:47 -05:00
[PM-40527] feat: Add SendControls policy data model and feature flags (#7179)
This commit is contained in:
+38
@@ -1,5 +1,7 @@
|
||||
package com.x8bit.bitwarden.data.auth.repository.model
|
||||
|
||||
import com.bitwarden.network.model.SendTypeJson
|
||||
import com.bitwarden.network.model.SendAccessTypeJson
|
||||
import com.bitwarden.network.model.SyncResponseJson
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -113,6 +115,42 @@ sealed class PolicyInformation {
|
||||
val shouldDisableHideEmail: Boolean?,
|
||||
) : PolicyInformation()
|
||||
|
||||
/**
|
||||
* Represents a policy enforcing rules on the creation and sharing of Sends. Supersedes the
|
||||
* disable-send policy and [SendOptions] when the `pm-31885-send-controls` feature flag is
|
||||
* active.
|
||||
*
|
||||
* @property disableSend Whether the ability to create and edit Sends is disabled.
|
||||
* @property disableHideEmail Whether the user should have the ability to hide their email
|
||||
* address from Send recipients.
|
||||
* @property whoCanAccess The access type Sends are restricted to, if any.
|
||||
* @property allowedDomains A comma-separated list of email domains recipients must belong to
|
||||
* when [whoCanAccess] is [SendAccessTypeJson.SPECIFIC_PEOPLE].
|
||||
* @property deletionHours The number of hours until a Send is deleted, if enforced.
|
||||
* @property allowedSendTypes The types of Sends that are allowed to be created, if
|
||||
* restricted.
|
||||
*/
|
||||
@Serializable
|
||||
data class SendControls(
|
||||
@SerialName("disableSend")
|
||||
val disableSend: Boolean?,
|
||||
|
||||
@SerialName("disableHideEmail")
|
||||
val disableHideEmail: Boolean?,
|
||||
|
||||
@SerialName("whoCanAccess")
|
||||
val whoCanAccess: SendAccessTypeJson?,
|
||||
|
||||
@SerialName("allowedDomains")
|
||||
val allowedDomains: String?,
|
||||
|
||||
@SerialName("deletionHours")
|
||||
val deletionHours: Int?,
|
||||
|
||||
@SerialName("allowedSendTypes")
|
||||
val allowedSendTypes: List<SendTypeJson>?,
|
||||
) : PolicyInformation()
|
||||
|
||||
/**
|
||||
* Represents a policy enforcing rules on the user's vault timeout settings.
|
||||
*/
|
||||
|
||||
+4
@@ -153,6 +153,10 @@ val PolicyView.policyInformation: PolicyInformation?
|
||||
JSON.decodeFromStringOrNull<PolicyInformation.SendOptions>(it)
|
||||
}
|
||||
|
||||
PolicyType.SEND_CONTROLS -> {
|
||||
JSON.decodeFromStringOrNull<PolicyInformation.SendControls>(it)
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -34,6 +34,7 @@ inline fun <reified T : PolicyInformation> getPolicyType(): PolicyType =
|
||||
PolicyInformation.MasterPassword::class.java -> PolicyType.MASTER_PASSWORD
|
||||
PolicyInformation.PasswordGenerator::class.java -> PolicyType.PASSWORD_GENERATOR
|
||||
PolicyInformation.SendOptions::class.java -> PolicyType.SEND_OPTIONS
|
||||
PolicyInformation.SendControls::class.java -> PolicyType.SEND_CONTROLS
|
||||
PolicyInformation.VaultTimeout::class.java -> PolicyType.MAXIMUM_VAULT_TIMEOUT
|
||||
|
||||
else -> {
|
||||
|
||||
+23
@@ -1,6 +1,8 @@
|
||||
package com.x8bit.bitwarden.data.auth.repository.util
|
||||
|
||||
import com.bitwarden.network.model.OrganizationType
|
||||
import com.bitwarden.network.model.SendTypeJson
|
||||
import com.bitwarden.network.model.SendAccessTypeJson
|
||||
import com.bitwarden.network.model.SyncResponseJson
|
||||
import com.bitwarden.network.model.createMockOrganizationNetwork
|
||||
import com.bitwarden.network.model.createMockPermissions
|
||||
@@ -172,6 +174,27 @@ class SyncResponseJsonExtensionsTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `policyInformation converts the SendControls Json data to policy information`() {
|
||||
val policyInformation = PolicyInformation.SendControls(
|
||||
disableSend = false,
|
||||
disableHideEmail = true,
|
||||
whoCanAccess = SendAccessTypeJson.SPECIFIC_PEOPLE,
|
||||
allowedDomains = "bitwarden.com",
|
||||
deletionHours = 168,
|
||||
allowedSendTypes = listOf(SendTypeJson.TEXT),
|
||||
)
|
||||
val policy = createMockPolicyView(
|
||||
type = PolicyType.SEND_CONTROLS,
|
||||
data = Json.encodeToString(policyInformation),
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
policyInformation,
|
||||
policy.policyInformation,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `policyInformation returns null policy information for null data`() {
|
||||
val masterPasswordPolicy = createMockPolicyView(
|
||||
|
||||
+8
@@ -70,6 +70,14 @@ class PolicyManagerExtensionsTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPolicyType with SendControls should map to appropriate PolicyTypeJson`() {
|
||||
assertEquals(
|
||||
PolicyType.SEND_CONTROLS,
|
||||
getPolicyType<PolicyInformation.SendControls>(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPolicyType with VaultTimeout should map to appropriate PolicyTypeJson`() {
|
||||
assertEquals(
|
||||
|
||||
@@ -46,6 +46,8 @@ sealed class FlagKey<out T : Any> {
|
||||
FillAssistTargetingRules,
|
||||
PoliciesInAcceptedState,
|
||||
FedRamp,
|
||||
SendControls,
|
||||
SendControlsExistingSends,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -189,6 +191,23 @@ sealed class FlagKey<out T : Any> {
|
||||
override val defaultValue: Boolean = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Data object holding the feature flag key for the consolidated Send Controls policy.
|
||||
*/
|
||||
data object SendControls : FlagKey<Boolean>() {
|
||||
override val keyName: String = "pm-31885-send-controls"
|
||||
override val defaultValue: Boolean = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Data object holding the feature flag key for enforcing the Send Controls policy against
|
||||
* Sends created before the policy existed.
|
||||
*/
|
||||
data object SendControlsExistingSends : FlagKey<Boolean>() {
|
||||
override val keyName: String = "pm-31885-send-controls-existing-sends"
|
||||
override val defaultValue: Boolean = false
|
||||
}
|
||||
|
||||
//region Dummy keys for testing
|
||||
/**
|
||||
* Data object holding the key for a [Boolean] flag to be used in tests.
|
||||
|
||||
@@ -64,6 +64,14 @@ class FlagKeyTest {
|
||||
FlagKey.FedRamp.keyName,
|
||||
"fedramp-gov-region",
|
||||
)
|
||||
assertEquals(
|
||||
FlagKey.SendControls.keyName,
|
||||
"pm-31885-send-controls",
|
||||
)
|
||||
assertEquals(
|
||||
FlagKey.SendControlsExistingSends.keyName,
|
||||
"pm-31885-send-controls-existing-sends",
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -84,6 +92,8 @@ class FlagKeyTest {
|
||||
FlagKey.ManageDevices,
|
||||
FlagKey.PoliciesInAcceptedState,
|
||||
FlagKey.FedRamp,
|
||||
FlagKey.SendControls,
|
||||
FlagKey.SendControlsExistingSends,
|
||||
).all {
|
||||
!it.defaultValue
|
||||
},
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.bitwarden.network.model
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import com.bitwarden.core.data.serializer.BaseEnumeratedIntSerializer
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Represents who is allowed to view a Send under the `SendControls` policy.
|
||||
*/
|
||||
@Serializable(SendAccessTypeSerializer::class)
|
||||
enum class SendAccessTypeJson {
|
||||
/**
|
||||
* Anyone with the link can view the Send.
|
||||
*/
|
||||
@SerialName("0")
|
||||
ANY,
|
||||
|
||||
/**
|
||||
* Only individuals with the password set on the Send can view it.
|
||||
*/
|
||||
@SerialName("1")
|
||||
PASSWORD_PROTECTED,
|
||||
|
||||
/**
|
||||
* Only specific people, identified by email, can view the Send.
|
||||
*/
|
||||
@SerialName("2")
|
||||
SPECIFIC_PEOPLE,
|
||||
}
|
||||
|
||||
@Keep
|
||||
private class SendAccessTypeSerializer :
|
||||
BaseEnumeratedIntSerializer<SendAccessTypeJson>(
|
||||
className = "SendAccessTypeJson",
|
||||
values = SendAccessTypeJson.entries.toTypedArray(),
|
||||
)
|
||||
@@ -40,6 +40,8 @@ fun <T : Any> FlagKey<T>.ListItemContent(
|
||||
FlagKey.DebugDisableSelfHostPremiumCheck,
|
||||
FlagKey.PoliciesInAcceptedState,
|
||||
FlagKey.FedRamp,
|
||||
FlagKey.SendControls,
|
||||
FlagKey.SendControlsExistingSends,
|
||||
-> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
BooleanFlagItem(
|
||||
@@ -104,4 +106,8 @@ private fun <T : Any> FlagKey<T>.getDisplayLabel(): String = when (this) {
|
||||
}
|
||||
|
||||
FlagKey.FedRamp -> stringResource(BitwardenString.fed_ramp)
|
||||
FlagKey.SendControls -> stringResource(BitwardenString.send_controls)
|
||||
FlagKey.SendControlsExistingSends -> {
|
||||
stringResource(BitwardenString.send_controls_existing_sends)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
<string name="debug_disable_self_host_premium_check">Debug: Disable self-host premium check</string>
|
||||
<string name="policies_in_accepted_state">Policies in accepted state</string>
|
||||
<string name="fed_ramp">FedRAMP</string>
|
||||
<string name="send_controls">Send Controls</string>
|
||||
<string name="send_controls_existing_sends">Send Controls - Existing Sends</string>
|
||||
|
||||
<!-- endregion Debug Menu -->
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user