Skip to content

Move Auth notification constant into Core. #155

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 2 commits into from
Aug 4, 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
8 changes: 3 additions & 5 deletions Firebase/Auth/Source/FIRAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@

#pragma mark - Constants

NSString *const FIRAuthStateDidChangeInternalNotification =
@"FIRAuthStateDidChangeInternalNotification";
NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey =
@"FIRAuthStateDidChangeInternalNotificationTokenKey";

#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
const NSNotificationName FIRAuthStateDidChangeNotification = @"FIRAuthStateDidChangeNotification";
#else
Expand Down Expand Up @@ -1040,6 +1035,9 @@ - (void)notifyListenersOfAuthStateChangeWithUser:(FIRUser *)user token:(NSString
[self scheduleAutoTokenRefresh];
}
NSMutableDictionary *internalNotificationParameters = [NSMutableDictionary dictionary];
if (self.app) {
internalNotificationParameters[FIRAuthStateDidChangeInternalNotificationAppKey] = self.app;
}
if (token.length) {
internalNotificationParameters[FIRAuthStateDidChangeInternalNotificationTokenKey] = token;
}
Expand Down
16 changes: 0 additions & 16 deletions Firebase/Auth/Source/FIRAuth_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,6 @@

NS_ASSUME_NONNULL_BEGIN

/** @var FIRAuthStateDidChangeInternalNotification
@brief The name of the @c NSNotificationCenter notification which is posted when the auth state
changes (e.g. a new token has been produced, a user logs in or out). The object parameter of
the notification is a dictionary possibly containing the key:
@c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not
contain this key it indicates a sign-out event took place.
*/
extern NSString *const FIRAuthStateDidChangeInternalNotification;

/** @var FIRAuthStateDidChangeInternalNotificationTokenKey
@brief A key present in the dictionary object parameter of the
@c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
key will contain the new access token.
*/
extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey;

@interface FIRAuth ()

/** @property requestConfiguration
Expand Down
8 changes: 8 additions & 0 deletions Firebase/Core/FIRApp.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@
NSString *const kFIRAppDiagnosticsSDKNameKey = @"SDKName";
NSString *const kFIRAppDiagnosticsSDKVersionKey = @"SDKVersion";

// Auth internal notification notification and key.
NSString *const FIRAuthStateDidChangeInternalNotification =
@"FIRAuthStateDidChangeInternalNotification";
NSString *const FIRAuthStateDidChangeInternalNotificationAppKey =
@"FIRAuthStateDidChangeInternalNotificationAppKey";
NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey =
@"FIRAuthStateDidChangeInternalNotificationTokenKey";

/**
* The URL to download plist files.
*/
Expand Down
23 changes: 23 additions & 0 deletions Firebase/Core/Private/FIRAppInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,29 @@ extern NSString *const kFIRAppIsDefaultAppKey;
extern NSString *const kFIRAppNameKey;
extern NSString *const kFIRGoogleAppIDKey;

/** @var FIRAuthStateDidChangeInternalNotification
@brief The name of the @c NSNotificationCenter notification which is posted when the auth state
changes (e.g. a new token has been produced, a user logs in or out). The object parameter of
the notification is a dictionary possibly containing the key:
@c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not
contain this key it indicates a sign-out event took place.
*/
extern NSString *const FIRAuthStateDidChangeInternalNotification;

/** @var FIRAuthStateDidChangeInternalNotificationTokenKey
@brief A key present in the dictionary object parameter of the
@c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
key will contain the new access token.
*/
extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey;

/** @var FIRAuthStateDidChangeInternalNotificationAppKey
@brief A key present in the dictionary object parameter of the
@c FIRAuthStateDidChangeInternalNotification notification. The value associated with this
key will contain the FIRApp associated with the auth instance.
*/
extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey;

/** @typedef FIRTokenCallback
@brief The type of block which gets called when a token is ready.
*/
Expand Down
67 changes: 19 additions & 48 deletions Firebase/Database/Api/FIRDatabase.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#import <Foundation/Foundation.h>
#import "FIRAppInternal.h"
#import "FIRLogger.h"
#import "FIRDatabase.h"
#import "FIRDatabase_Private.h"
Expand All @@ -25,25 +26,7 @@
#import "FRepoInfo.h"
#import "FIRDatabaseConfig.h"
#import "FIRDatabaseReference_Private.h"

