-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathViewController.swift
More file actions
151 lines (124 loc) · 5.16 KB
/
Copy pathViewController.swift
File metadata and controls
151 lines (124 loc) · 5.16 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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import UIKit
import PutioSDK
import AuthenticationServices
class ViewController: UIViewController {
var api: PutioSDK?
var session: ASWebAuthenticationSession?
var pendingOAuthState: String?
private let authCallbackScheme = "putioswift"
private let authCallbackHost = "auth"
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var startButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
@IBAction func startButtonTapped(_ sender: Any) {
guard let clientID = textField.text else { return }
createAPI(clientID: clientID)
}
func createAPI(clientID: String) {
api = PutioSDK(config: PutioSDKConfig(clientID: clientID))
startAuthFlow()
}
// https://developer.apple.com/documentation/authenticationservices/authenticating_a_user_through_a_web_service
func startAuthFlow() {
guard let api = api else { return }
let state: String
do {
state = try PutioSDK.generateOAuthState()
} catch {
return handleAuthCallbackFailure(error: error)
}
pendingOAuthState = state
let url = api.getAuthURL(redirectURI: "\(authCallbackScheme)://\(authCallbackHost)", state: state)
session = ASWebAuthenticationSession(url: url, callbackURLScheme: authCallbackScheme) { [weak self] callbackURL, error in
guard let self else { return }
self.session = nil
guard error == nil, let callbackURL = callbackURL else {
return self.handleAuthCallbackFailure(error: error ?? self.makeAuthError("Missing OAuth callback URL"))
}
// Callback URL: putioswift://auth#access_token={TOKEN}
return self.handleAuthCallbackSuccess(callbackURL: callbackURL)
}
session?.presentationContextProvider = self
session?.start()
}
func handleAuthCallbackFailure(error: Error) {
pendingOAuthState = nil
session = nil
let alertController = UIAlertController(title: "Auth Failure", message: error.localizedDescription, preferredStyle: .alert)
let closeButton = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(closeButton)
present(alertController, animated: true, completion: nil)
}
func handleAuthCallbackSuccess(callbackURL: URL) {
defer {
pendingOAuthState = nil
session = nil
}
guard let api else { return }
guard let pendingOAuthState else {
return handleAuthCallbackFailure(error: makeAuthError("Missing pending OAuth state"))
}
let token: String
do {
token = try api.accessToken(
fromOAuthCallback: callbackURL,
expectedScheme: authCallbackScheme,
expectedHost: authCallbackHost,
expectedState: pendingOAuthState
)
} catch {
return handleAuthCallbackFailure(error: error)
}
Task {
await fetchAccountInfo(token: token)
}
}
func makeAuthError(_ message: String) -> NSError {
NSError(domain: "PutioSDKExampleAuth", code: 0, userInfo: [NSLocalizedDescriptionKey: message])
}
@MainActor
func fetchAccountInfo(token: String) async {
api?.setToken(token: token)
guard let api else { return }
do {
let account = try await api.getAccountInfo()
fetchAccountInfoSuccess(account: account)
} catch {
fetchAccountInfoFailure(error: error)
}
}
func fetchAccountInfoFailure(error: Error) {
let alertController = UIAlertController(title: "API: Fetch Account Info Failure", message: error.localizedDescription, preferredStyle: .alert)
let closeButton = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(closeButton)
present(alertController, animated: true, completion: nil)
}
func fetchAccountInfoSuccess(account: PutioAccount) {
let alertController = UIAlertController(title: "API: Fetch Account Info Success", message: account.username, preferredStyle: .alert)
let closeButton = UIAlertAction(title: "OK", style: .cancel, handler: { _ in
guard let api = self.api else { return }
Task {
do {
let response = try await api.getFiles(parentID: 0)
print("Files result: \(response.children.count)")
} catch let error as PutioSDKError {
print("Files error: \(error.type)")
} catch {
print("Files error: \(error.localizedDescription)")
}
}
})
alertController.addAction(closeButton)
present(alertController, animated: true, completion: nil)
}
}
extension ViewController: ASWebAuthenticationPresentationContextProviding {
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
return view.window ?? ASPresentationAnchor()
}
}