Error handling: Use WireGuardAppError and WireGuardResult throughout the app

Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
Roopesh Chander 2018-12-06 19:05:46 +05:30
parent 782dd2ea4e
commit dcfa9473e9
5 changed files with 45 additions and 41 deletions

View File

@ -5,37 +5,10 @@ import UIKit
import os.log import os.log
class ErrorPresenter { class ErrorPresenter {
static func errorMessage(for error: Error) -> (String, String) { static func showErrorAlert(error: WireGuardAppError, from sourceVC: UIViewController?,
if let error = error as? WireGuardAppError {
return error.alertText()
}
switch (error) {
// Importing a zip file
case ZipArchiveError.cantOpenInputZipFile:
return ("Unable to read zip archive", "The zip archive could not be read.")
case ZipArchiveError.badArchive:
return ("Unable to read zip archive", "Bad or corrupt zip archive.")
case ZipImporterError.noTunnelsInZipArchive:
return ("No tunnels in zip archive", "No .conf tunnel files were found inside the zip archive.")
// Exporting a zip file
case ZipArchiveError.cantOpenOutputZipFileForWriting:
return ("Unable to create zip archive", "Could not create a zip file in the app's document directory.")
case ZipExporterError.noTunnelsToExport:
return ("Nothing to export", "There are no tunnels to export")
default:
return ("Error", error.localizedDescription)
}
}
static func showErrorAlert(error: Error, from sourceVC: UIViewController?,
onDismissal: (() -> Void)? = nil, onPresented: (() -> Void)? = nil) { onDismissal: (() -> Void)? = nil, onPresented: (() -> Void)? = nil) {
guard let sourceVC = sourceVC else { return } guard let sourceVC = sourceVC else { return }
let (title, message) = ErrorPresenter.errorMessage(for: error) let (title, message) = error.alertText()
let okAction = UIAlertAction(title: "OK", style: .default) { (_) in let okAction = UIAlertAction(title: "OK", style: .default) { (_) in
onDismissal?() onDismissal?()
} }

View File

@ -165,11 +165,12 @@ class TunnelsListTableViewController: UIViewController {
func importFromFile(url: URL) { func importFromFile(url: URL) {
guard let tunnelsManager = tunnelsManager else { return } guard let tunnelsManager = tunnelsManager else { return }
if (url.pathExtension == "zip") { if (url.pathExtension == "zip") {
ZipImporter.importConfigFiles(from: url) { (configs, error) in ZipImporter.importConfigFiles(from: url) { [weak self] result in
if let error = error { if let error = result.error {
ErrorPresenter.showErrorAlert(error: error, from: self) ErrorPresenter.showErrorAlert(error: error, from: self)
return return
} }
let configs: [TunnelConfiguration?] = result.value!
tunnelsManager.addMultiple(tunnelConfigurations: configs.compactMap { $0 }) { [weak self] (numberSuccessful) in tunnelsManager.addMultiple(tunnelConfigurations: configs.compactMap { $0 }) { [weak self] (numberSuccessful) in
if numberSuccessful == configs.count { if numberSuccessful == configs.count {
return return

View File

@ -3,10 +3,21 @@
import Foundation import Foundation
enum ZipArchiveError: Error { enum ZipArchiveError: WireGuardAppError {
case cantOpenInputZipFile case cantOpenInputZipFile
case cantOpenOutputZipFileForWriting case cantOpenOutputZipFileForWriting
case badArchive case badArchive
func alertText() -> (String, String) {
switch (self) {
case .cantOpenInputZipFile:
return ("Unable to read zip archive", "The zip archive could not be read.")
case .cantOpenOutputZipFileForWriting:
return ("Unable to create zip archive", "Could not open zip file for writing.")
case .badArchive:
return ("Unable to read zip archive", "Bad or corrupt zip archive.")
}
}
} }
class ZipArchive { class ZipArchive {

View File

@ -3,12 +3,20 @@
import UIKit import UIKit
enum ZipExporterError: Error { enum ZipExporterError: WireGuardAppError {
case noTunnelsToExport case noTunnelsToExport
func alertText() -> (String, String) {
switch (self) {
case .noTunnelsToExport:
return ("Nothing to export", "There are no tunnels to export")
}
}
} }
class ZipExporter { class ZipExporter {
static func exportConfigFiles(tunnelConfigurations: [TunnelConfiguration], to url: URL, completion: @escaping (Error?) -> Void) { static func exportConfigFiles(tunnelConfigurations: [TunnelConfiguration], to url: URL,
completion: @escaping (WireGuardAppError?) -> Void) {
guard (!tunnelConfigurations.isEmpty) else { guard (!tunnelConfigurations.isEmpty) else {
completion(ZipExporterError.noTunnelsToExport) completion(ZipExporterError.noTunnelsToExport)
@ -27,9 +35,11 @@ class ZipExporter {
} }
do { do {
try ZipArchive.archive(inputs: inputsToArchiver, to: url) try ZipArchive.archive(inputs: inputsToArchiver, to: url)
} catch (let e) { } catch (let error as WireGuardAppError) {
DispatchQueue.main.async { completion(e) } DispatchQueue.main.async { completion(error) }
return return
} catch {
fatalError()
} }
DispatchQueue.main.async { completion(nil) } DispatchQueue.main.async { completion(nil) }
} }

View File

@ -3,12 +3,19 @@
import UIKit import UIKit
enum ZipImporterError: Error { enum ZipImporterError: WireGuardAppError {
case noTunnelsInZipArchive case noTunnelsInZipArchive
func alertText() -> (String, String) {
switch (self) {
case .noTunnelsInZipArchive:
return ("No tunnels in zip archive", "No .conf tunnel files were found inside the zip archive.")
}
}
} }
class ZipImporter { class ZipImporter {
static func importConfigFiles(from url: URL, completion: @escaping ([TunnelConfiguration?], Error?) -> Void) { static func importConfigFiles(from url: URL, completion: @escaping (WireGuardResult<[TunnelConfiguration?]>) -> Void) {
DispatchQueue.global(qos: .userInitiated).async { DispatchQueue.global(qos: .userInitiated).async {
var unarchivedFiles: [(fileName: String, contents: Data)] var unarchivedFiles: [(fileName: String, contents: Data)]
do { do {
@ -26,9 +33,11 @@ class ZipImporter {
if (unarchivedFiles.isEmpty) { if (unarchivedFiles.isEmpty) {
throw ZipImporterError.noTunnelsInZipArchive throw ZipImporterError.noTunnelsInZipArchive
} }
} catch (let error) { } catch (let error as WireGuardAppError) {
DispatchQueue.main.async { completion([], error) } DispatchQueue.main.async { completion(.failure(error)) }
return return
} catch {
fatalError()
} }
unarchivedFiles.sort { $0.fileName < $1.fileName } unarchivedFiles.sort { $0.fileName < $1.fileName }
@ -45,7 +54,7 @@ class ZipImporter {
} }
configs[i] = tunnelConfig configs[i] = tunnelConfig
} }
DispatchQueue.main.async { completion(configs, nil) } DispatchQueue.main.async { completion(.success(configs)) }
} }
} }
} }