Skip to content
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

feat(pluto): add persistence to connection data and messages #47

Merged
merged 1 commit into from
Dec 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions Domain/Sources/BBs/Pluto.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,38 @@ import Combine
import Foundation

public protocol Pluto {
func storeDID(
func storePrismDID(
did: DID,
keyPairIndex: Int,
alias: String?
) -> AnyPublisher<Void, Error>
func storePeerDID(did: DID, privateKey: PrivateKey) -> AnyPublisher<Void, Error>
func storeDIDPair(holder: DID, other: DID, name: String) -> AnyPublisher<Void, Error>
func storeMessage(message: Message) -> AnyPublisher<Void, Error>
func storeMediator(peer: DID, routingDID: DID, url: URL) -> AnyPublisher<Void, Error>

func getAllDIDs() -> AnyPublisher<[(did: DID, keyPairIndex: Int, alias: String?)], Error>
func getDIDInfo(did: DID) -> AnyPublisher<(did: DID, keyPairIndex: Int, alias: String?)?, Error>
func getDIDInfo(alias: String) -> AnyPublisher<[(did: DID, keyPairIndex: Int)], Error>
func getDIDKeyPairIndex(did: DID) -> AnyPublisher<Int?, Error>
func getLastKeyPairIndex() -> AnyPublisher<Int, Error>
func getAllPrismDIDs() -> AnyPublisher<[(did: DID, keyPairIndex: Int, alias: String?)], Error>
func getPrismDIDInfo(did: DID) -> AnyPublisher<(did: DID, keyPairIndex: Int, alias: String?)?, Error>
func getPrismDIDInfo(alias: String) -> AnyPublisher<[(did: DID, keyPairIndex: Int)], Error>
func getPrismDIDKeyPairIndex(did: DID) -> AnyPublisher<Int?, Error>
func getPrismLastKeyPairIndex() -> AnyPublisher<Int, Error>

func getAllPeerDIDs() -> AnyPublisher<[(did: DID, privateKey: PrivateKey)], Error>
func getPeerDIDInfo(did: DID) -> AnyPublisher<(did: DID, privateKey: PrivateKey)?, Error>
func getPeerDIDPrivateKey(did: DID) -> AnyPublisher<PrivateKey?, Error>

func getAllDidPairs() -> AnyPublisher<[(holder: DID, other: DID, name: String?)], Error>
func getPair(otherDID: DID) -> AnyPublisher<(holder: DID, other: DID, name: String?)?, Error>
func getPair(name: String) -> AnyPublisher<(holder: DID, other: DID, name: String?)?, Error>
func getPair(holderDID: DID) -> AnyPublisher<(holder: DID, other: DID, name: String?)?, Error>

func getAllMessages() -> AnyPublisher<[Message], Error>
func getAllMessages(did: DID) -> AnyPublisher<[Message], Error>
func getAllMessagesSentTo(did: DID) -> AnyPublisher<[Message], Error>
func getAllMessagesReceivedFrom(did: DID) -> AnyPublisher<[Message], Error>
func getAllMessagesOfType(type: String, relatedWithDID: DID?) -> AnyPublisher<[Message], Error>
func getAllMessages(from: DID, to: DID) -> AnyPublisher<[Message], Error>
func getMessage(id: String) -> AnyPublisher<Message?, Error>

func getAllMediators() -> AnyPublisher<[(did: DID, routingDID: DID, url: URL)], Error>
}
5 changes: 5 additions & 0 deletions Domain/Sources/Models/DIDPair.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public struct DIDPair: Equatable {
public let holder: DID
public let other: DID
public let name: String?
}
7 changes: 7 additions & 0 deletions Domain/Sources/Models/Errors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@ public enum MercuryError: Error {
case noDIDReceiverSetError
case noValidServiceFoundError
}

public enum PlutoError: Error {
case invalidHolderDIDNotPersistedError
case messageMissingFromOrToDIDError
case didPairIsNotPersistedError
case holderDIDAlreadyPairingError
}
10 changes: 10 additions & 0 deletions Pluto/Sources/Domain/Providers/DIDPairProvider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Combine
import Domain
import Foundation

protocol DIDPairProvider {
func getAll() -> AnyPublisher<[(holder: DID, other: DID, name: String?)], Error>
func getPair(otherDID: DID) -> AnyPublisher<(holder: DID, other: DID, name: String?)?, Error>
func getPair(name: String) -> AnyPublisher<(holder: DID, other: DID, name: String?)?, Error>
func getPair(holderDID: DID) -> AnyPublisher<(holder: DID, other: DID, name: String?)?, Error>
}
9 changes: 9 additions & 0 deletions Pluto/Sources/Domain/Providers/DIDPrivateKeyProvider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Combine
import Domain
import Foundation

protocol DIDPrivateKeyProvider {
func getAll() -> AnyPublisher<[(did: DID, privateKey: PrivateKey)], Error>
func getDIDInfo(did: DID) -> AnyPublisher<(did: DID, privateKey: PrivateKey)?, Error>
func getPrivateKey(did: DID) -> AnyPublisher<PrivateKey?, Error>
}
7 changes: 7 additions & 0 deletions Pluto/Sources/Domain/Providers/MediatorProvider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Combine
import Domain
import Foundation

protocol MediatorProvider {
func getAll() -> AnyPublisher<[(did: DID, routingDID: DID, url: URL)], Error>
}
13 changes: 13 additions & 0 deletions Pluto/Sources/Domain/Providers/MessageProvider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Combine
import Domain
import Foundation

protocol MessageProvider {
func getAll() -> AnyPublisher<[Message], Error>
func getAllFor(did: DID) -> AnyPublisher<[Message], Error>
func getAllSentTo(did: DID) -> AnyPublisher<[Message], Error>
func getAllReceivedFrom(did: DID) -> AnyPublisher<[Message], Error>
func getAllOfType(type: String, relatedWithDID: DID?) -> AnyPublisher<[Message], Error>
func getAll(from: DID, to: DID) -> AnyPublisher<[Message], Error>
func getMessage(id: String) -> AnyPublisher<Message?, Error>
}
9 changes: 9 additions & 0 deletions Pluto/Sources/Domain/Stores/DIDPairStore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Combine
import Domain
import Foundation

protocol DIDPairStore {
func addDIDPair(holder: DID, other: DID, name: String) -> AnyPublisher<Void, Error>
func removeDIDPair(holder: DID, other: DID) -> AnyPublisher<Void, Error>
func removeAll() -> AnyPublisher<Void, Error>
}
9 changes: 9 additions & 0 deletions Pluto/Sources/Domain/Stores/DIDPrivateKeyStore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Combine
import Domain
import Foundation

protocol DIDPrivateKeyStore {
func addDID(did: DID, privateKey: PrivateKey) -> AnyPublisher<Void, Error>
func removeDID(did: DID) -> AnyPublisher<Void, Error>
func removeAll() -> AnyPublisher<Void, Error>
}
8 changes: 8 additions & 0 deletions Pluto/Sources/Domain/Stores/MediatorStore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Combine
import Domain
import Foundation

protocol MediatorStore {
func addMediator(peer: DID, routingDID: DID, url: URL) -> AnyPublisher<Void, Error>
func removeMediator(peer: DID) -> AnyPublisher<Void, Error>
}
9 changes: 9 additions & 0 deletions Pluto/Sources/Domain/Stores/MessageStore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Combine
import Domain
import Foundation

protocol MessageStore {
func addMessage(msg: Message) -> AnyPublisher<Void, Error>
func removeMessage(id: String) -> AnyPublisher<Void, Error>
func removeAll() -> AnyPublisher<Void, Error>
}
73 changes: 73 additions & 0 deletions Pluto/Sources/Helpers/AttachmentDescriptor+Codable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import Domain
import Foundation

extension AttachmentDescriptor: Codable {
enum CodingKeys: String, CodingKey {
case id
case mediaType
case data
case filename
case lastmodTime
case byteCount
case description
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try mediaType.map { try container.encode($0, forKey: .mediaType) }
try filename.map { try container.encode($0, forKey: .filename) }
try lastmodTime.map { try container.encode($0, forKey: .lastmodTime) }
try byteCount.map { try container.encode($0, forKey: .byteCount) }
try description.map { try container.encode($0, forKey: .description) }

if let attachment = data as? AttachmentBase64 {
try container.encode(attachment, forKey: .data)
} else if let attachment = data as? AttachmentJws {
try container.encode(attachment, forKey: .data)
} else if let attachment = data as? AttachmentHeader {
try container.encode(attachment, forKey: .data)
} else if let attachment = data as? AttachmentJwsData {
try container.encode(attachment, forKey: .data)
} else if let attachment = data as? AttachmentJsonData {
try container.encode(attachment, forKey: .data)
} else if let attachment = data as? AttachmentLinkData {
try container.encode(attachment, forKey: .data)
} else { fatalError("Cannot do this") }
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let id = try container.decode(String.self, forKey: .id)
let mediaType = try? container.decode(String.self, forKey: .mediaType)
let filename = try? container.decode([String].self, forKey: .filename)
let lastmodTime = try? container.decode(Date.self, forKey: .lastmodTime)
let byteCount = try? container.decode(Int.self, forKey: .byteCount)
let description = try? container.decode([String].self, forKey: .description)

let data: AttachmentData
if let attachment = try? container.decode(AttachmentBase64.self, forKey: .data) {
data = attachment
} else if let attachment = try? container.decode(AttachmentJws.self, forKey: .data) {
data = attachment
} else if let attachment = try? container.decode(AttachmentHeader.self, forKey: .data) {
data = attachment
} else if let attachment = try? container.decode(AttachmentJwsData.self, forKey: .data) {
data = attachment
} else if let attachment = try? container.decode(AttachmentJsonData.self, forKey: .data) {
data = attachment
} else if let attachment = try? container.decode(AttachmentLinkData.self, forKey: .data) {
data = attachment
} else { fatalError("Cannot do this") }

self.init(
id: id,
mediaType: mediaType,
data: data,
filename: filename,
lastmodTime: lastmodTime,
byteCount: byteCount,
description: description
)
}
}
4 changes: 2 additions & 2 deletions Pluto/Sources/Helpers/CoreData/CoreDataDAO+Combine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ extension CoreDataDAO where CoreDataObject: Identifiable {
func updateOrCreate(
_ id: CoreDataObject.ID,
context: NSManagedObjectContext,
modify: @escaping (CoreDataObject, NSManagedObjectContext) -> Void
modify: @escaping (CoreDataObject, NSManagedObjectContext) throws -> Void
) -> AnyPublisher<CoreDataObject.ID, Error> {
context.write { context in
modify(self.fetchByID(id, context: context) ?? self.newEntity(context: context), context)
try modify(self.fetchByID(id, context: context) ?? self.newEntity(context: context), context)
return id
}
.eraseToAnyPublisher()
Expand Down
26 changes: 26 additions & 0 deletions Pluto/Sources/Helpers/DID+Codable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Domain
import Foundation

extension DID: Codable {
enum CodingKeys: String, CodingKey {
case schema
case method
case methodId
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(schema, forKey: .schema)
try container.encode(method, forKey: .method)
try container.encode(methodId, forKey: .methodId)
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let schema = try container.decode(String.self, forKey: .schema)
let method = try container.decode(DIDMethod.self, forKey: .method)
let methodId = try container.decode(DIDMethodId.self, forKey: .methodId)

self.init(schema: schema, method: method, methodId: methodId)
}
}
70 changes: 70 additions & 0 deletions Pluto/Sources/Helpers/Message+Codable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import Domain
import Foundation

extension Message: Codable {
enum CodingKeys: String, CodingKey {
case id
case piuri
case from
case to
case fromPrior
case extraHeaders
case createdTime
case expiresTimePlus
case attachments
case thid
case pthid
case ack
case body
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(piuri, forKey: .piuri)
try container.encode(body, forKey: .body)
try container.encode(extraHeaders, forKey: .extraHeaders)
try container.encode(createdTime, forKey: .createdTime)
try container.encode(expiresTimePlus, forKey: .expiresTimePlus)
try container.encode(attachments, forKey: .attachments)
try container.encode(ack, forKey: .ack)
try from.map { try container.encode($0, forKey: .from) }
try to.map { try container.encode($0, forKey: .to) }
try fromPrior.map { try container.encode($0, forKey: .fromPrior) }
try thid.map { try container.encode($0, forKey: .thid) }
try pthid.map { try container.encode($0, forKey: .pthid) }
}

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 body = try container.decode(Data.self, forKey: .body)
let extraHeaders = try container.decode([String: String].self, forKey: .extraHeaders)
let createdTime = try container.decode(Date.self, forKey: .createdTime)
let expiresTimePlus = try container.decode(Date.self, forKey: .expiresTimePlus)
let attachments = try container.decode([AttachmentDescriptor].self, forKey: .attachments)
let ack = try container.decode([String].self, forKey: .ack)
let from = try? container.decode(DID.self, forKey: .from)
let to = try? container.decode(DID.self, forKey: .to)
let fromPrior = try? container.decode(String.self, forKey: .fromPrior)
let thid = try? container.decode(String.self, forKey: .thid)
let pthid = try? container.decode(String.self, forKey: .pthid)

self.init(
id: id,
piuri: piuri,
from: from,
to: to,
fromPrior: fromPrior,
body: body,
extraHeaders: extraHeaders,
createdTime: createdTime,
expiresTimePlus: expiresTimePlus,
attachments: attachments,
thid: thid,
pthid: pthid,
ack: ack
)
}
}
19 changes: 19 additions & 0 deletions Pluto/Sources/PersistentStorage/DAO/CDDIDDAO.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Combine
import CoreData
import Domain

struct CDDIDDAO: CoreDataDAO {
typealias CoreDataObject = CDDID
let readContext: NSManagedObjectContext
let writeContext: NSManagedObjectContext
let identifierKey: String? = "did"
}

extension CDDID {
func parseFrom(did: DID) {
self.did = did.string
self.schema = did.schema
self.method = did.method
self.methodId = did.methodId
}
}
Loading