[ABANDONED] Mastodon iOS client.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
5.7 KiB

//
// AuthenticateViewController.swift
// elpha-ios
//
// Created by Dwayne Harris on 8/26/18.
// Copyright © 2018 Elpha. All rights reserved.
//
import Alamofire
import CoreData
import MastodonKit
import OAuthSwift
import UIKit
class AuthenticateViewController: UIViewController {
@IBOutlet var signInButton: UIButton!
@IBOutlet var instanceTextField: UITextField!
var oauthswift: OAuthSwift?
let defaultInstanceName = "mastodon.social"
override func viewDidLoad() {
super.viewDidLoad()
signInButton.layer.cornerRadius = 10
signInButton.clipsToBounds = true
randomInstanceName { instance in
self.instanceTextField.attributedPlaceholder = NSAttributedString(string: instance, attributes: [NSAttributedString.Key.foregroundColor: UIColor.init(red: 0.9, green: 0.9, blue: 0.9, alpha: 1)])
}
}
override open var shouldAutorotate: Bool {
return false
}
func randomInstanceName(completion: @escaping (String) -> Void) {
let requestURL = "\(Config.instancesServiceURL)\(Config.instancesServiceRandomEndpoint)?count=1"
let headers: HTTPHeaders = ["Authorization": "Bearer \(Config.instancesServiceSecret)"]
Alamofire.request(requestURL, headers: headers).validate().responseJSON { response in
switch response.result {
case .success(let value):
guard let result = value as? [String: Any],
let instances = result["instances"] as? [Any],
let instance = instances.first as? [String: Any],
let name = instance["name"] as? String else {
completion(self.defaultInstanceName)
return
}
completion(name)
case .failure(let error):
print("\(error)")
completion(self.defaultInstanceName)
}
}
}
func authorize(client: ClientMO) {
let oauthswift = OAuth2Swift(
consumerKey: client.clientID!,
consumerSecret: client.clientSecret!,
authorizeUrl: "https://\(client.url!)/oauth/authorize",
accessTokenUrl: "https://\(client.url!)/oauth/token",
responseType: "code"
)
oauthswift.authorizeURLHandler = OAuthSwiftOpenURLExternally.sharedInstance
self.oauthswift = oauthswift
let _ = oauthswift.authorize(
withCallbackURL: URL(string: "elpha://oauth")!,
scope: "read write follow",
state: NSUUID().uuidString,
success: { credential, _, _ in
let mkClient = Client(
baseURL: "https://\(client.url!)",
accessToken: credential.oauthToken
)
let request = Accounts.currentUser()
mkClient.run(request) { result in
switch result {
case .success(let account, _):
let account = MastodonDataManager.upsertAccount(account)
let _ = AuthenticationManager.shared.saveSession(client: client, account: account!, token: credential.oauthToken)
self.dismiss(animated: true)
case .failure(let error):
print("\(error)")
}
}
},
failure: { error in
print("\(error)")
}
)
}
@IBAction func signIn(_ sender: Any) {
guard var url = instanceTextField.text, !url.isEmpty else {
return
}
if url.contains("@") {
if let urlPart = url.split(separator: "@").last {
url = String(urlPart)
} else {
return
}
}
if url.starts(with: "http") {
let regex = try! NSRegularExpression(pattern: "https?://")
url = regex.stringByReplacingMatches(in: url, options: [], range: NSMakeRange(0, url.count), withTemplate: "")
}
signInButton.isEnabled = false
defer {
signInButton.isEnabled = true
}
let request = NSFetchRequest<ClientMO>(entityName: "Client")
request.predicate = NSPredicate(format: "url == %@", url)
do {
let response = try CoreDataManager.shared.context.fetch(request)
if let client = response.first {
self.authorize(client: client)
} else {
let client = Client(baseURL: "https://\(url)")
let request = Clients.register(
clientName: Config.clientDisplayName,
redirectURI: "elpha://oauth",
scopes: [.read, .write, .follow],
website: Config.clientWebsite
)
client.run(request) { result in
switch result {
case .success(let remoteClient, _):
let client = MastodonDataManager.saveClient(
id: remoteClient.id,
clientID: remoteClient.clientID,
clientSecret: remoteClient.clientSecret,
url: url
)
self.authorize(client: client)
case .failure(let error):
print("\(error)")
}
}
}
} catch {
print("\(error)")
}
}
}