diff --git a/Podfile b/Podfile index 7cd4398..8b80dca 100644 --- a/Podfile +++ b/Podfile @@ -6,6 +6,7 @@ target 'RxFirebase_Example' do pod 'RxFirebase/RemoteConfig', :path => './' pod 'RxFirebase/Database', :path => './' pod 'RxFirebase/Storage', :path => './' + pod 'RxFirebase/Auth', :path => './' target 'RxFirebase_Tests' do inherit! :search_paths diff --git a/Podfile.lock b/Podfile.lock index 03ee150..9482dab 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,97 +1,140 @@ PODS: - - BoringSSL (10.0.2): - - BoringSSL/Implementation (= 10.0.2) - - BoringSSL/Interface (= 10.0.2) - - BoringSSL/Implementation (10.0.2): - - BoringSSL/Interface (= 10.0.2) - - BoringSSL/Interface (10.0.2) + - BoringSSL (10.0.6): + - BoringSSL/Implementation (= 10.0.6) + - BoringSSL/Interface (= 10.0.6) + - BoringSSL/Implementation (10.0.6): + - BoringSSL/Interface (= 10.0.6) + - BoringSSL/Interface (10.0.6) - FirebaseABTesting (2.0.0): - FirebaseCore (~> 5.0) - Protobuf (~> 3.5) - - FirebaseAnalytics (5.0.0): - - FirebaseCore (~> 5.0) - - FirebaseInstanceID (~> 3.0) - - "GoogleToolboxForMac/NSData+zlib (~> 2.1)" + - FirebaseAnalytics (5.1.1): + - FirebaseCore (~> 5.1) + - FirebaseInstanceID (~> 3.2) + - GoogleAppMeasurement (~> 5.1) + - GoogleUtilities/AppDelegateSwizzler (~> 5.2.0) + - GoogleUtilities/MethodSwizzler (~> 5.2.0) + - GoogleUtilities/Network (~> 5.2) + - "GoogleUtilities/NSData+zlib (~> 5.2)" - nanopb (~> 0.3) - - FirebaseCore (5.0.1): - - "GoogleToolboxForMac/NSData+zlib (~> 2.1)" - - FirebaseDatabase (5.0.0): + - FirebaseAuth (5.0.3): + - FirebaseAuthInterop (~> 1.0) + - FirebaseCore (~> 5.0) + - GoogleUtilities/Environment (~> 5.2) + - GTMSessionFetcher/Core (~> 1.1) + - FirebaseAuthInterop (1.0.0) + - FirebaseCore (5.1.2): + - GoogleUtilities/Logger (~> 5.2) + - FirebaseDatabase (5.0.2): - FirebaseCore (~> 5.0) - leveldb-library (~> 1.18) - - FirebaseFirestore (0.12.1): + - FirebaseFirestore (0.13.2): + - FirebaseAuthInterop (~> 1.0) - FirebaseCore (~> 5.0) - - FirebaseFirestore/abseil-cpp (= 0.12.1) + - FirebaseFirestore/abseil-cpp (= 0.13.2) - gRPC-ProtoRPC (~> 1.0) - leveldb-library (~> 1.18) + - nanopb (~> 0.3.8) - Protobuf (~> 3.1) - - FirebaseFirestore/abseil-cpp (0.12.1): + - FirebaseFirestore/abseil-cpp (0.13.2): + - FirebaseAuthInterop (~> 1.0) - FirebaseCore (~> 5.0) - gRPC-ProtoRPC (~> 1.0) - leveldb-library (~> 1.18) + - nanopb (~> 0.3.8) - Protobuf (~> 3.1) - - FirebaseInstanceID (3.0.0): - - FirebaseCore (~> 5.0) - - FirebaseRemoteConfig (3.0.0): + - FirebaseInstanceID (3.2.1): + - FirebaseCore (~> 5.1) + - GoogleUtilities/Environment (~> 5.2) + - FirebaseRemoteConfig (3.0.1): - FirebaseABTesting (~> 2.0) - - FirebaseAnalytics (~> 5.0) - - FirebaseCore (~> 5.0) - - FirebaseInstanceID (~> 3.0) - - "GoogleToolboxForMac/NSData+zlib (~> 2.1)" + - FirebaseAnalytics (~> 5.1) + - FirebaseCore (~> 5.1) + - FirebaseInstanceID (~> 3.2) + - GoogleUtilities/Environment (~> 5.2) + - "GoogleUtilities/NSData+zlib (~> 5.2)" - Protobuf (~> 3.5) - - FirebaseStorage (3.0.0): + - FirebaseStorage (3.0.1): - FirebaseCore (~> 5.0) - GTMSessionFetcher/Core (~> 1.1) - - GoogleToolboxForMac/Defines (2.1.4) - - "GoogleToolboxForMac/NSData+zlib (2.1.4)": - - GoogleToolboxForMac/Defines (= 2.1.4) - - gRPC (1.11.0): - - gRPC-RxLibrary (= 1.11.0) - - gRPC/Main (= 1.11.0) - - gRPC-Core (1.11.0): - - gRPC-Core/Implementation (= 1.11.0) - - gRPC-Core/Interface (= 1.11.0) - - gRPC-Core/Implementation (1.11.0): + - GoogleAppMeasurement (5.1.1): + - GoogleUtilities/AppDelegateSwizzler (~> 5.2.0) + - GoogleUtilities/MethodSwizzler (~> 5.2.0) + - GoogleUtilities/Network (~> 5.2) + - "GoogleUtilities/NSData+zlib (~> 5.2)" + - nanopb (~> 0.3) + - GoogleUtilities/AppDelegateSwizzler (5.2.2): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (5.2.2) + - GoogleUtilities/Logger (5.2.2): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (5.2.2): + - GoogleUtilities/Logger + - GoogleUtilities/Network (5.2.2): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (5.2.2)" + - GoogleUtilities/Reachability (5.2.2): + - GoogleUtilities/Logger + - gRPC (1.14.1): + - gRPC-RxLibrary (= 1.14.1) + - gRPC/Main (= 1.14.1) + - gRPC-Core (1.14.1): + - gRPC-Core/Implementation (= 1.14.1) + - gRPC-Core/Interface (= 1.14.1) + - gRPC-Core/Implementation (1.14.1): - BoringSSL (~> 10.0) - - gRPC-Core/Interface (= 1.11.0) + - gRPC-Core/Interface (= 1.14.1) - nanopb (~> 0.3) - - gRPC-Core/Interface (1.11.0) - - gRPC-ProtoRPC (1.11.0): - - gRPC (= 1.11.0) - - gRPC-RxLibrary (= 1.11.0) + - gRPC-Core/Interface (1.14.1) + - gRPC-ProtoRPC (1.14.1): + - gRPC-ProtoRPC/Main (= 1.14.1) + - gRPC-ProtoRPC/Main (1.14.1): + - gRPC (= 1.14.1) + - gRPC-RxLibrary (= 1.14.1) - Protobuf (~> 3.0) - - gRPC-RxLibrary (1.11.0) - - gRPC/Main (1.11.0): - - gRPC-Core (= 1.11.0) - - gRPC-RxLibrary (= 1.11.0) - - GTMSessionFetcher/Core (1.1.15) + - gRPC-RxLibrary (1.14.1) + - gRPC/Main (1.14.1): + - gRPC-Core (= 1.14.1) + - gRPC-RxLibrary (= 1.14.1) + - GTMSessionFetcher/Core (1.2.0) - leveldb-library (1.20) - nanopb (0.3.8): - nanopb/decode (= 0.3.8) - nanopb/encode (= 0.3.8) - nanopb/decode (0.3.8) - nanopb/encode (0.3.8) - - Protobuf (3.5.0) - - RxCocoa (4.1.2): + - Protobuf (3.6.1) + - RxCocoa (4.2.0): - RxSwift (~> 4.0) - - RxFirebase/Database (0.2.1): + - RxFirebase/Auth (0.2.2): + - FirebaseAuth (~> 5) + - FirebaseCore (~> 5.1) + - RxCocoa (~> 4) + - RxSwift (~> 4) + - RxFirebase/Database (0.2.2): - FirebaseDatabase (~> 5) - RxCocoa (~> 4) - RxSwift (~> 4) - - RxFirebase/Firestore (0.2.1): + - RxFirebase/Firestore (0.2.2): - FirebaseFirestore (~> 0.12) - RxCocoa (~> 4) - RxSwift (~> 4) - - RxFirebase/RemoteConfig (0.2.1): + - RxFirebase/RemoteConfig (0.2.2): - FirebaseRemoteConfig (~> 3) - RxCocoa (~> 4) - RxSwift (~> 4) - - RxFirebase/Storage (0.2.1): + - RxFirebase/Storage (0.2.2): - FirebaseStorage (~> 3) - RxCocoa (~> 4) - RxSwift (~> 4) - - RxSwift (4.1.2) + - RxSwift (4.2.0) DEPENDENCIES: + - RxFirebase/Auth (from `./`) - RxFirebase/Database (from `./`) - RxFirebase/Firestore (from `./`) - RxFirebase/RemoteConfig (from `./`) @@ -102,13 +145,16 @@ SPEC REPOS: - BoringSSL - FirebaseABTesting - FirebaseAnalytics + - FirebaseAuth + - FirebaseAuthInterop - FirebaseCore - FirebaseDatabase - FirebaseFirestore - FirebaseInstanceID - FirebaseRemoteConfig - FirebaseStorage - - GoogleToolboxForMac + - GoogleAppMeasurement + - GoogleUtilities - gRPC - gRPC-Core - gRPC-ProtoRPC @@ -125,28 +171,31 @@ EXTERNAL SOURCES: :path: "./" SPEC CHECKSUMS: - BoringSSL: 60dd24df4af296bf41d78e5841dbb95d75f88c0d + BoringSSL: e10f92a27043805c01071fe815a5cd98ae8212e7 FirebaseABTesting: 1f50b8d50f5e3469eea54e7463a7b7fe221d1f5e - FirebaseAnalytics: 19812b49fa5f283dd6b23edf8a14b5d477029ab8 - FirebaseCore: cafc814b2d84fc8733f09e653041cc2165332ad7 - FirebaseDatabase: 697eb53e5b4fe7cd4fa8756c1f82a9fca011345f - FirebaseFirestore: f686b8e83f3cf8bbc37db6e98e01029a14f01f55 - FirebaseInstanceID: 83e0040351565df711a5db3d8ebe5ea21aca998a - FirebaseRemoteConfig: 3c57e4644bd6976b671ae0b725cd709f198bd1f5 - FirebaseStorage: 7ca4bb7b58a25fa647b04f524033fc7cb7eb272b - GoogleToolboxForMac: 91c824d21e85b31c2aae9bb011c5027c9b4e738f - gRPC: 70703dc9ba31c72341fc7f37745cc1c379edee96 - gRPC-Core: 164639cd8ae18ca8b65477fafb2efbaecf4f181a - gRPC-ProtoRPC: bb5fddf3424aa4fad74d76736578a79fe40e244e - gRPC-RxLibrary: 26d53d1b1f306befd4ad4e15bd6de27839a82481 - GTMSessionFetcher: 5fa5b80fd20e439ef5f545fb2cb3ca6c6714caa2 + FirebaseAnalytics: 993577e91157feb40945abedd6ab346d8a4b6ac8 + FirebaseAuth: 657a25e4be044d2d333663ebf515a861c5a59cd7 + FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc + FirebaseCore: 3a97432acb324b439fbed338e642f9cbb516a63d + FirebaseDatabase: 27be5ac5bc75e0b17537b2bbfada8258addcc8cd + FirebaseFirestore: 7eec93809ad61e7ebe303089c5cc5efa63424b72 + FirebaseInstanceID: ea5af6920d0a4a29b40459d055bebe4a6c1333c4 + FirebaseRemoteConfig: 7b6d675dfb11f0e0e638caee00908b06af150d56 + FirebaseStorage: 43f823b96b72a08539eba21a7de043348a69d4c6 + GoogleAppMeasurement: f7507b39b70ad0bd80b3d81518b2f43868974307 + GoogleUtilities: 06b66f9567769a7958db20a92f0128b2843e49d5 + gRPC: 65fa2a50c4fd61940b76f4962d75c239c92c6a8d + gRPC-Core: e3ace1e1161e75903135de8d8231bb69c9d35721 + gRPC-ProtoRPC: 78f976fc6a1eafc0e1f4965c255c313aa0859b1e + gRPC-RxLibrary: c4c826507ad3c8c8fab6887f153938eb04b86d59 + GTMSessionFetcher: 0c4baf0a73acd0041bf9f71ea018deedab5ea84e leveldb-library: 08cba283675b7ed2d99629a4bc5fd052cd2bb6a5 nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3 - Protobuf: 8a9838fba8dae3389230e1b7f8c104aa32389c03 - RxCocoa: d88ba0f1f6abf040011a9eb4b539324fc426843a - RxFirebase: 25a2fd31fe5795d90338fba7beb9b415209a215e - RxSwift: e49536837d9901277638493ea537394d4b55f570 + Protobuf: 1eb9700044745f00181c136ef21b8ff3ad5a0fd5 + RxCocoa: 0b54909c902e1e581212a03e690bbd94032d8baa + RxFirebase: 8fa5c30d4ad3645f3be7cc0e780a0dc6083430ad + RxSwift: 99e10317ddfcc7fbe01356aafd118fde4a0be104 -PODFILE CHECKSUM: 973a2757330c974ebe33f0c1e979ded68c8ec05a +PODFILE CHECKSUM: 65fe2926d5235467f5da97e2c5e400ae4db298cf COCOAPODS: 1.5.3 diff --git a/README.md b/README.md index 204f5a8..d804108 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ pod 'RxFirebase/Firestore' pod 'RxFirebase/RemoteConfig' pod 'RxFirebase/Database' pod 'RxFirebase/Storage' +pod 'RxFirebase/Auth' ``` ## Usage @@ -33,6 +34,7 @@ import RxFirebase - [Firestore](#firestore) - [RemoteConfig](#remoteconfig) - [Storage](#storage) +- [Auth](#auth) ### Database @@ -434,6 +436,8 @@ reference.delete() }).disposed(by: disposeBag) ``` +### Auth + ## License This library belongs to _RxSwiftCommunity_. diff --git a/RxFirebase.podspec b/RxFirebase.podspec index 9e836b9..517b59e 100644 --- a/RxFirebase.podspec +++ b/RxFirebase.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'RxFirebase' - s.version = '0.2.2' + s.version = '0.2.3' s.summary = 'RxSwift extensions for Firebase.' # This description is used to generate tags and improve search results. @@ -52,4 +52,9 @@ Pod::Spec.new do |s| storage.source_files = 'Sources/Storage/**/*' storage.dependency 'FirebaseStorage', '~> 3' end + s.subspec 'Auth' do |auth| + auth.source_files = 'Sources/Auth/**/*' + auth.dependency 'FirebaseAuth', '~> 5' + auth.dependency 'FirebaseCore', '~> 5.1' + end end diff --git a/RxFirebase.xcodeproj/project.pbxproj b/RxFirebase.xcodeproj/project.pbxproj index 6a6454b..b1eaecb 100644 --- a/RxFirebase.xcodeproj/project.pbxproj +++ b/RxFirebase.xcodeproj/project.pbxproj @@ -306,7 +306,7 @@ "${SRCROOT}/Pods/Target Support Files/Pods-RxFirebase_Example/Pods-RxFirebase_Example-frameworks.sh", "${BUILT_PRODUCTS_DIR}/BoringSSL/openssl.framework", "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework", - "${BUILT_PRODUCTS_DIR}/GoogleToolboxForMac/GoogleToolboxForMac.framework", + "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework", "${BUILT_PRODUCTS_DIR}/RxCocoa/RxCocoa.framework", "${BUILT_PRODUCTS_DIR}/RxSwift/RxSwift.framework", @@ -321,7 +321,7 @@ outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/openssl.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleToolboxForMac.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Protobuf.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwift.framework", diff --git a/Sources/Auth/FIRAuth+Rx.swift b/Sources/Auth/FIRAuth+Rx.swift new file mode 100644 index 0000000..67e58e5 --- /dev/null +++ b/Sources/Auth/FIRAuth+Rx.swift @@ -0,0 +1,564 @@ +// +// FIRAuth+Rx.swift +// RxFirebase +// +// Created by Arnaud Dorgans on 29/08/2018. +// + +import RxSwift +import FirebaseAuth + +extension Reactive where Base: Auth { + + /** + @brief Sets the currentUser on the calling Auth instance to the provided user object. + @param user The user object to be set as the current user of the calling Auth instance. + @param completion Optionally; a block invoked after the user of the calling Auth instance has + been updated or an error was encountered. + */ + public func updateCurrentUser(_ user: User) -> Observable { + return Observable.create { observer in + self.base.updateCurrentUser(user) { error in + guard let error = error else { + observer.onNext(()) + observer.onCompleted() + return + } + observer.onError(error) + } + return Disposables.create() + } + } + + /** + @brief Fetches the list of IdPs that can be used for signing in with the provided email address. + Useful for an "identifier-first" sign-in flow. + + @param email The email address for which to obtain a list of identity providers. + @param completion Optionally; a block which is invoked when the list of providers for the + specified email address is ready or an error was encountered. Invoked asynchronously on the + main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ + public func fetchProviders(forEmail email: String) -> Observable<[String]> { + return Observable.create { observer in + self.base.fetchProviders(forEmail: email) { providers, error in + guard let error = error else { + observer.onNext(providers ?? []) + observer.onCompleted() + return + } + observer.onError(error) + } + return Disposables.create() + } + } + + /** + @brief Fetches the list of all sign-in methods previously used for the provided email address. + + @param email The email address for which to obtain a list of sign-in methods. + @param completion Optionally; a block which is invoked when the list of sign in methods for the + specified email address is ready or an error was encountered. Invoked asynchronously on the + main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed. + + @remarks See @c FIRAuthErrors for a list of error codes that are common to all API methods. + */ + public func fetchSignInMethods(forEmail email: String) -> Observable<[String]> { + return Observable.create { observer in + self.base.fetchSignInMethods(forEmail: email) { methods, error in + guard let error = error else { + observer.onNext(methods ?? []) + observer.onCompleted() + return + } + observer.onError(error) + } + return Disposables.create() + } + } + + /** + @brief Signs in using an email address and password. + + @param email The user's email address. + @param password The user's password. + @param completion Optionally; a block which is invoked when the sign in flow finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that email and password + accounts are not enabled. Enable them in the Auth section of the + Firebase console. + + `FIRAuthErrorCodeUserDisabled` - Indicates the user's account is disabled. + + `FIRAuthErrorCodeWrongPassword` - Indicates the user attempted + sign in with an incorrect password. + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed. + + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ + public func signIn(withEmail email: String, password: String) -> Observable { + return Observable.create { observer in + self.base.signIn(withEmail: email, password: password) { auth, error in + if let error = error { + observer.onError(error) + } else if let auth = auth { + observer.onNext(auth) + observer.onCompleted() + } + } + return Disposables.create() + } + } + + /** + @brief Signs in using an email address and email sign-in link. + + @param email The user's email address. + @param link The email sign-in link. + @param completion Optionally; a block which is invoked when the sign in flow finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that email and email sign-in link + accounts are not enabled. Enable them in the Auth section of the + Firebase console. + + `FIRAuthErrorCodeUserDisabled` - Indicates the user's account is disabled. + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is invalid. + + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ + public func signIn(withEmail email: String, link: String) -> Observable { + return Observable.create { observer in + self.base.signIn(withEmail: email, link: link) { auth, error in + if let error = error { + observer.onError(error) + } else if let auth = auth { + observer.onNext(auth) + observer.onCompleted() + } + } + return Disposables.create() + } + } + + /** + @brief Asynchronously signs in to Firebase with the given 3rd-party credentials (e.g. a Facebook + login Access Token, a Google ID Token/Access Token pair, etc.) and returns additional + identity provider data. + + @param credential The credential supplied by the IdP. + @param completion Optionally; a block which is invoked when the sign in flow finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidCredential` - Indicates the supplied credential is invalid. + This could happen if it has expired or it is malformed. + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that accounts + with the identity provider represented by the credential are not enabled. + Enable them in the Auth section of the Firebase console. + + `FIRAuthErrorCodeAccountExistsWithDifferentCredential` - Indicates the email asserted + by the credential (e.g. the email in a Facebook access token) is already in use by an + existing account, that cannot be authenticated with this sign-in method. Call + fetchProvidersForEmail for this user’s email and then prompt them to sign in with any of + the sign-in providers returned. This error will only be thrown if the "One account per + email address" setting is enabled in the Firebase console, under Auth settings. + + `FIRAuthErrorCodeUserDisabled` - Indicates the user's account is disabled. + + `FIRAuthErrorCodeWrongPassword` - Indicates the user attempted sign in with an + incorrect password, if credential is of the type EmailPasswordAuthCredential. + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed. + + `FIRAuthErrorCodeMissingVerificationID` - Indicates that the phone auth credential was + created with an empty verification ID. + + `FIRAuthErrorCodeMissingVerificationCode` - Indicates that the phone auth credential + was created with an empty verification code. + + `FIRAuthErrorCodeInvalidVerificationCode` - Indicates that the phone auth credential + was created with an invalid verification Code. + + `FIRAuthErrorCodeInvalidVerificationID` - Indicates that the phone auth credential was + created with an invalid verification ID. + + `FIRAuthErrorCodeSessionExpired` - Indicates that the SMS code has expired. + + + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods + */ + public func signInAndRetrieveData(with credential: AuthCredential) -> Observable { + return Observable.create { observer in + self.base.signInAndRetrieveData(with: credential) { auth, error in + if let error = error { + observer.onError(error) + } else if let auth = auth { + observer.onNext(auth) + observer.onCompleted() + } + } + return Disposables.create() + } + } + + /** + @brief Asynchronously creates and becomes an anonymous user. + @param completion Optionally; a block which is invoked when the sign in finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks If there is already an anonymous user signed in, that user will be returned instead. + If there is any other existing user signed in, that user will be signed out. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that anonymous accounts are + not enabled. Enable them in the Auth section of the Firebase console. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ + public func signInAnonymously() -> Observable { + return Observable.create { observer in + self.base.signInAnonymously { auth, error in + if let error = error { + observer.onError(error) + } else if let auth = auth { + observer.onNext(auth) + observer.onCompleted() + } + } + return Disposables.create() + } + } + + /** + @brief Asynchronously signs in to Firebase with the given Auth token. + + @param token A self-signed custom auth token. + @param completion Optionally; a block which is invoked when the sign in finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidCustomToken` - Indicates a validation error with + the custom token. + + `FIRAuthErrorCodeCustomTokenMismatch` - Indicates the service account and the API key + belong to different projects. + + + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ + public func signIn(withCustomToken token: String) -> Observable { + return Observable.create { observer in + self.base.signIn(withCustomToken: token) { auth, error in + if let error = error { + observer.onError(error) + } else if let auth = auth { + observer.onNext(auth) + observer.onCompleted() + } + } + return Disposables.create() + } + } + + /** + @brief Creates and, on success, signs in a user with the given email address and password. + + @param email The user's email address. + @param password The user's desired password. + @param completion Optionally; a block which is invoked when the sign up flow finishes, or is + canceled. Invoked asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed. + + `FIRAuthErrorCodeEmailAlreadyInUse` - Indicates the email used to attempt sign up + already exists. Call fetchProvidersForEmail to check which sign-in mechanisms the user + used, and prompt the user to sign in with one of those. + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates that email and password accounts + are not enabled. Enable them in the Auth section of the Firebase console. + + `FIRAuthErrorCodeWeakPassword` - Indicates an attempt to set a password that is + considered too weak. The NSLocalizedFailureReasonErrorKey field in the NSError.userInfo + dictionary object will contain more detailed explanation that can be shown to the user. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ + public func createUser(withEmail email: String, password: String) -> Observable { + return Observable.create { observer in + self.base.createUser(withEmail: email, password: password) { auth, error in + if let error = error { + observer.onError(error) + } else if let auth = auth { + observer.onNext(auth) + observer.onCompleted() + } + } + return Disposables.create() + } + } + + /** + @brief Resets the password given a code sent to the user outside of the app and a new password + for the user. + + @param newPassword The new password. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeWeakPassword` - Indicates an attempt to set a password that is + considered too weak. + + `FIRAuthErrorCodeOperationNotAllowed` - Indicates the administrator disabled sign + in with the specified identity provider. + + `FIRAuthErrorCodeExpiredActionCode` - Indicates the OOB code is expired. + + `FIRAuthErrorCodeInvalidActionCode` - Indicates the OOB code is invalid. + + @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods. + */ + public func confirmPasswordReset(withCode code: String, newPassword: String) -> Observable { + return Observable.create { observer in + self.base.confirmPasswordReset(withCode: code, newPassword: newPassword) { error in + guard let error = error else { + observer.onNext(()) + observer.onCompleted() + return + } + observer.onError(error) + } + return Disposables.create() + } + } + + /** + @brief Checks the validity of an out of band code. + + @param code The out of band code to check validity. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + */ + public func checkActionCode(_ code: String) -> Observable { + return Observable.create { observer in + self.base.checkActionCode(code) { info, error in + if let error = error { + observer.onError(error) + } else if let info = info { + observer.onNext(info) + observer.onCompleted() + } + } + return Disposables.create() + } + } + + /** + @brief Checks the validity of a verify password reset code. + + @param code The password reset code to be verified. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + */ + public func verifyPasswordResetCode(_ code: String) -> Observable { + return Observable.create { observer in + self.base.verifyPasswordResetCode(code) { result, error in + if let error = error { + observer.onError(error) + } else if let result = result { + observer.onNext(result) + observer.onCompleted() + } + } + return Disposables.create() + } + } + + /** + @brief Applies out of band code. + + @param code The out of band code to be applied. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + + @remarks This method will not work for out of band codes which require an additional parameter, + such as password reset code. + */ + public func applyActionCode(_ code: String) -> Observable { + return Observable.create { observer in + self.base.applyActionCode(code) { error in + guard let error = error else { + observer.onNext(()) + observer.onCompleted() + return + } + observer.onError(error) + } + return Disposables.create() + } + } + + /** + @brief Initiates a password reset for the given email address. + + @param email The email address of the user. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidRecipientEmail` - Indicates an invalid recipient email was + sent in the request. + + `FIRAuthErrorCodeInvalidSender` - Indicates an invalid sender email is set in + the console for this action. + + `FIRAuthErrorCodeInvalidMessagePayload` - Indicates an invalid email template for + sending update email. + + + */ + public func sendPasswordReset(withEmail email: String) -> Observable { + return Observable.create { observer in + self.base.sendPasswordReset(withEmail: email) { error in + guard let error = error else { + observer.onNext(()) + observer.onCompleted() + return + } + observer.onError(error) + } + return Disposables.create() + } + } + + /** + @brief Initiates a password reset for the given email address and @FIRActionCodeSettings object. + + @param email The email address of the user. + @param actionCodeSettings An `FIRActionCodeSettings` object containing settings related to + handling action codes. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + + @remarks Possible error codes: + + + `FIRAuthErrorCodeInvalidRecipientEmail` - Indicates an invalid recipient email was + sent in the request. + + `FIRAuthErrorCodeInvalidSender` - Indicates an invalid sender email is set in + the console for this action. + + `FIRAuthErrorCodeInvalidMessagePayload` - Indicates an invalid email template for + sending update email. + + `FIRAuthErrorCodeMissingIosBundleID` - Indicates that the iOS bundle ID is missing when + `handleCodeInApp` is set to YES. + + `FIRAuthErrorCodeMissingAndroidPackageName` - Indicates that the android package name + is missing when the `androidInstallApp` flag is set to true. + + `FIRAuthErrorCodeUnauthorizedDomain` - Indicates that the domain specified in the + continue URL is not whitelisted in the Firebase console. + + `FIRAuthErrorCodeInvalidContinueURI` - Indicates that the domain specified in the + continue URI is not valid. + + + */ + public func sendPasswordReset(withEmail email: String, actionCodeSettings: ActionCodeSettings) -> Observable { + return Observable.create { observer in + self.base.sendPasswordReset(withEmail: email, actionCodeSettings: actionCodeSettings) { error in + guard let error = error else { + observer.onNext(()) + observer.onCompleted() + return + } + observer.onError(error) + } + return Disposables.create() + } + } + + /** + @brief Sends a sign in with email link to provided email address. + + @param email The email address of the user. + @param actionCodeSettings An `FIRActionCodeSettings` object containing settings related to + handling action codes. + @param completion Optionally; a block which is invoked when the request finishes. Invoked + asynchronously on the main thread in the future. + */ + public func sendSignInLink(toEmail email: String, actionCodeSettings: ActionCodeSettings) -> Observable { + return Observable.create { observer in + self.base.sendSignInLink(toEmail: email, actionCodeSettings: actionCodeSettings) { error in + guard let error = error else { + observer.onNext(()) + observer.onCompleted() + return + } + observer.onError(error) + } + return Disposables.create() + } + } + + /** + @brief Registers a block as an "auth state did change" listener. To be invoked when: + + + The block is registered as a listener, + + A user with a different UID from the current user has signed in, or + + The current user has signed out. + + @param listener The block to be invoked. The block is always invoked asynchronously on the main + thread, even for it's initial invocation after having been added as a listener. + + @remarks The block is invoked immediately after adding it according to it's standard invocation + semantics, asynchronously on the main thread. Users should pay special attention to + making sure the block does not inadvertently retain objects which should not be retained by + the long-lived block. The block itself will be retained by `FIRAuth` until it is + unregistered or until the `FIRAuth` instance is otherwise deallocated. + + @return A handle useful for manually unregistering the block as a listener. + */ + public var stateDidChange: Observable { + return Observable.create { observer in + let handle = self.base.addStateDidChangeListener { _, user in + observer.onNext(user) + } + return Disposables.create { + self.base.removeStateDidChangeListener(handle) + } + } + } + + /** + @brief Registers a block as an "ID token did change" listener. To be invoked when: + + + The block is registered as a listener, + + A user with a different UID from the current user has signed in, + + The ID token of the current user has been refreshed, or + + The current user has signed out. + + @param listener The block to be invoked. The block is always invoked asynchronously on the main + thread, even for it's initial invocation after having been added as a listener. + + @remarks The block is invoked immediately after adding it according to it's standard invocation + semantics, asynchronously on the main thread. Users should pay special attention to + making sure the block does not inadvertently retain objects which should not be retained by + the long-lived block. The block itself will be retained by `FIRAuth` until it is + unregistered or until the `FIRAuth` instance is otherwise deallocated. + + @return A handle useful for manually unregistering the block as a listener. + */ + public var idTokenDidChange: Observable { + return Observable.create { observer in + let handle = self.base.addIDTokenDidChangeListener { _, user in + observer.onNext(user) + } + return Disposables.create { + self.base.removeIDTokenDidChangeListener(handle) + } + } + } +} +