-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #34 from uport-project/uport_project/support/depre…
…cate-universaldid-singleton UniversalDID deprecation
- Loading branch information
Showing
12 changed files
with
484 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
universal-did/src/main/java/me/uport/sdk/universaldid/DIDResolverImpl.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package me.uport.sdk.universaldid | ||
|
||
internal class DIDResolverImpl: DIDResolver { | ||
|
||
private val resolvers = mapOf<String, DIDResolver>().toMutableMap() | ||
|
||
/** | ||
* Register a resolver for a particular DID [method] | ||
*/ | ||
fun registerResolver(resolver: DIDResolver) { | ||
if (resolver.method.isBlank()) { | ||
return | ||
} | ||
resolvers[resolver.method] = resolver | ||
} | ||
|
||
/** | ||
* @hide | ||
*/ | ||
fun clearResolvers() = resolvers.clear() | ||
|
||
/** | ||
* This universal resolver can't be used for any one particular did but for all [DIDResolver]s | ||
* that have been added using [registerResolver] | ||
*/ | ||
override val method: String = "" | ||
|
||
/** | ||
* Checks if any of the registered resolvers can resolve | ||
*/ | ||
override fun canResolve(potentialDID: String): Boolean { | ||
val resolver = resolvers.values.find { | ||
it.canResolve(potentialDID) | ||
} | ||
return (resolver != null) | ||
} | ||
|
||
/** | ||
* Looks for a [DIDResolver] that can resolve the provided [did] either by method if the did contains one or by trial | ||
* | ||
* @throws IllegalStateException if the proper resolver is not registered or produces `null` | ||
* @throws IllegalArgumentException if the given [did] has no `method` but could be resolved by one of the registered resolvers and that one fails with `null` | ||
*/ | ||
override suspend fun resolve(did: String): DIDDocument { | ||
val (method, _) = parse(did) | ||
|
||
if (method.isBlank() || !resolvers.containsKey(method)) { | ||
//if there is no clear mapping to a resolver, try each one that claims it can resolve | ||
return resolvers.filterValues { | ||
it.canResolve(did) | ||
}.values.mapNotNull { | ||
try { | ||
it.resolve(did) | ||
} catch (ex: Exception) { | ||
null | ||
} | ||
}.firstOrNull() | ||
?: throw IllegalArgumentException("The provided did ($did) could not be resolved by any of the ${resolvers.size} registered resolvers") | ||
} //no else clause, carry on | ||
|
||
if (resolvers.containsKey(method)) { | ||
return resolvers[method]?.resolve(did) | ||
?: throw IllegalStateException("There DIDResolver for '$method' failed to resolve '$did' for an unknown reason.") | ||
} else { | ||
throw IllegalStateException("There is no DIDResolver registered to resolve '$method' DIDs and none of the other ${resolvers.size} registered ones can do it.") | ||
} | ||
} | ||
|
||
/** | ||
* @hide | ||
*/ | ||
internal fun parse(did: String): Pair<String, String> { | ||
val matchResult = didPattern.find(did) ?: return ("" to "") | ||
val (method, identifier) = matchResult.destructured | ||
return (method to identifier) | ||
} | ||
|
||
//language=RegExp | ||
private val didPattern = "^did:(.*?):(.+)".toRegex() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
universal-did/src/test/java/me/uport/sdk/universaldid/DIDResolverImplTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package me.uport.sdk.universaldid | ||
|
||
import assertk.assertThat | ||
import assertk.assertions.isEmpty | ||
import assertk.assertions.isEqualTo | ||
import assertk.assertions.isInstanceOf | ||
import kotlinx.coroutines.runBlocking | ||
import me.uport.sdk.testhelpers.coAssert | ||
import org.junit.Test | ||
|
||
class DIDResolverImplTest { | ||
|
||
private val testDDO = object : DIDDocument { | ||
override val context: String = "test context" | ||
override val id: String = "1234" | ||
override val publicKey: List<PublicKeyEntry> = emptyList() | ||
override val authentication: List<AuthenticationEntry> = emptyList() | ||
override val service: List<ServiceEntry> = emptyList() | ||
} | ||
|
||
private val testResolver = object : DIDResolver { | ||
override fun canResolve(potentialDID: String): Boolean = true | ||
|
||
override val method: String = "test" | ||
|
||
override suspend fun resolve(did: String): DIDDocument { | ||
return if (did.contains("test")) testDDO else throw IllegalArgumentException("can't use test resolver") | ||
} | ||
} | ||
|
||
@Test | ||
fun `blank resolves to error`() { | ||
|
||
val resolver = DIDResolverImpl() | ||
resolver.clearResolvers() | ||
|
||
coAssert { | ||
resolver.resolve("") | ||
}.thrownError { | ||
isInstanceOf(IllegalArgumentException::class) | ||
} | ||
} | ||
|
||
@Test | ||
fun `testResolver resolves to error with blank`() { | ||
|
||
val resolver = DIDResolverImpl() | ||
resolver.clearResolvers() | ||
resolver.registerResolver(testResolver) | ||
|
||
coAssert { | ||
resolver.resolve("") | ||
}.thrownError { | ||
isInstanceOf(IllegalArgumentException::class) | ||
} | ||
} | ||
|
||
@Test | ||
fun `can register and find resolver`() = runBlocking { | ||
|
||
val resolver = DIDResolverImpl() | ||
resolver.clearResolvers() | ||
resolver.registerResolver(testResolver) | ||
|
||
val ddo = resolver.resolve("did:test:this is a test did") | ||
assertThat(ddo).isEqualTo(testDDO) | ||
} | ||
|
||
private val validDIDs = listOf( | ||
"did:generic:0x0011223344556677889900112233445566778899", | ||
"did:generic:01234", | ||
"did:generic:has spaces", | ||
"did:generic:more:colons", | ||
"did:generic:01234#fragment-attached", | ||
"did:generic:01234?key=value", | ||
"did:generic:01234?key=value&other-key=other-value" | ||
) | ||
|
||
private val invalidDIDs = listOf( | ||
"", | ||
"0x0011223344556677889900112233445566778899", | ||
"ethr:0x0011223344556677889900112233445566778899", | ||
"did:ethr", | ||
"did::something", | ||
"did:ethr:" | ||
) | ||
|
||
@Test | ||
fun `parses dids correctly`() { | ||
|
||
val resolver = DIDResolverImpl() | ||
|
||
validDIDs.forEach { | ||
val (method, _) = resolver.parse(it) | ||
assertThat(method).isEqualTo("generic") | ||
} | ||
|
||
invalidDIDs.forEach { | ||
val (method, _) = resolver.parse(it) | ||
assertThat(method).isEmpty() | ||
} | ||
} | ||
|
||
@Test | ||
fun `serializes to basic doc`() { | ||
val docString = DIDDocumentImpl("test context", "example document").toJson() | ||
//language=json | ||
assertThat(docString).isEqualTo("""{"@context":"test context","id":"example document","publicKey":[],"authentication":[],"service":[]}""") | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
apply plugin: 'java-library' | ||
apply plugin: "kotlin" | ||
apply plugin: "maven" | ||
apply plugin: "com.jfrog.bintray" | ||
|
||
project.ext.description = "Default values and configuration for DIDResolver" | ||
|
||
|
||
dependencies { | ||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" | ||
api "com.github.uport-project.kotlin-common:jsonrpc:$uport_kotlin_common_version" | ||
api "com.github.uport-project.kotlin-common:signer-common:$uport_kotlin_common_version" | ||
|
||
api project(":universal-did") | ||
api project(":uport-did") | ||
api project(":ethr-did") | ||
api project(":web-did") | ||
|
||
testImplementation "junit:junit:$junit_version" | ||
testImplementation "com.willowtreeapps.assertk:assertk-jvm:$assertk_version" | ||
} |
Oops, something went wrong.