Skip to content
Snippets Groups Projects
Commit 822397ec authored by Bruno Muniz's avatar Bruno Muniz :apple:
Browse files

Handling received requests and confirmations

parent ef8b7555
No related branches found
No related tags found
No related merge requests found
......@@ -9,6 +9,8 @@ import ElixxirDAppsSDK
import CombineSchedulers
import DependencyInjection
import struct ElixxirDAppsSDK.FileTransfer
struct OnboardingUsernameViewState: Equatable {
var input: String = ""
var status: InputField.ValidationStatus = .unknown(nil)
......@@ -22,7 +24,8 @@ final class OnboardingUsernameViewModel {
@KeyObject(.username, defaultValue: "") var username: String
var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
var backgroundScheduler: AnySchedulerOf<DispatchQueue>
= DispatchQueue.global().eraseToAnyScheduler()
var greenPublisher: AnyPublisher<Void, Never> { greenRelay.eraseToAnyPublisher() }
private let greenRelay = PassthroughSubject<Void, Never>()
......@@ -51,105 +54,114 @@ final class OnboardingUsernameViewModel {
guard let self = self else { return }
do {
let cMix = try self.cMixManager.create()
let cMix = try self.initCMix()
try cMix.startNetworkFollower(timeoutMS: 10_000)
let e2e = try self.initE2E(cMix)
_ = try self.initUD(alternative: false, e2e: e2e, cMix: cMix)
_ = try self.initGroupManager(e2e)
_ = try self.initTransferManager(e2e)
self.hudRelay.send(.none)
self.greenRelay.send()
} catch {
self.hudRelay.send(.none)
self.stateRelay.value.status = .invalid(error.localizedDescription)
}
}
}
private func initCMix() throws -> CMix {
if let cMix = try? DependencyInjection.Container.shared.resolve() as CMix {
return cMix
}
let cMix = try cMixManager.create()
DependencyInjection.Container.shared.register(cMix)
return cMix
}
private func initE2E(_ cMix: CMix) throws -> E2E {
if let e2e = try? DependencyInjection.Container.shared.resolve() as E2E {
return e2e
}
let e2e = try Login.live(
cMixId: cMix.getId(),
authCallbacks: .init(
handle: {
switch $0 {
case .reset(
contact: let contact,
receptionId: _,
ephemeralId: _,
roundId: _
):
break
case .confirm(
contact: let contact,
receptionId: _,
ephemeralId: _,
roundId: _
):
break
case .request(
contact: let contact,
receptionId: _,
ephemeralId: _,
roundId: _
):
if let contactId = try? self.getIdFromContact(contact),
let _ = try? self.database.fetchContacts(Contact.Query(id: [contactId])).first {
return
}
let contactId = try! self.getIdFromContact(contact)
let facts = try? self.getFactsFromContact(contact: contact)
let username = facts?.first(where: { $0.type == FactType.username.rawValue })?.fact
let email = facts?.first(where: { $0.type == FactType.email.rawValue })?.fact
let phone = facts?.first(where: { $0.type == FactType.phone.rawValue })?.fact
_ = try? self.database.saveContact(.init(
id: contactId,
marshaled: contact,
username: username,
email: email,
phone: phone,
nickname: nil,
photo: nil,
authStatus: .verificationInProgress,
isRecent: true,
createdAt: Date()
))
case .reset(contact: let contact, receptionId: _, ephemeralId: _, roundId: _):
self.handleReset(from: contact)
case .confirm(contact: let contact, receptionId: _, ephemeralId: _, roundId: _):
self.handleConfirm(from: contact)
case .request(contact: let contact, receptionId: _, ephemeralId: _, roundId: _):
self.handleRequest(from: contact)
}
}
),
identity: cMix.makeLegacyReceptionIdentity()
)
DependencyInjection.Container.shared.register(cMix)
try e2e.registerListener(
senderId: nil,
messageType: 2,
callback: .init(handle: { message in
print(message.timestamp)
})
)
DependencyInjection.Container.shared.register(e2e)
return e2e
}
private func initUD(alternative: Bool, e2e: E2E, cMix: CMix) throws -> UserDiscovery {
if let userDiscovery = try? DependencyInjection.Container.shared.resolve() as UserDiscovery {
return userDiscovery
}
guard let certPath = Bundle.module.path(forResource: "cmix.rip", ofType: "crt"),
let contactFilePath = Bundle.module.path(forResource: "udContact", ofType: "bin") else {
fatalError("Couldn't retrieve alternative UD credentials")
}
let address = alternative ? "46.101.98.49:18001" : e2e.getUdAddressFromNdf()
let cert = alternative ? try Data(contentsOf: URL(fileURLWithPath: certPath)) : e2e.getUdCertFromNdf()
let contactFile = alternative ? try Data(contentsOf: URL(fileURLWithPath: contactFilePath)) : try e2e.getUdContactFromNdf()
let userDiscovery = try NewOrLoadUd.live(.init(
e2eId: e2e.getId(),
follower: .init(handle: { cMix.networkFollowerStatus().rawValue }),
username: self.stateRelay.value.input,
registrationValidationSignature: cMix.getReceptionRegistrationValidationSignature(),
cert: Data(contentsOf: URL(fileURLWithPath: certPath)),
contactFile: Data(contentsOf: URL(fileURLWithPath: contactFilePath)),
address: "46.101.98.49:18001"
cert: cert,
contactFile: contactFile,
address: address
))
self.username = self.stateRelay.value.input
username = self.stateRelay.value.input
DependencyInjection.Container.shared.register(userDiscovery)
return userDiscovery
}
try e2e.registerListener(
senderId: nil,
messageType: 2,
callback: .init(handle: { message in
print(message.timestamp)
})
)
DependencyInjection.Container.shared.register(e2e)
private func initGroupManager(_ e2e: E2E) throws -> GroupChat {
if let groupManager = try? DependencyInjection.Container.shared.resolve() as GroupChat {
return groupManager
}
let groupManager = try NewGroupChat.live(
e2eId: e2e.getId(),
groupRequest: .init(handle: {
print($0)
}),
groupChatProcessor: .init(handle: {
print($0)
})
groupRequest: .init(handle: { print($0) }),
groupChatProcessor: .init(handle: { print($0) })
)
DependencyInjection.Container.shared.register(groupManager)
return groupManager
}
private func initTransferManager(_ e2e: E2E) throws -> ElixxirDAppsSDK.FileTransfer {
if let transferManager = try? DependencyInjection.Container.shared.resolve() as FileTransfer {
return transferManager
}
let transferManager = try InitFileTransfer.live(
e2eId: e2e.getId(),
......@@ -164,14 +176,113 @@ final class OnboardingUsernameViewModel {
)
DependencyInjection.Container.shared.register(transferManager)
return transferManager
}
self.hudRelay.send(.none)
self.greenRelay.send()
private func handleRequest(from contact: Data) {
guard isRepeatedRequest(from: contact) == false else { return }
do {
let facts = try? getFactsFromContact(contact: contact)
let model = try self.database.saveContact(.init(
id: try getIdFromContact(contact),
marshaled: contact,
username: facts?.first(where: { $0.type == FactType.username.rawValue })?.fact,
email: facts?.first(where: { $0.type == FactType.email.rawValue })?.fact,
phone: facts?.first(where: { $0.type == FactType.phone.rawValue })?.fact,
nickname: nil,
photo: nil,
authStatus: .verificationInProgress,
isRecent: true,
createdAt: Date()
))
if model.email == nil, model.phone == nil {
performLookup(on: model)
} else {
//performSearch()
}
} catch {
self.hudRelay.send(.none)
self.stateRelay.value.status = .invalid(error.localizedDescription)
print("^^^ Request processing failed: \(error.localizedDescription)")
}
}
private func isRepeatedRequest(from contact: Data) -> Bool {
if let id = try? getIdFromContact(contact),
let _ = try? self.database.fetchContacts(Contact.Query(id: [id])).first {
return true
}
return false
}
private func performLookup(on contact: Contact) {
guard let e2e = try? DependencyInjection.Container.shared.resolve() as E2E,
let userDiscovery = try? DependencyInjection.Container.shared.resolve() as UserDiscovery else {
print("^^^ couldn't resolve UD/E2E to process lookup")
return
}
do {
let _ = try LookupUD.live(
e2eId: e2e.getId(),
udContact: try userDiscovery.getContact(),
lookupId: contact.id,
callback: .init(handle: { [weak self] in
guard let self = self else { return }
switch $0 {
case .success(let id):
self.performOwnershipVerification(contact: contact, idLookedUp: id)
case .failure(let error):
print("^^^ Lookup failed: \(error.localizedDescription)")
}
})
)
} catch {
print("^^^ Error when trying to run lookup: \(error.localizedDescription)")
}
}
private func performOwnershipVerification(contact: Contact, idLookedUp: Data) {
guard let e2e = try? DependencyInjection.Container.shared.resolve() as E2E else {
print("^^^ couldn't resolve E2E to process verification")
return
}
do {
let result = try e2e.verifyOwnership(
receivedContact: contact.marshaled!,
verifiedContact: idLookedUp,
e2eId: e2e.getId()
)
if result == true {
var contact = contact
contact.authStatus = .verified
try database.saveContact(contact)
} else {
try database.deleteContact(contact)
}
} catch {
print("^^^ Exception thrown at verify ownership")
}
}
private func handleConfirm(from contact: Data) {
guard let id = try? getIdFromContact(contact) else {
print("^^^ Couldn't get id from contact. Confirmation failed")
return
}
if var model = try? database.fetchContacts(.init(id: [id])).first {
model.authStatus = .friend
_ = try? database.saveContact(model)
}
}
private func handleReset(from contact: Data) {
// TODO
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment