diff options
author | Paul Beusterien <paulbeusterien@google.com> | 2017-05-15 12:27:07 -0700 |
---|---|---|
committer | Paul Beusterien <paulbeusterien@google.com> | 2017-05-15 12:27:07 -0700 |
commit | 98ba64449a632518bd2b86fe8d927f4a960d3ddc (patch) | |
tree | 131d9c4272fa6179fcda6c5a33fcb3b1bd57ad2e /Firebase/Database/Login | |
parent | 32461366c9e204a527ca05e6e9b9404a2454ac51 (diff) |
Initial
Diffstat (limited to 'Firebase/Database/Login')
-rw-r--r-- | Firebase/Database/Login/FAuthTokenProvider.h | 36 | ||||
-rw-r--r-- | Firebase/Database/Login/FAuthTokenProvider.m | 162 | ||||
-rw-r--r-- | Firebase/Database/Login/FIRNoopAuthTokenProvider.h | 22 | ||||
-rw-r--r-- | Firebase/Database/Login/FIRNoopAuthTokenProvider.m | 33 |
4 files changed, 253 insertions, 0 deletions
diff --git a/Firebase/Database/Login/FAuthTokenProvider.h b/Firebase/Database/Login/FAuthTokenProvider.h new file mode 100644 index 0000000..dca0026 --- /dev/null +++ b/Firebase/Database/Login/FAuthTokenProvider.h @@ -0,0 +1,36 @@ +/* + * 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> + +#import "FTypedefs.h" +#import "FTypedefs_Private.h" + +@protocol FAuthTokenProvider <NSObject> + +- (void) fetchTokenForcingRefresh:(BOOL)forceRefresh withCallback:(fbt_void_nsstring_nserror)callback; + +- (void) listenForTokenChanges:(fbt_void_nsstring)listener; + +@end + +@interface FAuthTokenProvider : NSObject + ++ (id<FAuthTokenProvider>) authTokenProviderForApp:(id)app; + +- (instancetype)init NS_UNAVAILABLE; + +@end diff --git a/Firebase/Database/Login/FAuthTokenProvider.m b/Firebase/Database/Login/FAuthTokenProvider.m new file mode 100644 index 0000000..e406ae7 --- /dev/null +++ b/Firebase/Database/Login/FAuthTokenProvider.m @@ -0,0 +1,162 @@ +/* + * 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 "FAuthTokenProvider.h" +#import "FUtilities.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRNoopAuthTokenProvider.h" + +static NSString *const FIRAuthStateDidChangeInternalNotification = @"FIRAuthStateDidChangeInternalNotification"; +static NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey = @"FIRAuthStateDidChangeInternalNotificationTokenKey"; + + +/** + * This is a hack that defines all the methods we need from FIRFirebaseApp. At runtime we use reflection to get an + * actual instance of FIRFirebaseApp. Since protocols don't carry any runtime information and selectors are invoked + * by name we can write code against this protocol as long as the method signatures of FIRFirebaseApp don't change. + */ +@protocol FIRFirebaseAppLike <NSObject> + +- (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(void (^)(NSString *_Nullable token, NSError *_Nullable error))callback; + +@end + + +/** + * This is a hack that defines all the methods we need from FIRAuth. + */ +@protocol FIRFirebaseAuthLike <NSObject> + +- (id<FIRFirebaseAppLike>) app; + +@end + +/** + * This is a hack that copies the definitions of Firebear error codes. If the error codes change in the original code, this + * will break at runtime due to undefined behavior! + */ +typedef NS_ENUM(NSUInteger, FIRErrorCode) { + /*! @var FIRErrorCodeNoAuth + @brief Represents the case where an auth-related message was sent to a @c FIRFirebaseApp + instance which has no associated @c FIRAuth instance. + */ + FIRErrorCodeNoAuth, + + /*! @var FIRErrorCodeNoSignedInUser + @brief Represents the case where an attempt was made to fetch a token when there is no signed + in user. + */ + FIRErrorCodeNoSignedInUser, +}; + + +@interface FAuthStateListenerWrapper : NSObject + +@property (nonatomic, copy) fbt_void_nsstring listener; + +@property (nonatomic, weak) id<FIRFirebaseAppLike> app; + +@end + +@implementation FAuthStateListenerWrapper + +- (instancetype) initWithListener:(fbt_void_nsstring)listener app:(id<FIRFirebaseAppLike>)app { + self = [super init]; + if (self != nil) { + self->_listener = listener; + self->_app = app; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(authStateDidChangeNotification:) + name:FIRAuthStateDidChangeInternalNotification + object:nil]; + } + return self; +} + +- (void) authStateDidChangeNotification:(NSNotification *)notification { + id<FIRFirebaseAuthLike> auth = notification.object; + if (auth.app == self->_app) { + NSDictionary *userInfo = notification.userInfo; + NSString *token = userInfo[FIRAuthStateDidChangeInternalNotificationTokenKey]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + self.listener(token); + }); + } +} + +- (void) dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end + + +@interface FIRFirebearAuthTokenProvider : NSObject <FAuthTokenProvider> + +@property (nonatomic, strong) id<FIRFirebaseAppLike> app; +/** Strong references to the auth listeners as they are only weak in FIRFirebaseApp */ +@property (nonatomic, strong) NSMutableArray *authListeners; + +- (instancetype) initWithFirebaseApp:(id<FIRFirebaseAppLike>)app; + +@end + +@implementation FIRFirebearAuthTokenProvider + +- (instancetype) initWithFirebaseApp:(id<FIRFirebaseAppLike>)app { + self = [super init]; + if (self != nil) { + self->_app = app; + self->_authListeners = [NSMutableArray array]; + } + return self; +} + +- (void) fetchTokenForcingRefresh:(BOOL)forceRefresh withCallback:(fbt_void_nsstring_nserror)callback { + // TODO: Don't fetch token if there is no current user + [self.app getTokenForcingRefresh:forceRefresh withCallback:^(NSString * _Nullable token, NSError * _Nullable error) { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + if (error != nil) { + if (error.code == FIRErrorCodeNoAuth) { + FFLog(@"I-RDB073001", @"Firebase Auth is not configured, not going to use authentication."); + callback(nil, nil); + } else if (error.code == FIRErrorCodeNoSignedInUser) { + // No signed in user is an expected case, callback as success with no token + callback(nil, nil); + } else { + callback(nil, error); + } + } else { + callback(token, nil); + } + }); + }]; +} + +- (void) listenForTokenChanges:(_Nonnull fbt_void_nsstring)listener { + FAuthStateListenerWrapper *wrapper = [[FAuthStateListenerWrapper alloc] initWithListener:listener app:self.app]; + [self.authListeners addObject:wrapper]; +} + +@end + +@implementation FAuthTokenProvider + ++ (id<FAuthTokenProvider>) authTokenProviderForApp:(id)app { + return [[FIRFirebearAuthTokenProvider alloc] initWithFirebaseApp:app]; +} + +@end diff --git a/Firebase/Database/Login/FIRNoopAuthTokenProvider.h b/Firebase/Database/Login/FIRNoopAuthTokenProvider.h new file mode 100644 index 0000000..e27ddb4 --- /dev/null +++ b/Firebase/Database/Login/FIRNoopAuthTokenProvider.h @@ -0,0 +1,22 @@ +/* + * 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> +#import "FAuthTokenProvider.h" + +@interface FIRNoopAuthTokenProvider : NSObject <FAuthTokenProvider> + +@end diff --git a/Firebase/Database/Login/FIRNoopAuthTokenProvider.m b/Firebase/Database/Login/FIRNoopAuthTokenProvider.m new file mode 100644 index 0000000..8bf467b --- /dev/null +++ b/Firebase/Database/Login/FIRNoopAuthTokenProvider.m @@ -0,0 +1,33 @@ +/* + * 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 "FIRNoopAuthTokenProvider.h" +#import "FAuthTokenProvider.h" +#import "FIRDatabaseQuery_Private.h" + +@implementation FIRNoopAuthTokenProvider + +- (void) fetchTokenForcingRefresh:(BOOL)forceRefresh withCallback:(fbt_void_nsstring_nserror)callback { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + callback(nil, nil); + }); +} + +- (void) listenForTokenChanges:(fbt_void_nsstring)listener { + // no-op, because token never changes +} + +@end |