User+Combine.swift 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright 2021 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #if canImport(Combine) && swift(>=5.0)
  15. import Combine
  16. import FirebaseAuth
  17. @available(swift 5.0)
  18. @available(iOS 13.0, macOS 10.15, macCatalyst 13.0, tvOS 13.0, watchOS 6.0, *)
  19. public extension User {
  20. /// Associates a user account from a third-party identity provider with this user and
  21. /// returns additional identity provider data.
  22. ///
  23. /// The publisher will emit events on the **main** thread.
  24. ///
  25. /// - Parameter credential: The credential for the identity provider.
  26. /// - Returns: A publisher that emits an `AuthDataResult` when the association flow completed
  27. /// successfully, or an error otherwise. The publisher will emit on the *main* thread.
  28. /// - Remark: Possible error codes:
  29. /// - `FIRAuthErrorCodeProviderAlreadyLinked` - Indicates an attempt to link a provider of a
  30. /// type already linked to this account.
  31. /// - `FIRAuthErrorCodeCredentialAlreadyInUse` - Indicates an attempt to link with a
  32. /// credential that has already been linked with a different Firebase account.
  33. /// - `FIRAuthErrorCodeOperationNotAllowed` - Indicates that accounts with the identity
  34. /// provider represented by the credential are not enabled. Enable them in the Auth
  35. /// section of the Firebase console.
  36. ///
  37. /// See `FIRAuthErrors` for a list of error codes that are common to all FIRUser methods.
  38. func link(with credential: AuthCredential) -> Future<AuthDataResult, Error> {
  39. Future<AuthDataResult, Error> { promise in
  40. self.link(with: credential) { authDataResult, error in
  41. if let error = error {
  42. promise(.failure(error))
  43. } else if let authDataResult = authDataResult {
  44. promise(.success(authDataResult))
  45. }
  46. }
  47. }
  48. }
  49. /// Renews the user's authentication tokens by validating a fresh set of credentials supplied
  50. /// by the user and returns additional identity provider data.
  51. ///
  52. /// The publisher will emit events on the **main** thread.
  53. ///
  54. /// - Parameter credential: A user-supplied credential, which will be validated by the server.
  55. /// This can be a successful third-party identity provider sign-in, or an email address and
  56. /// password.
  57. /// - Returns: A publisher that emits an `AuthDataResult` when the reauthentication flow
  58. /// completed successfully, or an error otherwise.
  59. /// - Remark: If the user associated with the supplied credential is different from the current
  60. /// user, or if the validation of the supplied credentials fails; an error is returned and the
  61. /// current user remains signed in.
  62. ///
  63. /// Possible error codes:
  64. ///
  65. /// - `FIRAuthErrorCodeInvalidCredential` - Indicates the supplied credential is invalid.
  66. /// This could happen if it has expired or it is malformed.
  67. /// - `FIRAuthErrorCodeOperationNotAllowed` - Indicates that accounts with the
  68. /// identity provider represented by the credential are not enabled. Enable them in the
  69. /// Auth section of the Firebase console.
  70. /// - `FIRAuthErrorCodeEmailAlreadyInUse` - Indicates the email asserted by the credential
  71. /// (e.g. the email in a Facebook access token) is already in use by an existing account,
  72. /// that cannot be authenticated with this method. Call fetchProvidersForEmail for
  73. /// this user’s email and then prompt them to sign in with any of the sign-in providers
  74. /// returned. This error will only be thrown if the "One account per email address"
  75. /// setting is enabled in the Firebase console, under Auth settings. Please note that the
  76. /// error code raised in this specific situation may not be the same on Web and Android.
  77. /// - `FIRAuthErrorCodeUserDisabled` - Indicates the user's account is disabled.
  78. /// - `FIRAuthErrorCodeWrongPassword` - Indicates the user attempted reauthentication with
  79. /// an incorrect password, if credential is of the type EmailPasswordAuthCredential.
  80. /// - `FIRAuthErrorCodeUserMismatch` - Indicates that an attempt was made to
  81. /// reauthenticate with a user which is not the current user.
  82. /// - `FIRAuthErrorCodeInvalidEmail` - Indicates the email address is malformed.
  83. ///
  84. /// See `FIRAuthErrors` for a list of error codes that are common to all FIRUser methods.
  85. func reauthenticate(with credential: AuthCredential) -> Future<AuthDataResult, Error> {
  86. Future<AuthDataResult, Error> { promise in
  87. self.reauthenticate(with: credential) { authDataResult, error in
  88. if let error = error {
  89. promise(.failure(error))
  90. } else if let authDataResult = authDataResult {
  91. promise(.success(authDataResult))
  92. }
  93. }
  94. }
  95. }
  96. /// Disassociates a user account from a third-party identity provider with this user.
  97. ///
  98. /// The publisher will emit events on the **main** thread.
  99. ///
  100. /// - Parameter provider: The provider ID of the provider to unlink.
  101. /// - Returns: A publisher that emits a `User` when the disassociation flow completed
  102. /// successfully, or an error otherwise. The publisher will emit on the *main* thread.
  103. ///
  104. /// Possible error codes:
  105. ///
  106. /// - `FIRAuthErrorCodeNoSuchProvider` - Indicates an attempt to unlink a provider
  107. /// that is not linked to the account.
  108. /// - `FIRAuthErrorCodeRequiresRecentLogin` - Updating email is a security sensitive
  109. /// operation that requires a recent login from the user. This error indicates the user
  110. /// has not signed in recently enough. To resolve, reauthenticate the user by invoking
  111. /// reauthenticateWithCredential:completion: on `FIRUser`.
  112. ///
  113. /// See `FIRAuthErrors` for a list of error codes that are common to all `FIRUser` methods.
  114. func unlink(fromProvider provider: String) -> Future<User, Error> {
  115. Future<User, Error> { promise in
  116. self.unlink(fromProvider: provider) { user, error in
  117. if let user = user {
  118. promise(.success(user))
  119. } else if let error = error {
  120. promise(.failure(error))
  121. }
  122. }
  123. }
  124. }
  125. /// Initiates email verification for the user.
  126. ///
  127. /// The publisher will emit events on the **main** thread.
  128. ///
  129. /// - Returns: A publisher that emits no type when the verification flow completed
  130. /// successfully, or an error otherwise.
  131. ///
  132. /// Possible error codes:
  133. ///
  134. /// - `FIRAuthErrorCodeInvalidRecipientEmail` - Indicates an invalid recipient email was
  135. /// sent in the request.
  136. /// - `FIRAuthErrorCodeInvalidSender` - Indicates an invalid sender email is set in
  137. /// the console for this action.
  138. /// - `FIRAuthErrorCodeInvalidMessagePayload` - Indicates an invalid email template for
  139. /// sending update email.
  140. /// - `FIRAuthErrorCodeUserNotFound` - Indicates the user account was not found.
  141. ///
  142. /// See `FIRAuthErrors` for a list of error codes that are common to all `FIRUser` methods.
  143. func sendEmailVerification() -> Future<Void, Error> {
  144. Future<Void, Error> { promise in
  145. self.sendEmailVerification { error in
  146. if let error = error {
  147. promise(.failure(error))
  148. } else {
  149. promise(.success(()))
  150. }
  151. }
  152. }
  153. }
  154. /// Initiates email verification for the user.
  155. ///
  156. /// The publisher will emit events on the **main** thread.
  157. ///
  158. /// - Parameter actionCodeSettings: An `FIRActionCodeSettings` object containing settings
  159. /// related to handling action codes.
  160. /// - Returns: A publisher that emits no type when the verification flow completed
  161. /// successfully, or an error otherwise.
  162. ///
  163. /// Possible error codes:
  164. ///
  165. /// - `FIRAuthErrorCodeInvalidRecipientEmail` - Indicates an invalid recipient email was
  166. /// sent in the request.
  167. /// - `FIRAuthErrorCodeInvalidSender` - Indicates an invalid sender email is set in
  168. /// the console for this action.
  169. /// - `FIRAuthErrorCodeInvalidMessagePayload` - Indicates an invalid email template for
  170. /// sending update email.
  171. /// - `FIRAuthErrorCodeUserNotFound` - Indicates the user account was not found.
  172. /// - `FIRAuthErrorCodeMissingIosBundleID` - Indicates that the iOS bundle ID is missing when
  173. /// a iOS App Store ID is provided.
  174. /// - `FIRAuthErrorCodeMissingAndroidPackageName` - Indicates that the android package name
  175. /// is missing when the `androidInstallApp` flag is set to true.
  176. /// - `FIRAuthErrorCodeUnauthorizedDomain` - Indicates that the domain specified in the
  177. /// continue URL is not allowlisted in the Firebase console.
  178. /// - `FIRAuthErrorCodeInvalidContinueURI` - Indicates that the domain specified in the
  179. /// continue URI is not valid.
  180. func sendEmailVerification(with actionCodeSettings: ActionCodeSettings)
  181. -> Future<Void, Error> {
  182. Future<Void, Error> { promise in
  183. self.sendEmailVerification(with: actionCodeSettings) { error in
  184. if let error = error {
  185. promise(.failure(error))
  186. } else {
  187. promise(.success(()))
  188. }
  189. }
  190. }
  191. }
  192. }
  193. #endif // canImport(Combine) && swift(>=5.0)