Add PolicyInformation data structure (#846)

This commit is contained in:
Shannon Draeker 2024-01-29 11:27:26 -07:00 committed by Álison Fernandes
parent 91207df3fa
commit 39e37eb7c7
5 changed files with 126 additions and 3 deletions

View file

@ -0,0 +1,45 @@
package com.x8bit.bitwarden.data.auth.repository.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* The policy information decoded from the [data] parameter of the [SyncResponseJson.Policy] object.
*/
@Serializable
sealed class PolicyInformation {
/**
* Represents a policy enforcing rules on the user's master password.
*
* @property minLength The minimum length of the password.
* @property minComplexity The minimum complexity of the password.
* @property requireUpper Whether the password requires upper case letters.
* @property requireLower Whether the password requires lower case letters.
* @property requireNumbers Whether the password requires numbers.
* @property requireSpecial Whether the password requires special characters.
* @property enforceOnLogin Whether the password should be enforced on login.
*/
@Serializable
data class MasterPassword(
@SerialName("minLength")
val minLength: Int?,
@SerialName("minComplexity")
val minComplexity: Int?,
@SerialName("requireUpper")
val requireUpper: Boolean?,
@SerialName("requireLower")
val requireLower: Boolean?,
@SerialName("requireNumbers")
val requireNumbers: Boolean?,
@SerialName("requireSpecial")
val requireSpecial: Boolean?,
@SerialName("enforceOnLogin")
val enforceOnLogin: Boolean?,
) : PolicyInformation()
}

View file

@ -1,7 +1,10 @@
package com.x8bit.bitwarden.data.auth.repository.util
import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import kotlinx.serialization.json.Json
/**
* Maps the given [SyncResponseJson.Profile.Organization] to an [Organization].
@ -18,3 +21,17 @@ fun SyncResponseJson.Profile.Organization.toOrganization(): Organization =
*/
fun List<SyncResponseJson.Profile.Organization>.toOrganizations(): List<Organization> =
this.map { it.toOrganization() }
/**
* Convert the JSON data of the [SyncResponseJson.Policy] object into [PolicyInformation] data.
*/
val SyncResponseJson.Policy.policyInformation: PolicyInformation?
get() = data?.toString()?.let {
when (type) {
PolicyTypeJson.MASTER_PASSWORD -> {
Json.decodeFromString<PolicyInformation.MasterPassword>(it)
}
else -> null
}
}

View file

@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.vault.datasource.network.model
import kotlinx.serialization.Contextual
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
import java.time.ZonedDateTime
/**
@ -101,6 +102,7 @@ data class SyncResponseJson(
* @property id The ID of the policy.
* @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.
*/
@Serializable
data class Policy(
@ -115,6 +117,9 @@ data class SyncResponseJson(
@SerialName("enabled")
val isEnabled: Boolean,
@SerialName("data")
val data: JsonObject?,
)
/**

View file

@ -1,8 +1,15 @@
package com.x8bit.bitwarden.data.auth.repository.util
import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockOrganization
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockPolicy
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Test
class SyncResponseJsonExtensionsTest {
@ -37,4 +44,46 @@ class SyncResponseJsonExtensionsTest {
.toOrganizations(),
)
}
@Test
@OptIn(ExperimentalSerializationApi::class)
fun `policyInformation converts the Json data to policy information`() {
val masterPasswordData = buildJsonObject {
put(key = "minLength", value = 10)
put(key = "minComplexity", value = 3)
put(key = "requireUpper", value = null)
put(key = "requireLower", value = null)
put(key = "requireNumbers", value = true)
put(key = "requireSpecial", value = null)
put(key = "enforceOnLogin", value = true)
}
val masterPasswordPolicy = createMockPolicy(
type = PolicyTypeJson.MASTER_PASSWORD,
data = masterPasswordData,
)
val policyInformation = PolicyInformation.MasterPassword(
minLength = 10,
minComplexity = 3,
requireUpper = null,
requireLower = null,
requireNumbers = true,
requireSpecial = null,
enforceOnLogin = true,
)
assertEquals(
policyInformation,
masterPasswordPolicy.policyInformation,
)
}
@Test
fun `policyInformation returns null policy information for null data`() {
val masterPasswordPolicy = createMockPolicy(
type = PolicyTypeJson.MASTER_PASSWORD,
data = null,
)
assertNull(masterPasswordPolicy.policyInformation)
}
}

View file

@ -1,12 +1,19 @@
package com.x8bit.bitwarden.data.vault.datasource.network.model
import kotlinx.serialization.json.JsonObject
/**
* Create a mock [SyncResponseJson.Policy] with a given [number].
* Create a mock [SyncResponseJson.Policy] with the given [number], [type], and [data].
*/
fun createMockPolicy(number: Int): SyncResponseJson.Policy =
fun createMockPolicy(
number: Int = 1,
type: PolicyTypeJson = PolicyTypeJson.MASTER_PASSWORD,
data: JsonObject? = null,
): SyncResponseJson.Policy =
SyncResponseJson.Policy(
organizationId = "mockOrganizationId-$number",
id = "mockId-$number",
type = PolicyTypeJson.MASTER_PASSWORD,
type = type,
isEnabled = false,
data = data,
)