Skip to content

Commit

Permalink
feat(agent)!: now the agent can process a connectionless presentation…
Browse files Browse the repository at this point in the history
… request

BREAKING CHANGE: AttachmentJsonData was wrong and is now a AnyCodable instead of a Data

Signed-off-by: goncalo-frade-iohk <goncalo.frade@iohk.io>
  • Loading branch information
goncalo-frade-iohk committed Aug 29, 2024
1 parent 7e2737c commit d5a9958
Show file tree
Hide file tree
Showing 21 changed files with 116 additions and 58 deletions.
6 changes: 3 additions & 3 deletions EdgeAgentSDK/Castor/Sources/Resolvers/PeerDIDResolver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -203,15 +203,15 @@ extension DIDCore.DIDDocument.VerificationMethod {
}

extension DIDCore.DIDDocument.Service {
init(from: AnyCodable) throws {
init(from: DIDCore.AnyCodable) throws {
guard
let dic = from.value as? [String: Any],
let id = dic["id"] as? String,
let type = dic["type"] as? String,
let serviceEndpoint = dic["serviceEndpoint"]
else { throw CommonError.invalidCoding(message: "Could not decode service") }
switch serviceEndpoint {
case let value as AnyCodable:
case let value as DIDCore.AnyCodable:
self = .init(
id: id,
type: type,
Expand Down Expand Up @@ -240,7 +240,7 @@ extension DIDCore.DIDDocument.Service {
}
}

func toAnyCodable() -> AnyCodable {
func toAnyCodable() -> DIDCore.AnyCodable {
AnyCodable(dictionaryLiteral:
("id", self.id),
("type", self.type),
Expand Down
38 changes: 19 additions & 19 deletions EdgeAgentSDK/Domain/Sources/AnyCodable.swift
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import Foundation

struct AnyCodable {
let value: Any
public struct AnyCodable {
public let value: Any

init<T: Codable>(_ value: T) {
public init<T: Codable>(_ value: T) {
self.value = value
}

init(_ value: Any) {
public init(_ value: Any) {
self.value = value
}

func get<T>() -> T? {
public func get<T>() -> T? {
value as? T
}

func get() -> Any {
public func get() -> Any {
value
}
}

extension AnyCodable: Codable {
init(from decoder: Decoder) throws {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()

if container.decodeNil() {
Expand All @@ -48,7 +48,7 @@ extension AnyCodable: Codable {
}
}

func encode(to encoder: Encoder) throws {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()

switch self.value {
Expand Down Expand Up @@ -103,7 +103,7 @@ extension AnyCodable: Codable {
}

extension AnyCodable: Equatable {
static func ==(lhs: AnyCodable, rhs: AnyCodable) -> Bool {
public static func ==(lhs: AnyCodable, rhs: AnyCodable) -> Bool {
switch (lhs.value, rhs.value) {
case is (Void, Void):
return true
Expand Down Expand Up @@ -146,7 +146,7 @@ extension AnyCodable: Equatable {
}

extension AnyCodable: CustomStringConvertible {
var description: String {
public var description: String {
switch value {
case is Void:
return String(describing: nil as Any?)
Expand All @@ -159,7 +159,7 @@ extension AnyCodable: CustomStringConvertible {
}

extension AnyCodable: CustomDebugStringConvertible {
var debugDescription: String {
public var debugDescription: String {
switch value {
case let value as CustomDebugStringConvertible:
return "AnyCodable(\(value.debugDescription))"
Expand All @@ -171,35 +171,35 @@ extension AnyCodable: CustomDebugStringConvertible {

extension AnyCodable: ExpressibleByNilLiteral, ExpressibleByBooleanLiteral, ExpressibleByIntegerLiteral, ExpressibleByFloatLiteral, ExpressibleByStringLiteral, ExpressibleByArrayLiteral, ExpressibleByDictionaryLiteral {

init(nilLiteral: ()) {
public init(nilLiteral: ()) {
self.init(nil ?? ())
}

init(booleanLiteral value: Bool) {
public init(booleanLiteral value: Bool) {
self.init(value)
}

init(integerLiteral value: Int) {
public init(integerLiteral value: Int) {
self.init(value)
}

init(floatLiteral value: Double) {
public init(floatLiteral value: Double) {
self.init(value)
}

init(extendedGraphemeClusterLiteral value: String) {
public init(extendedGraphemeClusterLiteral value: String) {
self.init(value)
}

init(stringLiteral value: String) {
public init(stringLiteral value: String) {
self.init(value)
}

init(arrayLiteral elements: Any...) {
public init(arrayLiteral elements: Any...) {
self.init(elements)
}

init(dictionaryLiteral elements: (AnyHashable, Any)...) {
public init(dictionaryLiteral elements: (AnyHashable, Any)...) {
self.init(Dictionary<AnyHashable, Any>(elements, uniquingKeysWith: { (first, _) in first }))
}
}
8 changes: 7 additions & 1 deletion EdgeAgentSDK/Domain/Sources/Models/Message+Codable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ extension Message: Codable {
enum CodingKeys: String, CodingKey {
case id
case piuri
case type
case from
case to
case fromPrior
Expand Down Expand Up @@ -49,7 +50,12 @@ extension Message: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let id = try container.decode(String.self, forKey: .id)
let piuri = try container.decode(String.self, forKey: .piuri)
let piuri: String
if let aux = try container.decodeIfPresent(String.self, forKey: .piuri) {
piuri = aux
} else {
piuri = try container.decode(String.self, forKey: .type)
}
let body: Data?
if
let bodyCodable = try? container.decodeIfPresent(AnyCodable.self, forKey: .body),
Expand Down
6 changes: 3 additions & 3 deletions EdgeAgentSDK/Domain/Sources/Models/MessageAttachment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,12 @@ public struct AttachmentLinkData: AttachmentData {
/// The `AttachmentJsonData` struct represents a DIDComm attachment containing JSON data.
public struct AttachmentJsonData: AttachmentData {
/// The JSON data associated with the attachment.
public let data: Data
public let json: AnyCodable

/// Initializes a new `AttachmentJsonData` object with the specified properties.
/// - Parameter data: The JSON data associated with the attachment.
public init(data: Data) {
self.data = data
public init(json: AnyCodable) {
self.json = json
}
}

Expand Down
38 changes: 34 additions & 4 deletions EdgeAgentSDK/EdgeAgent/Sources/EdgeAgent+Invitations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public extension EdgeAgent {
case onboardingPrism(PrismOnboarding)
/// Case representing a DIDComm Out-of-Band invitation
case onboardingDIDComm(OutOfBandInvitation)
/// Case representing a DIDComm Connectionless Presentation
case connectionlessPresentation(RequestPresentation)
}

/// Parses the given string as an invitation
Expand All @@ -28,8 +30,27 @@ public extension EdgeAgent {
func parseInvitation(str: String) async throws -> InvitationType {
if let prismOnboarding = try? await parsePrismInvitation(str: str) {
return .onboardingPrism(prismOnboarding)
} else if let message = try? parseOOBInvitation(url: str) {
return .onboardingDIDComm(message)
} else if let oobMessage = try? parseOOBInvitation(url: str) {
if let attachment = oobMessage.attachments?.first {
switch attachment.data {
case let value as AttachmentJsonData:
let normalizeJson = try JSONEncoder.didComm().encode(value.json)
let message = try JSONDecoder.didComm().decode(Message.self, from: normalizeJson)
guard let request = try? RequestPresentation(fromMessage: message) else {
return .onboardingDIDComm(oobMessage)
}
return .connectionlessPresentation(request)
case let value as AttachmentBase64:
let message = try JSONDecoder.didComm().decode(Message.self, from: try value.decoded())
guard let request = try? RequestPresentation(fromMessage: message) else {
return .onboardingDIDComm(oobMessage)
}
return .connectionlessPresentation(request)
default:
return .onboardingDIDComm(oobMessage)
}
}
return .onboardingDIDComm(oobMessage)
}
throw EdgeAgentError.unknownInvitationTypeError
}
Expand Down Expand Up @@ -69,8 +90,17 @@ public extension EdgeAgent {
/// - Returns: The parsed Out-of-Band invitation
/// - Throws: `EdgeAgentError` if the string is not a valid URL
func parseOOBInvitation(url: String) throws -> OutOfBandInvitation {
guard let url = URL(string: url) else { throw CommonError.invalidURLError(url: url) }
return try parseOOBInvitation(url: url)
guard let messageData = Data(fromBase64URL: url) else {
guard let url = URL(string: url) else {
throw CommonError.invalidURLError(url: url)
}
return try parseOOBInvitation(url: url)
}
let message = try JSONDecoder.didComm().decode(OutOfBandInvitation.self, from: messageData)
guard message.type == ProtocolTypes.didcomminvitation.rawValue else {
throw EdgeAgentError.unknownInvitationTypeError
}
return message
}

/// Parses the given URL as an Out-of-Band invitation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public struct OutOfBandInvitation: Decodable {
public let type = ProtocolTypes.didcomminvitation.rawValue
public let from: String
public let body: Body
public let attachments: [AttachmentDescriptor]?

/**
Creates a new `OutOfBandInvitation` object.
Expand All @@ -42,11 +43,13 @@ public struct OutOfBandInvitation: Decodable {
init(
id: String = UUID().uuidString,
body: Body,
from: DID
from: DID,
attachments: [AttachmentDescriptor]? = nil
) {
self.id = id
self.body = body
self.from = from.string
self.attachments = attachments
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class PickupRunner {
else { return nil }
return (base64String, attachment.id)
case let json as AttachmentJsonData:
return String(data: json.data, encoding: .utf8).map { ($0, attachment.id) }
return (try JSONEncoder.didComm().encode(json.json).tryToString(), attachment.id)
default:
return nil
}
Expand Down
13 changes: 13 additions & 0 deletions EdgeAgentSDK/EdgeAgent/Tests/PrismOnboardingInvitationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ final class PrismOnboardingInvitationTests: XCTestCase {
XCTAssertThrowsError(try PrismOnboardingInvitation(jsonString: jsonString))
}

func testConnectionlessPresentationParsing() async throws {
let connectionLessPresentation = "eyJpZCI6IjViMjUwMjIzLWExNDItNDRmYi1hOWJkLWU1MjBlNGI0ZjQzMiIsInR5cGUiOiJodHRwczovL2RpZGNvbW0ub3JnL291dC1vZi1iYW5kLzIuMC9pbnZpdGF0aW9uIiwiZnJvbSI6ImRpZDpwZWVyOjIuRXo2TFNkV0hWQ1BFOHc0NWZETjM4aUh0ZFJ6WGkyTFNqQmRSUjRGTmNOUm12VkNKcy5WejZNa2Z2aUI5S1F1OGlnNVZpeG1HZHM3dmdMNmoyUXNOUGFybkZaanBNQ0E5aHpQLlNleUowSWpvaVpHMGlMQ0p6SWpwN0luVnlhU0k2SW1oMGRIQTZMeTh4T1RJdU1UWTRMakV1TXpjNk9EQTNNQzlrYVdSamIyMXRJaXdpY2lJNlcxMHNJbUVpT2xzaVpHbGtZMjl0YlM5Mk1pSmRmWDAiLCJib2R5Ijp7ImdvYWxfY29kZSI6InByZXNlbnQtdnAiLCJnb2FsIjoiUmVxdWVzdCBwcm9vZiBvZiB2YWNjaW5hdGlvbiBpbmZvcm1hdGlvbiIsImFjY2VwdCI6W119LCJhdHRhY2htZW50cyI6W3siaWQiOiIyYTZmOGM4NS05ZGE3LTRkMjQtOGRhNS0wYzliZDY5ZTBiMDEiLCJtZWRpYV90eXBlIjoiYXBwbGljYXRpb24vanNvbiIsImRhdGEiOnsianNvbiI6eyJpZCI6IjI1NTI5MTBiLWI0NmMtNDM3Yy1hNDdhLTlmODQ5OWI5ZTg0ZiIsInR5cGUiOiJodHRwczovL2RpZGNvbW0uYXRhbGFwcmlzbS5pby9wcmVzZW50LXByb29mLzMuMC9yZXF1ZXN0LXByZXNlbnRhdGlvbiIsImJvZHkiOnsiZ29hbF9jb2RlIjoiUmVxdWVzdCBQcm9vZiBQcmVzZW50YXRpb24iLCJ3aWxsX2NvbmZpcm0iOmZhbHNlLCJwcm9vZl90eXBlcyI6W119LCJhdHRhY2htZW50cyI6W3siaWQiOiJiYWJiNTJmMS05NDUyLTQzOGYtYjk3MC0yZDJjOTFmZTAyNGYiLCJtZWRpYV90eXBlIjoiYXBwbGljYXRpb24vanNvbiIsImRhdGEiOnsianNvbiI6eyJvcHRpb25zIjp7ImNoYWxsZW5nZSI6IjExYzkxNDkzLTAxYjMtNGM0ZC1hYzM2LWIzMzZiYWI1YmRkZiIsImRvbWFpbiI6Imh0dHBzOi8vcHJpc20tdmVyaWZpZXIuY29tIn0sInByZXNlbnRhdGlvbl9kZWZpbml0aW9uIjp7ImlkIjoiMGNmMzQ2ZDItYWY1Ny00Y2E1LTg2Y2EtYTA1NTE1NjZlYzZmIiwiaW5wdXRfZGVzY3JpcHRvcnMiOltdfX19LCJmb3JtYXQiOiJwcmlzbS9qd3QifV0sInRoaWQiOiI1YjI1MDIyMy1hMTQyLTQ0ZmItYTliZC1lNTIwZTRiNGY0MzIiLCJmcm9tIjoiZGlkOnBlZXI6Mi5FejZMU2RXSFZDUEU4dzQ1ZkROMzhpSHRkUnpYaTJMU2pCZFJSNEZOY05SbXZWQ0pzLlZ6Nk1rZnZpQjlLUXU4aWc1Vml4bUdkczd2Z0w2ajJRc05QYXJuRlpqcE1DQTloelAuU2V5SjBJam9pWkcwaUxDSnpJanA3SW5WeWFTSTZJbWgwZEhBNkx5OHhPVEl1TVRZNExqRXVNemM2T0RBM01DOWthV1JqYjIxdElpd2ljaUk2VzEwc0ltRWlPbHNpWkdsa1kyOXRiUzkyTWlKZGZYMCJ9fX1dLCJjcmVhdGVkX3RpbWUiOjE3MjQzMzkxNDQsImV4cGlyZXNfdGltZSI6MTcyNDMzOTQ0NH0="

let agent = EdgeAgent(mediatorDID: .init(method: "peer", methodId: "test"))
let result = try await agent.parseInvitation(str: connectionLessPresentation)
switch result {
case .connectionlessPresentation(let requestPresentation):
break
default:
XCTFail("It should give a connectionless presentation request")
}
}

// func testLocal() async throws {
// let example = PrismOnboardingInvitation.Body(
// type: "https://atalaprism.io/did-request",
Expand Down
2 changes: 1 addition & 1 deletion EdgeAgentSDK/Mercury/Sources/Forward/ForwardMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public struct ForwardMessage {
to: to,
body: try JSONEncoder.didComm().encode(self.body),
attachments: [
.init(mediaType: "application/json", data: AttachmentJsonData(data: encryptedJsonMessage))
.init(mediaType: "application/json", data: AttachmentBase64(base64: encryptedJsonMessage.base64URLEncoded()))
]
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ extension Domain.AttachmentData {
return try JsonAttachmentData(
hash: nil,
jws: nil,
json: jsonData.data.tryToString()
json: JSONEncoder.didComm().encode(jsonData.json).tryToString()
)
} else if let jwsData = self as? AttachmentJwsData {
return Base64AttachmentData(
Expand All @@ -118,10 +118,8 @@ extension DIDCommSwift.AttachmentData {
}
return AttachmentLinkData(links: value.links, hash: hash)
case let value as JsonAttachmentData:
guard let jsonData = value.json.data(using: .utf8) else {
throw MercuryError.unknownAttachmentDataTypeError
}
return AttachmentJsonData(data: jsonData)
let jsonObject = try JSONDecoder.didComm().decode(Domain.AnyCodable.self, from: value.json.tryToData())
return AttachmentJsonData(json: jsonObject)
default:
throw MercuryError.unknownAttachmentDataTypeError
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ extension AnoncredsCredentialStack: ProvableCredential {
}
switch attachment.data {
case let attachmentData as AttachmentJsonData:
requestStr = try attachmentData.data.toString()
requestStr = try JSONEncoder.didComm().encode(attachmentData.json).tryToString()
case let attachmentData as AttachmentBase64:
guard let data = Data(fromBase64URL: attachmentData.base64) else {
throw PolluxError.messageDoesntProvideEnoughInformation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extension JWTCredential: ProvableCredential {
case let attchedData as AttachmentBase64:
jsonData = Data(fromBase64URL: attchedData.base64)!
case let attchedData as AttachmentJsonData:
jsonData = attchedData.data
jsonData = try JSONEncoder.didComm().encode(attchedData.json)
default:
throw PolluxError.invalidAttachmentType(supportedTypes: ["Json", "Base64"])
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Core
import Domain
import Foundation

Expand Down
4 changes: 2 additions & 2 deletions EdgeAgentSDK/Pollux/Sources/Models/JWT/JWTPayload.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct JWTPayload {
let context: Set<String>
let type: Set<String>
let credentialSchema: VerifiableCredentialTypeContainer?
let credentialSubject: AnyCodable
let credentialSubject: Domain.AnyCodable
let refreshService: VerifiableCredentialTypeContainer?
let evidence: VerifiableCredentialTypeContainer?
let termsOfUse: VerifiableCredentialTypeContainer?
Expand All @@ -41,7 +41,7 @@ struct JWTPayload {
context: Set<String> = Set(),
type: Set<String> = Set(),
credentialSchema: VerifiableCredentialTypeContainer? = nil,
credentialSubject: AnyCodable,
credentialSubject: Domain.AnyCodable,
credentialStatus: JWTRevocationStatus? = nil,
refreshService: VerifiableCredentialTypeContainer? = nil,
evidence: VerifiableCredentialTypeContainer? = nil,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ struct JWTPresentation {
let requestData = request.attachments.first.flatMap({
switch $0.data {
case let json as AttachmentJsonData:
return json.data
return try? JSONEncoder.didComm().encode(json.json)
case let bas64 as AttachmentBase64:
return Data(fromBase64URL: bas64.base64)
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct SDJWTPresentation {
let requestData = request.attachments.first.flatMap({
switch $0.data {
case let json as AttachmentJsonData:
return json.data
return try? JSONEncoder.didComm().encode(json.json)
case let bas64 as AttachmentBase64:
return Data(fromBase64URL: bas64.base64)
default:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Core
import Domain
import Foundation

Expand Down
Loading

0 comments on commit d5a9958

Please sign in to comment.