From 17e117a36eecaf06192a66d5ec085a82b4205b9c Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Wed, 21 Sep 2022 18:18:36 +0200
Subject: [PATCH] Add MessengerRestoreBackup function wrapper

---
 .../Functions/MessengerRestoreBackup.swift    | 75 +++++++++++++++++++
 .../Messenger/Messenger.swift                 |  3 +
 .../Messenger/MessengerEnvironment.swift      |  6 ++
 .../Utils/BackupParams.swift                  | 17 +++++
 4 files changed, 101 insertions(+)
 create mode 100644 Sources/XXMessengerClient/Messenger/Functions/MessengerRestoreBackup.swift
 create mode 100644 Sources/XXMessengerClient/Utils/BackupParams.swift

diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerRestoreBackup.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerRestoreBackup.swift
new file mode 100644
index 00000000..02b45c61
--- /dev/null
+++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerRestoreBackup.swift
@@ -0,0 +1,75 @@
+import Foundation
+import XXClient
+import XCTestDynamicOverlay
+
+public struct MessengerRestoreBackup {
+  public var run: (Data, String) throws -> BackupParams
+
+  public func callAsFunction(
+    backupData: Data,
+    backupPassphrase: String
+  ) throws -> BackupParams {
+    try run(backupData, backupPassphrase)
+  }
+}
+
+extension MessengerRestoreBackup {
+  public static func live(_ env: MessengerEnvironment) -> MessengerRestoreBackup {
+    MessengerRestoreBackup { backupData, backupPassphrase in
+      let storageDir = env.storageDir
+      do {
+        let ndfData = try env.downloadNDF(env.ndfEnvironment)
+        let password = env.generateSecret()
+        try env.passwordStorage.save(password)
+        try env.fileManager.removeDirectory(storageDir)
+        try env.fileManager.createDirectory(storageDir)
+        let report = try env.newCMixFromBackup(
+          ndfJSON: String(data: ndfData, encoding: .utf8)!,
+          storageDir: storageDir,
+          backupPassphrase: backupPassphrase,
+          sessionPassword: password,
+          backupFileContents: backupData
+        )
+        let cMix = try env.loadCMix(
+          storageDir: storageDir,
+          password: password,
+          cMixParamsJSON: env.getCMixParams()
+        )
+        let e2e = try env.login(
+          cMixId: cMix.getId(),
+          authCallbacks: env.authCallbacks.registered(),
+          identity: try cMix.makeReceptionIdentity(legacy: true),
+          e2eParamsJSON: env.getE2EParams()
+        )
+        let decoder = JSONDecoder()
+        let paramsData = report.params.data(using: .utf8)!
+        let params = try decoder.decode(BackupParams.self, from: paramsData)
+        let ud = try env.newUdManagerFromBackup(
+          params: NewUdManagerFromBackup.Params(
+            e2eId: e2e.getId(),
+            username: Fact(type: .username, value: params.username),
+            email: params.email.map { Fact(type: .email, value: $0) },
+            phone: params.phone.map { Fact(type: .phone, value: $0) },
+            cert: env.udCert ?? e2e.getUdCertFromNdf(),
+            contact: env.udContact ?? (try e2e.getUdContactFromNdf()),
+            address: env.udAddress ?? e2e.getUdAddressFromNdf()
+          ),
+          follower: UdNetworkStatus { cMix.networkFollowerStatus() }
+        )
+        env.cMix.set(cMix)
+        env.e2e.set(e2e)
+        env.ud.set(ud)
+        return params
+      } catch {
+        try? env.fileManager.removeDirectory(storageDir)
+        throw error
+      }
+    }
+  }
+}
+
+extension MessengerRestoreBackup {
+  public static let unimplemented = MessengerRestoreBackup(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/XXMessengerClient/Messenger/Messenger.swift b/Sources/XXMessengerClient/Messenger/Messenger.swift
index 77f7f1e5..ad3fff79 100644
--- a/Sources/XXMessengerClient/Messenger/Messenger.swift
+++ b/Sources/XXMessengerClient/Messenger/Messenger.swift
@@ -6,6 +6,7 @@ public struct Messenger {
   public var ud: Stored<UserDiscovery?>
   public var isCreated: MessengerIsCreated
   public var create: MessengerCreate
+  public var restoreBackup: MessengerRestoreBackup
   public var isLoaded: MessengerIsLoaded
   public var load: MessengerLoad
   public var registerAuthCallbacks: MessengerRegisterAuthCallbacks
@@ -37,6 +38,7 @@ extension Messenger {
       ud: env.ud,
       isCreated: .live(env),
       create: .live(env),
+      restoreBackup: .live(env),
       isLoaded: .live(env),
       load: .live(env),
       registerAuthCallbacks: .live(env),
@@ -69,6 +71,7 @@ extension Messenger {
     ud: .unimplemented(),
     isCreated: .unimplemented,
     create: .unimplemented,
+    restoreBackup: .unimplemented,
     isLoaded: .unimplemented,
     load: .unimplemented,
     registerAuthCallbacks: .unimplemented,
diff --git a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
index f125c1ef..00ab6338 100644
--- a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
+++ b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift
@@ -20,7 +20,9 @@ public struct MessengerEnvironment {
   public var multiLookupUD: MultiLookupUD
   public var ndfEnvironment: NDFEnvironment
   public var newCMix: NewCMix
+  public var newCMixFromBackup: NewCMixFromBackup
   public var newOrLoadUd: NewOrLoadUd
+  public var newUdManagerFromBackup: NewUdManagerFromBackup
   public var passwordStorage: PasswordStorage
   public var registerForNotifications: RegisterForNotifications
   public var searchUD: SearchUD
@@ -58,7 +60,9 @@ extension MessengerEnvironment {
       multiLookupUD: .live(),
       ndfEnvironment: .mainnet,
       newCMix: .live,
+      newCMixFromBackup: .live,
       newOrLoadUd: .live,
+      newUdManagerFromBackup: .live,
       passwordStorage: .keychain,
       registerForNotifications: .live,
       searchUD: .live,
@@ -91,7 +95,9 @@ extension MessengerEnvironment {
     multiLookupUD: .unimplemented,
     ndfEnvironment: .unimplemented,
     newCMix: .unimplemented,
+    newCMixFromBackup: .unimplemented,
     newOrLoadUd: .unimplemented,
+    newUdManagerFromBackup: .unimplemented,
     passwordStorage: .unimplemented,
     registerForNotifications: .unimplemented,
     searchUD: .unimplemented,
diff --git a/Sources/XXMessengerClient/Utils/BackupParams.swift b/Sources/XXMessengerClient/Utils/BackupParams.swift
new file mode 100644
index 00000000..28523748
--- /dev/null
+++ b/Sources/XXMessengerClient/Utils/BackupParams.swift
@@ -0,0 +1,17 @@
+import Foundation
+
+public struct BackupParams: Codable {
+  public init(
+    email: String?,
+    phone: String?,
+    username: String
+  ) {
+    self.email = email
+    self.phone = phone
+    self.username = username
+  }
+
+  public var email: String?
+  public var phone: String?
+  public var username: String
+}
-- 
GitLab