/**
* This is a hack that defines all the methods we need from FIRApp/Options. At runtime we use reflection to get the
* default FIRApp instance if we need it. 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 don't change.
*
* TODO: Consider weak-linking the actual Firebase/Core framework or something.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for cleaning all this up!!!


extern NSString *const kFIRDefaultAppName;

@protocol FIROptionsLike <NSObject>
@property(nonatomic, readonly, copy) NSString *databaseURL;
@end

@protocol FIRAppLike <NSObject>
@property(nonatomic, readonly) id<FIROptionsLike> options;
@property(nonatomic, copy, readonly) NSString *name;
@end
#import "FIROptions.h"

@interface FIRDatabase ()
@property (nonatomic, strong) FRepoInfo *repoInfo;
Expand Down Expand Up @@ -77,23 +60,25 @@ + (NSMutableDictionary *)instances {
}

+ (FIRDatabase *)database {
id<FIRAppLike> app = [FIRDatabase getDefaultApp];
if (app == nil) {
[NSException raise:@"FIRAppNotConfigured" format:@"Failed to get default FIRDatabase instance. Must call FIRApp.configure() before using FIRDatabase."];
if (![FIRApp isDefaultAppConfigured]) {
[NSException raise:@"FIRAppNotConfigured"
format:@"Failed to get default Firebase Database instance. Must call `[FIRApp "
@"configure]` (`FirebaseApp.configure()` in Swift) before using "
@"Firebase Database."];
}
return [FIRDatabase databaseForApp:(FIRApp*)app];
FIRApp *app = [FIRApp defaultApp];
return [FIRDatabase databaseForApp:app];
}

+ (FIRDatabase *)databaseForApp:(id)app {
+ (FIRDatabase *)databaseForApp:(FIRApp *)app {
if (app == nil) {
[NSException raise:@"InvalidFIRApp" format:@"nil FIRApp instance passed to databaseForApp."];
}
NSMutableDictionary *instances = [self instances];
@synchronized (instances) {
id<FIRAppLike> appLike = (id<FIRAppLike>)app;
FIRDatabase *database = instances[appLike.name];
FIRDatabase *database = instances[app.name];
if (!database) {
NSString *databaseUrl = appLike.options.databaseURL;
NSString *databaseUrl = app.options.databaseURL;
if (databaseUrl == nil) {
[NSException raise:@"MissingDatabaseURL" format:@"Failed to get FIRDatabase instance: FIRApp object has no "
"databaseURL in its FirebaseOptions object."];
Expand All @@ -106,20 +91,20 @@ + (FIRDatabase *)databaseForApp:(id)app {
databaseUrl, [parsedUrl.path toString]];
}

id<FAuthTokenProvider> authTokenProvider = [FAuthTokenProvider authTokenProviderForApp:appLike];
id<FAuthTokenProvider> authTokenProvider = [FAuthTokenProvider authTokenProviderForApp:app];

// If this is the default app, don't set the session persistence key so that we use our
// default ("default") instead of the FIRApp default ("[DEFAULT]") so that we
// preserve the default location used by the legacy Firebase SDK.
NSString *sessionIdentifier = @"default";
if (![appLike.name isEqualToString:kFIRDefaultAppName]) {
sessionIdentifier = appLike.name;
if ([FIRApp isDefaultAppConfigured] && app == [FIRApp defaultApp]) {
sessionIdentifier = app.name;
}

FIRDatabaseConfig *config = [[FIRDatabaseConfig alloc] initWithSessionIdentifier:sessionIdentifier
authTokenProvider:authTokenProvider];
database = [[FIRDatabase alloc] initWithApp:appLike repoInfo:parsedUrl.repoInfo config:config];
instances[appLike.name] = database;
database = [[FIRDatabase alloc] initWithApp:app repoInfo:parsedUrl.repoInfo config:config];
instances[app.name] = database;
}

return database;
Expand Down Expand Up @@ -148,12 +133,12 @@ + (void) setLoggingEnabled:(BOOL)enabled {
}


- (id)initWithApp:(id <FIRAppLike>)appLike repoInfo:(FRepoInfo *)info config:(FIRDatabaseConfig *)config {
- (id)initWithApp:(FIRApp *)app repoInfo:(FRepoInfo *)info config:(FIRDatabaseConfig *)config {
self = [super init];
if (self != nil) {
self->_repoInfo = info;
self->_config = config;
self->_app = (FIRApp*) appLike;
self->_app = app;
}
return self;
}
Expand Down Expand Up @@ -204,7 +189,6 @@ - (void)goOnline {
});
}


- (void)goOffline {
[self ensureRepo];

Expand All @@ -213,19 +197,6 @@ - (void)goOffline {
});
}

+ (id<FIRAppLike>) getDefaultApp {
Class appClass = NSClassFromString(@"FIRApp");
if (appClass == nil) {
[NSException raise:@"FailedToFindFIRApp" format:@"Failed to find FIRApp class."];
return nil;
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
return [appClass performSelector:@selector(defaultApp)];
#pragma clang diagnostic pop
}
}

- (void)setPersistenceEnabled:(BOOL)persistenceEnabled {
[self assertUnfrozen:@"setPersistenceEnabled"];
self->_config.persistenceEnabled = persistenceEnabled;
Expand Down
4 changes: 3 additions & 1 deletion Firebase/Database/Login/FAuthTokenProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#import "FTypedefs.h"
#import "FTypedefs_Private.h"

@class FIRApp;

@protocol FAuthTokenProvider <NSObject>

- (void) fetchTokenForcingRefresh:(BOOL)forceRefresh withCallback:(fbt_void_nsstring_nserror)callback;
Expand All @@ -29,7 +31,7 @@

@interface FAuthTokenProvider : NSObject

+ (id<FAuthTokenProvider>) authTokenProviderForApp:(id)app;
+ (id<FAuthTokenProvider>) authTokenProviderForApp:(FIRApp *)app;

- (instancetype)init NS_UNAVAILABLE;

Expand Down
75 changes: 10 additions & 65 deletions Firebase/Database/Login/FAuthTokenProvider.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,65 +16,22 @@

#import "FAuthTokenProvider.h"
#import "FUtilities.h"
#import "FIRAppInternal.h"
#import "FIRLogger.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 Firebase Auth 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;
@property (nonatomic, weak) FIRApp *app;

@end

@implementation FAuthStateListenerWrapper

- (instancetype) initWithListener:(fbt_void_nsstring)listener app:(id<FIRFirebaseAppLike>)app {
- (instancetype) initWithListener:(fbt_void_nsstring)listener app:(FIRApp *)app {
self = [super init];
if (self != nil) {
self->_listener = listener;
Expand All @@ -88,9 +45,9 @@ - (instancetype) initWithListener:(fbt_void_nsstring)listener app:(id<FIRFirebas
}

- (void) authStateDidChangeNotification:(NSNotification *)notification {
id<FIRFirebaseAuthLike> auth = notification.object;
if (auth.app == self->_app) {
NSDictionary *userInfo = notification.userInfo;
NSDictionary *userInfo = notification.userInfo;
FIRApp *authApp = userInfo[FIRAuthStateDidChangeInternalNotificationAppKey];
if (authApp == self.app) {
NSString *token = userInfo[FIRAuthStateDidChangeInternalNotificationTokenKey];
dispatch_async([FIRDatabaseQuery sharedQueue], ^{
self.listener(token);
Expand All @@ -107,17 +64,17 @@ - (void) dealloc {

@interface FIRFirebaseAuthTokenProvider : NSObject <FAuthTokenProvider>

@property (nonatomic, strong) id<FIRFirebaseAppLike> app;
@property (nonatomic, strong) FIRApp *app;
/** Strong references to the auth listeners as they are only weak in FIRFirebaseApp */
@property (nonatomic, strong) NSMutableArray *authListeners;

