[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.

145 lines
5.2 KiB

//
// AuthenticationManager.swift
// elpha-ios
//
// Created by Dwayne Harris on 8/25/18.
// Copyright © 2018 Elpha. All rights reserved.
//
import Alamofire
import CoreData
import UIKit
protocol AuthenticationDelegate: class {
func authenticationSuccess(_ sender: Any)
func authenticationFailure(_ sender: Any, error: Error?)
}
class AuthenticationManager {
static var authenticationState: String?
static var authenticationClient: ClientMO?
static weak var authenticationDelegate: AuthenticationDelegate?
static var sessions: [SessionMO] {
get {
do {
let request = NSFetchRequest<SessionMO>(entityName: "Session")
return try CoreDataManager.shared.context.fetch(request)
} catch {
print("Error fetching Sessions \(error)")
return []
}
}
}
static var session: SessionMO? {
get {
let request = NSFetchRequest<SessionMO>(entityName: "Session")
request.predicate = NSPredicate(format: "selected = YES")
do {
let results = try CoreDataManager.shared.context.fetch(request)
return results.first
} catch {
print("Error fetching Session \(error)")
return nil
}
}
}
static var token: String? {
get {
guard let account = session?.account, let client = session?.client else {
return nil
}
return KeychainWrapper.standard.string(forKey: "token:\(account.username!)@\(client.host!)")
}
}
static func saveSession(client: ClientMO, account: AccountMO, token: String) -> SessionMO? {
if let session = self.session {
session.selected = false
}
let session = SessionMO(context: CoreDataManager.shared.context)
session.client = client
session.account = account
session.order = 0
session.createdAt = Date()
session.selected = true
CoreDataManager.shared.saveContext()
KeychainWrapper.standard.set(token, forKey: "token:\(account.username!)@\(client.host!)")
return session
}
static func deleteSelectedSession() {
guard let session = self.session else {
return
}
KeychainWrapper.standard.removeObject(forKey: "token:\(session.account!.username!)@\(session.client!.host!)")
CoreDataManager.shared.context.delete(session)
}
static func handle(url: URL) {
guard let state = authenticationState, let client = authenticationClient else {
return
}
if let components = URLComponents(url: url, resolvingAgainstBaseURL: false), let queryItems = components.queryItems {
var code: String?
for item in queryItems {
switch item.name.lowercased() {
case "code":
code = item.value
case "state":
if item.value != state {
self.authenticationDelegate?.authenticationFailure(self, error: nil)
return
}
default:
continue
}
}
let parameters: Parameters = [
"client_id": client.clientID!,
"client_secret": client.clientSecret!,
"grant_type": "authorization_code",
"code": code!,
"redirect_uri": Config.clientRedirectURI,
]
Alamofire.request(
"https://\(client.host!)/oauth/token",
method: .post,
parameters: parameters,
encoding: URLEncoding.default
).validate().responseJSON { response in
switch response.result {
case .success(let data):
let serverURL = URL(string: "https://\(client.host!)")
if let json = data as? [String: Any], let token = json["access_token"] as? String {
MastodonAPI.currentUser(token: token, serverURL: serverURL!) { data, error in
guard let data = data, error == nil else {
AlertManager.shared.show(message: error!.localizedDescription, category: .error)
return
}
let account = MastodonDataManager.upsertAccount(data)
_ = AuthenticationManager.saveSession(client: client, account: account!, token: token)
self.authenticationDelegate?.authenticationSuccess(self)
}
}
case .failure(let error):
self.authenticationDelegate?.authenticationFailure(self, error: error)
}
}
}
}
}