60 lines
1.5 KiB
Swift
60 lines
1.5 KiB
Swift
//
|
|
// AuthStore.swift
|
|
// Snail
|
|
//
|
|
|
|
import Foundation
|
|
import Observation
|
|
|
|
@Observable
|
|
final class AuthStore {
|
|
enum State: Equatable {
|
|
case loading
|
|
case signedOut
|
|
case signedIn(User)
|
|
}
|
|
|
|
private(set) var state: State
|
|
private let service: AuthService
|
|
|
|
init(service: AuthService = AuthService(), state: State = .loading) {
|
|
self.service = service
|
|
self.state = state
|
|
}
|
|
|
|
var currentUser: User? {
|
|
if case .signedIn(let user) = state { user } else { nil }
|
|
}
|
|
|
|
/// Проверяет сохранённую cookie сессии при запуске.
|
|
func restoreSession() async {
|
|
do {
|
|
state = try await service.currentUser().map(State.signedIn) ?? .signedOut
|
|
} catch {
|
|
state = .signedOut
|
|
}
|
|
}
|
|
|
|
func sendCode(to email: String) async throws {
|
|
try await service.sendSignInCode(to: email)
|
|
}
|
|
|
|
func signIn(email: String, code: String) async throws {
|
|
state = .signedIn(try await service.signIn(email: email, code: code))
|
|
}
|
|
|
|
/// Обновляет профиль; если сессия больше не действительна — разлогинивает.
|
|
func refreshUser() async {
|
|
do {
|
|
state = try await service.currentUser().map(State.signedIn) ?? .signedOut
|
|
} catch {
|
|
// Сетевая ошибка — оставляем текущие данные.
|
|
}
|
|
}
|
|
|
|
func signOut() async {
|
|
await service.signOut()
|
|
state = .signedOut
|
|
}
|
|
}
|