This repository was archived by the owner on Oct 7, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathAPIController.swift
More file actions
120 lines (87 loc) · 3.12 KB
/
APIController.swift
File metadata and controls
120 lines (87 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import Alamofire
import Foundation
import Sonar
protocol APIDelegate: class {
func didStartLoading()
func didFail(with error: SonarError)
func didPostToAppleRadar()
func didPostToOpenRadar()
}
protocol TwoFactorAuthenticationHandler: class {
func askForCode(completion: @escaping (String) -> Void)
}
final class APIController {
// MARK: - Properties
weak var delegate: APIDelegate?
weak var twoFactorHandler: TwoFactorAuthenticationHandler?
// MARK: - Init/Deinit
init(delegate: APIDelegate? = nil, twoFactorHandler: TwoFactorAuthenticationHandler? = nil) {
self.delegate = delegate
self.twoFactorHandler = twoFactorHandler
}
// MARK: - Duping
// TODO: Use delegate
func search(forRadarWithId radarId: String, loading: @escaping (Bool) -> Void, success: @escaping (Radar) -> Void, failure: @escaping (String, String) -> Void) {
// Fetch existing radar
guard let url = URL(string: "https://openradar.appspot.com/api/radar?number=\(radarId)") else {
preconditionFailure()
}
loading(true)
Alamofire.request(url)
.validate()
.responseJSON { result in
loading(false)
if let error = result.error {
failure("Error", error.localizedDescription)
return
}
guard let json = result.value as? [String: Any], let result = json["result"] as? [String: Any], !result.isEmpty else {
failure("No OpenRadar found", "Couldn't find an OpenRadar with ID #\(radarId)")
return
}
guard let radar = try? Radar(openRadar: json) else {
failure("Invalid OpenRadar", "OpenRadar is missing required fields")
return
}
success(radar)
}
}
// MARK: - Filing
func file(radar: Radar) {
guard let (username, password) = Keychain.get(.radar) else {
preconditionFailure("Shouldn't be able to submit a radar without credentials")
}
delegate?.didStartLoading()
let handleTwoFactorAuth: (@escaping (String?) -> Void) -> Void = { [weak self] closure in
self?.twoFactorHandler?.askForCode(completion: closure)
}
var radar = radar
// Post to Apple Radar
let appleRadar = Sonar(service: .appleRadar(appleID: username, password: password))
appleRadar.loginThenCreate(radar: radar, getTwoFactorCode: handleTwoFactorAuth) { [weak self] result in
switch result {
case .success(let radarID):
// Don't post to OpenRadar if no token is present.
// TODO: Should we show a confirmation/login for OpenRadar?
guard let (_, token) = Keychain.get(.openRadar) else {
self?.delegate?.didPostToAppleRadar()
return
}
// Post to open radar
radar.ID = radarID
let openRadar = Sonar(service: .openRadar(token: token))
openRadar.loginThenCreate(radar: radar, getTwoFactorCode: handleTwoFactorAuth) { [weak self] result in
switch result {
case .success:
self?.delegate?.didPostToAppleRadar()
self?.delegate?.didPostToOpenRadar()
case .failure(let error):
self?.delegate?.didFail(with: error)
}
}
case .failure(let error):
self?.delegate?.didFail(with: error)
}
}
}
}