Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public protocol DeleteUserSwift {
@MainActor func deleteUser(user: User) async throws
}

public protocol PhoneAuthProviderAuthUIProtocol: AuthProviderSwift {
public protocol PhoneAuthProviderSwift: AuthProviderSwift {
@MainActor func verifyPhoneNumber(phoneNumber: String) async throws -> String
}

Expand Down Expand Up @@ -108,42 +108,6 @@ public final class AuthService {
public var currentMFARequired: MFARequired?
private var currentMFAResolver: MultiFactorResolver?

// MARK: - AuthPickerView Modal APIs

public var isShowingAuthModal = false

public enum AuthModalContentType {
case phoneAuth
}

public var currentModal: AuthModalContentType?

public var authModalViewBuilderRegistry: [AuthModalContentType: () -> AnyView] = [:]

public func registerModalView(for type: AuthModalContentType,
@ViewBuilder builder: @escaping () -> AnyView) {
authModalViewBuilderRegistry[type] = builder
}

public func viewForCurrentModal() -> AnyView? {
guard let type = currentModal,
let builder = authModalViewBuilderRegistry[type] else {
return nil
}
return builder()
}

public func presentModal(for type: AuthModalContentType) {
currentModal = type
isShowingAuthModal = true
}

public func dismissModal() {
isShowingAuthModal = false
}

// MARK: - End AuthPickerView Modal APIs

// MARK: - Provider APIs

private var listenerManager: AuthListenerManager?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@ public struct AuthPickerView {
.authenticationFlow == .signIn ? .signUp : .signIn
}

private var isAuthModalPresented: Binding<Bool> {
Binding(
get: { authService.isShowingAuthModal },
set: { authService.isShowingAuthModal = $0 }
)
}

@ViewBuilder
private var authPickerTitleView: some View {
if authService.authView == .authPicker {
Expand Down Expand Up @@ -103,33 +96,6 @@ extension AuthPickerView: View {
EmptyView()
}
}
}.sheet(isPresented: isAuthModalPresented) {
VStack(spacing: 0) {
HStack {
Button(action: {
authService.dismissModal()
}) {
HStack(spacing: 4) {
Image(systemName: "chevron.left")
.font(.system(size: 17, weight: .medium))
Text(authService.string.backButtonLabel)
.font(.system(size: 17))
}
.foregroundColor(.blue)
}
Spacer()
}
.padding()
.background(Color(.systemBackground))

Divider()

if let view = authService.viewForCurrentModal() {
view
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding()
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import FirebaseAuthSwiftUI
import Observation

protocol FacebookOperationReauthentication {
var facebookProvider: FacebookProviderAuthUI { get }
var facebookProvider: FacebookProviderSwift { get }
}

extension FacebookOperationReauthentication {
Expand All @@ -47,8 +47,8 @@ extension FacebookOperationReauthentication {
@MainActor
class FacebookDeleteUserOperation: AuthenticatedOperation,
@preconcurrency FacebookOperationReauthentication {
let facebookProvider: FacebookProviderAuthUI
init(facebookProvider: FacebookProviderAuthUI) {
let facebookProvider: FacebookProviderSwift
init(facebookProvider: FacebookProviderSwift) {
self.facebookProvider = facebookProvider
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import FirebaseAuthSwiftUI

public extension AuthService {
@discardableResult
func withFacebookSignIn(scopes scopes: [String]? = nil) -> AuthService {
FacebookProviderAuthUI.configureProvider(scopes: scopes)
registerProvider(providerWithButton: FacebookProviderAuthUI.shared)
func withFacebookSignIn(_ provider: FacebookProviderSwift? = nil) -> AuthService {
registerProvider(providerWithButton: FacebookProviderAuthUI(provider: provider ??
FacebookProviderSwift()))
return self
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ import FirebaseAuth
import FirebaseAuthSwiftUI
import SwiftUI

let kFacebookEmailScope = "email"
let kFacebookProfileScope = "public_profile"
let kDefaultFacebookScopes = [kFacebookEmailScope, kFacebookProfileScope]

public enum FacebookProviderError: Error {
case signInCancelled(String)
case configurationInvalid(String)
Expand All @@ -31,44 +27,20 @@ public enum FacebookProviderError: Error {
case authenticationToken(String)
}

public class FacebookProviderAuthUI: AuthProviderSwift, AuthProviderUI, DeleteUserSwift {
public let id: String = "facebook"
public class FacebookProviderSwift: AuthProviderSwift, DeleteUserSwift {
let scopes: [String]
let shortName = "Facebook"
let providerId = "facebook.com"
private let loginManager = LoginManager()
private var rawNonce: String?
private var shaNonce: String?
// Needed for reauthentication
var isLimitedLogin: Bool = true

public var provider: AuthProviderSwift { self }

@MainActor private static var _shared: FacebookProviderAuthUI = FacebookProviderAuthUI(scopes: kDefaultFacebookScopes)

@MainActor public static var shared: FacebookProviderAuthUI {
return _shared
}

@MainActor public static func configureProvider(scopes: [String]? = nil, isLimitedLogin: Bool = true) {
_shared = FacebookProviderAuthUI(scopes: scopes, isLimitedLogin: isLimitedLogin)
}

public init(scopes: [String]? = nil, isLimitedLogin: Bool = true) {
self.scopes = scopes ?? kDefaultFacebookScopes
public init(scopes: [String] = ["email", "public_profile"], isLimitedLogin: Bool = true) {
self.scopes = scopes
self.isLimitedLogin = isLimitedLogin
}

@MainActor public func authButton() -> AnyView {
AnyView(SignInWithFacebookButton())
}

public func deleteUser(user: User) async throws {
let operation = FacebookDeleteUserOperation(facebookProvider: self)
try await operation(on: user)
}


@MainActor public func createAuthCredential() async throws -> AuthCredential {
let loginType: LoginTracking = isLimitedLogin ? .limited : .enabled

Expand Down Expand Up @@ -149,4 +121,22 @@ public class FacebookProviderAuthUI: AuthProviderSwift, AuthProviderUI, DeleteUs
)
}
}

public func deleteUser(user: User) async throws {
let operation = FacebookDeleteUserOperation(facebookProvider: self)
try await operation(on: user)
}
}

public class FacebookProviderAuthUI: AuthProviderUI {
public var provider: AuthProviderSwift
public let id: String = "facebook.com"

public init(provider: AuthProviderSwift) {
self.provider = provider
}

@MainActor public func authButton() -> AnyView {
AnyView(SignInWithFacebookButton(facebookProvider: provider))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ import SwiftUI
@MainActor
public struct SignInWithFacebookButton {
@Environment(AuthService.self) private var authService
let facebookProvider: AuthProviderSwift
@State private var errorMessage = ""
@State private var showCanceledAlert = false
@State private var limitedLogin = true
@State private var showUserTrackingAlert = false
@State private var trackingAuthorizationStatus: ATTrackingManager
.AuthorizationStatus = .notDetermined

public init() {
public init(facebookProvider: AuthProviderSwift) {
self.facebookProvider = facebookProvider
_trackingAuthorizationStatus = State(initialValue: ATTrackingManager
.trackingAuthorizationStatus)
}
Expand Down Expand Up @@ -65,7 +67,6 @@ extension SignInWithFacebookButton: View {
Button(action: {
Task {
do {
let facebookProvider = FacebookProviderAuthUI(isLimitedLogin: limitedLogin)
try await authService.signIn(facebookProvider)
} catch {
switch error {
Expand Down Expand Up @@ -128,6 +129,7 @@ extension SignInWithFacebookButton: View {

#Preview {
FirebaseOptions.dummyConfigurationForPreview()
return SignInWithFacebookButton()
let facebookProvider = FacebookProviderSwift()
return SignInWithFacebookButton(facebookProvider: facebookProvider)
.environment(AuthService())
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import FirebaseAuthSwiftUI
import Observation

protocol GoogleOperationReauthentication {
var googleProvider: GoogleProviderAuthUI { get }
var googleProvider: GoogleProviderSwift { get }
}

extension GoogleOperationReauthentication {
Expand All @@ -54,8 +54,8 @@ extension GoogleOperationReauthentication {
@MainActor
class GoogleDeleteUserOperation: AuthenticatedOperation,
@preconcurrency GoogleOperationReauthentication {
let googleProvider: GoogleProviderAuthUI
init(googleProvider: GoogleProviderAuthUI) {
let googleProvider: GoogleProviderSwift
init(googleProvider: GoogleProviderSwift) {
self.googleProvider = googleProvider
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import FirebaseAuthSwiftUI

public extension AuthService {
@discardableResult
func withGoogleSignIn(scopes scopes: [String]? = nil) -> AuthService {
let clientID = auth.app?.options.clientID ?? ""
registerProvider(providerWithButton: GoogleProviderAuthUI(scopes: scopes, clientID: clientID))
func withGoogleSignIn(_ provider: GoogleProviderSwift? = nil) -> AuthService {
registerProvider(providerWithButton: GoogleProviderAuthUI(provider: provider ??
GoogleProviderSwift(clientID: auth.app?.options.clientID ?? "")))
return self
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,24 @@ import GoogleSignIn
import GoogleSignInSwift
import SwiftUI

let kGoogleUserInfoEmailScope = "https://www.googleapis.com/auth/userinfo.email"
let kGoogleUserInfoProfileScope = "https://www.googleapis.com/auth/userinfo.profile"
let kDefaultScopes = [kGoogleUserInfoEmailScope, kGoogleUserInfoProfileScope]

public enum GoogleProviderError: Error {
case rootViewControllerNotFound(String)
case authenticationToken(String)
case user(String)
}

public class GoogleProviderAuthUI: AuthProviderSwift, AuthProviderUI, DeleteUserSwift {
public let id: String = "google"
public class GoogleProviderSwift: AuthProviderSwift, DeleteUserSwift {
let scopes: [String]
let shortName = "Google"
let clientID: String
let providerId = "google.com"
public let clientID: String

public var provider: AuthProviderSwift { self }

public init(scopes: [String]? = nil, clientID: String = FirebaseApp.app()!.options.clientID!) {
self.scopes = scopes ?? kDefaultScopes
self.clientID = clientID
}

@MainActor public func authButton() -> AnyView {
AnyView(SignInWithGoogleButton())
}

public func deleteUser(user: User) async throws {
let operation = GoogleDeleteUserOperation(googleProvider: self)
try await operation(on: user)
public init(scopes: [String] = [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
],
clientID: String) {
self.clientID = clientID
self.scopes = scopes
}

@MainActor public func createAuthCredential() async throws -> AuthCredential {
Expand All @@ -61,7 +48,7 @@ public class GoogleProviderAuthUI: AuthProviderSwift, AuthProviderUI, DeleteUser
)
}

let config = GIDConfiguration(clientID: self.clientID)
let config = GIDConfiguration(clientID: clientID)
GIDSignIn.sharedInstance.configuration = config

return try await withCheckedThrowingContinuation { continuation in
Expand All @@ -86,4 +73,22 @@ public class GoogleProviderAuthUI: AuthProviderSwift, AuthProviderUI, DeleteUser
}
}
}

public func deleteUser(user: User) async throws {
let operation = GoogleDeleteUserOperation(googleProvider: self)
try await operation(on: user)
}
}

public class GoogleProviderAuthUI: AuthProviderUI {
public var provider: AuthProviderSwift
public let id: String = "google.com"

public init(provider: AuthProviderSwift) {
self.provider = provider
}

@MainActor public func authButton() -> AnyView {
AnyView(SignInWithGoogleButton(googleProvider: provider))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ import SwiftUI
@MainActor
public struct SignInWithGoogleButton {
@Environment(AuthService.self) private var authService
private let googleProvider = GoogleProviderAuthUI()
let googleProvider: AuthProviderSwift

public init(googleProvider: AuthProviderSwift) {
self.googleProvider = googleProvider
}

let customViewModel = GoogleSignInButtonViewModel(
scheme: .light,
Expand All @@ -48,6 +52,7 @@ extension SignInWithGoogleButton: View {

#Preview {
FirebaseOptions.dummyConfigurationForPreview()
return SignInWithGoogleButton()
let googleProvider = GoogleProviderSwift(clientID: "")
return SignInWithGoogleButton(googleProvider: googleProvider)
.environment(AuthService())
}
Loading
Loading