-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAuthServiceImpl.swift
More file actions
141 lines (115 loc) · 3.81 KB
/
Copy pathAuthServiceImpl.swift
File metadata and controls
141 lines (115 loc) · 3.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//
// AuthServiceImpl.swift
// DevLogInfra
//
// Created by 최윤진 on 11/29/25.
//
import Combine
import FirebaseAuth
import FirebaseFirestore
import FirebaseMessaging
import DevLogCore
import DevLogData
final class AuthServiceImpl: AuthService {
private let store = Firestore.firestore()
private let messaging = Messaging.messaging()
private let logger = Logger(category: "AuthServiceImpl")
private let subject = CurrentValueSubject<Bool, Never>(Auth.auth().currentUser != nil)
private var handler: AuthStateDidChangeListenerHandle?
private var isCompletingSignIn = false
var uid: String? {
Auth.auth().currentUser?.uid
}
var providerIDs: [String] {
Auth.auth().currentUser?.providerData.map { $0.providerID } ?? []
}
var currentUserEmail: String? {
Auth.auth().currentUser?.email
}
var providerCount: Int {
Auth.auth().currentUser?.providerData.count ?? 0
}
init() {
handler = Auth.auth().addStateDidChangeListener { [weak self] _, user in
self?.handleAuthStateChange(user)
}
}
deinit {
guard let handler else { return }
Auth.auth().removeStateDidChangeListener(handler)
}
func observeSignedIn() -> AnyPublisher<Bool, Never> {
subject.eraseToAnyPublisher()
}
func beginSignIn() {
logger.info("Beginning sign-in bootstrap")
isCompletingSignIn = true
subject.send(false)
}
func completeSignIn() {
logger.info("Completing sign-in bootstrap")
isCompletingSignIn = false
subject.send(Auth.auth().currentUser != nil)
}
func cancelSignIn() {
logger.info("Cancelling sign-in bootstrap")
isCompletingSignIn = false
subject.send(Auth.auth().currentUser != nil)
}
func getProviderID() async throws -> String? {
logger.info("Fetching current provider ID")
guard let uid = uid else {
logger.warning("No user ID available")
return nil
}
do {
let document = try await store
.document(FirestorePath.userData(uid, document: .info))
.getDocument()
let providerID = document.data()?["currentProvider"] as? String
logger.info("Successfully fetched provider ID: \(providerID ?? "nil")")
return providerID
} catch {
logger.error("Failed to fetch provider ID", error: error)
throw error
}
}
func deleteCurrentUser() async throws {
logger.info("Deleting FirebaseAuth current user")
guard let currentUser = Auth.auth().currentUser else {
logger.warning("No current user to delete")
throw DataLayerError.notAuthenticated
}
do {
try await currentUser.delete()
} catch {
logger.error("Failed to delete FirebaseAuth current user", error: error)
throw error
}
}
func clearCurrentSession() async throws {
logger.info("Clearing current auth session")
do {
try await messaging.deleteToken()
} catch {
logger.error("Failed to delete FCM token while clearing session", error: error)
}
do {
try Auth.auth().signOut()
} catch {
logger.error("Failed to sign out while clearing session", error: error)
throw error
}
}
}
private extension AuthServiceImpl {
func handleAuthStateChange(_ user: User?) {
let signedIn = user != nil
logger.info("Firebase auth state changed. signedIn: \(signedIn)")
if signedIn && isCompletingSignIn {
logger.info("Delaying signed-in publication until user bootstrap finishes")
return
}
subject.send(signedIn)
}
}