Skip to content
Snippets Groups Projects
SFTPService.swift 4.86 KiB
Newer Older
import Shout
import Keychain
import Foundation
import DependencyInjection

public typealias SFTPAuthParams = (String, String, String)
public typealias SFTPFetchResult = (Result<RestoreSettings?, Error>) -> Void
public typealias SFTPFetchParams = (SFTPAuthParams, SFTPFetchResult)

Bruno Muniz's avatar
Bruno Muniz committed
public struct SFTPService {
    public var isAuthorized: () -> Bool
    public var upload: (URL) throws -> Void
    public var fetch: (SFTPFetchParams) -> Void
    public var download: (String) throws -> Void
    public var justAuthenticate: (SFTPAuthParams) throws -> Void
Bruno Muniz's avatar
Bruno Muniz committed
}

public extension SFTPService {
    static var mock = SFTPService(
        isAuthorized: {
            print("^^^ Requested auth status on sftp service")
            return true
        },
        upload: { url in
            print("^^^ Requested upload on sftp service")
            print("^^^ URL path: \(url.path)")
        },
        fetch: { (authParams, completion) in
            print("^^^ Requested backup metadata on sftp service.")
            print("^^^ Host: \(authParams.0)")
            print("^^^ Username: \(authParams.1)")
            print("^^^ Password: \(authParams.2)")
            completion(.success(nil))
        },
        download: { path in
            print("^^^ Requested backup download on sftp service.")
            print("^^^ Path: \(path)")
        },
        justAuthenticate: { host, username, password in
            print("^^^ Requested to authenticate on sftp service")
            print("^^^ Host: \(host)")
            print("^^^ Username: \(username)")
            print("^^^ Password: \(password)")
Bruno Muniz's avatar
Bruno Muniz committed
    static var live = SFTPService(
        isAuthorized: {
            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
            }
Bruno Muniz's avatar
Bruno Muniz committed
        },
        upload: { url 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()

            try sftp.upload(localURL: url, remotePath: "backup/backup.xxm")
        },
        fetch: { (authParams, completion) in
            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
            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)