From 21244ac328c80aed264ae288d703ea3ad16ca4be Mon Sep 17 00:00:00 2001 From: Zsika Phillip Date: Thu, 22 Feb 2018 17:09:36 -0800 Subject: [PATCH 1/3] =?UTF-8?q?Adds=20email/password=20=E2=80=9Cemail-alre?= =?UTF-8?q?ady-in-use=E2=80=9D=20flow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FirebaseAuthUI/FUIAuth.m | 68 +++++++++++-------- .../FUIPasswordSignInViewController.m | 19 +++++- ...FUIPasswordSignInViewController_Internal.h | 35 ++++++++++ 3 files changed, 92 insertions(+), 30 deletions(-) create mode 100644 FirebaseAuthUI/FUIPasswordSignInViewController_Internal.h diff --git a/FirebaseAuthUI/FUIAuth.m b/FirebaseAuthUI/FUIAuth.m index 2d9a37e6c67..79e100c18ff 100644 --- a/FirebaseAuthUI/FUIAuth.m +++ b/FirebaseAuthUI/FUIAuth.m @@ -28,6 +28,7 @@ #import "FUIAuthStrings.h" #import "FUIGoogleAuth.h" #import "FUIEmailEntryViewController.h" +#import "FUIPasswordSignInViewController_Internal.h" #import "FUIPasswordVerificationViewController.h" /** @var kAppNameCodingKey @@ -154,7 +155,7 @@ - (BOOL)signOutWithError:(NSError *_Nullable *_Nullable)error { } - (void)signInWithProviderUI:(id)providerUI - presentingViewController:(UIViewController *)presentingViewController + presentingViewController:(FUIAuthBaseViewController *)presentingViewController defaultValue:(nullable NSString *)defaultValue { // Sign out first to make sure sign in starts with a clean state. @@ -280,7 +281,7 @@ - (void)signInWithProviderUI:(id)providerUI } - (void)signInWithEmailHint:(NSString *)emailHint - presentingViewController:(UIViewController *)presentingViewController + presentingViewController:(FUIAuthBaseViewController *)presentingViewController completion:(FIRAuthDataResultCallback)completion { NSString *kTempApp = @"tempApp"; FIROptions *options = [FIROptions defaultOptions]; @@ -291,7 +292,7 @@ - (void)signInWithEmailHint:(NSString *)emailHint FIRApp *tempApp = [FIRApp appNamed:kTempApp]; // Create a new auth instance in order to perform a successful sign-in without losing the // currently signed in user on the default auth instance. - FIRAuth *auth = [FIRAuth authWithApp:tempApp]; + FIRAuth *tempAuth = [FIRAuth authWithApp:tempApp]; [self.auth fetchProvidersForEmail:emailHint completion:^(NSArray *_Nullable providers, NSError *_Nullable error) { @@ -299,39 +300,52 @@ - (void)signInWithEmailHint:(NSString *)emailHint completion(nil, error); return; } - NSString *existingFederatedProviderID = [self federatedAuthProviderFromProviders:providers]; - // Set of providers which can be auto-linked + NSString *existingFederatedProviderID = [self authProviderFromProviders:providers]; + // Set of providers which can be auto-linked. NSSet *supportedProviders = - [NSSet setWithObjects:FIRGoogleAuthProviderID, FIRFacebookAuthProviderID, nil]; + [NSSet setWithObjects:FIRGoogleAuthProviderID, + FIRFacebookAuthProviderID, + FIREmailAuthProviderID, + nil]; if ([supportedProviders containsObject:existingFederatedProviderID]) { - id authProviderUI; - // Retrieve the FUIAuthProvider instance from FUIAuth for the existing provider ID. - for (id provider in self.providers) { - if ([provider.providerID isEqualToString:existingFederatedProviderID]) { - authProviderUI = provider; - break; + if ([existingFederatedProviderID isEqualToString:FIREmailAuthProviderID]) { + FUIAuth *authUI = [[FUIAuth alloc]initWithAuth:tempAuth]; + // Email password sign-in + FUIPasswordSignInViewController *controller = + [[FUIPasswordSignInViewController alloc] initWithAuthUI:authUI email:emailHint]; + [controller setOnDismissCallback:completion]; + [presentingViewController pushViewController:controller]; + } else { + id authProviderUI; + // Retrieve the FUIAuthProvider instance from FUIAuth for the existing provider ID. + for (id provider in self.providers) { + if ([provider.providerID isEqualToString:existingFederatedProviderID]) { + authProviderUI = provider; + break; + } } + [authProviderUI signOut]; + [authProviderUI signInWithDefaultValue:emailHint + presentingViewController:presentingViewController + completion:^(FIRAuthCredential *_Nullable credential, + NSError *_Nullable error, + FIRAuthResultCallback _Nullable result) { + if (error) { + completion(nil, error); + return; + } + [tempAuth signInAndRetrieveDataWithCredential:credential completion:completion]; + }]; } - [authProviderUI signOut]; - [authProviderUI signInWithDefaultValue:emailHint - presentingViewController:presentingViewController - completion:^(FIRAuthCredential *_Nullable credential, - NSError *_Nullable error, - FIRAuthResultCallback _Nullable result) { - if (error) { - completion(nil, error); - return; - } - - [auth signInAndRetrieveDataWithCredential:credential completion:completion]; - }]; } }]; } -- (nullable NSString *)federatedAuthProviderFromProviders:(NSArray *) providers { +- (nullable NSString *)authProviderFromProviders:(NSArray *) providers { NSSet *providerSet = - [NSSet setWithArray:@[ FIRFacebookAuthProviderID, FIRGoogleAuthProviderID ]]; + [NSSet setWithArray:@[ FIRFacebookAuthProviderID, + FIRGoogleAuthProviderID, + FIREmailAuthProviderID ]]; for (NSString *provider in providers) { if ( [providerSet containsObject:provider]) { return provider; diff --git a/FirebaseAuthUI/FUIPasswordSignInViewController.m b/FirebaseAuthUI/FUIPasswordSignInViewController.m index 12426ad6157..5338f5b76c6 100644 --- a/FirebaseAuthUI/FUIPasswordSignInViewController.m +++ b/FirebaseAuthUI/FUIPasswordSignInViewController.m @@ -14,7 +14,7 @@ // limitations under the License. // -#import "FUIPasswordSignInViewController.h" +#import "FUIPasswordSignInViewController_Internal.h" #import #import "FUIAuthBaseViewController_Internal.h" @@ -59,6 +59,11 @@ @implementation FUIPasswordSignInViewController { @brief The @c UIButton which handles forgot password action. */ __weak IBOutlet UIButton *_forgotPasswordButton; + + /** @var _onDismissCallback + @brief The callback to be executed during view controller dismissal. + */ + FIRAuthDataResultCallback _onDismissCallback; } - (instancetype)initWithAuthUI:(FUIAuth *)authUI @@ -78,7 +83,7 @@ - (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil authUI:authUI]; if (self) { _email = [email copy]; - + _onDismissCallback = nil; self.title = FUILocalizedString(kStr_SignInTitle); } return self; @@ -134,7 +139,11 @@ - (void)signInWithDefaultValue:(NSString *)email andPassword:(NSString *)passwor } } [self.navigationController dismissViewControllerAnimated:YES completion:^{ - [self.authUI invokeResultCallbackWithAuthDataResult:authResult error:error]; + if (self->_onDismissCallback) { + self->_onDismissCallback(authResult, error); + } else { + [self.authUI invokeResultCallbackWithAuthDataResult:authResult error:error]; + } }]; }; @@ -195,6 +204,10 @@ - (void)didChangeEmail:(NSString *)email andPassword:(NSString *)password { self.navigationItem.rightBarButtonItem.enabled = enableActionButton; } +- (void)setOnDismissCallback:(FIRAuthDataResultCallback)callback { + _onDismissCallback = callback; +} + #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { diff --git a/FirebaseAuthUI/FUIPasswordSignInViewController_Internal.h b/FirebaseAuthUI/FUIPasswordSignInViewController_Internal.h new file mode 100644 index 00000000000..bee5ee7e504 --- /dev/null +++ b/FirebaseAuthUI/FUIPasswordSignInViewController_Internal.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2018 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 "FUIPasswordSignInViewController.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FUIPasswordSignInViewController () + +/** @fn setOnDismissCallback: + @brief Sets an optional custom callback for FUIPasswordSigInViewController during dismissal. If + this callback is set the default dismissal routine is not triggered and should be included + in this block if necessary. + @param callback The custom callback to execute during dismissal of the view controller. + */ +- (void)setOnDismissCallback:(FIRAuthDataResultCallback)callback; + +NS_ASSUME_NONNULL_END + + +@end From 96d079868287438d90c3e77033879678374000e8 Mon Sep 17 00:00:00 2001 From: Zsika Phillip Date: Fri, 23 Feb 2018 10:37:02 -0800 Subject: [PATCH 2/3] addresses commnets --- FirebaseAuthUI/FUIAuth.m | 2 +- .../FUIPasswordSignInViewController.m | 17 +++++------------ .../FUIPasswordSignInViewController_Internal.h | 10 +++++----- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/FirebaseAuthUI/FUIAuth.m b/FirebaseAuthUI/FUIAuth.m index 79e100c18ff..8e2dedcf7fb 100644 --- a/FirebaseAuthUI/FUIAuth.m +++ b/FirebaseAuthUI/FUIAuth.m @@ -313,7 +313,7 @@ - (void)signInWithEmailHint:(NSString *)emailHint // Email password sign-in FUIPasswordSignInViewController *controller = [[FUIPasswordSignInViewController alloc] initWithAuthUI:authUI email:emailHint]; - [controller setOnDismissCallback:completion]; + controller.onDismissCallback = completion; [presentingViewController pushViewController:controller]; } else { id authProviderUI; diff --git a/FirebaseAuthUI/FUIPasswordSignInViewController.m b/FirebaseAuthUI/FUIPasswordSignInViewController.m index 5338f5b76c6..d90a6398c67 100644 --- a/FirebaseAuthUI/FUIPasswordSignInViewController.m +++ b/FirebaseAuthUI/FUIPasswordSignInViewController.m @@ -59,11 +59,6 @@ @implementation FUIPasswordSignInViewController { @brief The @c UIButton which handles forgot password action. */ __weak IBOutlet UIButton *_forgotPasswordButton; - - /** @var _onDismissCallback - @brief The callback to be executed during view controller dismissal. - */ - FIRAuthDataResultCallback _onDismissCallback; } - (instancetype)initWithAuthUI:(FUIAuth *)authUI @@ -83,8 +78,12 @@ - (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil authUI:authUI]; if (self) { _email = [email copy]; - _onDismissCallback = nil; + self.title = FUILocalizedString(kStr_SignInTitle); + __weak FUIPasswordSignInViewController *weakself = self; + _onDismissCallback = ^(FIRAuthDataResult *authResult, NSError *error){ + [weakself.authUI invokeResultCallbackWithAuthDataResult:authResult error:error]; + }; } return self; } @@ -141,8 +140,6 @@ - (void)signInWithDefaultValue:(NSString *)email andPassword:(NSString *)passwor [self.navigationController dismissViewControllerAnimated:YES completion:^{ if (self->_onDismissCallback) { self->_onDismissCallback(authResult, error); - } else { - [self.authUI invokeResultCallbackWithAuthDataResult:authResult error:error]; } }]; }; @@ -204,10 +201,6 @@ - (void)didChangeEmail:(NSString *)email andPassword:(NSString *)password { self.navigationItem.rightBarButtonItem.enabled = enableActionButton; } -- (void)setOnDismissCallback:(FIRAuthDataResultCallback)callback { - _onDismissCallback = callback; -} - #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { diff --git a/FirebaseAuthUI/FUIPasswordSignInViewController_Internal.h b/FirebaseAuthUI/FUIPasswordSignInViewController_Internal.h index bee5ee7e504..3958533cf87 100644 --- a/FirebaseAuthUI/FUIPasswordSignInViewController_Internal.h +++ b/FirebaseAuthUI/FUIPasswordSignInViewController_Internal.h @@ -21,13 +21,13 @@ NS_ASSUME_NONNULL_BEGIN @interface FUIPasswordSignInViewController () -/** @fn setOnDismissCallback: +/** @property onDismissCallback: @brief Sets an optional custom callback for FUIPasswordSigInViewController during dismissal. If - this callback is set the default dismissal routine is not triggered and should be included - in this block if necessary. - @param callback The custom callback to execute during dismissal of the view controller. + this property is set the default dismissal routine is not triggered and should be included + in this block if necessary. This block is NOT set to nil after use, set to nil after using + if you wish to avoid circular references. */ -- (void)setOnDismissCallback:(FIRAuthDataResultCallback)callback; +@property(nonatomic, strong, nullable) FIRAuthDataResultCallback onDismissCallback; NS_ASSUME_NONNULL_END From 101b9a158450cb5be29575582acd8d09eae74292 Mon Sep 17 00:00:00 2001 From: Zsika Phillip Date: Fri, 23 Feb 2018 10:47:30 -0800 Subject: [PATCH 3/3] Addresses comments --- FirebaseAuthUI/FUIAuth.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/FirebaseAuthUI/FUIAuth.m b/FirebaseAuthUI/FUIAuth.m index 8e2dedcf7fb..08970c626c4 100644 --- a/FirebaseAuthUI/FUIAuth.m +++ b/FirebaseAuthUI/FUIAuth.m @@ -331,7 +331,9 @@ - (void)signInWithEmailHint:(NSString *)emailHint NSError *_Nullable error, FIRAuthResultCallback _Nullable result) { if (error) { - completion(nil, error); + if (completion) { + completion(nil, error); + } return; } [tempAuth signInAndRetrieveDataWithCredential:credential completion:completion];