[PM-20373] Migrate Digital Asset Link API to network module (#5071)

This commit is contained in:
Patrick Honkonen
2025-04-17 12:55:01 -04:00
committed by GitHub
parent 3722a45359
commit d5d8da2410
9 changed files with 18 additions and 18 deletions

View File

@@ -0,0 +1,20 @@
package com.bitwarden.network.api
import com.bitwarden.network.model.DigitalAssetLinkResponseJson
import com.bitwarden.network.model.NetworkResult
import retrofit2.http.GET
import retrofit2.http.Url
/**
* Defines calls to an RP digital asset link file.
*/
interface DigitalAssetLinkApi {
/**
* Attempts to download the asset links file from the RP.
*/
@GET
suspend fun getDigitalAssetLinks(
@Url url: String,
): NetworkResult<List<DigitalAssetLinkResponseJson>>
}

View File

@@ -0,0 +1,32 @@
package com.bitwarden.network.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Models a response from an RP digital asset link request.
*/
@Serializable
data class DigitalAssetLinkResponseJson(
@SerialName("relation")
val relation: List<String>,
@SerialName("target")
val target: Target,
) {
/**
* Represents targets for an asset link statement.
*/
@Serializable
data class Target(
@SerialName("namespace")
val namespace: String,
@SerialName("package_name")
val packageName: String?,
@SerialName("sha256_cert_fingerprints")
val sha256CertFingerprints: List<String>?,
)
}

View File

@@ -0,0 +1,17 @@
package com.bitwarden.network.service
import com.bitwarden.network.model.DigitalAssetLinkResponseJson
/**
* Provides an API for querying digital asset links.
*/
interface DigitalAssetLinkService {
/**
* Attempt to retrieve the asset links file from the provided [relyingParty].
*/
suspend fun getDigitalAssetLinkForRp(
scheme: String = "https://",
relyingParty: String,
): Result<List<DigitalAssetLinkResponseJson>>
}

View File

@@ -0,0 +1,23 @@
package com.bitwarden.network.service
import com.bitwarden.network.api.DigitalAssetLinkApi
import com.bitwarden.network.model.DigitalAssetLinkResponseJson
import com.bitwarden.network.util.toResult
/**
* Primary implementation of [DigitalAssetLinkService].
*/
class DigitalAssetLinkServiceImpl(
private val digitalAssetLinkApi: DigitalAssetLinkApi,
) : DigitalAssetLinkService {
override suspend fun getDigitalAssetLinkForRp(
scheme: String,
relyingParty: String,
): Result<List<DigitalAssetLinkResponseJson>> =
digitalAssetLinkApi
.getDigitalAssetLinks(
url = "$scheme$relyingParty/.well-known/assetlinks.json",
)
.toResult()
}

View File

@@ -0,0 +1,67 @@
package com.bitwarden.network.service
import com.bitwarden.network.api.DigitalAssetLinkApi
import com.bitwarden.network.base.BaseServiceTest
import com.bitwarden.network.model.DigitalAssetLinkResponseJson
import kotlinx.coroutines.test.runTest
import okhttp3.mockwebserver.MockResponse
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import retrofit2.create
class DigitalAssetLinkServiceTest : BaseServiceTest() {
private val digitalAssetLinkApi: DigitalAssetLinkApi = retrofit.create()
private val digitalAssetLinkService: DigitalAssetLinkService = DigitalAssetLinkServiceImpl(
digitalAssetLinkApi = digitalAssetLinkApi,
)
@Test
fun `getDigitalAssetLinkForRp should return the correct response`() = runTest {
server.enqueue(MockResponse().setBody(GET_DIGITAL_ASSET_LINK_SUCCESS_JSON))
val result = digitalAssetLinkService.getDigitalAssetLinkForRp(
scheme = url.scheme,
relyingParty = url.host,
)
assertEquals(
createDigitalAssetLinkResponse(),
result.getOrThrow(),
)
}
}
@Suppress("MaxLineLength")
private fun createDigitalAssetLinkResponse() = listOf(
DigitalAssetLinkResponseJson(
relation = listOf(
"delegate_permission/common.get_login_creds",
"delegate_permission/common.handle_all_urls",
),
target = DigitalAssetLinkResponseJson.Target(
namespace = "android_app",
packageName = "com.mock.package",
sha256CertFingerprints = listOf(
"00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F:10:11:12:13:14:15:16:17:18:19:1A:1B:1C:1D:1E:1F",
),
),
),
)
private const val GET_DIGITAL_ASSET_LINK_SUCCESS_JSON = """
[
{
"relation": [
"delegate_permission/common.get_login_creds",
"delegate_permission/common.handle_all_urls"
],
"target": {
"namespace": "android_app",
"package_name": "com.mock.package",
"sha256_cert_fingerprints": [
"00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F:10:11:12:13:14:15:16:17:18:19:1A:1B:1C:1D:1E:1F"
]
}
}
]
"""