mirror of
https://github.com/bitwarden/android.git
synced 2026-06-11 00:56:24 -05:00
Compare commits
3 Commits
PM-37255/f
...
sdlc/sdk-u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cada80b4b8 | ||
|
|
b7a2691804 | ||
|
|
2c2c534bcd |
@@ -27,10 +27,4 @@ interface EnvironmentDiskSource {
|
||||
* Stores the [urls] for the given [userEmail].
|
||||
*/
|
||||
fun storePreAuthEnvironmentUrlDataForEmail(userEmail: String, urls: EnvironmentUrlDataJson)
|
||||
|
||||
/**
|
||||
* The fill-assist URL provided by the server config, or `null` if the server does not
|
||||
* configure fill-assist targeting rules.
|
||||
*/
|
||||
var fillAssistRulesUrl: String?
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import kotlinx.serialization.json.Json
|
||||
|
||||
private const val PRE_AUTH_URLS_KEY = "preAuthEnvironmentUrls"
|
||||
private const val EMAIL_VERIFICATION_URLS = "emailVerificationUrls"
|
||||
private const val FILL_ASSIST_RULES_URL_KEY = "fillAssistRulesUrl"
|
||||
|
||||
/**
|
||||
* Primary implementation of [EnvironmentDiskSource].
|
||||
@@ -55,8 +54,4 @@ class EnvironmentDiskSourceImpl(
|
||||
value = json.encodeToString(urls),
|
||||
)
|
||||
}
|
||||
|
||||
override var fillAssistRulesUrl: String?
|
||||
get() = getString(key = FILL_ASSIST_RULES_URL_KEY)
|
||||
set(value) = putString(key = FILL_ASSIST_RULES_URL_KEY, value = value)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.bitwarden.network.interceptor.BaseUrlsProvider
|
||||
import com.bitwarden.network.model.BitwardenServiceClientConfig
|
||||
import com.bitwarden.network.service.ConfigService
|
||||
import com.bitwarden.network.service.EventService
|
||||
import com.bitwarden.network.service.FillAssistService
|
||||
import com.bitwarden.network.service.PushService
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||
import com.x8bit.bitwarden.data.auth.manager.AuthTokenManager
|
||||
@@ -33,12 +32,6 @@ import javax.inject.Singleton
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object PlatformNetworkModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesFillAssistService(
|
||||
bitwardenServiceClient: BitwardenServiceClient,
|
||||
): FillAssistService = bitwardenServiceClient.fillAssistService
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesConfigService(
|
||||
|
||||
@@ -31,6 +31,4 @@ class BaseUrlsProviderImpl(
|
||||
.toEnvironmentUrlsOrDefault()
|
||||
.environmentUrlData
|
||||
.baseEventsUrl
|
||||
|
||||
override fun getBaseFillAssistUrl(): String? = environmentDiskSource.fillAssistRulesUrl
|
||||
}
|
||||
|
||||
@@ -7589,7 +7589,6 @@ class AuthRepositoryTest {
|
||||
identityUrl = "mockIdentityUrl",
|
||||
notificationsUrl = "mockNotificationsUrl",
|
||||
ssoUrl = "mockSsoUrl",
|
||||
fillAssistRulesUrl = null,
|
||||
),
|
||||
featureStates = emptyMap(),
|
||||
communication = null,
|
||||
|
||||
@@ -95,26 +95,11 @@ class EnvironmentDiskSourceTest {
|
||||
json.parseToJsonElement(requireNotNull(actual)),
|
||||
)
|
||||
}
|
||||
@Test
|
||||
fun `fillAssistRulesUrl should pull from and update SharedPreferences`() {
|
||||
assertNull(environmentDiskSource.fillAssistRulesUrl)
|
||||
assertNull(fakeSharedPreferences.getString(FILL_ASSIST_RULES_URL_KEY, null))
|
||||
|
||||
environmentDiskSource.fillAssistRulesUrl = "https://fill-assist.example.com/"
|
||||
assertEquals(
|
||||
"https://fill-assist.example.com/",
|
||||
fakeSharedPreferences.getString(FILL_ASSIST_RULES_URL_KEY, null),
|
||||
)
|
||||
|
||||
environmentDiskSource.fillAssistRulesUrl = null
|
||||
assertNull(fakeSharedPreferences.getString(FILL_ASSIST_RULES_URL_KEY, null))
|
||||
}
|
||||
}
|
||||
|
||||
private const val EMAIL = "email@example.com"
|
||||
private const val EMAIL_VERIFICATION_URLS_KEY = "bwPreferencesStorage:emailVerificationUrls"
|
||||
private const val PRE_AUTH_URLS_KEY = "bwPreferencesStorage:preAuthEnvironmentUrls"
|
||||
private const val FILL_ASSIST_RULES_URL_KEY = "bwPreferencesStorage:fillAssistRulesUrl"
|
||||
|
||||
private const val ENVIRONMENT_URL_DATA_JSON = """
|
||||
{
|
||||
|
||||
@@ -29,8 +29,6 @@ class FakeEnvironmentDiskSource : EnvironmentDiskSource {
|
||||
storedEmailVerificationUrls[userEmail] = urls
|
||||
}
|
||||
|
||||
override var fillAssistRulesUrl: String? = null
|
||||
|
||||
private val mutablePreAuthEnvironmentUrlDataFlow =
|
||||
bufferedMutableSharedFlow<EnvironmentUrlDataJson?>(replay = 1)
|
||||
}
|
||||
|
||||
@@ -62,7 +62,6 @@ class ServerCommunicationConfigRepositoryTest {
|
||||
identityUrl = null,
|
||||
notificationsUrl = null,
|
||||
ssoUrl = null,
|
||||
fillAssistRulesUrl = null,
|
||||
),
|
||||
featureStates = null,
|
||||
communication = ConfigResponseJson.CommunicationJson(
|
||||
|
||||
@@ -319,7 +319,6 @@ private val SERVER_CONFIG = ServerConfig(
|
||||
identityUrl = "http://localhost:33656",
|
||||
notificationsUrl = "http://localhost:61840",
|
||||
ssoUrl = "http://localhost:51822",
|
||||
fillAssistRulesUrl = null,
|
||||
),
|
||||
featureStates = mapOf(
|
||||
"dummy-boolean" to JsonPrimitive(true),
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.bitwarden.data.repository.model.Environment
|
||||
import com.x8bit.bitwarden.data.platform.datasource.disk.FakeEnvironmentDiskSource
|
||||
import com.x8bit.bitwarden.data.platform.provider.BaseUrlsProviderImpl
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNull
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class BaseUrlsProviderTest {
|
||||
@@ -67,16 +66,4 @@ class BaseUrlsProviderTest {
|
||||
baseUrlsManager.getBaseEventsUrl(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getBaseFillAssistUrl should return url from disk source when present`() {
|
||||
fakeEnvironmentDiskSource.fillAssistRulesUrl = "https://example.com/"
|
||||
assertEquals("https://example.com/", baseUrlsManager.getBaseFillAssistUrl())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getBaseFillAssistUrl should return null when not set`() {
|
||||
fakeEnvironmentDiskSource.fillAssistRulesUrl = null
|
||||
assertNull(baseUrlsManager.getBaseFillAssistUrl())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ class SdkRepositoryFactoryTests {
|
||||
override fun getBaseApiUrl(): String = BASE_API_URL
|
||||
override fun getBaseIdentityUrl(): String = BASE_IDENTITY_URL
|
||||
override fun getBaseEventsUrl(): String = BASE_EVENTS_URL
|
||||
override fun getBaseFillAssistUrl(): String? = null
|
||||
},
|
||||
authTokenProvider = mockk(),
|
||||
certificateProvider = mockk(),
|
||||
|
||||
@@ -48,7 +48,6 @@ private val SERVER_CONFIG = ServerConfig(
|
||||
identityUrl = "http://localhost:33656",
|
||||
notificationsUrl = "http://localhost:61840",
|
||||
ssoUrl = "http://localhost:51822",
|
||||
fillAssistRulesUrl = null,
|
||||
),
|
||||
featureStates = mapOf(
|
||||
"duo-redirect" to JsonPrimitive(true),
|
||||
|
||||
@@ -20,6 +20,4 @@ object BaseUrlsProviderImpl : BaseUrlsProvider {
|
||||
|
||||
override fun getBaseEventsUrl(): String =
|
||||
Environment.Us.environmentUrlData.baseEventsUrl
|
||||
|
||||
override fun getBaseFillAssistUrl(): String? = null
|
||||
}
|
||||
|
||||
@@ -262,7 +262,6 @@ private val SERVER_CONFIG = ServerConfig(
|
||||
identityUrl = "http://localhost:33656",
|
||||
notificationsUrl = "http://localhost:61840",
|
||||
ssoUrl = "http://localhost:51822",
|
||||
fillAssistRulesUrl = null,
|
||||
),
|
||||
featureStates = mapOf(
|
||||
"dummy-boolean" to JsonPrimitive(true),
|
||||
|
||||
@@ -48,7 +48,6 @@ private val SERVER_CONFIG = ServerConfig(
|
||||
identityUrl = "http://localhost:33656",
|
||||
notificationsUrl = "http://localhost:61840",
|
||||
ssoUrl = "http://localhost:51822",
|
||||
fillAssistRulesUrl = null,
|
||||
),
|
||||
featureStates = mapOf(
|
||||
"duo-redirect" to JsonPrimitive(true),
|
||||
|
||||
@@ -107,7 +107,6 @@ private val SERVER_CONFIG = ServerConfig(
|
||||
identityUrl = "http://localhost:33656",
|
||||
notificationsUrl = "http://localhost:61840",
|
||||
ssoUrl = "http://localhost:51822",
|
||||
fillAssistRulesUrl = null,
|
||||
),
|
||||
featureStates = mapOf(
|
||||
"duo-redirect" to JsonPrimitive(true),
|
||||
|
||||
@@ -161,7 +161,6 @@ private val SERVER_CONFIG = ServerConfig(
|
||||
identityUrl = "http://localhost:33656",
|
||||
notificationsUrl = "http://localhost:61840",
|
||||
ssoUrl = "http://localhost:51822",
|
||||
fillAssistRulesUrl = null,
|
||||
),
|
||||
featureStates = mapOf(
|
||||
"duo-redirect" to JsonPrimitive(true),
|
||||
@@ -186,7 +185,6 @@ private val CONFIG_RESPONSE_JSON = ConfigResponseJson(
|
||||
identityUrl = "http://localhost:33656",
|
||||
notificationsUrl = "http://localhost:61840",
|
||||
ssoUrl = "http://localhost:51822",
|
||||
fillAssistRulesUrl = null,
|
||||
),
|
||||
featureStates = mapOf(
|
||||
"duo-redirect" to JsonPrimitive(true),
|
||||
|
||||
@@ -30,7 +30,7 @@ androidxRoom = "2.8.4"
|
||||
androidxSecurityCrypto = "1.1.0"
|
||||
androidxSplash = "1.2.0"
|
||||
androidxWork = "2.11.2"
|
||||
bitwardenSdk = "3.0.0-7338-5bdc976f"
|
||||
bitwardenSdk = "3.0.0-7360-56536238"
|
||||
crashlytics = "3.0.7"
|
||||
detekt = "1.23.8"
|
||||
firebaseBom = "34.14.0"
|
||||
|
||||
@@ -16,7 +16,6 @@ import com.bitwarden.network.service.DevicesService
|
||||
import com.bitwarden.network.service.DigitalAssetLinkService
|
||||
import com.bitwarden.network.service.DownloadService
|
||||
import com.bitwarden.network.service.EventService
|
||||
import com.bitwarden.network.service.FillAssistService
|
||||
import com.bitwarden.network.service.FolderService
|
||||
import com.bitwarden.network.service.HaveIBeenPwnedService
|
||||
import com.bitwarden.network.service.IdentityService
|
||||
@@ -108,11 +107,6 @@ interface BitwardenServiceClient {
|
||||
*/
|
||||
val eventService: EventService
|
||||
|
||||
/**
|
||||
* Provides access to the Fill-Assist service.
|
||||
*/
|
||||
val fillAssistService: FillAssistService
|
||||
|
||||
/**
|
||||
* Provides access to the Folder service.
|
||||
*/
|
||||
|
||||
@@ -29,8 +29,6 @@ import com.bitwarden.network.service.DownloadService
|
||||
import com.bitwarden.network.service.DownloadServiceImpl
|
||||
import com.bitwarden.network.service.EventService
|
||||
import com.bitwarden.network.service.EventServiceImpl
|
||||
import com.bitwarden.network.service.FillAssistService
|
||||
import com.bitwarden.network.service.FillAssistServiceImpl
|
||||
import com.bitwarden.network.service.FolderService
|
||||
import com.bitwarden.network.service.FolderServiceImpl
|
||||
import com.bitwarden.network.service.HaveIBeenPwnedService
|
||||
@@ -157,10 +155,6 @@ internal class BitwardenServiceClientImpl(
|
||||
)
|
||||
}
|
||||
|
||||
override val fillAssistService: FillAssistService by lazy {
|
||||
FillAssistServiceImpl(api = retrofits.fillAssistRetrofit.create())
|
||||
}
|
||||
|
||||
override val haveIBeenPwnedService: HaveIBeenPwnedService by lazy {
|
||||
HaveIBeenPwnedServiceImpl(
|
||||
api = retrofits
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.bitwarden.network.api
|
||||
|
||||
import com.bitwarden.network.model.FillAssistFormsJson
|
||||
import com.bitwarden.network.model.FillAssistManifestJson
|
||||
import com.bitwarden.network.model.NetworkResult
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Path
|
||||
|
||||
/**
|
||||
* Defines endpoints for retrieving fill-assist targeting rules. The base URL is set dynamically
|
||||
* at runtime via [com.bitwarden.network.interceptor.BaseUrlInterceptors.fillAssistInterceptor].
|
||||
*/
|
||||
internal interface FillAssistApi {
|
||||
/**
|
||||
* Fetches the fill-assist manifest.
|
||||
*/
|
||||
@GET("manifest.json")
|
||||
suspend fun getManifest(): NetworkResult<FillAssistManifestJson>
|
||||
|
||||
/**
|
||||
* Fetches the forms rules file by [filename] (e.g. "forms.v1.json").
|
||||
*/
|
||||
@GET("{filename}")
|
||||
suspend fun getForms(
|
||||
@Path("filename") filename: String,
|
||||
): NetworkResult<FillAssistFormsJson>
|
||||
}
|
||||
@@ -29,11 +29,4 @@ internal class BaseUrlInterceptors(
|
||||
val eventsInterceptor: BaseUrlInterceptor = BaseUrlInterceptor {
|
||||
baseUrlsProvider.getBaseEventsUrl()
|
||||
}
|
||||
|
||||
/**
|
||||
* An interceptor for fill-assist calls.
|
||||
*/
|
||||
val fillAssistInterceptor: BaseUrlInterceptor = BaseUrlInterceptor {
|
||||
baseUrlsProvider.getBaseFillAssistUrl()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,4 @@ interface BaseUrlsProvider {
|
||||
* Gets the base URL for "/events" calls.
|
||||
*/
|
||||
fun getBaseEventsUrl(): String
|
||||
|
||||
/**
|
||||
* Gets the base URL for fill-assist calls, or null if the server does not provide
|
||||
* fill-assist targeting rules.
|
||||
*/
|
||||
fun getBaseFillAssistUrl(): String?
|
||||
}
|
||||
|
||||
@@ -62,8 +62,6 @@ data class ConfigResponseJson(
|
||||
* @param identityUrl The URL of the identity service in the environment.
|
||||
* @param notificationsUrl The URL of the notifications service in the environment.
|
||||
* @param ssoUrl The URL of the single sign-on (SSO) service in the environment.
|
||||
* @param fillAssistRulesUrl The base URL of the fill-assist targeting rules, or null if
|
||||
* the server does not provide fill-assist rules.
|
||||
*/
|
||||
@Serializable
|
||||
data class EnvironmentJson(
|
||||
@@ -84,9 +82,6 @@ data class ConfigResponseJson(
|
||||
|
||||
@SerialName("sso")
|
||||
val ssoUrl: String?,
|
||||
|
||||
@SerialName("fillAssistRules")
|
||||
val fillAssistRulesUrl: String?,
|
||||
)
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.bitwarden.network.model
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
|
||||
/**
|
||||
* Represents the fill-assist forms rules file.
|
||||
*
|
||||
* @property schemaVersion The semantic version string for this file (e.g. "1.0.0").
|
||||
* @property hosts Map of hostname (optionally with port) to [HostEntryJson], or null if the host
|
||||
* is explicitly excluded from fill-assist.
|
||||
*/
|
||||
@Serializable
|
||||
data class FillAssistFormsJson(
|
||||
@SerialName("schemaVersion")
|
||||
val schemaVersion: String,
|
||||
|
||||
@SerialName("hosts")
|
||||
val hosts: Map<String, HostEntryJson?>,
|
||||
) {
|
||||
/**
|
||||
* Form descriptions and pathname-specific overrides for a single host.
|
||||
*
|
||||
* @property forms Site-wide fallback form descriptions.
|
||||
* @property pathnames Pathname-specific overrides; a null value means that path is excluded.
|
||||
*/
|
||||
@Serializable
|
||||
data class HostEntryJson(
|
||||
@SerialName("forms")
|
||||
val forms: List<FormJson>?,
|
||||
|
||||
@SerialName("pathnames")
|
||||
val pathnames: Map<String, PathnameEntryJson?>?,
|
||||
)
|
||||
|
||||
/**
|
||||
* Form descriptions for a specific pathname.
|
||||
*
|
||||
* @property forms The form descriptions for this path.
|
||||
*/
|
||||
@Serializable
|
||||
data class PathnameEntryJson(
|
||||
@SerialName("forms")
|
||||
val forms: List<FormJson>,
|
||||
)
|
||||
|
||||
/**
|
||||
* Describes one logical form on a page.
|
||||
*
|
||||
* @property category The categorical purpose of this form (e.g. "account-login").
|
||||
* @property container Optional CSS selectors identifying the form's container element.
|
||||
* @property fields Map of field key to [JsonElement] representing a compositeSelectorArray.
|
||||
* Each array element is either a CSS selector string or an array of strings for composite
|
||||
* multi-input fields. Unknown fields are gracefully ignored via [ignoreUnknownKeys].
|
||||
*/
|
||||
@Serializable
|
||||
data class FormJson(
|
||||
@SerialName("category")
|
||||
val category: String,
|
||||
|
||||
@SerialName("container")
|
||||
val container: List<String>?,
|
||||
|
||||
@SerialName("fields")
|
||||
val fields: Map<String, JsonElement>,
|
||||
)
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package com.bitwarden.network.model
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Represents the fill-assist manifest returned by the fill-assist service.
|
||||
*
|
||||
* @property buildId The unique identifier for this build.
|
||||
* @property timestamp The ISO-8601 timestamp when this build was produced.
|
||||
* @property gitSha The git commit SHA for this build.
|
||||
* @property maps The map data entries keyed by map type.
|
||||
*/
|
||||
@Serializable
|
||||
data class FillAssistManifestJson(
|
||||
@SerialName("buildId")
|
||||
val buildId: String,
|
||||
|
||||
@SerialName("timestamp")
|
||||
val timestamp: String,
|
||||
|
||||
@SerialName("gitSha")
|
||||
val gitSha: String,
|
||||
|
||||
@SerialName("maps")
|
||||
val maps: MapsJson,
|
||||
) {
|
||||
/**
|
||||
* Container for all available maps.
|
||||
*
|
||||
* @property forms Map of schema version string (e.g. "v1", "v2") to [FileEntryJson].
|
||||
* Using a [Map] allows new versions to appear automatically without model changes.
|
||||
*/
|
||||
@Serializable
|
||||
data class MapsJson(
|
||||
@SerialName("forms")
|
||||
val forms: Map<String, FileEntryJson>,
|
||||
)
|
||||
|
||||
/**
|
||||
* Metadata for a single versioned file in a map.
|
||||
*
|
||||
* @property filename The filename to fetch (e.g. "forms.v1.json").
|
||||
* @property cid The SHA-256 content hash in "sha256:<hex>" format. Used as a staleness key
|
||||
* to detect when the forms file has changed on the server, avoiding unnecessary re-downloads.
|
||||
* @property schema The schema filename associated with this file version.
|
||||
* @property deprecated When true, this version has entered its end-of-life support window.
|
||||
* Consumers should plan migration but may continue using the version until it is removed.
|
||||
*/
|
||||
@Serializable
|
||||
data class FileEntryJson(
|
||||
@SerialName("filename")
|
||||
val filename: String,
|
||||
|
||||
@SerialName("cid")
|
||||
val cid: String,
|
||||
|
||||
@SerialName("schema")
|
||||
val schema: String,
|
||||
|
||||
@SerialName("deprecated")
|
||||
val deprecated: Boolean?,
|
||||
)
|
||||
}
|
||||
@@ -36,12 +36,6 @@ internal interface Retrofits {
|
||||
*/
|
||||
val unauthenticatedIdentityRetrofit: Retrofit
|
||||
|
||||
/**
|
||||
* Allows access to fill-assist calls. The base URL is determined dynamically via the
|
||||
* [BaseUrlInterceptors.fillAssistInterceptor].
|
||||
*/
|
||||
val fillAssistRetrofit: Retrofit
|
||||
|
||||
/**
|
||||
* Allows access to static API calls (ex: external APIs).
|
||||
*
|
||||
|
||||
@@ -64,16 +64,6 @@ internal class RetrofitsImpl(
|
||||
|
||||
//endregion Unauthenticated Retrofits
|
||||
|
||||
//region Fill-Assist Retrofit
|
||||
|
||||
override val fillAssistRetrofit: Retrofit by lazy {
|
||||
createUnauthenticatedRetrofit(
|
||||
baseUrlInterceptor = baseUrlInterceptors.fillAssistInterceptor,
|
||||
)
|
||||
}
|
||||
|
||||
//endregion Fill-Assist Retrofit
|
||||
|
||||
//region Static Retrofit
|
||||
|
||||
override fun createStaticRetrofit(isAuthenticated: Boolean, baseUrl: String): Retrofit {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.bitwarden.network.service
|
||||
|
||||
import com.bitwarden.network.model.FillAssistFormsJson
|
||||
import com.bitwarden.network.model.FillAssistManifestJson
|
||||
|
||||
/**
|
||||
* Provides access to the fill-assist targeting rules service.
|
||||
*/
|
||||
interface FillAssistService {
|
||||
/**
|
||||
* Fetches and parses the fill-assist manifest.
|
||||
*/
|
||||
suspend fun getManifest(): Result<FillAssistManifestJson>
|
||||
|
||||
/**
|
||||
* Downloads and parses the forms rules file identified by [filename] (e.g. "forms.v1.json").
|
||||
*
|
||||
* Returns [Result.failure] if the network request fails or parsing fails.
|
||||
*/
|
||||
suspend fun getForms(filename: String): Result<FillAssistFormsJson>
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.bitwarden.network.service
|
||||
|
||||
import com.bitwarden.network.api.FillAssistApi
|
||||
import com.bitwarden.network.model.FillAssistFormsJson
|
||||
import com.bitwarden.network.model.FillAssistManifestJson
|
||||
import com.bitwarden.network.util.toResult
|
||||
|
||||
/**
|
||||
* Default implementation of [FillAssistService].
|
||||
*/
|
||||
internal class FillAssistServiceImpl(
|
||||
private val api: FillAssistApi,
|
||||
) : FillAssistService {
|
||||
|
||||
override suspend fun getManifest(): Result<FillAssistManifestJson> =
|
||||
api.getManifest().toResult()
|
||||
|
||||
override suspend fun getForms(filename: String): Result<FillAssistFormsJson> =
|
||||
api.getForms(filename = filename).toResult()
|
||||
}
|
||||
@@ -68,7 +68,6 @@ private val CONFIG_RESPONSE = ConfigResponseJson(
|
||||
notificationsUrl = "notificationsUrl",
|
||||
identityUrl = "identityUrl",
|
||||
ssoUrl = "ssoUrl",
|
||||
fillAssistRulesUrl = null,
|
||||
),
|
||||
featureStates = mapOf(
|
||||
"feature one" to JsonPrimitive(false),
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
package com.bitwarden.network.service
|
||||
|
||||
import com.bitwarden.core.data.util.asSuccess
|
||||
import com.bitwarden.network.api.FillAssistApi
|
||||
import com.bitwarden.network.base.BaseServiceTest
|
||||
import com.bitwarden.network.model.FillAssistFormsJson
|
||||
import com.bitwarden.network.model.FillAssistManifestJson
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import okhttp3.mockwebserver.MockResponse
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import retrofit2.create
|
||||
|
||||
class FillAssistServiceTest : BaseServiceTest() {
|
||||
|
||||
private val api: FillAssistApi = retrofit.create()
|
||||
private val service = FillAssistServiceImpl(api = api)
|
||||
|
||||
@Test
|
||||
fun `getManifest should parse manifest response`() = runTest {
|
||||
server.enqueue(MockResponse().setBody(MANIFEST_JSON))
|
||||
assertEquals(MANIFEST.asSuccess(), service.getManifest())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getManifest should return failure on server error`() = runTest {
|
||||
server.enqueue(MockResponse().setResponseCode(500))
|
||||
assertTrue(service.getManifest().isFailure)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getForms should parse and return forms`() = runTest {
|
||||
server.enqueue(MockResponse().setBody(FORMS_V1_JSON))
|
||||
assertEquals(FORMS_V1.asSuccess(), service.getForms(filename = "forms.v1.json"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getForms should return failure on server error`() = runTest {
|
||||
server.enqueue(MockResponse().setResponseCode(404))
|
||||
assertTrue(service.getForms(filename = "forms.v1.json").isFailure)
|
||||
}
|
||||
}
|
||||
|
||||
private val MANIFEST = FillAssistManifestJson(
|
||||
buildId = "local-build",
|
||||
timestamp = "2026-05-20T15:01:02.956Z",
|
||||
gitSha = "abc123",
|
||||
maps = FillAssistManifestJson.MapsJson(
|
||||
forms = mapOf(
|
||||
"v1" to FillAssistManifestJson.FileEntryJson(
|
||||
filename = "forms.v1.json",
|
||||
cid = "sha256:5b8f688d24bb9c38b4094838fa2baacb3cc4ab302e3545adf016b05f6b6b96db",
|
||||
schema = "forms.v1.schema.json",
|
||||
deprecated = null,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
private val FORMS_V1 = FillAssistFormsJson(
|
||||
schemaVersion = "1.0.0",
|
||||
hosts = mapOf(
|
||||
"example.com" to FillAssistFormsJson.HostEntryJson(
|
||||
forms = listOf(
|
||||
FillAssistFormsJson.FormJson(
|
||||
category = "account-login",
|
||||
container = null,
|
||||
fields = mapOf(
|
||||
"username" to JsonArray(listOf(JsonPrimitive("input#user"))),
|
||||
"password" to JsonArray(listOf(JsonPrimitive("input#pass"))),
|
||||
),
|
||||
),
|
||||
),
|
||||
pathnames = null,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
private const val MANIFEST_JSON = """
|
||||
{
|
||||
"buildId": "local-build",
|
||||
"timestamp": "2026-05-20T15:01:02.956Z",
|
||||
"gitSha": "abc123",
|
||||
"maps": {
|
||||
"forms": {
|
||||
"v1": {
|
||||
"filename": "forms.v1.json",
|
||||
"cid": "sha256:5b8f688d24bb9c38b4094838fa2baacb3cc4ab302e3545adf016b05f6b6b96db",
|
||||
"schema": "forms.v1.schema.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
private const val FORMS_V1_JSON = """
|
||||
{
|
||||
"schemaVersion": "1.0.0",
|
||||
"hosts": {
|
||||
"example.com": {
|
||||
"forms": [
|
||||
{
|
||||
"category": "account-login",
|
||||
"fields": {
|
||||
"username": ["input#user"],
|
||||
"password": ["input#pass"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
Reference in New Issue
Block a user