138 lines
4.5 KiB
Swift
138 lines
4.5 KiB
Swift
import Foundation
|
|
import Combine
|
|
import SwiftUI
|
|
|
|
class AuthManager: ObservableObject {
|
|
@Published var isAuthenticated = false
|
|
@Published var currentUser: User?
|
|
@Published var isLoading = false
|
|
@Published var errorMessage: String?
|
|
@Published var authMode: AuthMode = .oauth
|
|
|
|
private var cancellables = Set<AnyCancellable>()
|
|
private let apiClient = APIClient.shared
|
|
private let oauthService = AtprotoOAuthService.shared
|
|
|
|
enum AuthMode {
|
|
case oauth
|
|
case legacy
|
|
}
|
|
|
|
init() {
|
|
// Monitor OAuth service
|
|
oauthService.$isAuthenticated
|
|
.receive(on: DispatchQueue.main)
|
|
.sink { [weak self] isAuth in
|
|
if isAuth, let session = self?.oauthService.session {
|
|
self?.isAuthenticated = true
|
|
self?.currentUser = User(did: session.did, handle: session.handle)
|
|
}
|
|
}
|
|
.store(in: &cancellables)
|
|
|
|
checkAuthStatus()
|
|
}
|
|
|
|
private func checkAuthStatus() {
|
|
isLoading = true
|
|
|
|
// Check OAuth session first
|
|
if oauthService.isAuthenticated, let session = oauthService.session {
|
|
isAuthenticated = true
|
|
currentUser = User(did: session.did, handle: session.handle)
|
|
isLoading = false
|
|
return
|
|
}
|
|
|
|
// Fallback to legacy auth
|
|
apiClient.verify()
|
|
.receive(on: DispatchQueue.main)
|
|
.sink(
|
|
receiveCompletion: { [weak self] completion in
|
|
self?.isLoading = false
|
|
if case .failure = completion {
|
|
self?.isAuthenticated = false
|
|
self?.currentUser = nil
|
|
}
|
|
},
|
|
receiveValue: { [weak self] user in
|
|
self?.isAuthenticated = true
|
|
self?.currentUser = user
|
|
}
|
|
)
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
func loginWithOAuth() {
|
|
isLoading = true
|
|
errorMessage = nil
|
|
|
|
oauthService.initiateOAuthFlow()
|
|
.receive(on: DispatchQueue.main)
|
|
.sink(
|
|
receiveCompletion: { [weak self] completion in
|
|
self?.isLoading = false
|
|
if case .failure(let error) = completion {
|
|
self?.errorMessage = error.localizedDescription
|
|
}
|
|
},
|
|
receiveValue: { [weak self] session in
|
|
self?.isAuthenticated = true
|
|
self?.currentUser = User(did: session.did, handle: session.handle)
|
|
}
|
|
)
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
func loginWithPassword(identifier: String, password: String) {
|
|
isLoading = true
|
|
errorMessage = nil
|
|
|
|
apiClient.login(identifier: identifier, password: password)
|
|
.receive(on: DispatchQueue.main)
|
|
.sink(
|
|
receiveCompletion: { [weak self] completion in
|
|
self?.isLoading = false
|
|
if case .failure(let error) = completion {
|
|
self?.errorMessage = self?.getErrorMessage(from: error)
|
|
}
|
|
},
|
|
receiveValue: { [weak self] response in
|
|
self?.isAuthenticated = true
|
|
self?.currentUser = User(did: response.did, handle: response.handle)
|
|
}
|
|
)
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
func logout() {
|
|
isLoading = true
|
|
|
|
// Logout from both services
|
|
oauthService.logout()
|
|
|
|
apiClient.logout()
|
|
.receive(on: DispatchQueue.main)
|
|
.sink(
|
|
receiveCompletion: { [weak self] _ in
|
|
self?.isLoading = false
|
|
self?.isAuthenticated = false
|
|
self?.currentUser = nil
|
|
UserDefaults.standard.removeObject(forKey: "authToken")
|
|
},
|
|
receiveValue: { _ in }
|
|
)
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
private func getErrorMessage(from error: APIError) -> String {
|
|
switch error {
|
|
case .unauthorized:
|
|
return "認証情報が正しくありません"
|
|
case .networkError:
|
|
return "ネットワークエラーが発生しました"
|
|
default:
|
|
return "エラーが発生しました"
|
|
}
|
|
}
|
|
} |