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

Finished restore integration w/ 3rd party

parent add5f413
No related branches found
No related tags found
2 merge requests!54Releasing 1.1.4,!42Adding SFTP as a service to backup/restore
......@@ -69,6 +69,7 @@ let package = Package(
.package(url: "https://github.com/google/google-api-objectivec-client-for-rest", from: "1.6.0"),
.package(url: "https://git.xx.network/elixxir/client-ios-db.git", .upToNextMajor(from: "1.0.5")),
.package(url: "https://github.com/firebase/firebase-ios-sdk.git", .upToNextMajor(from: "8.10.0")),
.package(url: "https://github.com/darrarski/Shout.git", revision: "df5a662293f0ac15eeb4f2fd3ffd0c07b73d0de0"),
.package(url: "https://github.com/pointfreeco/swift-composable-architecture.git",.upToNextMajor(from: "0.32.0"))
],
targets: [
......@@ -216,7 +217,13 @@ let package = Package(
name: "SFTPFeature",
dependencies: [
"Shared",
"InputField"
"Keychain",
"InputField",
"DependencyInjection",
.product(
name: "Shout",
package: "Shout"
)
]
),
......
......@@ -54,9 +54,14 @@ final class BackupSFTPViewModel {
let password = stateSubject.value.password
let authParams = SFTPAuthParams(host, username, password)
service.justAuthenticate(authParams)
hudSubject.send(.none)
popSubject.send(())
do {
try service.justAuthenticate(authParams)
hudSubject.send(.none)
popSubject.send(())
} catch {
hudSubject.send(.error(.init(with: error)))
}
}
private func validate() {
......
import Foundation
import KeychainAccess
public enum KeychainSFTP: String {
case pwd
case host
case username
}
public protocol KeychainHandling {
func clear() throws
func getPassword() throws -> Data?
func store(password pwd: Data) throws
func get(key: KeychainSFTP) throws -> String?
func store(key: KeychainSFTP, value: String) throws
}
public struct KeychainHandler: KeychainHandling {
private let password = "password"
private let keychain: Keychain
private let password = "password"
public init() {
self.keychain = Keychain(service: "XXM")
......@@ -26,4 +35,12 @@ public struct KeychainHandler: KeychainHandling {
public func getPassword() throws -> Data? {
try keychain.getData(password)
}
public func get(key: KeychainSFTP) throws -> String? {
try keychain.get(key.rawValue)
}
public func store(key: KeychainSFTP, value: String) throws {
try keychain.set(value, key: key.rawValue)
}
}
......@@ -6,4 +6,6 @@ public struct MockKeychainHandler: KeychainHandling {
public func clear() throws {}
public func store(password pwd: Data) throws {}
public func getPassword() throws -> Data? { Data() }
public func get(key: KeychainSFTP) throws -> String? { nil }
public func store(key: KeychainSFTP, value: String) throws {}
}
......@@ -8,6 +8,7 @@ import Integration
import BackupFeature
import DependencyInjection
import SFTPFeature
import iCloudFeature
import DropboxFeature
import GoogleDriveFeature
......@@ -38,13 +39,16 @@ extension RestorationStep: Equatable {
}
final class RestoreViewModel {
@Dependency private var sftpService: SFTPService
@Dependency private var iCloudService: iCloudInterface
@Dependency private var dropboxService: DropboxInterface
@Dependency private var googleService: GoogleDriveInterface
@KeyObject(.username, defaultValue: nil) var username: String?
var step: AnyPublisher<RestorationStep, Never> { stepRelay.eraseToAnyPublisher() }
var step: AnyPublisher<RestorationStep, Never> {
stepRelay.eraseToAnyPublisher()
}
// TO REFACTOR:
//
......@@ -86,7 +90,11 @@ final class RestoreViewModel {
}
private func downloadBackupForSFTP(_ backup: Backup) {
// TODO
do {
try sftpService.download(backup.id)
} catch {
print(error.localizedDescription)
}
}
private func downloadBackupForDropbox(_ backup: Backup) {
......
import Shout
import Models
import Keychain
import Foundation
import DependencyInjection
public typealias SFTPAuthParams = (String, String, String)
public typealias SFTPFetchResult = (Result<RestoreSettings?, Error>) -> Void
......@@ -8,42 +11,88 @@ public typealias SFTPFetchParams = (SFTPAuthParams, SFTPFetchResult)
public struct SFTPService {
public var isAuthorized: () -> Bool
public var fetch: (SFTPFetchParams) -> Void
public var justAuthenticate: (SFTPAuthParams) -> Void
public var download: (String) throws -> Void
public var justAuthenticate: (SFTPAuthParams) throws -> Void
}
public extension SFTPService {
static var mock = SFTPService(
isAuthorized: {
false
true
},
fetch: { (authParams, completion) in
print("^^^ RestoreSFTP Host: \(authParams.0)")
print("^^^ RestoreSFTP Username: \(authParams.1)")
print("^^^ RestoreSFTP Password: \(authParams.2)")
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
completion(.success(.init(
backup: .init(id: "ASDF", date: Date.distantPast, size: 100_000_000),
cloudService: .sftp
)))
}
completion(.success(nil))
},
download: { path in
},
justAuthenticate: { host, username, password in
// TODO: Store these params on the keychain
})
static var live = SFTPService(
isAuthorized: {
/// If it has host/username/password on keychain
/// means its authorized, not that is working
///
true
if let keychain = try? DependencyInjection.Container.shared.resolve() as KeychainHandling,
let pwd = try? keychain.get(key: .pwd),
let host = try? keychain.get(key: .host),
let username = try? keychain.get(key: .username) {
return true
} else {
return false
}
},
fetch: { (authParams, completion) in
// TODO: Store host/username/password on keychain
let host = authParams.0
let username = authParams.1
let password = authParams.2
do {
let ssh = try SSH(host: host, port: 22)
try ssh.authenticate(username: username, password: password)
let sftp = try ssh.openSftp()
let keychain = try DependencyInjection.Container.shared.resolve() as KeychainHandling
try keychain.store(key: .host, value: host)
try keychain.store(key: .pwd, value: password)
try keychain.store(key: .username, value: username)
if let files = try? sftp.listFiles(in: "backup"),
let backup = files.filter({ file in file.0 == "backup.xxm" }).first {
completion(.success(.init(
backup: .init(
id: "backup/backup.xxm",
date: backup.value.lastModified,
size: Float(backup.value.size)
),
cloudService: .sftp
)))
return
}
completion(.success(nil))
} catch {
completion(.failure(error))
}
},
download: { path in
let keychain = try DependencyInjection.Container.shared.resolve() as KeychainHandling
let host = try keychain.get(key: .host)
let password = try keychain.get(key: .pwd)
let username = try keychain.get(key: .username)
let ssh = try SSH(host: host!, port: 22)
try ssh.authenticate(username: username!, password: password!)
let sftp = try ssh.openSftp()
let temp = NSTemporaryDirectory()
try sftp.download(remotePath: path, localURL: URL(string: temp)!)
print(FileManager.default.fileExists(atPath: temp))
},
justAuthenticate: { host, username, password in
// TODO: Store host/username/password on keychain
let keychain = try DependencyInjection.Container.shared.resolve() as KeychainHandling
try keychain.store(key: .host, value: host)
try keychain.store(key: .pwd, value: password)
try keychain.store(key: .username, value: username)
}
)
}
......@@ -27,6 +27,15 @@
"version" : "1.4.0"
}
},
{
"identity" : "bluesocket",
"kind" : "remoteSourceControl",
"location" : "https://github.com/IBM-Swift/BlueSocket.git",
"state" : {
"revision" : "c9894fd117457f1d006575fbfb2fdfd6f79eac03",
"version" : "1.0.200"
}
},
{
"identity" : "boringssl-swiftpm",
"kind" : "remoteSourceControl",
......@@ -207,6 +216,15 @@
"version" : "1.22.2"
}
},
{
"identity" : "libssh2prebuild",
"kind" : "remoteSourceControl",
"location" : "https://github.com/DimaRU/Libssh2Prebuild.git",
"state" : {
"branch" : "1.10.0+OpenSSL_1_1_1o",
"revision" : "a91bcf205a6cbc84144f840c44145656abbd266a"
}
},
{
"identity" : "nanopb",
"kind" : "remoteSourceControl",
......@@ -261,6 +279,14 @@
"version" : "1.2.0"
}
},
{
"identity" : "shout",
"kind" : "remoteSourceControl",
"location" : "https://github.com/darrarski/Shout.git",
"state" : {
"revision" : "df5a662293f0ac15eeb4f2fd3ffd0c07b73d0de0"
}
},
{
"identity" : "snapkit",
"kind" : "remoteSourceControl",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment