NetNewsWire/Mac/Preferences/Accounts/AccountsFeedlyWebWindowCont...

120 lines
3.5 KiB
Swift

//
// AccountsFeedlyWebWindowController.swift
// NetNewsWire
//
// Created by Kiel Gillard on 30/8/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
import Cocoa
import Account
import WebKit
class AccountsFeedlyWebWindowController: NSWindowController, WKNavigationDelegate {
@IBOutlet private weak var webView: WKWebView!
private weak var hostWindow: NSWindow?
convenience init() {
self.init(windowNibName: NSNib.Name("AccountsFeedlyWeb"))
}
// MARK: API
func runSheetOnWindow(_ hostWindow: NSWindow, completionHandler handler: ((NSApplication.ModalResponse) -> Void)? = nil) {
self.hostWindow = hostWindow
hostWindow.beginSheet(window!, completionHandler: handler)
beginAuthorization()
}
// MARK: Requesting an Access Token
private let client = OAuthAuthorizationClient.feedlySandboxClient
private func beginAuthorization() {
let request = Account.oauthAuthorizationCodeGrantRequest(for: .feedly, client: client)
webView.load(request)
}
private func requestAccessToken(for response: OAuthAuthorizationResponse) {
Account.requestOAuthAccessToken(with: response, client: client, accountType: .feedly) { [weak self] result in
switch result {
case .success(let tokenResponse):
self?.saveAccount(for: tokenResponse)
case .failure(let error):
NSApplication.shared.presentError(error)
}
}
}
// MARK: Actions
@IBAction func cancel(_ sender: Any) {
hostWindow!.endSheet(window!, returnCode: NSApplication.ModalResponse.cancel)
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
do {
guard let url = navigationAction.request.url else { return }
let response = try OAuthAuthorizationResponse(url: url, client: client)
requestAccessToken(for: response)
// No point the web view trying to load this.
return decisionHandler(.cancel)
} catch let error as OAuthAuthorizationErrorResponse {
NSApplication.shared.presentError(error)
} catch {
print(error)
}
decisionHandler(.allow)
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
print(error)
}
private func saveAccount(for grant: OAuthAuthorizationGrant) {
// TODO: Find an already existing account for this username?
let account = AccountManager.shared.createAccount(type: .feedly)
do {
// Store the refresh token first because it sends this token to the account delegate.
if let token = grant.refreshToken {
try account.storeCredentials(token)
}
// Now store the access token because we want the account delegate to use it.
try account.storeCredentials(grant.accessToken)
self.hostWindow?.endSheet(self.window!, returnCode: NSApplication.ModalResponse.OK)
} catch {
NSApplication.shared.presentError(error)
}
}
}
private extension OAuthAuthorizationClient {
/// Models public sandbox API values found at:
/// https://groups.google.com/forum/#!topic/feedly-cloud/WwQWMgDmOuw
static var feedlySandboxClient: OAuthAuthorizationClient {
return OAuthAuthorizationClient(id: "sandbox",
redirectUri: "http://localhost",
state: nil,
secret: "ReVGXA6WekanCxbf")
}
/// Models private NetNewsWire client secrets.
/// https://developer.feedly.com/v3/auth/#authenticating-a-user-and-obtaining-an-auth-code
static var netNewsWireClient: OAuthAuthorizationClient {
fatalError("This app is not registered as a client with Feedly. Follow the URL in the code comments for this property.")
}
}