Skip to content

Commit 8ceccc3

Browse files
committed
Created DIDResolver
1 parent 27b88c6 commit 8ceccc3

File tree

6 files changed

+88
-2
lines changed

6 files changed

+88
-2
lines changed

app-shared/app_shared.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@ Pod::Spec.new do |spec|
5353
spec.resources = ['build/compose/cocoapods/compose-resources']
5454
spec.info_plist = {
5555
"CFBundleShortVersionString": "1.0.0-beta10",
56-
"CFBundleVersion": "714"
56+
"CFBundleVersion": "715"
5757
}
5858
end

component-stargate/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ kotlin {
5454
// https://github.com/mooncloak/compose-serialization
5555
// Apache 2.0: https://github.com/mooncloak/compose-serialization
5656
implementation("com.mooncloak.kodetools.compose.serialization:compose-serialization-core:_")
57+
58+
// Http Client - Ktor
59+
// https://github.com/ktorio/ktor
60+
implementation("io.ktor:ktor-client-core:_")
5761
}
5862
}
5963

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.mooncloak.vpn.component.stargate.entanglement
2+
3+
import com.mooncloak.vpn.util.shared.validation.fromOrNull
4+
import io.ktor.client.HttpClient
5+
import io.ktor.client.request.get
6+
import io.ktor.client.statement.bodyAsText
7+
import io.ktor.http.isSuccess
8+
9+
public class DIDResolver public constructor(
10+
private val defaultDomainProvider: DomainProvider,
11+
private val dnsTxtRecordResolver: DnsTxtRecordResolver,
12+
private val httpClient: HttpClient
13+
) {
14+
15+
public suspend fun resolve(handle: IdentityHandle): DID =
16+
when (handle.format) {
17+
IdentityHandleFormat.DID -> DID.from(value = handle.value)
18+
19+
IdentityHandleFormat.ALIAS -> {
20+
val value = handle.value
21+
.split(':')
22+
.reversed()
23+
.filter { it.isNotBlank() }
24+
.joinToString(separator = ":")
25+
26+
DID.from(value = if (value.startsWith("did:")) value else "did:$value")
27+
}
28+
29+
else -> {
30+
val localPart = handle.localPart
31+
32+
var remotePart = handle.remotePart
33+
if (remotePart.isNullOrBlank()) {
34+
remotePart = defaultDomainProvider.get()
35+
}
36+
37+
// Note that we construct the value from the different parts manually here because the handle.value can
38+
// contain different separators (ex: '@' for ActivityPub or ':' for Matrix). We are flexible for what
39+
// we accept for a user handle but we have to format it properly for resolution and we currently only
40+
// support the AT Protocol for DID resolution.
41+
val value = "$localPart.$remotePart"
42+
43+
// See the AT Protocol documentation for resolving the DID from the user handle:
44+
// https://atproto.com/specs/handle
45+
46+
val record = dnsTxtRecordResolver.resolve("_atproto.$value")
47+
.firstOrNull { it.startsWith("did=") }
48+
?.substringAfter("did=")
49+
?.let { DID.fromOrNull(value = it) }
50+
51+
if (record != null) {
52+
record
53+
} else {
54+
val httpResponse = httpClient.get("https://$value/.well-known/atproto-did")
55+
56+
if (!httpResponse.status.isSuccess()) {
57+
error("Failed to resolve DID.")
58+
}
59+
60+
DID.from(value = httpResponse.bodyAsText())
61+
}
62+
}
63+
}
64+
65+
public companion object
66+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.mooncloak.vpn.component.stargate.entanglement
2+
3+
public fun interface DnsTxtRecordResolver {
4+
5+
public suspend fun resolve(domain: String): List<String>
6+
7+
public companion object
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.mooncloak.vpn.component.stargate.entanglement
2+
3+
public fun interface DomainProvider {
4+
5+
public suspend fun get(): String
6+
7+
public companion object
8+
}

component-stargate/src/commonMain/kotlin/com/mooncloak/vpn/component/stargate/entanglement/IdentityHandle.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class IdentityHandle private constructor(
2020
public companion object : ValidatingConstructor<String, IdentityHandle> {
2121

2222
override fun validate(value: String): Result<IdentityHandle> {
23-
val formatted = value.trim().removePrefix("@")
23+
val formatted = value.trim().removePrefix("@").lowercase()
2424

2525
when {
2626
formatted.startsWith("did:") -> return validateDid(value = formatted)

0 commit comments

Comments
 (0)