Bläddra i källkod

[auth-swift] ActionCode classes to Swift (#11181)

Paul Beusterien 2 år sedan
förälder
incheckning
53e5bd6cae

+ 0 - 183
FirebaseAuth/Sources/Auth/FIRAuth.m

@@ -82,195 +82,12 @@ static NSString *const kInvalidEmailSignInLinkExceptionMessage =
     @"The link provided is not valid for email/link sign-in. Please check the link by calling "
      "isSignInWithEmailLink:link: on Auth before attempting to use it for email/link sign-in.";
 
-/** @var kPasswordResetRequestType
-    @brief The action code type value for resetting password in the check action code response.
- */
-static NSString *const kPasswordResetRequestType = @"PASSWORD_RESET";
-
-/** @var kVerifyEmailRequestType
-    @brief The action code type value for verifying email in the check action code response.
- */
-static NSString *const kVerifyEmailRequestType = @"VERIFY_EMAIL";
-
-/** @var kRecoverEmailRequestType
-    @brief The action code type value for recovering email in the check action code response.
- */
-static NSString *const kRecoverEmailRequestType = @"RECOVER_EMAIL";
-
-/** @var kEmailLinkSignInRequestType
-    @brief The action code type value for an email sign-in link in the check action code response.
-*/
-static NSString *const kEmailLinkSignInRequestType = @"EMAIL_SIGNIN";
-
-/** @var kVerifyAndChangeEmailRequestType
-    @brief The action code type value for verifying and changing email in the check action code
-           response.
- */
-static NSString *const kVerifyAndChangeEmailRequestType = @"VERIFY_AND_CHANGE_EMAIL";
-
-/** @var kRevertSecondFactorAdditionRequestType
-    @brief The action code type value for reverting second factor addition in the check action code
-           response.
- */
-static NSString *const kRevertSecondFactorAdditionRequestType = @"REVERT_SECOND_FACTOR_ADDITION";
-
 /** @var kMissingPasswordReason
     @brief The reason why the @c FIRAuthErrorCodeWeakPassword error is thrown.
     @remarks This error message will be localized in the future.
  */
 static NSString *const kMissingPasswordReason = @"Missing Password";
 
-#pragma mark - FIRActionCodeInfo
-
-@interface FIRActionCodeInfo ()
-
-/**
-    @brief The operation being performed.
- */
-@property(nonatomic, readwrite) FIRActionCodeOperation operation;
-
-/** @property email
-    @brief The email address to which the code was sent. The new email address in the case of
-        FIRActionCodeOperationRecoverEmail.
- */
-@property(nonatomic, nullable, readwrite, copy) NSString *email;
-
-/** @property previousEmail
-    @brief The current email address in the case of FIRActionCodeOperationRecoverEmail.
- */
-@property(nonatomic, nullable, readwrite, copy) NSString *previousEmail;
-
-#if TARGET_OS_IOS
-/** @property multiFactorInfo
-    @brief The MultiFactorInfo object of the second factor to be reverted in case of
-        FIRActionCodeMultiFactorInfoKey.
- */
-@property(nonatomic, nullable, readwrite) FIRMultiFactorInfo *multiFactorInfo;
-#endif
-
-@end
-
-@implementation FIRActionCodeInfo
-
-- (instancetype)initWithOperation:(FIRActionCodeOperation)operation
-                            email:(NSString *)email
-                         newEmail:(nullable NSString *)newEmail {
-  self = [super init];
-  if (self) {
-    _operation = operation;
-    if (newEmail) {
-      _email = [newEmail copy];
-      _previousEmail = [email copy];
-    } else {
-      _email = [email copy];
-    }
-  }
-  return self;
-}
-
-/** @fn actionCodeOperationForRequestType:
-    @brief Returns the corresponding operation type per provided request type string.
-    @param requestType Request type returned in in the server response.
-    @return The corresponding FIRActionCodeOperation for the supplied request type.
- */
-+ (FIRActionCodeOperation)actionCodeOperationForRequestType:(NSString *)requestType {
-  if ([requestType isEqualToString:kPasswordResetRequestType]) {
-    return FIRActionCodeOperationPasswordReset;
-  }
-  if ([requestType isEqualToString:kVerifyEmailRequestType]) {
-    return FIRActionCodeOperationVerifyEmail;
-  }
-  if ([requestType isEqualToString:kRecoverEmailRequestType]) {
-    return FIRActionCodeOperationRecoverEmail;
-  }
-  if ([requestType isEqualToString:kEmailLinkSignInRequestType]) {
-    return FIRActionCodeOperationEmailLink;
-  }
-  if ([requestType isEqualToString:kVerifyAndChangeEmailRequestType]) {
-    return FIRActionCodeOperationVerifyAndChangeEmail;
-  }
-  if ([requestType isEqualToString:kRevertSecondFactorAdditionRequestType]) {
-    return FIRActionCodeOperationRevertSecondFactorAddition;
-  }
-  return FIRActionCodeOperationUnknown;
-}
-
-@end
-
-#pragma mark - FIRActionCodeURL
-
-@implementation FIRActionCodeURL
-
-/** @fn FIRAuthParseURL:NSString
-    @brief Parses an incoming URL into all available query items.
-    @param urlString The url to be parsed.
-    @return A dictionary of available query items in the target URL.
- */
-+ (NSDictionary<NSString *, NSString *> *)parseURL:(NSString *)urlString {
-  NSString *linkURL = [NSURLComponents componentsWithString:urlString].query;
-  if (!linkURL) {
-    return @{};
-  }
-  NSArray<NSString *> *URLComponents = [linkURL componentsSeparatedByString:@"&"];
-  NSMutableDictionary<NSString *, NSString *> *queryItems =
-      [[NSMutableDictionary alloc] initWithCapacity:URLComponents.count];
-  for (NSString *component in URLComponents) {
-    NSRange equalRange = [component rangeOfString:@"="];
-    if (equalRange.location != NSNotFound) {
-      NSString *queryItemKey =
-          [[component substringToIndex:equalRange.location] stringByRemovingPercentEncoding];
-      NSString *queryItemValue =
-          [[component substringFromIndex:equalRange.location + 1] stringByRemovingPercentEncoding];
-      if (queryItemKey && queryItemValue) {
-        queryItems[queryItemKey] = queryItemValue;
-      }
-    }
-  }
-  return queryItems;
-}
-
-+ (nullable instancetype)actionCodeURLWithLink:(NSString *)link {
-  NSDictionary<NSString *, NSString *> *queryItems = [FIRActionCodeURL parseURL:link];
-  if (!queryItems.count) {
-    NSURLComponents *urlComponents = [NSURLComponents componentsWithString:link];
-    queryItems = [FIRActionCodeURL parseURL:urlComponents.query];
-  }
-  if (!queryItems.count) {
-    return nil;
-  }
-  NSString *APIKey = queryItems[@"apiKey"];
-  NSString *actionCode = queryItems[@"oobCode"];
-  NSString *continueURLString = queryItems[@"continueUrl"];
-  NSString *languageCode = queryItems[@"languageCode"];
-  NSString *mode = queryItems[@"mode"];
-  NSString *tenantID = queryItems[@"tenantID"];
-  return [[FIRActionCodeURL alloc] initWithAPIKey:APIKey
-                                       actionCode:actionCode
-                                continueURLString:continueURLString
-                                     languageCode:languageCode
-                                             mode:mode
-                                         tenantID:tenantID];
-}
-
-- (nullable instancetype)initWithAPIKey:(NSString *)APIKey
-                             actionCode:(NSString *)actionCode
-                      continueURLString:(NSString *)continueURLString
-                           languageCode:(NSString *)languageCode
-                                   mode:(NSString *)mode
-                               tenantID:(NSString *)tenantID {
-  self = [super init];
-  if (self) {
-    _APIKey = APIKey;
-    _operation = [FIRActionCodeInfo actionCodeOperationForRequestType:mode];
-    _code = actionCode;
-    _continueURL = [NSURL URLWithString:continueURLString];
-    _languageCode = languageCode;
-  }
-  return self;
-}
-
-@end
-
 #pragma mark - FIRAuth
 
 #if TARGET_OS_IOS

+ 2 - 103
FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuth.h

@@ -36,6 +36,8 @@
 @protocol FIRAuthStorage;
 @class FIRAuthAPNSTokenManager;
 @class FIRAuthAppCredentialManager;
+@class FIRActionCodeInfo;
+@class FIRActionCodeURL;
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -176,109 +178,6 @@ typedef void (^FIRApplyActionCodeCallback)(NSError *_Nullable error)
 typedef void (^FIRAuthVoidErrorCallback)(NSError *_Nullable)
     NS_SWIFT_UNAVAILABLE("Use Swift's closure syntax instead.");
 
-/** @class FIRActionCodeInfo
-    @brief Manages information regarding action codes.
- */
-NS_SWIFT_NAME(ActionCodeInfo)
-@interface FIRActionCodeInfo : NSObject
-
-/**
-    @brief Operations which can be performed with action codes.
-  */
-typedef NS_ENUM(NSInteger, FIRActionCodeOperation) {
-  /** Action code for unknown operation. */
-  FIRActionCodeOperationUnknown = 0,
-
-  /** Action code for password reset operation. */
-  FIRActionCodeOperationPasswordReset = 1,
-
-  /** Action code for verify email operation. */
-  FIRActionCodeOperationVerifyEmail = 2,
-
-  /** Action code for recover email operation. */
-  FIRActionCodeOperationRecoverEmail = 3,
-
-  /** Action code for email link operation. */
-  FIRActionCodeOperationEmailLink = 4,
-
-  /** Action code for verifying and changing email */
-  FIRActionCodeOperationVerifyAndChangeEmail = 5,
-
-  /** Action code for reverting second factor addition */
-  FIRActionCodeOperationRevertSecondFactorAddition = 6,
-
-} NS_SWIFT_NAME(ActionCodeOperation);
-
-/**
-    @brief The operation being performed.
- */
-@property(nonatomic, readonly) FIRActionCodeOperation operation;
-
-/** @property email
-    @brief The email address to which the code was sent. The new email address in the case of
-        `ActionCodeOperationRecoverEmail`.
- */
-@property(nonatomic, nullable, readonly, copy) NSString *email;
-
-/** @property previousEmail
-    @brief The email that is being recovered in the case of `ActionCodeOperationRecoverEmail`.
- */
-@property(nonatomic, nullable, readonly, copy) NSString *previousEmail;
-
-/** @fn init
-    @brief please use initWithOperation: instead.
- */
-- (instancetype)init NS_UNAVAILABLE;
-
-@end
-
-/** @class FIRActionCodeURL
-    @brief This class will allow developers to easily extract information about out of band links.
- */
-NS_SWIFT_NAME(ActionCodeURL)
-@interface FIRActionCodeURL : NSObject
-
-/** @property APIKey
-    @brief Returns the API key from the link. nil, if not provided.
- */
-@property(nonatomic, nullable, copy, readonly) NSString *APIKey;
-
-/** @property operation
-    @brief Returns the mode of oob action. The property will be of `FIRActionCodeOperation` type.
-        It will return `FIRActionCodeOperationUnknown` if no oob action is provided.
- */
-@property(nonatomic, readonly) FIRActionCodeOperation operation;
-
-/** @property code
-    @brief Returns the email action code from the link. nil, if not provided.
- */
-@property(nonatomic, nullable, copy, readonly) NSString *code;
-
-/** @property continueURL
-    @brief Returns the continue URL from the link. nil, if not provided.
- */
-@property(nonatomic, nullable, copy, readonly) NSURL *continueURL;
-
-/** @property languageCode
-    @brief Returns the language code from the link. nil, if not provided.
- */
-@property(nonatomic, nullable, copy, readonly) NSString *languageCode;
-
-/** @fn actionCodeURLWithLink:
-    @brief Construct an `ActionCodeURL` from an out of band link (e.g. email link).
-    @param link The oob link string used to construct the action code URL.
-    @return The `ActionCodeURL` object constructed based on the oob link provided.
- */
-+ (nullable instancetype)actionCodeURLWithLink:(NSString *)link;
-
-/** @fn init
-    @brief Please use `init(link:)` in Swift or `actionCodeURLWithLink:` in Objective-C
-        instead.
- */
-- (instancetype)init NS_UNAVAILABLE;
-
-@end
-
 /** @typedef FIRCheckActionCodeCallBack
     @brief The type of block invoked when performing a check action code operation.
 

+ 68 - 0
FirebaseAuth/Sources/Swift/ActionCode/ActionCodeInfo.swift

@@ -0,0 +1,68 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import Foundation
+
+/** @class ActionCodeInfo
+    @brief Manages information regarding action codes.
+ */
+@objc(FIRActionCodeInfo) public class ActionCodeInfo: NSObject {
+  /**
+      @brief The operation being performed.
+   */
+  @objc public let operation: ActionCodeOperation
+
+  /** @property email
+      @brief The email address to which the code was sent. The new email address in the case of
+          `ActionCodeOperationRecoverEmail`.
+   */
+  @objc public let email: String
+
+  /** @property previousEmail
+      @brief The email that is being recovered in the case of `ActionCodeOperationRecoverEmail`.
+   */
+  @objc public let previousEmail: String?
+
+  // TODO: Below here change to internal.
+
+  @objc public init(withOperation operation: ActionCodeOperation, email: String,
+                    newEmail: String?) {
+    self.operation = operation
+    if let newEmail {
+      self.email = newEmail
+      previousEmail = email
+    } else {
+      self.email = email
+      previousEmail = nil
+    }
+  }
+
+  /** @fn actionCodeOperationForRequestType:
+      @brief Returns the corresponding operation type per provided request type string.
+      @param requestType Request type returned in in the server response.
+      @return The corresponding ActionCodeOperation for the supplied request type.
+   */
+  @objc public
+  class func actionCodeOperation(forRequestType requestType: String?) -> ActionCodeOperation {
+    switch requestType {
+    case "PASSWORD_RESET": return .passwordReset
+    case "VERIFY_EMAIL": return .verifyEmail
+    case "RECOVER_EMAIL": return .recoverEmail
+    case "EMAIL_SIGNIN": return .emailLink
+    case "VERIFY_AND_CHANGE_EMAIL": return .verifyAndChangeEmail
+    case "REVERT_SECOND_FACTOR_ADDITION": return .revertSecondFactorAddition
+    default: return .unknown
+    }
+  }
+}

+ 42 - 0
FirebaseAuth/Sources/Swift/ActionCode/ActionCodeOperation.swift

@@ -0,0 +1,42 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import Foundation
+
+/**
+    @brief Operations which can be performed with action codes.
+  */
+@objc(FIRActionCodeOperation) public enum ActionCodeOperation : Int, @unchecked Sendable {
+
+    /** Action code for unknown operation. */
+    case unknown = 0
+
+    /** Action code for password reset operation. */
+    case passwordReset = 1
+
+    /** Action code for verify email operation. */
+    case verifyEmail = 2
+
+    /** Action code for recover email operation. */
+    case recoverEmail = 3
+
+    /** Action code for email link operation. */
+    case emailLink = 4
+
+    /** Action code for verifying and changing email */
+    case verifyAndChangeEmail = 5
+
+    /** Action code for reverting second factor addition */
+    case revertSecondFactorAddition = 6
+}

+ 0 - 0
FirebaseAuth/Sources/Swift/Auth/ActionCodeSettings.swift → FirebaseAuth/Sources/Swift/ActionCode/ActionCodeSettings.swift


+ 91 - 0
FirebaseAuth/Sources/Swift/ActionCode/ActionCodeURL.swift

@@ -0,0 +1,91 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import Foundation
+
+/** @class FIRActionCodeURL
+    @brief This class will allow developers to easily extract information about out of band links.
+ */
+@objc(FIRActionCodeURL) public class ActionCodeURL: NSObject {
+  /** @property APIKey
+      @brief Returns the API key from the link. nil, if not provided.
+   */
+  @objc public let apiKey: String?
+
+  /** @property operation
+      @brief Returns the mode of oob action. The property will be of `FIRActionCodeOperation` type.
+          It will return `FIRActionCodeOperationUnknown` if no oob action is provided.
+   */
+  @objc public let operation: ActionCodeOperation
+
+  /** @property code
+      @brief Returns the email action code from the link. nil, if not provided.
+   */
+  @objc public let code: String?
+
+  /** @property continueURL
+      @brief Returns the continue URL from the link. nil, if not provided.
+   */
+  @objc public let continueURL: URL?
+
+  /** @property languageCode
+      @brief Returns the language code from the link. nil, if not provided.
+   */
+  @objc public let languageCode: String?
+
+  /** @fn actionCodeURLWithLink:
+      @brief Construct an `ActionCodeURL` from an out of band link (e.g. email link).
+      @param link The oob link string used to construct the action code URL.
+      @return The `ActionCodeURL` object constructed based on the oob link provided.
+   */
+  @objc(actionCodeURLWithLink:) public init?(link: String) {
+    var queryItems = ActionCodeURL.parseURL(link)
+    if queryItems.count == 0 {
+      let urlComponents = URLComponents(string: link)
+      if let query = urlComponents?.query {
+        queryItems = ActionCodeURL.parseURL(query)
+      }
+    }
+    guard queryItems.count > 0 else {
+      return nil
+    }
+    apiKey = queryItems["apiKey"]
+    operation = ActionCodeInfo.actionCodeOperation(forRequestType: queryItems["mode"])
+    code = queryItems["oobCode"]
+    if let continueURL = queryItems["continueUrl"] {
+      self.continueURL = URL(string: continueURL)
+    } else {
+      continueURL = nil
+    }
+    languageCode = queryItems["languageCode"]
+  }
+
+  // TODO: internal below here.
+
+  @objc public class func parseURL(_ urlString: String) -> [String: String] {
+    guard let linkURL = URLComponents(string: urlString)?.query else {
+      return [:]
+    }
+    var queryItems: [String: String] = [:]
+    let urlComponents = linkURL.components(separatedBy: "&")
+    for component in urlComponents {
+      let splitArray = component.split(separator: "=")
+      if let queryItemKey = String(splitArray[0]).removingPercentEncoding,
+         let queryItemValue = String(splitArray[1]).removingPercentEncoding {
+        queryItems[queryItemKey] = queryItemValue
+      }
+    }
+    return queryItems
+  }
+}