-
Notifications
You must be signed in to change notification settings - Fork 7
feat(castor)!: http did resolver #221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+824
−120
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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
27 changes: 27 additions & 0 deletions
27
EdgeAgentSDK/Castor/Sources/Resolvers/CompactPrismDIDResolver.swift
This file contains hidden or 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,27 @@ | ||
| import Domain | ||
|
|
||
| public struct CompactPrismDIDResolver: DIDResolverDomain { | ||
| public let method = "prism" | ||
| let longFormResolver: DIDResolverDomain | ||
| let shortFormResolver: DIDResolverDomain | ||
|
|
||
| init(longFormResolver: DIDResolverDomain, shortFormResolver: DIDResolverDomain) { | ||
| self.longFormResolver = longFormResolver | ||
| self.shortFormResolver = shortFormResolver | ||
| } | ||
|
|
||
| public func resolve(did: Domain.DID) async throws -> Domain.DIDDocument { | ||
| do { | ||
| return try await shortFormResolver.resolve(did: did) | ||
| } catch { | ||
| guard did.isLongFormDID() else { throw error } | ||
| return try await longFormResolver.resolve(did: did) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private extension DID { | ||
| func isLongFormDID() -> Bool { | ||
| return string.split(separator: ":").count > 3 | ||
| } | ||
| } | ||
38 changes: 38 additions & 0 deletions
38
EdgeAgentSDK/Castor/Sources/Resolvers/EndpointShortFormPrismDIDRemoteResolver.swift
This file contains hidden or 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,38 @@ | ||
| import Domain | ||
| import Foundation | ||
|
|
||
| public protocol DIDDocumentUrlBuilder { | ||
| func didDocumentEndpoint(did: DID) throws -> String | ||
| } | ||
|
|
||
| public protocol DIDDocumentSerializer { | ||
| func serialize(data: Data) throws -> DIDDocument | ||
| } | ||
|
|
||
| public struct EndpointShortFormPrismDIDRemoteResolver: DIDResolverDomain { | ||
| public let method = "prism" | ||
| let urlBuilder: DIDDocumentUrlBuilder | ||
| let downloader: Downloader | ||
| let serializer: DIDDocumentSerializer | ||
|
|
||
| init(urlBuilder: DIDDocumentUrlBuilder, downloader: Downloader, serializer: DIDDocumentSerializer) { | ||
| self.urlBuilder = urlBuilder | ||
| self.downloader = downloader | ||
| self.serializer = serializer | ||
| } | ||
|
|
||
| public func resolve(did: DID) async throws -> DIDDocument { | ||
| let did = try did.removingPrismLongForm() | ||
| let data = try await downloader.downloadFromEndpoint(urlOrDID: urlBuilder.didDocumentEndpoint(did: did)) | ||
| return try serializer.serialize(data: data) | ||
| } | ||
| } | ||
|
|
||
| private extension DID { | ||
| func removingPrismLongForm() throws -> DID { | ||
| let separated = string | ||
| .split(separator: ":") | ||
| let shortForm = separated.prefix(3).joined(separator: ":") | ||
| return try DID(string: shortForm) | ||
| } | ||
| } |
59 changes: 59 additions & 0 deletions
59
EdgeAgentSDK/Castor/Sources/Resolvers/GitHubPrismDIDResolver.swift
This file contains hidden or 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,59 @@ | ||
| import Domain | ||
| import Foundation | ||
|
|
||
| public extension EndpointShortFormPrismDIDRemoteResolver { | ||
| static func githubResolver() -> Self { | ||
| .init( | ||
| urlBuilder: GitHubResolverURLBuilder(), | ||
| downloader: DownloadDataWithResolver(), | ||
| serializer: GitHubResolverDIDDocumentSerializer() | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| public struct GitHubResolverURLBuilder: DIDDocumentUrlBuilder { | ||
| let baseURL = "https://raw.githubusercontent.com/FabioPinheiro/prism-vdr/refs/heads/main/mainnet/diddoc/" | ||
|
|
||
| public func didDocumentEndpoint(did: DID) throws -> String { | ||
| return baseURL.appending(did.string) | ||
| } | ||
| } | ||
|
|
||
| public struct GitHubResolverDIDDocumentSerializer: DIDDocumentSerializer { | ||
| let coder: JSONDecoder | ||
|
|
||
| init(coder: JSONDecoder = .normalized) { | ||
| self.coder = coder | ||
| } | ||
|
|
||
| public func serialize(data: Data) throws -> DIDDocument { | ||
| return try coder.decode(DIDDocument.self, from: data) | ||
| } | ||
| } | ||
|
|
||
| fileprivate struct DownloadDataWithResolver: Downloader { | ||
|
|
||
| func downloadFromEndpoint(urlOrDID: String) async throws -> Data { | ||
| let url: URL | ||
|
|
||
| if let validUrl = URL(string: urlOrDID.replacingOccurrences(of: "host.docker.internal", with: "localhost")) { | ||
| url = validUrl | ||
| } else { | ||
| throw CommonError.invalidURLError(url: urlOrDID) | ||
| } | ||
|
|
||
| let (data, urlResponse) = try await URLSession.shared.data(from: url) | ||
|
|
||
| guard | ||
| let code = (urlResponse as? HTTPURLResponse)?.statusCode, | ||
| 200...299 ~= code | ||
| else { | ||
| throw CommonError.httpError( | ||
| code: (urlResponse as? HTTPURLResponse)?.statusCode ?? 500, | ||
| message: String(data: data, encoding: .utf8) ?? "" | ||
| ) | ||
| } | ||
|
|
||
| return data | ||
| } | ||
| } |
This file contains hidden or 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 hidden or 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
46 changes: 46 additions & 0 deletions
46
EdgeAgentSDK/Castor/Tests/CompactPrismDIDResolverTests.swift
This file contains hidden or 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,46 @@ | ||
| import XCTest | ||
| import Domain | ||
| @testable import Castor | ||
|
|
||
| final class CompactPrismDIDResolverTests: XCTestCase { | ||
| func testUsesShortFormResolverWhenItSucceeds() async throws { | ||
| let did = DID(method: "prism", methodId: "abc") | ||
| let expected = DIDDocument(id: did, coreProperties: []) | ||
|
|
||
| let short = DIDResolverMock(result: .success(expected)) | ||
| let long = DIDResolverMock(result: .failure(MockError.forced)) | ||
| let sut = CompactPrismDIDResolver(longFormResolver: long, shortFormResolver: short) | ||
| let doc = try await sut.resolve(did: did) | ||
|
|
||
| XCTAssertEqual(doc.id, did) | ||
| XCTAssertEqual(short.calls, [did]) | ||
| XCTAssertTrue(long.calls.isEmpty) | ||
| } | ||
|
|
||
| func testFallsBackToLongFormWhenShortFailsAndDIDIsLongForm() async throws { | ||
| let longForm = DID(method: "prism", methodId: "abc:def") | ||
| let expected = DIDDocument(id: longForm, coreProperties: []) | ||
|
|
||
| let short = DIDResolverMock(result: .failure(MockError.forced)) | ||
| let long = DIDResolverMock(result: .success(expected)) | ||
| let sut = CompactPrismDIDResolver(longFormResolver: long, shortFormResolver: short) | ||
| let doc = try await sut.resolve(did: longForm) | ||
|
|
||
| XCTAssertEqual(doc.id, longForm) | ||
| XCTAssertEqual(short.calls, [longForm]) | ||
| XCTAssertEqual(long.calls, [longForm]) | ||
| } | ||
|
|
||
| func testRethrowsWhenShortFailsAndDIDIsShortForm() async { | ||
| let shortForm = DID(method: "prism", methodId: "abc") | ||
| let short = DIDResolverMock(result: .failure(MockError.forced)) | ||
| let long = DIDResolverMock(result: .success(DIDDocument(id: shortForm, coreProperties: []))) | ||
| let sut = CompactPrismDIDResolver(longFormResolver: long, shortFormResolver: short) | ||
| do { | ||
| _ = try await sut.resolve(did: shortForm) | ||
| XCTFail("Expected error") | ||
| } catch { | ||
| XCTAssertTrue(long.calls.isEmpty) | ||
| } | ||
| } | ||
| } |
40 changes: 40 additions & 0 deletions
40
EdgeAgentSDK/Castor/Tests/EndpointShortFormPrismDIDRemoteResolverSmokeTests.swift
This file contains hidden or 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,40 @@ | ||
| import Domain | ||
| @testable import Castor | ||
| import XCTest | ||
|
|
||
| final class EndpointShortFormPrismDIDRemoteResolverSmokeTests: XCTestCase { | ||
| func testMethodIsPrism() { | ||
| let sut = EndpointShortFormPrismDIDRemoteResolver( | ||
| urlBuilder: DIDDocumentUrlBuilderMock(), | ||
| downloader: DownloaderMock(result: .failure(MockError.forced)), | ||
| serializer: DIDDocumentSerializerMock(result: .failure(MockError.forced)) | ||
| ) | ||
| XCTAssertEqual(sut.method, "prism") | ||
| } | ||
|
|
||
| func testTrimsLongFormBeforeBuildingURL() async { | ||
| let longForm = DID(method: "prism", methodId: "abc:def") | ||
| let expectedShort = DID(method: "prism", methodId: "abc") | ||
| let urlBuilder = DIDDocumentUrlBuilderMock() | ||
| let downloader = DownloaderMock(result: .success(Data("{}".utf8))) | ||
| let serializer = DIDDocumentSerializerMock(result: .failure(MockError.forced)) | ||
|
|
||
| let sut = EndpointShortFormPrismDIDRemoteResolver( | ||
| urlBuilder: urlBuilder, | ||
| downloader: downloader, | ||
| serializer: serializer | ||
| ) | ||
|
|
||
| do { | ||
| _ = try await sut.resolve(did: longForm) | ||
| XCTFail("Expected error") | ||
| } catch { | ||
| XCTAssertEqual(urlBuilder.dids.first, expectedShort) | ||
| } | ||
| } | ||
|
|
||
| func testIntegrationWithGithubResolver() async throws { | ||
| let githubResolver = EndpointShortFormPrismDIDRemoteResolver.githubResolver() | ||
| let document = try await githubResolver.resolve(did: DID(string: "did:prism:076b993f6070d39ee0f0964970ef3d07af3e821cb51106952100fa803b03cc51")) | ||
| } | ||
| } |
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this try to resolve the short form. Independently if the given DID is a long or a short form, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this is dependent on the dependency injection, but our short form resolver is here EdgeAgentSDK/Castor/Sources/Resolvers/EndpointShortFormPrismDIDRemoteResolver.swift, and is as you say it will work for short and long form independently.