- (instancetype) initWithFirebaseApp:(id<FIRFirebaseAppLike>)app;
- (instancetype) initWithFirebaseApp:(FIRApp *)app;

@end

@implementation FIRFirebaseAuthTokenProvider

- (instancetype) initWithFirebaseApp:(id<FIRFirebaseAppLike>)app {
- (instancetype) initWithFirebaseApp:(FIRApp *)app {
self = [super init];
if (self != nil) {
self->_app = app;
Expand All @@ -130,19 +87,7 @@ - (void) fetchTokenForcingRefresh:(BOOL)forceRefresh withCallback:(fbt_void_nsst
// 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);
}
callback(token, error);
});
}];
}
Expand Down
2 changes: 1 addition & 1 deletion Firebase/Database/Public/FIRDatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ FIR_SWIFT_NAME(Database)
* @param app The FIRApp to get a FIRDatabase for.
* @return A FIRDatabase instance.
*/
+ (FIRDatabase *) databaseForApp:(FIRApp*)app FIR_SWIFT_NAME(database(app:));
+ (FIRDatabase *) databaseForApp:(FIRApp *)app FIR_SWIFT_NAME(database(app:));

/** The FIRApp instance to which this FIRDatabase belongs. */
@property (weak, readonly, nonatomic) FIRApp *app;
Expand Down