From 02cb15fd7fdb0792bb6f60bb694473212af3f9a1 Mon Sep 17 00:00:00 2001
From: Bruno Muniz Azevedo Filho <bruno@elixxir.io>
Date: Thu, 11 Aug 2022 03:12:58 -0300
Subject: [PATCH] Added SwiftCSV package

---
 Package.swift                                 |   7 +-
 Sources/LaunchFeature/LaunchController.swift  |   8 +
 Sources/LaunchFeature/LaunchViewModel.swift   | 142 ++++++++++++------
 .../xcshareddata/swiftpm/Package.resolved     |  13 +-
 4 files changed, 117 insertions(+), 53 deletions(-)

diff --git a/Package.swift b/Package.swift
index 45958a19..2c6601fb 100644
--- a/Package.swift
+++ b/Package.swift
@@ -116,7 +116,7 @@ let package = Package(
         ),
         .package(
             url: "https://git.xx.network/elixxir/client-ios-db.git",
-            .upToNextMajor(from: "1.0.8")
+            branch: "feature/blocked-and-banned-contacts"
         ),
         .package(
             url: "https://github.com/firebase/firebase-ios-sdk.git",
@@ -134,6 +134,10 @@ let package = Package(
             url: "https://github.com/pointfreeco/swift-custom-dump.git",
             .upToNextMajor(from: "0.5.0")
         ),
+        .package(
+            url: "https://github.com/swiftcsv/SwiftCSV.git",
+            from: "0.8.0"
+        ),
         .package(
             url: "https://github.com/pointfreeco/xctest-dynamic-overlay.git",
             .upToNextMajor(from: "0.3.3")
@@ -507,6 +511,7 @@ let package = Package(
                 .target(name: "DropboxFeature"),
                 .target(name: "VersionChecking"),
                 .target(name: "DependencyInjection"),
+                .product(name: "SwiftCSV", package: "SwiftCSV"),
             ]
         ),
         .target(
diff --git a/Sources/LaunchFeature/LaunchController.swift b/Sources/LaunchFeature/LaunchController.swift
index 9d904232..cf8b093b 100644
--- a/Sources/LaunchFeature/LaunchController.swift
+++ b/Sources/LaunchFeature/LaunchController.swift
@@ -2,6 +2,7 @@ import HUD
 import UIKit
 import Shared
 import Combine
+import Defaults
 import PushFeature
 import DependencyInjection
 
@@ -9,6 +10,8 @@ public final class LaunchController: UIViewController {
     @Dependency private var hud: HUD
     @Dependency private var coordinator: LaunchCoordinating
 
+    @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool
+
     lazy private var screenView = LaunchView()
 
     private let blocker = UpdateBlocker()
@@ -50,6 +53,11 @@ public final class LaunchController: UIViewController {
             .sink { [unowned self] in
                 switch $0 {
                 case .chats:
+                    guard didAcceptTerms == true else {
+                        coordinator.toTerms(from: self)
+                        return
+                    }
+
                     if let pushRoute = pendingPushRoute {
                         switch pushRoute {
                         case .requests:
diff --git a/Sources/LaunchFeature/LaunchViewModel.swift b/Sources/LaunchFeature/LaunchViewModel.swift
index 0b8354da..9dea87ed 100644
--- a/Sources/LaunchFeature/LaunchViewModel.swift
+++ b/Sources/LaunchFeature/LaunchViewModel.swift
@@ -1,6 +1,7 @@
 import HUD
 import Shared
 import Models
+import SwiftCSV
 
 import Combine
 import Defaults
@@ -46,6 +47,10 @@ final class LaunchViewModel {
         routeSubject.eraseToAnyPublisher()
     }
 
+    var mainScheduler: AnySchedulerOf<DispatchQueue> = {
+        DispatchQueue.main.eraseToAnyScheduler()
+    }()
+
     var backgroundScheduler: AnySchedulerOf<DispatchQueue> = {
         DispatchQueue.global().eraseToAnyScheduler()
     }()
@@ -57,67 +62,74 @@ final class LaunchViewModel {
     private let hudSubject = CurrentValueSubject<HUDStatus, Never>(.none)
 
     func viewDidAppear() {
-        DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
-            self?.hudSubject.send(.on)
-            self?.checkVersion()
-        }
-    }
-
-    private func checkVersion() {
-        versionChecker().sink { [unowned self] in
-            switch $0 {
-            case .upToDate:
-                versionApproved()
-            case .failure(let error):
-                versionFailed(error: error)
-            case .updateRequired(let info):
-                versionUpdateRequired(info)
-            case .updateRecommended(let info):
-                versionUpdateRecommended(info)
-            }
-        }.store(in: &cancellables)
-    }
-
-    func versionApproved() {
-        network.writeLogs()
-
-        network.updateNDF { [weak self] in
+        mainScheduler.schedule(after: .init(.now() + 1)) { [weak self] in
             guard let self = self else { return }
 
-            switch $0 {
-            case .success(let ndf):
-                self.network.updateErrors()
+            self.hudSubject.send(.on)
 
-                guard self.network.hasClient else {
-                    self.hudSubject.send(.none)
-                    self.routeSubject.send(.onboarding(ndf))
-                    self.dropboxService.unlink()
-                    try? self.keychainHandler.clear()
-                    return
+            self.versionChecker().sink { [unowned self] in
+                switch $0 {
+                case .upToDate:
+                    self.versionApproved()
+                case .failure(let error):
+                    self.versionFailed(error: error)
+                case .updateRequired(let info):
+                    self.versionUpdateRequired(info)
+                case .updateRecommended(let info):
+                    self.versionUpdateRecommended(info)
                 }
+            }.store(in: &self.cancellables)
+        }
+    }
 
-                guard self.username != nil else {
-                    self.network.purgeFiles()
-                    self.hudSubject.send(.none)
-                    self.routeSubject.send(.onboarding(ndf))
-                    self.dropboxService.unlink()
-                    try? self.keychainHandler.clear()
-                    return
-                }
+    func versionApproved() {
+        Task {
+            do {
+                network.writeLogs()
+                let bannedList = try await fetchBannedList()
+                process(bannedList: bannedList)
 
-                self.backgroundScheduler.schedule { [weak self] in
+                network.updateNDF { [weak self] in
                     guard let self = self else { return }
 
-                    do {
-                        let session = try self.getSession(ndf)
-                        DependencyInjection.Container.shared.register(session as SessionType)
-                        self.hudSubject.send(.none)
-                        self.checkBiometrics()
-                    } catch {
+                    switch $0 {
+                    case .success(let ndf):
+                        self.network.updateErrors()
+
+                        guard self.network.hasClient else {
+                            self.hudSubject.send(.none)
+                            self.routeSubject.send(.onboarding(ndf))
+                            self.dropboxService.unlink()
+                            try? self.keychainHandler.clear()
+                            return
+                        }
+
+                        guard self.username != nil else {
+                            self.network.purgeFiles()
+                            self.hudSubject.send(.none)
+                            self.routeSubject.send(.onboarding(ndf))
+                            self.dropboxService.unlink()
+                            try? self.keychainHandler.clear()
+                            return
+                        }
+
+                        self.backgroundScheduler.schedule { [weak self] in
+                            guard let self = self else { return }
+
+                            do {
+                                let session = try self.getSession(ndf)
+                                DependencyInjection.Container.shared.register(session as SessionType)
+                                self.hudSubject.send(.none)
+                                self.checkBiometrics()
+                            } catch {
+                                self.hudSubject.send(.error(HUDError(with: error)))
+                            }
+                        }
+                    case .failure(let error):
                         self.hudSubject.send(.error(HUDError(with: error)))
                     }
                 }
-            case .failure(let error):
+            } catch {
                 self.hudSubject.send(.error(HUDError(with: error)))
             }
         }
@@ -195,4 +207,34 @@ final class LaunchViewModel {
             self.routeSubject.send(.chats)
         }
     }
+
+    private func fetchBannedList() async throws -> Data {
+        let request = URLRequest(
+            url: URL(string: "https://elixxir-bins.s3.us-west-1.amazonaws.com/client/bannedUsers/banned.csv")!,
+            cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
+            timeoutInterval: 5
+        )
+
+        return try await withCheckedThrowingContinuation { continuation in
+            URLSession.shared.dataTask(with: request) { data, _, error in
+                if let error = error {
+                    return continuation.resume(throwing: error)
+                }
+
+                guard let data = data else { fatalError("?") }
+                return continuation.resume(returning: data)
+            }.resume()
+        }
+    }
+
+    private func process(bannedList: Data) {
+        if let csv: CSV = try? CSV<Enumerated>(
+            string: String(data: bannedList, encoding: .utf8)!,
+            loadColumns: false
+        ) {
+            /// csv.rows[0][0] == userId
+            /// csv.rows[0][1] == username
+            csv.rows.forEach { print("^^^ Banned row: \($0)") }
+        }
+    }
 }
diff --git a/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved b/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 2932261c..453f1d5d 100644
--- a/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -59,8 +59,8 @@
       "kind" : "remoteSourceControl",
       "location" : "https://git.xx.network/elixxir/client-ios-db.git",
       "state" : {
-        "revision" : "785e1f653ee5eaaaf58a82c8abbcda2174fbc27a",
-        "version" : "1.0.8"
+        "branch" : "feature/blocked-and-banned-contacts",
+        "revision" : "b35a3779c276471aa6e79f047e1c843e49b0dea8"
       }
     },
     {
@@ -350,6 +350,15 @@
         "version" : "1.18.0"
       }
     },
+    {
+      "identity" : "swiftcsv",
+      "kind" : "remoteSourceControl",
+      "location" : "https://github.com/swiftcsv/SwiftCSV.git",
+      "state" : {
+        "revision" : "048a1d3c2950b9c151ef9364b36f91baadc2c28c",
+        "version" : "0.8.0"
+      }
+    },
     {
       "identity" : "swiftybeaver",
       "kind" : "remoteSourceControl",
-- 
GitLab