Skip to content

Add default phone number to the Phone Auth number flow. #334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 19, 2017
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 @@ -165,7 +165,7 @@ - (void)reauthenticateWithProvider:(NSString *)providerID
[self.delegate incrementActivity];
// Sign out first to make sure sign in starts with a clean state.
[providerUI signOut];
[providerUI signInWithEmail:self.delegate.auth.currentUser.email
[providerUI signInWithDefaultValue:self.delegate.auth.currentUser.email
presentingViewController:[self.delegate presentingController]
completion:^(FIRAuthCredential *_Nullable credential,
NSError *_Nullable error,
Expand Down
7 changes: 4 additions & 3 deletions FirebaseAuthUI/FUIAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,12 @@ - (BOOL)signOutWithError:(NSError *_Nullable *_Nullable)error {
}

- (void)signInWithProviderUI:(id<FUIAuthProvider>)providerUI
presentingViewController:(UIViewController *)presentingViewController {
presentingViewController:(UIViewController *)presentingViewController
defaultValue:(nullable NSString *)defaultValue {

// Sign out first to make sure sign in starts with a clean state.
[providerUI signOut];
[providerUI signInWithEmail:nil
[providerUI signInWithDefaultValue:defaultValue
presentingViewController:presentingViewController
completion:^(FIRAuthCredential *_Nullable credential,
NSError *_Nullable error,
Expand Down Expand Up @@ -247,7 +248,7 @@ - (void)handleAccountLinkingForEmail:(NSString *)email
signinHandler:^{
// Sign out first to make sure sign in starts with a clean state.
[bestProvider signOut];
[bestProvider signInWithEmail:email
[bestProvider signInWithDefaultValue:email
presentingViewController:presentingViewController
completion:^(FIRAuthCredential *_Nullable credential,
NSError *_Nullable error,
Expand Down
4 changes: 3 additions & 1 deletion FirebaseAuthUI/FUIAuthPickerViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ - (void)signInWithEmail {
}

- (void)didTapSignInButton:(FUIAuthSignInButton *)button {
[self.authUI signInWithProviderUI:button.providerUI presentingViewController:self];
[self.authUI signInWithProviderUI:button.providerUI
presentingViewController:self
defaultValue:nil];
}

@end
23 changes: 21 additions & 2 deletions FirebaseAuthUI/FUIAuthProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN

/** @typedef FIRAuthProviderSignInCompletionBlock
@brief The type of block used to notify the auth system of the result of a sign-in flow.
@see FUIAuthProvider.signInWithEmail:presentingViewController:completion:
@see FUIAuthProvider.signInWithDefaultValue:presentingViewController:completion:
@param credential The @c FIRAuthCredential object created after user interaction with third
party provider.
@param error The error which may happen during creation of The @c FIRAuthCredential object.
Expand Down Expand Up @@ -90,7 +90,26 @@ typedef void (^FIRAuthProviderSignInCompletionBlock) (
*/
- (void)signInWithEmail:(nullable NSString *)email
presentingViewController:(nullable UIViewController *)presentingViewController
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion;
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion
__attribute__((deprecated("This is deprecated API and will be removed in a future release."
"Use signInWithDefaultValue:presentingViewController:completion:")));

/** @fn signInWithDefaultValue:presentingViewController:completion:
@brief Called when the user wants to sign in using this auth provider.
@remarks Implementors should invoke the completion block when the sign-in process has terminated
or is canceled. There are two valid combinations of parameters; either @c credentials and
@c userInfo are both non-nil, or @c error is non-nil. Errors must specify an error code
which is one of the @c FIRAuthErrorCode codes. It is very important that all possible code
paths eventually call this method to inform the auth system of the result of the sign-in
flow.
@param defaultValue The default initialization value of the provider (email, phone number etc.).
@param presentingViewController The view controller used to present the UI.
@param completion See remarks. A block which should be invoked when the sign-in process
(using @c FIRAuthCredential) completes.
*/
- (void)signInWithDefaultValue:(nullable NSString *)defaultValue
presentingViewController:(nullable UIViewController *)presentingViewController
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion;

/** @fn signOut
@brief Called when the user wants to sign out.
Expand Down
7 changes: 5 additions & 2 deletions FirebaseAuthUI/FUIAuth_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,17 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (nullable id<FUIAuthProvider>)providerWithID:(NSString *)providerID;

/** @fn signInWithProviderUI:presentingViewController:
/** @fn signInWithProviderUI:presentingViewController:defaultValue:
@brief Signs in with specified provider. @see FUIAuthDelegate.authUI:didSignInWithUser:error:
for method callback.
@param providerUI The authentication provider used for signing in.
@param presentingViewController The view controller used to present the UI.
@param defaultValue The provider default initialization value (e g email or phone number)
used for signing in.
*/
- (void)signInWithProviderUI:(id<FUIAuthProvider>)providerUI
presentingViewController:(UIViewController *)presentingViewController;
presentingViewController:(UIViewController *)presentingViewController
defaultValue:(nullable NSString *)defaultValue;

@end

Expand Down
2 changes: 1 addition & 1 deletion FirebaseAuthUI/FUIEmailEntryViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ - (void)signInWithProvider:(id<FUIAuthProvider>)provider email:(NSString *)email

// Sign out first to make sure sign in starts with a clean state.
[provider signOut];
[provider signInWithEmail:email
[provider signInWithDefaultValue:email
presentingViewController:self
completion:^(FIRAuthCredential *_Nullable credential,
NSError *_Nullable error,
Expand Down
4 changes: 2 additions & 2 deletions FirebaseAuthUI/FUIPasswordSignInViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)didChangeEmail:(NSString *)email andPassword:(NSString *)password;

/** @fn signInWithEmail:andPassword:
/** @fn signInWithDefaultValue:andPassword:
@brief Should be called when user entered credentials. Sends authorization request
@param email The email address of the user.
@param password The password which user uses.
*/
- (void)signInWithEmail:(NSString *)email andPassword:(NSString *)password;
- (void)signInWithDefaultValue:(NSString *)email andPassword:(NSString *)password;

@end

Expand Down
4 changes: 2 additions & 2 deletions FirebaseAuthUI/FUIPasswordSignInViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ - (void)viewDidLoad {

#pragma mark - Actions

- (void)signInWithEmail:(NSString *)email andPassword:(NSString *)password {
- (void)signInWithDefaultValue:(NSString *)email andPassword:(NSString *)password {
if (![[self class] isValidEmail:email]) {
[self showAlertWithMessage:FUILocalizedString(kStr_InvalidEmailError)];
return;
Expand Down Expand Up @@ -138,7 +138,7 @@ - (void)signInWithEmail:(NSString *)email andPassword:(NSString *)password {
}

- (void)signIn {
[self signInWithEmail:_emailField.text andPassword:_passwordField.text];
[self signInWithDefaultValue:_emailField.text andPassword:_passwordField.text];
}

- (void)forgotPasswordForEmail:(NSString *)email {
Expand Down
8 changes: 8 additions & 0 deletions FirebaseFacebookAuthUI/FUIFacebookAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ - (UIColor *)buttonTextColor {
- (void)signInWithEmail:(nullable NSString *)email
presentingViewController:(nullable UIViewController *)presentingViewController
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion {
[self signInWithDefaultValue:email
presentingViewController:presentingViewController
completion:completion];
}

- (void)signInWithDefaultValue:(nullable NSString *)defaultValue
presentingViewController:(nullable UIViewController *)presentingViewController
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion {
_pendingSignInCallback = completion;
_presentingViewController = presentingViewController;

Expand Down
10 changes: 9 additions & 1 deletion FirebaseGoogleAuthUI/FUIGoogleAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ - (UIColor *)buttonTextColor {
- (void)signInWithEmail:(nullable NSString *)email
presentingViewController:(nullable UIViewController *)presentingViewController
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion {
[self signInWithDefaultValue:email
presentingViewController:presentingViewController
completion:completion];
}

- (void)signInWithDefaultValue:(nullable NSString *)defaultValue
presentingViewController:(nullable UIViewController *)presentingViewController
completion:(nullable FIRAuthProviderSignInCompletionBlock)completion {
_presentingViewController = presentingViewController;

GIDSignIn *signIn = [self configuredGoogleSignIn];
Expand All @@ -118,7 +126,7 @@ - (void)signInWithEmail:(nullable NSString *)email
}
};

signIn.loginHint = email;
signIn.loginHint = defaultValue;
[signIn signIn];
}

Expand Down
79 changes: 79 additions & 0 deletions FirebasePhoneAuthUI/CountryCode/FUIPhoneNumber.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//
// Copyright (c) 2016 Google Inc.
//
// 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/Foundation.h>
#import "FUICountryCodes.h"

NS_ASSUME_NONNULL_BEGIN

FOUNDATION_EXPORT NSString * const FUIPhoneNumberValidationErrorDomain;

typedef NS_ENUM(NSInteger, FUIPhoneNumberValidationError) {
FUIPhoneNumberValidationErrorMissingPlus = 0,
FUIPhoneNumberValidationErrorMissingDialCode = 1,
FUIPhoneNumberValidationErrorMissingNumber = 2,
};

/** Encapsulates a phone number with the raw and the normalized representations */
@interface FUIPhoneNumber : NSObject

@property (nonatomic, readonly) FUICountryCodeInfo *countryCode;
@property (nonatomic, copy, readonly) NSString *rawPhoneNumber;
@property (nonatomic, copy, readonly) NSString *normalizedPhoneNumber;

/** @fn initWithNormalizedPhoneNumber:
@brief Attempts to parse the given phone number into a raw phone number and country code.
Parse behavior:
If given phone number starts with a '+' character, then look for the country code matching
the prefix of the number.
Otherwise use the normalized number as the raw number, and find the country code using the
device locale.
@param normalizedPhoneNumber (required) A phone number string that will be parsed into
a raw phone number and country code.
@return object or nil if any of the required parameters is nil.
*/
- (instancetype)initWithNormalizedPhoneNumber:(NSString *)normalizedPhoneNumber;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These three initializers need to return nullable instancetype, not instancetype.


/** @fn initWithRawPhoneNumber:countryCode:
@param rawPhoneNumber (required) The raw phone number without country code
@param countryCode (required) The country code information
@return object or nil if any of the required parameters is nil.
*/
- (instancetype)initWithRawPhoneNumber:(NSString *)rawPhoneNumber
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nullable instancetype

countryCode:(FUICountryCodeInfo *)countryCode;

/** @fn initWithNormalizedPhoneNumber:rawPhoneNumber:countryCode:
@param normalizedPhoneNumber (optional) The phone number returned from the endpoint;
if null or empty it will be computed ('+' + rawCountryCode + rawPhoneNumber)
@param rawPhoneNumber (required) The raw phone number without country code
@param countryCode (required) The country code information
@return object or nil if any of the required parameters is nil.
*/
- (instancetype)initWithNormalizedPhoneNumber:(NSString *)normalizedPhoneNumber
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nullable instancetype

rawPhoneNumber:(NSString *)rawPhoneNumber
countryCode:(FUICountryCodeInfo *)countryCode;

- (instancetype)init NS_UNAVAILABLE;

/** @fn validate:
@brief Checks if current phone number has valid international format.
@param errorRef The error which occurred, if any.
@return True if phone number format is valid.
*/
- (BOOL)validate:(NSError *__autoreleasing _Nullable *_Nullable)errorRef;
@end

NS_ASSUME_NONNULL_END
120 changes: 120 additions & 0 deletions FirebasePhoneAuthUI/CountryCode/FUIPhoneNumber.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//
// Copyright (c) 2016 Google Inc.
//
// 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 "FUIPhoneNumber.h"

NS_ASSUME_NONNULL_BEGIN

NSString * const FUIPhoneNumberValidationErrorDomain = @"FUIPhoneNumberValidationErrorDomain";

@implementation FUIPhoneNumber

- (instancetype)initWithNormalizedPhoneNumber:(NSString *)normalizedPhoneNumber {
NSAssert(normalizedPhoneNumber, @"normalizedPhoneNumber can't be nil");
NSString *rawPhoneNumber;
FUICountryCodes *codes = [[FUICountryCodes alloc] init];
FUICountryCodeInfo *countryCode = [codes countryCodeInfoForPhoneNumber:normalizedPhoneNumber];

if (countryCode) {
// Add 1 for the '+' character
NSInteger countryCodeLength = countryCode.dialCode.length + 1;
if (normalizedPhoneNumber.length >= countryCodeLength) {
rawPhoneNumber = [normalizedPhoneNumber substringFromIndex:countryCodeLength];
}
}
if (!rawPhoneNumber) {
rawPhoneNumber = normalizedPhoneNumber;
countryCode = [codes countryCodeInfoFromDeviceLocale];
}
return [self initWithRawPhoneNumber:rawPhoneNumber countryCode:countryCode];
}

- (instancetype)initWithNormalizedPhoneNumber:(NSString *)normalizedPhoneNumber
rawPhoneNumber:(NSString *)rawPhoneNumber
countryCode:(FUICountryCodeInfo *)countryCode {
NSAssert(normalizedPhoneNumber, @"normalizedPhoneNumber can't be nil");
NSAssert(rawPhoneNumber, @"rawPhoneNumber can't be nil");
NSAssert(countryCode, @"countryCode can't be nil");
if (self = [super init]) {
_countryCode = countryCode;
_rawPhoneNumber = rawPhoneNumber;
_normalizedPhoneNumber = normalizedPhoneNumber;
}
return self;
}

- (instancetype)initWithRawPhoneNumber:(NSString *)rawPhoneNumber
countryCode:(FUICountryCodeInfo *)countryCode {
NSAssert(rawPhoneNumber, @"rawPhoneNumber can't be nil");
NSAssert(countryCode, @"countryCode can't be nil");
NSString *dialCode = countryCode.dialCode;
NSAssert(dialCode.length, @"dialCode can't be empty");
if ([dialCode characterAtIndex:0] != '+') {
dialCode = [@"+" stringByAppendingString:dialCode];
}
NSString *normalizedPhoneNumber = [NSString stringWithFormat:@"%@%@", dialCode, rawPhoneNumber];

return [self initWithNormalizedPhoneNumber:normalizedPhoneNumber
rawPhoneNumber:rawPhoneNumber
countryCode:countryCode];
}

- (BOOL)validate:(NSError *__autoreleasing _Nullable *_Nullable)errorRef {
// The first character is always the '+'
BOOL firstCharacterIsPlus = [_normalizedPhoneNumber characterAtIndex:0] == '+';
if (!firstCharacterIsPlus) {
if (errorRef) {
NSString *message = [NSString stringWithFormat:@"Phone number %@ should start with '+'",
_normalizedPhoneNumber];
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : message };
*errorRef = [NSError errorWithDomain:FUIPhoneNumberValidationErrorDomain
code:FUIPhoneNumberValidationErrorMissingPlus
userInfo:userInfo];
}
return false;
}
BOOL containsMoreThanThePlus = self.normalizedPhoneNumber.length > 1;
if (!containsMoreThanThePlus) {
if (errorRef) {
NSString *message = [NSString stringWithFormat:@"Phone number %@ should have only one '+'",
_normalizedPhoneNumber];
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : message };
*errorRef = [NSError errorWithDomain:FUIPhoneNumberValidationErrorDomain
code:FUIPhoneNumberValidationErrorMissingDialCode
userInfo:userInfo];
}
return false;
}
BOOL containsMoreThanTheCountryCode =
self.normalizedPhoneNumber.length > 1 + self.countryCode.dialCode.length;
if (!containsMoreThanTheCountryCode) {
if (errorRef) {
NSString *message =
[NSString stringWithFormat:@"Phone number %@ should have only one country code",
_normalizedPhoneNumber];
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : message };
*errorRef = [NSError errorWithDomain:FUIPhoneNumberValidationErrorDomain
code:FUIPhoneNumberValidationErrorMissingNumber
userInfo:userInfo];
}
return false;
}
return true;
}

@end

NS_ASSUME_NONNULL_END
Loading