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
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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|