Skip to content

Commit bb8866b

Browse files
chore: init auth provider as base class
1 parent d0e0b13 commit bb8866b

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,98 @@
11
// The Swift Programming Language
22
// https://docs.swift.org/swift-book
3+
import SwiftUI
4+
import FirebaseAuth
5+
import Combine
6+
7+
8+
protocol AuthListenerProtocol {
9+
func onError(_ error: Error)
10+
func onBeforeSignIn()
11+
func onSignedIn(_ user: User)
12+
func onCanceled()
13+
// TODO - add when I get to this point
14+
// func onCredentialReceived(_ credential: AuthCredential)
15+
// func onCredentialLinked(_ credential: AuthCredential)
16+
// func onMFARequired(_ resolver: MultiFactorResolver)
17+
}
18+
19+
protocol AuthProviderProtocol {
20+
associatedtype Listener: AuthListenerProtocol
21+
associatedtype Credential: AuthCredential
22+
23+
var auth: Auth { get }
24+
var authListener: Listener { get set }
25+
var providerId: String { get }
26+
27+
func signInWithCredential(_ credential: Credential)
28+
func linkWithCredential(_ credential: Credential)
29+
}
30+
31+
enum AuthAction {
32+
/// Performs user sign in
33+
case signIn
34+
35+
/// Creates a new account with for a provided credential
36+
case signUp
37+
38+
/// Links a provided credential with currently signed in user account
39+
case link
40+
41+
/// Disables automatic credential handling.
42+
/// It's up to the user to decide what to do with the obtained credential.
43+
case none
44+
}
45+
46+
class AuthProvider<Listener: AuthListenerProtocol, Credential: AuthCredential>: AuthProviderProtocol {
47+
var auth: Auth = Auth.auth()
48+
var authListener: Listener
49+
// add providerId to classes that extend this
50+
// var providerId: String = "default_provider_id"
51+
52+
init(listener: Listener) {
53+
self.authListener = listener
54+
}
55+
56+
func signInWithCredential(_ credential: Credential) {
57+
authListener.onBeforeSignIn()
58+
auth.signIn(with: credential) { [weak self] result, error in
59+
if let error = error {
60+
self?.authListener.onError(error)
61+
} else if let user = result?.user {
62+
self?.authListener.onSignedIn(user)
63+
}
64+
}
65+
}
66+
67+
func linkWithCredential(_ credential: Credential) {
68+
authListener.onCredentialReceived(credential)
69+
guard let user = auth.currentUser else { return }
70+
71+
user.link(with: credential) { [weak self] result, error in
72+
if let error = error {
73+
self?.authListener.onError(error)
74+
} else {
75+
self?.authListener.onCredentialLinked(credential)
76+
}
77+
}
78+
}
79+
80+
func onCredentialReceived(credential: AuthCredential, action: AuthAction) {
81+
switch action {
82+
case .link:
83+
linkWithCredential(credential: credential)
84+
case .signIn, .signUp:
85+
// Only email provider has a different action for sign in and sign up
86+
// and implements its own sign up logic.
87+
if shouldUpgradeAnonymous {
88+
linkWithCredential(credential: credential)
89+
} else {
90+
signInWithCredential(credential: credential)
91+
}
92+
case .none:
93+
authListener.onCredentialReceived(credential: credential)
94+
}
95+
}
96+
// TODO - fetchSignInMethodsForEmail/fetchProvidersForEmail is deprecated
97+
}
98+

0 commit comments

Comments
 (0)