aboutsummaryrefslogtreecommitdiffhomepage
path: root/AuthSamples
diff options
context:
space:
mode:
authorGravatar Xiangtian Dai <xiangtian@google.com>2017-08-01 11:15:35 -0700
committerGravatar GitHub <noreply@github.com>2017-08-01 11:15:35 -0700
commit18fef1fea0c2c1e95b6b0d9b154810d93d247df1 (patch)
treeb4e76944bb67a76a4202a89383b6ec4295b0deb9 /AuthSamples
parent91fee9d66dabc6d7db34df1a47fc22a50b45ffb2 (diff)
Enables auth sample app to use multiple Firebase Apps. (#162)
Diffstat (limited to 'AuthSamples')
-rw-r--r--AuthSamples/Sample/AppManager.h80
-rw-r--r--AuthSamples/Sample/AppManager.m135
-rw-r--r--AuthSamples/Sample/GoogleAuthProvider.m3
-rw-r--r--AuthSamples/Sample/MainViewController.m165
-rw-r--r--AuthSamples/Sample/SettingsViewController.m122
-rw-r--r--AuthSamples/Samples.xcodeproj/project.pbxproj6
6 files changed, 384 insertions, 127 deletions
diff --git a/AuthSamples/Sample/AppManager.h b/AuthSamples/Sample/AppManager.h
new file mode 100644
index 0000000..e8e53a7
--- /dev/null
+++ b/AuthSamples/Sample/AppManager.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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>
+
+@class FIRApp;
+@class FIRAuth;
+@class FIROptions;
+@class FIRPhoneAuthProvider;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** @class AppManager
+ @brief A manager of global FIRApp instances.
+ */
+@interface AppManager : NSObject
+
+/** @property count
+ @brief The total count of apps under management, including the default app.
+ */
+@property(nonatomic, assign, readonly) int count;
+
+/** @property active
+ @brief The index of the currently active app, 0 being the default app.
+ */
+@property(nonatomic, assign) int active;
+
+/** @fn appAtIndex:
+ @brief Retrieves the app at the given index.
+ @param index The index of the app to be retrieved, 0 being the default app.
+ @return The app at the given index.
+ */
+- (nullable FIRApp *)appAtIndex:(int)index;
+
+/** @fn recreateAppAtIndex:withOptions:completion:
+ @brief Deletes the app at the given index, and optionally creates it again with given options.
+ @param index The index of the app to be recreated, 0 being the default app.
+ @param options Optionally, the new options with which app should be created.
+ @param completion The block to call when completes.
+ */
+- (void)recreateAppAtIndex:(int)index
+ withOptions:(nullable FIROptions *)options
+ completion:(void (^)())completion;
+
+/** @fn sharedInstance
+ @brief Gets a shared instance of the class.
+ */
++ (instancetype)sharedInstance;
+
+/** @fn app
+ @brief A shortcut to get the currently active app.
+ */
++ (FIRApp *)app;
+
+/** @fn auth
+ @brief A shortcut to get the auth instance for the currently active app.
+ */
++ (FIRAuth *)auth;
+
+/** @fn phoneAuthProvider
+ @brief A shortcut to get the phone auth provider for the currently active app.
+ */
++ (FIRPhoneAuthProvider *)phoneAuthProvider;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/AuthSamples/Sample/AppManager.m b/AuthSamples/Sample/AppManager.m
new file mode 100644
index 0000000..116fcf7
--- /dev/null
+++ b/AuthSamples/Sample/AppManager.m
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2017 Google
+ *
+ * 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 "AppManager.h"
+
+#import "FirebaseAuth.h"
+#import "FirebaseCore.h"
+#import "FIRPhoneAuthProvider.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+// Declares a private method of FIRInstanceID to work around a bug.
+@interface FIRInstanceID : NSObject
++ (void)notifyTokenRefresh;
+@end
+
+@implementation AppManager {
+ /** @var _createdAppNames
+ @brief The set of names of live (created but not deleted) app, to avoid iCore warnings.
+ */
+ NSMutableSet<NSString *> *_liveAppNames;
+}
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ _count = 2;
+ _liveAppNames = [[NSMutableSet<NSString *> alloc] initWithCapacity:_count - 1];
+ }
+ return self;
+}
+
+- (nullable FIRApp *)appAtIndex:(int)index {
+ if (index == 0) {
+ return [FIRApp defaultApp];
+ }
+ NSString *name = [self appNameWithIndex:index];
+ if ([_liveAppNames containsObject:name]) {
+ return [FIRApp appNamed:[self appNameWithIndex:index]];
+ }
+ return nil;
+}
+
+- (void)recreateAppAtIndex:(int)index
+ withOptions:(nullable FIROptions *)options
+ completion:(void (^)())completion {
+ [self deleteAppAtIndex:index completion:^() {
+ if (index == 0) {
+ [FIRInstanceID notifyTokenRefresh]; // b/28967043
+ if (options) {
+ [FIRApp configureWithOptions:options];
+ }
+ } else {
+ NSString *name = [self appNameWithIndex:index];
+ if (options) {
+ [FIRApp configureWithName:name options:options];
+ [_liveAppNames addObject:name];
+ } else {
+ [_liveAppNames removeObject:name];
+ }
+ }
+ completion();
+ }];
+}
+
++ (instancetype)sharedInstance {
+ static dispatch_once_t onceToken;
+ static AppManager *sharedInstance;
+ dispatch_once(&onceToken, ^{
+ sharedInstance = [[self alloc] init];
+ });
+ return sharedInstance;
+}
+
++ (FIRApp *)app {
+ AppManager *manager = [self sharedInstance];
+ return [manager appAtIndex:manager.active];
+}
+
++ (FIRAuth *)auth {
+ return [FIRAuth authWithApp:[self app]];
+}
+
++ (FIRPhoneAuthProvider *)phoneAuthProvider {
+ return [FIRPhoneAuthProvider providerWithAuth:[self auth]];
+}
+
+#pragma mark - Helpers
+
+/** @fn appNameWithIndex:
+ @brief Gets the app name for the given index.
+ @param index The index of the app managed by this instance.
+ @returns The app name for the FIRApp instance.
+ */
+- (NSString *)appNameWithIndex:(int)index {
+ return [NSString stringWithFormat:@"APP_%02d", index];
+}
+
+/** @fn deleteAppAtIndex:withOptions:completion:
+ @brief Deletes the app at the given index.
+ @param index The index of the app to be deleted, 0 being the default app.
+ @param completion The block to call when completes.
+ */
+- (void)deleteAppAtIndex:(int)index
+ completion:(void (^)())completion {
+ FIRApp *app = [self appAtIndex:index];
+ if (app) {
+ [app deleteApp:^(BOOL success) {
+ if (success) {
+ completion();
+ } else {
+ NSLog(@"Failed to delete app '%@'.", app.name);
+ }
+ }];
+ } else {
+ completion();
+ }
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/AuthSamples/Sample/GoogleAuthProvider.m b/AuthSamples/Sample/GoogleAuthProvider.m
index 23285cc..e63ade0 100644
--- a/AuthSamples/Sample/GoogleAuthProvider.m
+++ b/AuthSamples/Sample/GoogleAuthProvider.m
@@ -18,6 +18,7 @@
#import <GoogleSignIn/GoogleSignIn.h>
+#import "AppManager.h"
#import "FIRApp.h"
#import "FIROptions.h"
#import "FIRGoogleAuthProvider.h"
@@ -123,7 +124,7 @@ typedef void (^GoogleSignInCallback)(GIDGoogleUser *user, NSError *error);
}
- (NSString *)googleClientID {
- return [FIRApp defaultApp].options.clientID;
+ return [AppManager app].options.clientID;
}
@end
diff --git a/AuthSamples/Sample/MainViewController.m b/AuthSamples/Sample/MainViewController.m
index 8ee1b39..ec97506 100644
--- a/AuthSamples/Sample/MainViewController.m
+++ b/AuthSamples/Sample/MainViewController.m
@@ -18,6 +18,7 @@
#import <objc/runtime.h>
+#import "AppManager.h"
#import "AuthCredentials.h"
#import "FIRAdditionalUserInfo.h"
#import "FirebaseCommunity/FIRApp.h"
@@ -578,6 +579,10 @@ typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable e
_userInMemoryInfoTableViewCell.userInfoProfileURLImageView.layer.cornerRadius =
_userInMemoryInfoTableViewCell.userInfoProfileURLImageView.frame.size.width / 2.0f;
_userInMemoryInfoTableViewCell.userInfoProfileURLImageView.layer.masksToBounds = YES;
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
[self updateTable];
[self updateUserInfo];
}
@@ -753,7 +758,7 @@ typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable e
}
- (IBAction)memoryPlus {
- _userInMemory = [FIRAuth auth].currentUser;
+ _userInMemory = [AppManager auth].currentUser;
[self updateUserInfo];
}
@@ -806,9 +811,9 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
if (!userPressedOK || !newPassword.length) {
return;
}
- [[FIRAuth auth] confirmPasswordResetWithCode:queryItems[@"oobCode"]
- newPassword:newPassword
- completion:^(NSError *_Nullable error) {
+ [[AppManager auth] confirmPasswordResetWithCode:queryItems[@"oobCode"]
+ newPassword:newPassword
+ completion:^(NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"Password reset failed" error:error];
@@ -843,8 +848,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
[self logFailedTest:@"The test needs a valid credential to continue."];
return;
}
- [[FIRAuth auth] signInWithCredential:credential completion:^(FIRUser *_Nullable user,
- NSError *_Nullable error) {
+ [[AppManager auth] signInWithCredential:credential completion:^(FIRUser *_Nullable user,
+ NSError *_Nullable error) {
if (error) {
[self logFailure:@"sign-in with provider failed" error:error];
[self logFailedTest:@"Sign-in should succeed"];
@@ -865,7 +870,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
message:kSafariGoogleSignOutMessagePrompt
showCancelButton:NO
completion:^(BOOL userPressedOK, NSString *_Nullable userInput) {
- FIRAuth *auth = [FIRAuth auth];
+ FIRAuth *auth = [AppManager auth];
if (!auth) {
[self logFailedTest:@"Could not obtain auth object."];
return;
@@ -906,7 +911,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
message:kSafariFacebookSignOutMessagePrompt
showCancelButton:NO
completion:^(BOOL userPressedOK, NSString *_Nullable userInput) {
- FIRAuth *auth = [FIRAuth auth];
+ FIRAuth *auth = [AppManager auth];
if (!auth) {
[self logFailedTest:@"Could not obtain auth object."];
return;
@@ -931,7 +936,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
*/
- (void)automatedEmailSignUp {
[self log:@"INITIATING AUTOMATED MANUAL TEST FOR FACEBOOK SIGN IN:"];
- FIRAuth *auth = [FIRAuth auth];
+ FIRAuth *auth = [AppManager auth];
if (!auth) {
[self logFailedTest:@"Could not obtain auth object."];
return;
@@ -974,7 +979,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
*/
- (void)automatedAnonymousSignIn {
[self log:@"INITIATING AUTOMATED MANUAL TEST FOR ANONYMOUS SIGN IN:"];
- FIRAuth *auth = [FIRAuth auth];
+ FIRAuth *auth = [AppManager auth];
if (!auth) {
[self logFailedTest:@"Could not obtain auth object."];
return;
@@ -999,7 +1004,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
@param callback The callback to be executed.
*/
- (void)signInAnonymouslyWithCallback:(nullable FIRAuthResultCallback)callback {
- FIRAuth *auth = [FIRAuth auth];
+ FIRAuth *auth = [AppManager auth];
if (!auth) {
[self logFailedTest:@"Could not obtain auth object."];
return;
@@ -1023,7 +1028,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
*/
- (void)automatedAccountLinking {
[self log:@"INITIATING AUTOMATED MANUAL TEST FOR ACCOUNT LINKING:"];
- FIRAuth *auth = [FIRAuth auth];
+ FIRAuth *auth = [AppManager auth];
if (!auth) {
[self logFailedTest:@"Could not obtain auth object."];
return;
@@ -1098,7 +1103,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
[self log:@"There was an error retrieving the custom token."];
return;
}
- FIRAuth *auth = [FIRAuth auth];
+ FIRAuth *auth = [AppManager auth];
[auth signInWithCustomToken:customToken
completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
if (error) {
@@ -1158,8 +1163,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
[self log:@"There was an error retrieving the custom token."];
return;
}
- [[FIRAuth auth] signInWithCustomToken:customToken
- completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
+ [[AppManager auth] signInWithCustomToken:customToken
+ completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
if (error) {
[self logFailure:@"sign-in with custom token failed" error:error];
[self logFailedTest:@"A fresh custom token should succeed in signing-in."];
@@ -1188,8 +1193,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
[self log:@"There was an error retrieving the custom token."];
return;
}
- [[FIRAuth auth] signInWithCustomToken:customToken
- completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
+ [[AppManager auth] signInWithCustomToken:customToken
+ completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
if (error) {
[self logFailure:@"sign-in with custom token failed" error:error];
[self logFailedTest:@"A fresh custom token should succeed in signing-in."];
@@ -1211,7 +1216,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
@param completion The completion block to continue the automatic test flow.
*/
- (void)updateEmailPasswordWithCompletion:(void(^)(void))completion {
- FIRAuth *auth = [FIRAuth auth];
+ FIRAuth *auth = [AppManager auth];
[auth.currentUser updateEmail:kFakeEmail completion:^(NSError *_Nullable error) {
if (error) {
[self logFailure:@"update email failed" error:error];
@@ -1258,7 +1263,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
@param completion The completion block to continue the automatic test flow.
*/
- (void)updateDisplayNameAndPhotoURlWithCompletion:(void(^)(void))completion {
- FIRAuth *auth = [FIRAuth auth];
+ FIRAuth *auth = [AppManager auth];
FIRUserProfileChangeRequest *changeRequest = [auth.currentUser profileChangeRequest];
changeRequest.photoURL = [NSURL URLWithString:kFakeDisplayPhotoUrl];
[changeRequest commitChangesWithCompletion:^(NSError *_Nullable error) {
@@ -1291,8 +1296,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
[self log:[NSString stringWithFormat:@"Auth State Did Change Listener #%lu was added.",
(unsigned long)index]];
FIRAuthStateDidChangeListenerHandle handle =
- [[FIRAuth auth] addAuthStateDidChangeListener:^(FIRAuth *_Nonnull auth,
- FIRUser *_Nullable user) {
+ [[AppManager auth] addAuthStateDidChangeListener:^(FIRAuth *_Nonnull auth,
+ FIRUser *_Nullable user) {
[weakSelf log:[NSString stringWithFormat:
@"Auth State Did Change Listener #%lu was invoked on user '%@'.",
(unsigned long)index, user.uid]];
@@ -1310,7 +1315,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
NSUInteger index = _authStateDidChangeListeners.count - 1;
FIRAuthStateDidChangeListenerHandle handle = _authStateDidChangeListeners.lastObject;
- [[FIRAuth auth] removeAuthStateDidChangeListener:handle];
+ [[AppManager auth] removeAuthStateDidChangeListener:handle];
[_authStateDidChangeListeners removeObject:handle];
NSString *logString =
[NSString stringWithFormat:@"Auth State Did Change Listener #%lu was removed.",
@@ -1327,8 +1332,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
[self log:[NSString stringWithFormat:@"ID Token Did Change Listener #%lu was added.",
(unsigned long)index]];
FIRIDTokenDidChangeListenerHandle handle =
- [[FIRAuth auth] addIDTokenDidChangeListener:^(FIRAuth *_Nonnull auth,
- FIRUser *_Nullable user) {
+ [[AppManager auth] addIDTokenDidChangeListener:^(FIRAuth *_Nonnull auth,
+ FIRUser *_Nullable user) {
[weakSelf log:[NSString stringWithFormat:
@"ID Token Did Change Listener #%lu was invoked on user '%@'.",
(unsigned long)index, user.uid]];
@@ -1346,7 +1351,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
NSUInteger index = _IDTokenDidChangeListeners.count - 1;
FIRIDTokenDidChangeListenerHandle handle = _IDTokenDidChangeListeners.lastObject;
- [[FIRAuth auth] removeIDTokenDidChangeListener:handle];
+ [[AppManager auth] removeIDTokenDidChangeListener:handle];
[_IDTokenDidChangeListeners removeObject:handle];
NSString *logString =
[NSString stringWithFormat:@"ID Token Did Change Listener #%lu was removed.",
@@ -1420,7 +1425,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
*/
- (void)presentUserInfo {
UserInfoViewController *userInfoViewController =
- [[UserInfoViewController alloc] initWithUser:[FIRAuth auth].currentUser];
+ [[UserInfoViewController alloc] initWithUser:[AppManager auth].currentUser];
[self presentViewController:userInfoViewController animated:YES completion:nil];
}
@@ -1480,8 +1485,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
[FIREmailAuthProvider credentialWithEmail:email
password:password];
[self showSpinner:^{
- [[FIRAuth auth] signInWithCredential:credential
- completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
+ [[AppManager auth] signInWithCredential:credential
+ completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"sign-in with Email/Password failed" error:error];
@@ -1504,9 +1509,9 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
- (void)signUpNewEmail:(NSString *)email
password:(NSString *)password
callback:(nullable FIRAuthResultCallback)callback {
- [[FIRAuth auth] createUserWithEmail:email
- password:password
- completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
+ [[AppManager auth] createUserWithEmail:email
+ password:password
+ completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
if (error) {
[self logFailure:@"sign-up with Email/Password failed" error:error];
if (callback) {
@@ -1546,7 +1551,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
- (void)signOut {
[[AuthProviders google] signOut];
[[AuthProviders facebook] signOut];
- [[FIRAuth auth] signOut:NULL];
+ [[AppManager auth] signOut:NULL];
}
/** @fn deleteAccount
@@ -1673,7 +1678,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
@param retrieveData Defines if additional provider data should be read.
*/
- (void)signinWithProvider:(id<AuthProvider>)authProvider retrieveData:(BOOL)retrieveData {
- FIRAuth *auth = [FIRAuth auth];
+ FIRAuth *auth = [AppManager auth];
if (!auth) {
return;
}
@@ -1965,9 +1970,9 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
[self showSpinner:^{
- [[FIRAuth auth] fetchProvidersForEmail:userInput
- completion:^(NSArray<NSString *> *_Nullable providers,
- NSError *_Nullable error) {
+ [[AppManager auth] fetchProvidersForEmail:userInput
+ completion:^(NSArray<NSString *> *_Nullable providers,
+ NSError *_Nullable error) {
if (error) {
[self logFailure:@"get providers for email failed" error:error];
} else {
@@ -2015,7 +2020,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
return;
}
[self showSpinner:^{
- [[FIRAuth auth] sendPasswordResetWithEmail:userInput completion:^(NSError *_Nullable error) {
+ [[AppManager auth] sendPasswordResetWithEmail:userInput completion:^(NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"request password reset failed" error:error];
@@ -2045,9 +2050,9 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
actionCodeSettings.URL = [NSURL URLWithString:KCONTINUE_URL];
actionCodeSettings.handleCodeInApp = YES;
- [[FIRAuth auth] sendPasswordResetWithEmail:userInput
- actionCodeSettings:actionCodeSettings
- completion:^(NSError *_Nullable error) {
+ [[AppManager auth] sendPasswordResetWithEmail:userInput
+ actionCodeSettings:actionCodeSettings
+ completion:^(NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"request password reset failed" error:error];
@@ -2080,9 +2085,9 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
[self showSpinner:^{
- [[FIRAuth auth] confirmPasswordResetWithCode:code
- newPassword:userInput
- completion:^(NSError *_Nullable error) {
+ [[AppManager auth] confirmPasswordResetWithCode:code
+ newPassword:userInput
+ completion:^(NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"Password reset failed" error:error];
@@ -2108,8 +2113,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
return;
}
[self showSpinner:^{
- [[FIRAuth auth] checkActionCode:userInput completion:^(FIRActionCodeInfo *_Nullable info,
- NSError *_Nullable error) {
+ [[AppManager auth] checkActionCode:userInput completion:^(FIRActionCodeInfo *_Nullable info,
+ NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"Check action code failed" error:error];
@@ -2139,7 +2144,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
[self showSpinner:^{
- [[FIRAuth auth] applyActionCode:userInput completion:^(NSError *_Nullable error) {
+ [[AppManager auth] applyActionCode:userInput completion:^(NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"Apply action code failed" error:error];
@@ -2164,8 +2169,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
return;
}
[self showSpinner:^{
- [[FIRAuth auth] verifyPasswordResetCode:userInput completion:^(NSString *_Nullable email,
- NSError *_Nullable error) {
+ [[AppManager auth] verifyPasswordResetCode:userInput completion:^(NSString *_Nullable email,
+ NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"Verify password reset code failed" error:error];
@@ -2267,9 +2272,9 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
[self showSpinner:^{
- [[FIRAuth auth] createUserWithEmail:email
- password:password
- completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
+ [[AppManager auth] createUserWithEmail:email
+ password:password
+ completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
if (error) {
[self logFailure:@"create user failed" error:error];
} else {
@@ -2295,9 +2300,9 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
return;
}
[self showSpinner:^{
- [[FIRPhoneAuthProvider provider] verifyPhoneNumber:phoneNumber
- completion:^(NSString *_Nullable verificationID,
- NSError *_Nullable error) {
+ [[AppManager phoneAuthProvider] verifyPhoneNumber:phoneNumber
+ completion:^(NSString *_Nullable verificationID,
+ NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"failed to send verification code" error:error];
@@ -2315,11 +2320,11 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
[self showSpinner:^{
FIRAuthCredential *credential =
- [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
- verificationCode:verificationCode];
- [[FIRAuth auth] signInWithCredential:credential
- completion:^(FIRUser *_Nullable user,
- NSError *_Nullable error) {
+ [[AppManager phoneAuthProvider] credentialWithVerificationID:verificationID
+ verificationCode:verificationCode];
+ [[AppManager auth] signInWithCredential:credential
+ completion:^(FIRUser *_Nullable user,
+ NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"failed to verify phone number" error:error];
@@ -2347,9 +2352,9 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
return;
}
[self showSpinner:^{
- [[FIRPhoneAuthProvider provider] verifyPhoneNumber:phoneNumber
- completion:^(NSString *_Nullable verificationID,
- NSError *_Nullable error) {
+ [[AppManager phoneAuthProvider] verifyPhoneNumber:phoneNumber
+ completion:^(NSString *_Nullable verificationID,
+ NSError *_Nullable error) {
if (error) {
[self logFailure:@"failed to send verification code" error:error];
[self showMessagePrompt:error.localizedDescription];
@@ -2366,8 +2371,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
[self showSpinner:^{
FIRPhoneAuthCredential *credential =
- [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
- verificationCode:verificationCode];
+ [[AppManager phoneAuthProvider] credentialWithVerificationID:verificationID
+ verificationCode:verificationCode];
[[self user] updatePhoneNumberCredential:credential
completion:^(NSError *_Nullable error) {
if (error) {
@@ -2398,9 +2403,9 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
return;
}
[self showSpinner:^{
- [[FIRPhoneAuthProvider provider] verifyPhoneNumber:phoneNumber
- completion:^(NSString *_Nullable verificationID,
- NSError *_Nullable error) {
+ [[AppManager phoneAuthProvider] verifyPhoneNumber:phoneNumber
+ completion:^(NSString *_Nullable verificationID,
+ NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"failed to send verification code" error:error];
@@ -2418,8 +2423,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
[self showSpinner:^{
FIRPhoneAuthCredential *credential =
- [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
- verificationCode:verificationCode];
+ [[AppManager phoneAuthProvider] credentialWithVerificationID:verificationID
+ verificationCode:verificationCode];
[[self user] linkWithCredential:credential
completion:^(FIRUser *_Nullable user,
NSError *_Nullable error) {
@@ -2438,9 +2443,9 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
[self showSpinner:^{
FIRPhoneAuthCredential *credential =
error.userInfo[FIRAuthUpdatedCredentialKey];
- [[FIRAuth auth] signInWithCredential:credential
- completion:^(FIRUser *_Nullable user,
- NSError *_Nullable error) {
+ [[AppManager auth] signInWithCredential:credential
+ completion:^(FIRUser *_Nullable user,
+ NSError *_Nullable error) {
[self hideSpinner:^{
if (error) {
[self logFailure:@"failed to verify phone number" error:error];
@@ -2473,8 +2478,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
@brief Signs in as an anonymous user.
*/
- (void)signInAnonymously {
- [[FIRAuth auth] signInAnonymouslyWithCompletion:^(FIRUser *_Nullable user,
- NSError *_Nullable error) {
+ [[AppManager auth] signInAnonymouslyWithCompletion:^(FIRUser *_Nullable user,
+ NSError *_Nullable error) {
if (error) {
[self logFailure:@"sign-in anonymously failed" error:error];
} else {
@@ -2497,8 +2502,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
FIRAuthCredential *credential =
[FIROAuthProvider credentialWithProviderID:FIRGitHubAuthProviderID accessToken:accessToken];
if (credential) {
- [[FIRAuth auth] signInWithCredential:credential completion:^(FIRUser *_Nullable user,
- NSError *_Nullable error) {
+ [[AppManager auth] signInWithCredential:credential completion:^(FIRUser *_Nullable user,
+ NSError *_Nullable error) {
if (error) {
[self logFailure:@"sign-in with provider failed" error:error];
} else {
@@ -2568,7 +2573,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
user in memory" setting.
*/
- (FIRUser *)user {
- return _useUserInMemory ? _userInMemory : [FIRAuth auth].currentUser;
+ return _useUserInMemory ? _userInMemory : [AppManager auth].currentUser;
}
/** @fn showTypicalUIForUserUpdateResultsWithTitle:error:
@@ -2623,8 +2628,8 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
- (void)doSignInWithCustomToken:(NSString *_Nullable)userEnteredTokenText {
- [[FIRAuth auth] signInWithCustomToken:userEnteredTokenText
- completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
+ [[AppManager auth] signInWithCustomToken:userEnteredTokenText
+ completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
if (error) {
[self logFailure:@"sign-in with custom token failed" error:error];
[self showMessagePromptWithTitle:kSignInErrorAlertTitle
@@ -2642,7 +2647,7 @@ static NSDictionary<NSString *, NSString *> *parseURL(NSString *urlString) {
}
- (void)updateUserInfo {
- [_userInfoTableViewCell updateContentsWithUser:[FIRAuth auth].currentUser];
+ [_userInfoTableViewCell updateContentsWithUser:[AppManager auth].currentUser];
[_userInMemoryInfoTableViewCell updateContentsWithUser:_userInMemory];
}
diff --git a/AuthSamples/Sample/SettingsViewController.m b/AuthSamples/Sample/SettingsViewController.m
index f0458bb..df30899 100644
--- a/AuthSamples/Sample/SettingsViewController.m
+++ b/AuthSamples/Sample/SettingsViewController.m
@@ -18,22 +18,17 @@
#import <objc/runtime.h>
-#import "FIRApp.h"
+#import "AppManager.h"
#import "FIRAuth_Internal.h"
#import "FIRAuthAPNSToken.h"
#import "FIRAuthAPNSTokenManager.h"
#import "FIRAuthAppCredential.h"
#import "FIRAuthAppCredentialManager.h"
-#import "FIROptions.h"
#import "FirebaseAuth.h"
+#import "FirebaseCore.h"
#import "StaticContentTableViewManager.h"
#import "UIViewController+Alerts.h"
-// Declares a private method of FIRInstanceID to work around a bug.
-@interface FIRInstanceID : NSObject
-+ (void)notifyTokenRefresh;
-@end
-
/** @var kIdentityToolkitRequestClassName
@brief The class name of Identity Toolkit requests.
*/
@@ -166,13 +161,6 @@ static NSString *truncatedString(NSString *string, NSUInteger length) {
value:versionString(
FirebaseAuthVersionString, FirebaseAuthVersionNumber)],
]],
- [StaticContentTableViewSection sectionWithTitle:@"Client Identity" cells:@[
- [StaticContentTableViewCell cellWithTitle:@"Project"
- value:[self currentProjectID]
- action:^{
- [weakSelf toggleClientProject];
- }],
- ]],
[StaticContentTableViewSection sectionWithTitle:@"API Hosts" cells:@[
[StaticContentTableViewCell cellWithTitle:@"Identity Toolkit"
value:APIHost(kIdentityToolkitRequestClassName)
@@ -185,6 +173,23 @@ static NSString *truncatedString(NSString *string, NSUInteger length) {
[weakSelf toggleAPIHostWithRequestClassName:kSecureTokenRequestClassName];
}],
]],
+ [StaticContentTableViewSection sectionWithTitle:@"Firebase Apps" cells:@[
+ [StaticContentTableViewCell cellWithTitle:@"Active App"
+ value:[self activeAppDescription]
+ action:^{
+ [weakSelf toggleActiveApp];
+ }],
+ [StaticContentTableViewCell cellWithTitle:@"Default App"
+ value:[self projectIDForAppAtIndex:0]
+ action:^{
+ [weakSelf toggleProjectForAppAtIndex:0];
+ }],
+ [StaticContentTableViewCell cellWithTitle:@"Other App"
+ value:[self projectIDForAppAtIndex:1]
+ action:^{
+ [weakSelf toggleProjectForAppAtIndex:1];
+ }],
+ ]],
[StaticContentTableViewSection sectionWithTitle:@"Phone Auth" cells:@[
[StaticContentTableViewCell cellWithTitle:@"APNs Token"
value:[self APNSTokenString]
@@ -196,13 +201,15 @@ static NSString *truncatedString(NSString *string, NSUInteger length) {
action:^{
[weakSelf clearAppCredential];
}],
+ ]],
+ [StaticContentTableViewSection sectionWithTitle:@"Language" cells:@[
[StaticContentTableViewCell cellWithTitle:@"Auth Language"
- value:[FIRAuth auth].languageCode ?: @"[none]"
+ value:[AppManager auth].languageCode ?: @"[none]"
action:^{
[weakSelf showLanguageInput];
}],
[StaticContentTableViewCell cellWithTitle:@"Use App language" action:^{
- [[FIRAuth auth] useAppLanguage];
+ [[AppManager auth] useAppLanguage];
[weakSelf loadTableView];
}],
]],
@@ -221,49 +228,72 @@ static NSString *truncatedString(NSString *string, NSUInteger length) {
[self loadTableView];
}
-/** @fn currentProjectID
- @brief Returns the the current Firebase project ID.
+/** @fn activeAppDescription
+ @brief Returns the description for the currently active Firebase app.
+ */
+- (NSString *)activeAppDescription {
+ return [AppManager sharedInstance].active == 0 ? @"[Default]" : @"[Other]";
+}
+
+/** @fn toggleActiveApp
+ @brief Toggles the active Firebase app for the rest of the application.
*/
-- (NSString *)currentProjectID {
- NSString *APIKey = [FIRApp defaultApp].options.APIKey;
+- (void)toggleActiveApp {
+ AppManager *apps = [AppManager sharedInstance];
+ // This changes the FIRAuth instance returned from `[AppManager auth]` to be one that is
+ // associated with a different `FIRApp` instance. The sample app uses `[AppManager auth]`
+ // instead of `[FIRAuth auth]` almost everywhere. Thus, this statement switches between default
+ // and non-default `FIRApp` instances for the sample app to test against.
+ apps.active = (apps.active + 1) % apps.count;
+ [self loadTableView];
+}
+
+/** @fn projectIDForAppAtIndex:
+ @brief Returns the Firebase project ID for the Firebase app at the given index.
+ @param index The index for the app in the app manager.
+ @return The ID of the project.
+ */
+- (NSString *)projectIDForAppAtIndex:(int)index {
+ NSString *APIKey = [[AppManager sharedInstance] appAtIndex:index].options.APIKey;
for (FIROptions *options in gFirebaseAppOptions) {
if ([options.APIKey isEqualToString:APIKey]) {
return options.projectID;
}
}
- return nil;
+ return @"[none]";
}
-/** @fn toggleClientProject
- @brief Toggles the Firebase/Google project this client presents by recreating the default
+/** @fn toggleProjectForAppAtIndex:
+ @brief Toggles the Firebase project for the Firebase app at the given index by recreating the
FIRApp instance with different options.
+ @param index The index for the app to be recreated in the app manager.
*/
-- (void)toggleClientProject {
- NSString *APIKey = [FIRApp defaultApp].options.APIKey;
- for (NSUInteger i = 0 ; i < gFirebaseAppOptions.count; i++) {
- FIROptions *options = gFirebaseAppOptions[i];
+- (void)toggleProjectForAppAtIndex:(int)index {
+ NSString *APIKey = [[AppManager sharedInstance] appAtIndex:index].options.APIKey;
+ int optionIndex;
+ for (optionIndex = 0; optionIndex < gFirebaseAppOptions.count; optionIndex++) {
+ FIROptions *options = gFirebaseAppOptions[optionIndex];
if ([options.APIKey isEqualToString:APIKey]) {
- __weak typeof(self) weakSelf = self;
- [[FIRApp defaultApp] deleteApp:^(BOOL success) {
- if (success) {
- [FIRInstanceID notifyTokenRefresh]; // b/28967043
- dispatch_async(dispatch_get_main_queue(), ^() {
- FIROptions *options = gFirebaseAppOptions[(i + 1) % gFirebaseAppOptions.count];
- [FIRApp configureWithOptions:options];
- [weakSelf loadTableView];
- });
- }
- }];
- return;
+ break;
}
}
+ // For non-default apps, `nil` is considered the next option after the last options in the array.
+ int useNil = index > 0;
+ optionIndex = (optionIndex + 1 + useNil) % (gFirebaseAppOptions.count + useNil) - useNil;
+ FIROptions *options = optionIndex >= 0 ? gFirebaseAppOptions[optionIndex] : nil;
+ __weak typeof(self) weakSelf = self;
+ [[AppManager sharedInstance] recreateAppAtIndex:index withOptions:options completion:^() {
+ dispatch_async(dispatch_get_main_queue(), ^() {
+ [weakSelf loadTableView];
+ });
+ }];
}
/** @fn APNSTokenString
@brief Returns a string representing APNS token.
*/
- (NSString *)APNSTokenString {
- FIRAuthAPNSToken *token = [FIRAuth auth].tokenManager.token;
+ FIRAuthAPNSToken *token = [AppManager auth].tokenManager.token;
if (!token) {
return @"";
}
@@ -276,7 +306,7 @@ static NSString *truncatedString(NSString *string, NSUInteger length) {
@brief Clears the saved app credential.
*/
- (void)clearAPNSToken {
- FIRAuthAPNSToken *token = [FIRAuth auth].tokenManager.token;
+ FIRAuthAPNSToken *token = [AppManager auth].tokenManager.token;
if (!token) {
return;
}
@@ -288,7 +318,7 @@ static NSString *truncatedString(NSString *string, NSUInteger length) {
showCancelButton:YES
completion:^(BOOL userPressedOK, NSString *_Nullable userInput) {
if (userPressedOK) {
- [FIRAuth auth].tokenManager.token = nil;
+ [AppManager auth].tokenManager.token = nil;
[self loadTableView];
}
}];
@@ -298,7 +328,7 @@ static NSString *truncatedString(NSString *string, NSUInteger length) {
@brief Returns a string representing app credential.
*/
- (NSString *)appCredentialString {
- FIRAuthAppCredential *credential = [FIRAuth auth].appCredentialManager.credential;
+ FIRAuthAppCredential *credential = [AppManager auth].appCredentialManager.credential;
if (!credential) {
return @"";
}
@@ -311,7 +341,7 @@ static NSString *truncatedString(NSString *string, NSUInteger length) {
@brief Clears the saved app credential.
*/
- (void)clearAppCredential {
- FIRAuthAppCredential *credential = [FIRAuth auth].appCredentialManager.credential;
+ FIRAuthAppCredential *credential = [AppManager auth].appCredentialManager.credential;
if (!credential) {
return;
}
@@ -322,7 +352,7 @@ static NSString *truncatedString(NSString *string, NSUInteger length) {
showCancelButton:YES
completion:^(BOOL userPressedOK, NSString *_Nullable userInput) {
if (userPressedOK) {
- [[FIRAuth auth].appCredentialManager clearCredential];
+ [[AppManager auth].appCredentialManager clearCredential];
[self loadTableView];
}
}];
@@ -337,7 +367,7 @@ static NSString *truncatedString(NSString *string, NSUInteger length) {
if (!userPressedOK) {
return;
}
- [FIRAuth auth].languageCode = languageCode.length ? languageCode : nil;
+ [AppManager auth].languageCode = languageCode.length ? languageCode : nil;
[self loadTableView];
}];
}
diff --git a/AuthSamples/Samples.xcodeproj/project.pbxproj b/AuthSamples/Samples.xcodeproj/project.pbxproj
index 3b1c2d8..30738ca 100644
--- a/AuthSamples/Samples.xcodeproj/project.pbxproj
+++ b/AuthSamples/Samples.xcodeproj/project.pbxproj
@@ -32,6 +32,7 @@
BD555A1DCF4E889DC3338248 /* Pods_FirebaseAuthUnitTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4FFAD3F37BC4D7CEF0CAD579 /* Pods_FirebaseAuthUnitTests.framework */; };
BE7B447C1EC2508300FA4C1B /* AuthCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE7B447A1EC2507800FA4C1B /* AuthCredentials.swift */; };
D99C31A11ED7A0ED00607534 /* GoogleService-Info_multi.plist in Resources */ = {isa = PBXBuildFile; fileRef = D99C31A01ED7A0ED00607534 /* GoogleService-Info_multi.plist */; };
+ D9AC266E1F2ABBC5002B789B /* AppManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D9AC266C1F2ABBC5002B789B /* AppManager.m */; };
D9AE2A641ED751C900DDAD18 /* FirebaseAuthApiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D9AE2A631ED751C900DDAD18 /* FirebaseAuthApiTests.m */; };
D9AE2A661ED757C400DDAD18 /* FirebaseAuthEarlGreyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D9AE2A651ED757C400DDAD18 /* FirebaseAuthEarlGreyTests.m */; };
DE5371B31EA7E89D000DA57F /* FIRAdditionalUserInfoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DE5371831EA7E89D000DA57F /* FIRAdditionalUserInfoTests.m */; };
@@ -199,6 +200,8 @@
D90D8C411ED3B72B00C6BE87 /* AuthCredentials.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuthCredentials.h; sourceTree = "<group>"; };
D930B7611EDF9AAD001265FD /* Sample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Sample.entitlements; sourceTree = "<group>"; };
D99C31A01ED7A0ED00607534 /* GoogleService-Info_multi.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info_multi.plist"; sourceTree = "<group>"; };
+ D9AC266C1F2ABBC5002B789B /* AppManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppManager.m; sourceTree = "<group>"; };
+ D9AC266D1F2ABBC5002B789B /* AppManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppManager.h; sourceTree = "<group>"; };
D9AE2A631ED751C900DDAD18 /* FirebaseAuthApiTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FirebaseAuthApiTests.m; sourceTree = "<group>"; };
D9AE2A651ED757C400DDAD18 /* FirebaseAuthEarlGreyTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FirebaseAuthEarlGreyTests.m; sourceTree = "<group>"; };
D9D6F0DE0BB3F49EF1B7CBB3 /* Pods-SwiftSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftSample.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample.release.xcconfig"; sourceTree = "<group>"; };
@@ -418,6 +421,8 @@
children = (
7EDFD35D1F0EA29200B29DC5 /* Localizable.strings */,
D930B7611EDF9AAD001265FD /* Sample.entitlements */,
+ D9AC266D1F2ABBC5002B789B /* AppManager.h */,
+ D9AC266C1F2ABBC5002B789B /* AppManager.m */,
DECEA5661EBBDFB400273585 /* AuthCredentials.h */,
DECE049B1E9FEAE600164CA4 /* Application.plist */,
DECE049C1E9FEAE600164CA4 /* ApplicationDelegate.h */,
@@ -1191,6 +1196,7 @@
DECE04E51E9FEAE600164CA4 /* CustomTokenDataEntryViewController.m in Sources */,
DECE04E41E9FEAE600164CA4 /* AuthProviders.m in Sources */,
DECE04EF1E9FEAE600164CA4 /* SettingsViewController.m in Sources */,
+ D9AC266E1F2ABBC5002B789B /* AppManager.m in Sources */,
DECE04E71E9FEAE600164CA4 /* GoogleAuthProvider.m in Sources */,
DECE04F51E9FEAE600164CA4 /* UserInfoViewController.m in Sources */,
DECE04EC1E9FEAE600164CA4 /* MainViewController.m in Sources */,