mirror of
https://github.com/bitwarden/android.git
synced 2026-04-28 11:58:40 -05:00
[PM-20309] Migrate Environment and EnvironmentUrlDataJson to data module (#5063)
This commit is contained in:
@@ -1,54 +0,0 @@
|
||||
package com.bitwarden.authenticator.data.auth.datasource.disk.model
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Represents URLs for various Bitwarden domains.
|
||||
*
|
||||
* @property base The overall base URL.
|
||||
* @property api Separate base URL for the "/api" domain (if applicable).
|
||||
* @property identity Separate base URL for the "/identity" domain (if applicable).
|
||||
* @property icon Separate base URL for the icon domain (if applicable).
|
||||
* @property notifications Separate base URL for the notifications domain (if applicable).
|
||||
* @property webVault Separate base URL for the web vault domain (if applicable).
|
||||
* @property events Separate base URL for the events domain (if applicable).
|
||||
*/
|
||||
@Serializable
|
||||
data class EnvironmentUrlDataJson(
|
||||
@SerialName("base")
|
||||
val base: String,
|
||||
|
||||
@SerialName("api")
|
||||
val api: String? = null,
|
||||
|
||||
@SerialName("identity")
|
||||
val identity: String? = null,
|
||||
|
||||
@SerialName("icons")
|
||||
val icon: String? = null,
|
||||
|
||||
@SerialName("notifications")
|
||||
val notifications: String? = null,
|
||||
|
||||
@SerialName("webVault")
|
||||
val webVault: String? = null,
|
||||
|
||||
@SerialName("events")
|
||||
val events: String? = null,
|
||||
) {
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
/**
|
||||
* Default [EnvironmentUrlDataJson] for the US region.
|
||||
*/
|
||||
val DEFAULT_US: EnvironmentUrlDataJson =
|
||||
EnvironmentUrlDataJson(base = "https://vault.bitwarden.com")
|
||||
|
||||
/**
|
||||
* Default [EnvironmentUrlDataJson] for the EU region.
|
||||
*/
|
||||
val DEFAULT_EU: EnvironmentUrlDataJson =
|
||||
EnvironmentUrlDataJson(base = "https://vault.bitwarden.eu")
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.bitwarden.authenticator.data.platform.datasource.network.interceptor
|
||||
|
||||
import com.bitwarden.authenticator.data.platform.repository.model.Environment
|
||||
import com.bitwarden.authenticator.data.platform.repository.util.baseApiUrl
|
||||
import com.bitwarden.data.repository.model.Environment
|
||||
import com.bitwarden.data.repository.util.baseApiUrl
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.bitwarden.authenticator.data.platform.repository.model
|
||||
|
||||
import com.bitwarden.authenticator.data.auth.datasource.disk.model.EnvironmentUrlDataJson
|
||||
import com.bitwarden.authenticator.data.platform.repository.util.labelOrBaseUrlHost
|
||||
|
||||
/**
|
||||
* A higher-level wrapper around [EnvironmentUrlDataJson] that provides type-safety, enumerability,
|
||||
* and human-readable labels.
|
||||
*/
|
||||
sealed class Environment {
|
||||
/**
|
||||
* The [Type] of the environment.
|
||||
*/
|
||||
abstract val type: Type
|
||||
|
||||
/**
|
||||
* The raw [environmentUrlData] that contains specific base URLs for each relevant domain.
|
||||
*/
|
||||
abstract val environmentUrlData: EnvironmentUrlDataJson
|
||||
|
||||
/**
|
||||
* A human-readable label for the environment based in some way on its base URL.
|
||||
*/
|
||||
abstract val label: String
|
||||
|
||||
/**
|
||||
* The default US environment.
|
||||
*/
|
||||
data object Us : Environment() {
|
||||
override val type: Type get() = Type.US
|
||||
override val environmentUrlData: EnvironmentUrlDataJson
|
||||
get() = EnvironmentUrlDataJson.DEFAULT_US
|
||||
override val label: String
|
||||
get() = "bitwarden.com"
|
||||
}
|
||||
|
||||
/**
|
||||
* The default EU environment.
|
||||
*/
|
||||
data object Eu : Environment() {
|
||||
override val type: Type get() = Type.EU
|
||||
override val environmentUrlData: EnvironmentUrlDataJson
|
||||
get() = EnvironmentUrlDataJson.DEFAULT_EU
|
||||
override val label: String
|
||||
get() = "bitwarden.eu"
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom self-hosted environment with a fully configurable [environmentUrlData].
|
||||
*/
|
||||
data class SelfHosted(
|
||||
override val environmentUrlData: EnvironmentUrlDataJson,
|
||||
) : Environment() {
|
||||
override val type: Type get() = Type.SELF_HOSTED
|
||||
override val label: String
|
||||
get() = environmentUrlData.labelOrBaseUrlHost
|
||||
}
|
||||
|
||||
/**
|
||||
* A summary of the various types that can be enumerated over and which contains a
|
||||
* human-readable [label].
|
||||
*/
|
||||
enum class Type {
|
||||
US,
|
||||
EU,
|
||||
SELF_HOSTED,
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
package com.bitwarden.authenticator.data.platform.repository.util
|
||||
|
||||
import com.bitwarden.authenticator.data.auth.datasource.disk.model.EnvironmentUrlDataJson
|
||||
import com.bitwarden.authenticator.data.platform.repository.model.Environment
|
||||
import java.net.URI
|
||||
|
||||
private const val DEFAULT_API_URL: String = "https://api.bitwarden.com"
|
||||
private const val DEFAULT_WEB_VAULT_URL: String = "https://vault.bitwarden.com"
|
||||
private const val DEFAULT_WEB_SEND_URL: String = "https://send.bitwarden.com/#"
|
||||
private const val DEFAULT_ICON_URL: String = "https://icons.bitwarden.net"
|
||||
|
||||
/**
|
||||
* Returns the base api URL or the default value if one is not present.
|
||||
*/
|
||||
val EnvironmentUrlDataJson.baseApiUrl: String
|
||||
get() = this.base.sanitizeUrl?.let { "$it/api" }
|
||||
?: this.api.sanitizeUrl
|
||||
?: DEFAULT_API_URL
|
||||
|
||||
/**
|
||||
* Returns the base web vault URL. This will check for a custom [EnvironmentUrlDataJson.webVault]
|
||||
* before falling back to the [EnvironmentUrlDataJson.base]. This can still return null if both are
|
||||
* null or blank.
|
||||
*/
|
||||
val EnvironmentUrlDataJson.baseWebVaultUrlOrNull: String?
|
||||
get() = this.webVault.sanitizeUrl
|
||||
?: this.base.sanitizeUrl
|
||||
|
||||
/**
|
||||
* Returns the base web vault URL or the default value if one is not present.
|
||||
*
|
||||
* See [baseWebVaultUrlOrNull] for more details.
|
||||
*/
|
||||
val EnvironmentUrlDataJson.baseWebVaultUrlOrDefault: String
|
||||
get() = this.baseWebVaultUrlOrNull ?: DEFAULT_WEB_VAULT_URL
|
||||
|
||||
/**
|
||||
* Returns the base web send URL or the default value if one is not present.
|
||||
*/
|
||||
val EnvironmentUrlDataJson.baseWebSendUrl: String
|
||||
get() =
|
||||
this
|
||||
.baseWebVaultUrlOrNull
|
||||
?.let { "$it/#/send/" }
|
||||
?: DEFAULT_WEB_SEND_URL
|
||||
|
||||
/**
|
||||
* Returns the base web vault import URL or the default value if one is not present.
|
||||
*/
|
||||
val EnvironmentUrlDataJson.toBaseWebVaultImportUrl: String
|
||||
get() =
|
||||
this
|
||||
.baseWebVaultUrlOrDefault
|
||||
.let { "$it/#/tools/import" }
|
||||
|
||||
/**
|
||||
* Returns a base icon url based on the environment or the default value if values are missing.
|
||||
*/
|
||||
val EnvironmentUrlDataJson.baseIconUrl: String
|
||||
get() = this.icon.sanitizeUrl
|
||||
?: this.base.sanitizeUrl?.let { "$it/icons" }
|
||||
?: DEFAULT_ICON_URL
|
||||
|
||||
/**
|
||||
* Returns the appropriate pre-defined labels for environments matching the known US/EU values.
|
||||
* Otherwise returns the host of the custom base URL.
|
||||
*
|
||||
* @see getSelfHostedUrlOrNull
|
||||
*/
|
||||
val EnvironmentUrlDataJson.labelOrBaseUrlHost: String
|
||||
get() = when (this) {
|
||||
EnvironmentUrlDataJson.DEFAULT_US -> Environment.Us.label
|
||||
EnvironmentUrlDataJson.DEFAULT_EU -> Environment.Eu.label
|
||||
else -> {
|
||||
// Grab the domain
|
||||
// Ex:
|
||||
// - "https://www.abc.com/path-1/path-1" -> "www.abc.com"
|
||||
URI
|
||||
.create(getSelfHostedUrlOrNull().orEmpty())
|
||||
.host
|
||||
.orEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first self-hosted environment URL from
|
||||
* [EnvironmentUrlDataJson.webVault], [EnvironmentUrlDataJson.base],
|
||||
* [EnvironmentUrlDataJson.api], and finally [EnvironmentUrlDataJson.identity]. Returns `null` if
|
||||
* all self-host environment URLs are null.
|
||||
*/
|
||||
private fun EnvironmentUrlDataJson.getSelfHostedUrlOrNull(): String? =
|
||||
this.webVault.sanitizeUrl
|
||||
?: this.base.sanitizeUrl
|
||||
?: this.api.sanitizeUrl
|
||||
?: this.identity.sanitizeUrl
|
||||
|
||||
/**
|
||||
* A helper method to filter out blank urls and remove any trailing forward slashes.
|
||||
*/
|
||||
private val String?.sanitizeUrl: String?
|
||||
get() = this?.trimEnd('/').takeIf { !it.isNullOrBlank() }
|
||||
|
||||
/**
|
||||
* Converts a raw [EnvironmentUrlDataJson] to an externally-consumable [Environment].
|
||||
*/
|
||||
fun EnvironmentUrlDataJson.toEnvironmentUrls(): Environment =
|
||||
when (this) {
|
||||
EnvironmentUrlDataJson.DEFAULT_US,
|
||||
-> Environment.Us
|
||||
|
||||
EnvironmentUrlDataJson.DEFAULT_EU,
|
||||
-> Environment.Eu
|
||||
|
||||
else -> Environment.SelfHosted(environmentUrlData = this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a nullable [EnvironmentUrlDataJson] to an [Environment], where `null` values default to
|
||||
* the US environment.
|
||||
*/
|
||||
fun EnvironmentUrlDataJson?.toEnvironmentUrlsOrDefault(): Environment =
|
||||
this?.toEnvironmentUrls() ?: Environment.Us
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.bitwarden.authenticator.data.platform.datasource.network.interceptor
|
||||
|
||||
import com.bitwarden.authenticator.data.auth.datasource.disk.model.EnvironmentUrlDataJson
|
||||
import com.bitwarden.authenticator.data.platform.repository.model.Environment
|
||||
import com.bitwarden.data.datasource.disk.model.EnvironmentUrlDataJson
|
||||
import com.bitwarden.data.repository.model.Environment
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
|
||||
@@ -1,278 +0,0 @@
|
||||
package com.bitwarden.authenticator.data.platform.repository.util
|
||||
|
||||
import com.bitwarden.authenticator.data.auth.datasource.disk.model.EnvironmentUrlDataJson
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class EnvironmentUrlsDataJsonExtensionsTest {
|
||||
@Test
|
||||
fun `baseApiUrl should return base if it is present`() {
|
||||
Assertions.assertEquals(
|
||||
"base/api",
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.baseApiUrl,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `baseApiUrl should return api value if base is empty`() {
|
||||
Assertions.assertEquals(
|
||||
"api",
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.copy(
|
||||
base = "",
|
||||
).baseApiUrl,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `baseApiUrl should return default url if base is empty and api is null`() {
|
||||
Assertions.assertEquals(
|
||||
"https://api.bitwarden.com",
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.copy(
|
||||
base = "",
|
||||
api = null,
|
||||
).baseApiUrl,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `baseWebVaultUrlOrNull should return webVault when populated`() {
|
||||
val result =
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.baseWebVaultUrlOrNull
|
||||
Assertions.assertEquals("webVault", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `baseWebVaultUrlOrNull should return base when webvault is not populated`() {
|
||||
val result =
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||
.copy(webVault = null)
|
||||
.baseWebVaultUrlOrNull
|
||||
Assertions.assertEquals("base", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `baseWebVaultUrlOrNull should return null when webvault and base are not populated`() {
|
||||
val result =
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||
.copy(
|
||||
webVault = null,
|
||||
base = "",
|
||||
)
|
||||
.baseWebVaultUrlOrNull
|
||||
Assertions.assertNull(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `baseWebVaultUrlOrDefault should return webVault when populated`() {
|
||||
val result =
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.baseWebVaultUrlOrDefault
|
||||
Assertions.assertEquals("webVault", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `baseWebVaultUrlOrDefault should return base when webvault is not populated`() {
|
||||
val result =
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||
.copy(webVault = null)
|
||||
.baseWebVaultUrlOrDefault
|
||||
Assertions.assertEquals("base", result)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `baseWebVaultUrlOrDefault should return the default when webvault and base are not populated`() {
|
||||
val result =
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||
.copy(
|
||||
webVault = null,
|
||||
base = "",
|
||||
)
|
||||
.baseWebVaultUrlOrDefault
|
||||
Assertions.assertEquals("https://vault.bitwarden.com", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `baseWebSendUrl should return the correct result when webVault when populated`() {
|
||||
val result =
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.baseWebSendUrl
|
||||
Assertions.assertEquals("webVault/#/send/", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `baseWebSendUrl should return the correct result when webvault is not populated`() {
|
||||
val result =
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||
.copy(webVault = null)
|
||||
.baseWebSendUrl
|
||||
Assertions.assertEquals("base/#/send/", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `baseWebSendUrl should return the default when webvault and base are not populated`() {
|
||||
val result =
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||
.copy(
|
||||
webVault = null,
|
||||
base = "",
|
||||
)
|
||||
.baseWebSendUrl
|
||||
Assertions.assertEquals("https://send.bitwarden.com/#", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `labelOrBaseUrlHost should correctly convert US environment to the correct label`() {
|
||||
val environment =
|
||||
EnvironmentUrlDataJson.Companion.DEFAULT_US
|
||||
Assertions.assertEquals(
|
||||
com.bitwarden.authenticator.data.platform.repository.model.Environment.Us.label,
|
||||
environment.labelOrBaseUrlHost,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `labelOrBaseUrlHost should correctly convert EU environment to the correct label`() {
|
||||
val environment =
|
||||
EnvironmentUrlDataJson.Companion.DEFAULT_EU
|
||||
Assertions.assertEquals(
|
||||
com.bitwarden.authenticator.data.platform.repository.model.Environment.Eu.label,
|
||||
environment.labelOrBaseUrlHost,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `labelOrBaseUrlHost should correctly convert self hosted environment to the correct label`() {
|
||||
val environment =
|
||||
EnvironmentUrlDataJson(base = "https://vault.qa.bitwarden.pw")
|
||||
Assertions.assertEquals(
|
||||
"vault.qa.bitwarden.pw",
|
||||
environment.labelOrBaseUrlHost,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toEnvironmentUrls should correctly convert US urls to the expected type`() {
|
||||
Assertions.assertEquals(
|
||||
com.bitwarden.authenticator.data.platform.repository.model.Environment.Us,
|
||||
EnvironmentUrlDataJson.Companion.DEFAULT_US.toEnvironmentUrls(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toEnvironmentUrls should correctly convert EU urls to the expected type`() {
|
||||
Assertions.assertEquals(
|
||||
com.bitwarden.authenticator.data.platform.repository.model.Environment.Eu,
|
||||
EnvironmentUrlDataJson.Companion.DEFAULT_EU.toEnvironmentUrls(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toEnvironmentUrls should correctly convert custom urls to the expected type`() {
|
||||
Assertions.assertEquals(
|
||||
com.bitwarden.authenticator.data.platform.repository.model.Environment.SelfHosted(
|
||||
environmentUrlData = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA,
|
||||
),
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.toEnvironmentUrls(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toEnvironmentUrlsOrDefault should correctly convert US urls to the expected type`() {
|
||||
Assertions.assertEquals(
|
||||
com.bitwarden.authenticator.data.platform.repository.model.Environment.Us,
|
||||
EnvironmentUrlDataJson.Companion.DEFAULT_US.toEnvironmentUrlsOrDefault(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toEnvironmentUrlsOrDefault should correctly convert EU urls to the expected type`() {
|
||||
Assertions.assertEquals(
|
||||
com.bitwarden.authenticator.data.platform.repository.model.Environment.Eu,
|
||||
EnvironmentUrlDataJson.Companion.DEFAULT_EU.toEnvironmentUrlsOrDefault(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toEnvironmentUrlsOrDefault should correctly convert custom urls to the expected type`() {
|
||||
Assertions.assertEquals(
|
||||
com.bitwarden.authenticator.data.platform.repository.model.Environment.SelfHosted(
|
||||
environmentUrlData = DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA,
|
||||
),
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.toEnvironmentUrlsOrDefault(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toEnvironmentUrlsOrDefault should convert null types to US values`() {
|
||||
Assertions.assertEquals(
|
||||
com.bitwarden.authenticator.data.platform.repository.model.Environment.Us,
|
||||
(null as EnvironmentUrlDataJson?).toEnvironmentUrlsOrDefault(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toIconBaseurl should return icon if value is present`() {
|
||||
Assertions.assertEquals(
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.baseIconUrl,
|
||||
"icon",
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toIconBaseurl should return base value if icon is null`() {
|
||||
Assertions.assertEquals(
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||
.copy(icon = null)
|
||||
.baseIconUrl,
|
||||
"base/icons",
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toIconBaseurl should return default url if base is empty and icon is null`() {
|
||||
val expectedUrl = "https://icons.bitwarden.net"
|
||||
|
||||
Assertions.assertEquals(
|
||||
expectedUrl,
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA
|
||||
.copy(
|
||||
base = "",
|
||||
icon = null,
|
||||
)
|
||||
.baseIconUrl,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toBaseWebVaultImportUrl should return correct url if webVault is empty`() {
|
||||
val expectedUrl = "base/#/tools/import"
|
||||
|
||||
Assertions.assertEquals(
|
||||
expectedUrl,
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.copy(
|
||||
webVault = null,
|
||||
)
|
||||
.toBaseWebVaultImportUrl,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `toBaseWebVaultImportUrl should correctly convert to the import url`() {
|
||||
val expectedUrl = "webVault/#/tools/import"
|
||||
|
||||
Assertions.assertEquals(
|
||||
expectedUrl,
|
||||
DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA.toBaseWebVaultImportUrl,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val DEFAULT_CUSTOM_ENVIRONMENT_URL_DATA = EnvironmentUrlDataJson(
|
||||
base = "base",
|
||||
api = "api",
|
||||
identity = "identity",
|
||||
icon = "icon",
|
||||
notifications = "notifications",
|
||||
webVault = "webVault",
|
||||
events = "events",
|
||||
)
|
||||
Reference in New Issue
Block a user