-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
replacing FSTGetTokenResult by C++ Token implementation #805
Changes from 4 commits
dc4f02c
b502b8e
bfbb0e2
a64ca8c
9fb7911
369f812
6e4fdef
5cb11ca
6775d9b
7d10621
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,38 +25,16 @@ | |
#import "Firestore/Source/Util/FSTClasses.h" | ||
#import "Firestore/Source/Util/FSTDispatchQueue.h" | ||
|
||
#include "Firestore/core/src/firebase/firestore/auth/token.h" | ||
#include "Firestore/core/src/firebase/firestore/auth/user.h" | ||
#include "Firestore/core/src/firebase/firestore/util/string_apple.h" | ||
|
||
namespace util = firebase::firestore::util; | ||
using firebase::firestore::auth::Token; | ||
using firebase::firestore::auth::User; | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
#pragma mark - FSTGetTokenResult | ||
|
||
@interface FSTGetTokenResult () { | ||
User _user; | ||
} | ||
|
||
@end | ||
|
||
@implementation FSTGetTokenResult | ||
|
||
- (instancetype)initWithUser:(const User &)user token:(NSString *_Nullable)token { | ||
if (self = [super init]) { | ||
_user = user; | ||
_token = token; | ||
} | ||
return self; | ||
} | ||
|
||
- (const User &)user { | ||
return _user; | ||
} | ||
|
||
@end | ||
|
||
#pragma mark - FSTFirebaseCredentialsProvider | ||
@interface FSTFirebaseCredentialsProvider () { | ||
/** The current user as reported to us via our AuthStateDidChangeListener. */ | ||
|
@@ -141,10 +119,9 @@ - (void)getTokenForcingRefresh:(BOOL)forceRefresh | |
NSError *cancelError = [NSError errorWithDomain:FIRFirestoreErrorDomain | ||
code:FIRFirestoreErrorCodeAborted | ||
userInfo:errorInfo]; | ||
completion(nil, cancelError); | ||
completion({"", User::Unauthenticated()}, cancelError); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Two minor nits:
Both optional. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
} else { | ||
FSTGetTokenResult *result = | ||
[[FSTGetTokenResult alloc] initWithUser:_currentUser token:token]; | ||
Token result(util::MakeStringView(token), _currentUser); | ||
completion(result, error); | ||
} | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,7 @@ @implementation FSTEmptyCredentialsProvider | |
|
||
- (void)getTokenForcingRefresh:(BOOL)forceRefresh | ||
completion:(FSTVoidGetTokenResultBlock)completion { | ||
completion(nil, nil); | ||
completion({"", User::Unauthenticated()}, nil); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (see comment in FSTCredentialsProvider.mm:122) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
} | ||
|
||
- (void)setUserChangeListener:(nullable FSTVoidUserBlock)block { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ | |
|
||
#include "Firestore/core/src/firebase/firestore/core/database_info.h" | ||
#include "Firestore/core/src/firebase/firestore/model/database_id.h" | ||
#include "absl/strings/string_view.h" | ||
|
||
@class FSTDocumentKey; | ||
@class FSTDispatchQueue; | ||
|
@@ -83,7 +84,7 @@ NS_ASSUME_NONNULL_BEGIN | |
/** Adds headers to the RPC including any OAuth access token if provided .*/ | ||
+ (void)prepareHeadersForRPC:(GRPCCall *)rpc | ||
databaseID:(const firebase::firestore::model::DatabaseId *)databaseID | ||
token:(nullable NSString *)token; | ||
token:(const absl::string_view)token; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it accepts nullptr. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: |
||
|
||
/** Looks up a list of documents in datastore. */ | ||
- (void)lookupDocuments:(NSArray<FSTDocumentKey *> *)keys | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,11 +35,13 @@ | |
|
||
#import "Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.h" | ||
|
||
#include "Firestore/core/src/firebase/firestore/auth/token.h" | ||
#include "Firestore/core/src/firebase/firestore/core/database_info.h" | ||
#include "Firestore/core/src/firebase/firestore/model/database_id.h" | ||
#include "Firestore/core/src/firebase/firestore/util/string_apple.h" | ||
|
||
namespace util = firebase::firestore::util; | ||
using firebase::firestore::auth::Token; | ||
using firebase::firestore::core::DatabaseInfo; | ||
using firebase::firestore::model::DatabaseId; | ||
|
||
|
@@ -299,22 +301,22 @@ - (void)invokeRPCWithFactory:(GRPCProtoCall * (^)(void))rpcFactory | |
errorHandler:(FSTVoidErrorBlock)errorHandler { | ||
// TODO(mikelehen): We should force a refresh if the previous RPC failed due to an expired token, | ||
// but I'm not sure how to detect that right now. http://b/32762461 | ||
[self.credentials | ||
getTokenForcingRefresh:NO | ||
completion:^(FSTGetTokenResult *_Nullable result, NSError *_Nullable error) { | ||
error = [FSTDatastore firestoreErrorForError:error]; | ||
[self.workerDispatchQueue dispatchAsyncAllowingSameQueue:^{ | ||
if (error) { | ||
errorHandler(error); | ||
} else { | ||
GRPCProtoCall *rpc = rpcFactory(); | ||
[FSTDatastore prepareHeadersForRPC:rpc | ||
databaseID:&self.databaseInfo->database_id() | ||
token:result.token]; | ||
[rpc start]; | ||
} | ||
}]; | ||
}]; | ||
[self.credentials getTokenForcingRefresh:NO | ||
completion:^(const Token &result, NSError *_Nullable error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bit of a semantic mess. If there was an error there should be no token. This is why in the old signature both are nullable. Only one can be non-null. We really need something like For now let's make it clearer at the call site that we're generating an invalid token. If you added something like this to static Token Token::Invalid() {
return {"", User::Unauthenticated()};
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
error = [FSTDatastore firestoreErrorForError:error]; | ||
[self.workerDispatchQueue dispatchAsyncAllowingSameQueue:^{ | ||
if (error) { | ||
errorHandler(error); | ||
} else { | ||
GRPCProtoCall *rpc = rpcFactory(); | ||
[FSTDatastore | ||
prepareHeadersForRPC:rpc | ||
databaseID:&self.databaseInfo->database_id() | ||
token:result.token()]; | ||
[rpc start]; | ||
} | ||
}]; | ||
}]; | ||
} | ||
|
||
- (FSTWatchStream *)createWatchStream { | ||
|
@@ -334,8 +336,11 @@ - (FSTWriteStream *)createWriteStream { | |
/** Adds headers to the RPC including any OAuth access token if provided .*/ | ||
+ (void)prepareHeadersForRPC:(GRPCCall *)rpc | ||
databaseID:(const DatabaseId *)databaseID | ||
token:(nullable NSString *)token { | ||
rpc.oauth2AccessToken = token; | ||
token:(const absl::string_view)token { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (see comment in FSTDatastore.h:87) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
rpc.oauth2AccessToken = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change isn't right. If there's no token this is setting this property to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done. empty check might be enough since an empty string token will cause the corruption of http header; so valid token will never be empty string. But let me check the nullptr instead just in case some test (not actually taking via a http call) may use empty string. |
||
[[NSString alloc] initWithBytes:const_cast<void *>(static_cast<const void *>(token.data())) | ||
length:token.length() | ||
encoding:NSUTF8StringEncoding]; | ||
rpc.requestHeaders[kXGoogAPIClientHeader] = [FSTDatastore googAPIClientHeaderValue]; | ||
// This header is used to improve routing and project isolation by the backend. | ||
rpc.requestHeaders[kGoogleCloudResourcePrefix] = | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,11 +35,13 @@ | |
|
||
#import "Firestore/Protos/objc/google/firestore/v1beta1/Firestore.pbrpc.h" | ||
|
||
#include "Firestore/core/src/firebase/firestore/auth/token.h" | ||
#include "Firestore/core/src/firebase/firestore/core/database_info.h" | ||
#include "Firestore/core/src/firebase/firestore/model/database_id.h" | ||
#include "Firestore/core/src/firebase/firestore/util/string_apple.h" | ||
|
||
namespace util = firebase::firestore::util; | ||
using firebase::firestore::auth::Token; | ||
using firebase::firestore::core::DatabaseInfo; | ||
using firebase::firestore::model::DatabaseId; | ||
|
||
|
@@ -251,18 +253,17 @@ - (void)startWithDelegate:(id)delegate { | |
FSTAssert(_delegate == nil, @"Delegate must be nil"); | ||
_delegate = delegate; | ||
|
||
[self.credentials | ||
getTokenForcingRefresh:NO | ||
completion:^(FSTGetTokenResult *_Nullable result, NSError *_Nullable error) { | ||
error = [FSTDatastore firestoreErrorForError:error]; | ||
[self.workerDispatchQueue dispatchAsyncAllowingSameQueue:^{ | ||
[self resumeStartWithToken:result error:error]; | ||
}]; | ||
}]; | ||
[self.credentials getTokenForcingRefresh:NO | ||
completion:^(const Token &result, NSError *_Nullable error) { | ||
error = [FSTDatastore firestoreErrorForError:error]; | ||
[self.workerDispatchQueue dispatchAsyncAllowingSameQueue:^{ | ||
[self resumeStartWithToken:result error:error]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't work. I'm surprised this isn't crashing you. The token passed into the completion handler is a stack allocated temporary whose reference you're capturing to pass into the block passed into the dispatch queue. By the time that block actually runs the original token will have been destroyed. You need to capture this by value rather than by reference to avoid these lifetime issues. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cannot change the signature, which has to match. I've made a copy; see whether this works. FYI: either ways the test all pass. |
||
}]; | ||
}]; | ||
} | ||
|
||
/** Add an access token to our RPC, after obtaining one from the credentials provider. */ | ||
- (void)resumeStartWithToken:(FSTGetTokenResult *)token error:(NSError *)error { | ||
- (void)resumeStartWithToken:(const Token &)token error:(NSError *)error { | ||
if (self.state == FSTStreamStateStopped) { | ||
// Streams can be stopped while waiting for authorization. | ||
return; | ||
|
@@ -284,7 +285,7 @@ - (void)resumeStartWithToken:(FSTGetTokenResult *)token error:(NSError *)error { | |
_rpc = [self createRPCWithRequestsWriter:self.requestsWriter]; | ||
[FSTDatastore prepareHeadersForRPC:_rpc | ||
databaseID:&self.databaseInfo->database_id() | ||
token:token.token]; | ||
token:token.token()]; | ||
FSTAssert(_callbackFilter == nil, @"GRX Filter must be nil"); | ||
_callbackFilter = [[FSTCallbackFilter alloc] initWithStream:self]; | ||
[_rpc startWithWriteable:_callbackFilter]; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The objective-c code suggests this may be nullable? If so a const* may be required rather than const&. OTOH, if an invalid token is represented by a concrete Token object (rather than by null) then this may be fine. (Either way, you may want to adjust the docstring to clarify.)
Update: Oh, I see below that it is indeed a concrete object rather than null, so the signature is fine. Suggested change to the docstring:
@param token An auth token or X
but X depends on what you pass in. (see below). Possibilities:
X=" nil if an error occurred"
X=" Token::invalid() if an error occurred"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. FYI: the code here will be removed by my next PR to replace the rest of Auth.