-
Notifications
You must be signed in to change notification settings - Fork 430
@W-19368408: [MSDK] Local dev instant login (iOS) #3944
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
Changes from 2 commits
785262b
f322cf4
b780b88
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 |
---|---|---|
|
@@ -53,13 +53,45 @@ NS_ASSUME_NONNULL_BEGIN | |
+ (SFSDKTestCredentialsData *)populateAuthCredentialsFromConfigFileForClass:(Class)testClass; | ||
|
||
/** | ||
Performs a synchronous refresh of the OAuth credentials, which will stage the remaining auth | ||
data (access token, User ID, Org ID, etc.) in SFUserAccountManager. | ||
`populateAuthCredentialsFromConfigFile` is required to run once before this method will attempt | ||
to refresh authentication. | ||
Loads a set of auth credentials from the provided JSON string, and configures | ||
SFUserAccountManager and the current account with the data from that JSON. | ||
Salesforce Mobile SDK will be initialized while populating test credentials. | ||
@param testCredentialsJsonString The test credentials JSON as a string. | ||
@return The configuration data used to configure SFUserAccountManager (useful | ||
e.g. for hybrid apps which need the data to bootstrap SFHybridViewController). | ||
*/ | ||
+ (SFSDKTestCredentialsData *)populateAuthCredentialsFromString:(NSString *)testCredentialsJsonString; | ||
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 new method lets us reuse the non-file logic around ingesting the JSON. |
||
|
||
/** | ||
Loads a set of auth credentials from the provided JSON string, and configures | ||
SFUserAccountManager and the current account with the data from that JSON. | ||
@param testCredentialsJsonString The test credentials JSON as a string. | ||
@param initializeSdk Indicates if Salesfore Mobile SDK should be initialized | ||
while populating test credentials. | ||
@return The configuration data used to configure SFUserAccountManager (useful | ||
e.g. for hybrid apps which need the data to bootstrap SFHybridViewController). | ||
*/ | ||
+ (SFSDKTestCredentialsData *)populateAuthCredentialsFromString:(NSString *)testCredentialsJsonString initializeSdk:(BOOL)initializeSdk; | ||
|
||
/** | ||
Performs a synchronous refresh of the OAuth credentials, which will stage the | ||
remaining auth data (access token, User ID, Org ID, etc.) in | ||
SFUserAccountManager. `populateAuthCredentialsFromConfigFile` | ||
is required to run once before this method will attempt to refresh authentication. | ||
The "user did log in" notification will not be posted. | ||
*/ | ||
+ (void)synchronousAuthRefresh; | ||
|
||
/** | ||
Performs a synchronous refresh of the OAuth credentials, which will stage the | ||
remaining auth data (access token, User ID, Org ID, etc.) in | ||
SFUserAccountManager. `populateAuthCredentialsFromConfigFile` | ||
is required to run once before this method will attempt to refresh authentication. | ||
@param postUserDidLogIn Indicates if the "user did log in" notification should | ||
be posted. | ||
*/ | ||
+ (void)synchronousAuthRefreshWithUserDidLoginNotification:(BOOL)postUserDidLogIn; | ||
|
||
+ (SFOAuthCredentials *)newClientCredentials; | ||
|
||
@end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,6 +55,71 @@ + (SFSDKTestCredentialsData *)populateAuthCredentialsFromConfigFileForClass:(Cla | |
NSFileManager *fm = [NSFileManager defaultManager]; | ||
NSData *tokenJson = [fm contentsAtPath:tokenPath]; | ||
id jsonResponse = [SFJsonUtils objectFromJSONData:tokenJson]; | ||
|
||
return [TestSetupUtils authCredentialsFromJson:jsonResponse initializeSdk:YES]; | ||
|
||
} | ||
|
||
+ (SFSDKTestCredentialsData *)populateAuthCredentialsFromString:(NSString *)testCredentialsJsonString { | ||
return [self populateAuthCredentialsFromString:testCredentialsJsonString initializeSdk:YES]; | ||
} | ||
|
||
+ (SFSDKTestCredentialsData *)populateAuthCredentialsFromString:(NSString *)testCredentialsJsonString initializeSdk:(BOOL)initializeSdk { | ||
|
||
return [TestSetupUtils authCredentialsFromJson:[SFJsonUtils objectFromJSONString:testCredentialsJsonString] initializeSdk:initializeSdk]; | ||
} | ||
|
||
+ (void)synchronousAuthRefresh { | ||
[self synchronousAuthRefreshWithUserDidLoginNotification:NO]; | ||
} | ||
|
||
+ (void)synchronousAuthRefreshWithUserDidLoginNotification:(BOOL)postUserDidLogIn | ||
{ | ||
// All of the setup and validation of prerequisite auth state is done in populateAuthCredentialsFromConfigFile. | ||
// Make sure that method has run before this one. | ||
NSAssert(credentials!=nil, @"You must call populateAuthCredentialsFromConfigFileForClass before synchronousAuthRefresh"); | ||
__block SFSDKTestRequestListener *authListener = [[SFSDKTestRequestListener alloc] init]; | ||
__block SFUserAccount *user = nil; | ||
[[SFUserAccountManager sharedInstance] | ||
refreshCredentials:credentials | ||
completion:^(SFOAuthInfo *authInfo, SFUserAccount *userAccount) { | ||
authListener.returnStatus = kTestRequestStatusDidLoad; | ||
user = userAccount; | ||
// Ensure tests don't change/corrupt the current user credentials. | ||
if (user.credentials.refreshToken == nil) { | ||
user.credentials = credentials; | ||
} | ||
if (postUserDidLogIn) { | ||
NSDictionary *userInfo = @{kSFNotificationUserInfoAccountKey: userAccount, | ||
kSFNotificationUserInfoAuthTypeKey: authInfo}; | ||
[[NSNotificationCenter defaultCenter] postNotificationName:kSFNotificationUserDidLogIn | ||
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. These two lines allow 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. That matches the behavior for Local Dev Instant Login for Android. 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. There is similar notification login in the user account manager, but its only a few lines and not visible to this scope, so I thought to leave that alone and replicate the notification here so we minimize authentication regression risk. All the changes in this pull request are non-production code so far. |
||
object:[SFUserAccountManager sharedInstance] | ||
userInfo:userInfo]; | ||
[[SFUserAccountManager sharedInstance] stopCurrentAuthentication:^(BOOL result){}]; | ||
} | ||
} failure:^(SFOAuthInfo *authInfo, NSError *error) { | ||
authListener.lastError = error; | ||
authListener.returnStatus = kTestRequestStatusDidFail; | ||
}]; | ||
[authListener waitForCompletion]; | ||
[[SFUserAccountManager sharedInstance] setCurrentUserInternal:user]; | ||
NSAssert([authListener.returnStatus isEqualToString:kTestRequestStatusDidLoad], @"After auth attempt, expected status '%@', got '%@'", | ||
kTestRequestStatusDidLoad, | ||
authListener.returnStatus); | ||
} | ||
|
||
+ (SFOAuthCredentials *)newClientCredentials { | ||
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 method did not change. This method didn't change, though Github marked it as a diff due to other logic moving. |
||
|
||
NSString *identifier = [[SFUserAccountManager sharedInstance] uniqueUserAccountIdentifier:[SFUserAccountManager sharedInstance].oauthClientId]; | ||
SFOAuthCredentials *creds = [[SFOAuthCredentials alloc] initWithIdentifier:identifier clientId:[SFUserAccountManager sharedInstance].oauthClientId encrypted:YES]; | ||
creds.clientId = [SFUserAccountManager sharedInstance].oauthClientId; | ||
creds.redirectUri = [SFUserAccountManager sharedInstance].oauthCompletionUrl; | ||
creds.domain = [SFUserAccountManager sharedInstance].loginHost; | ||
creds.accessToken = nil; | ||
return creds; | ||
} | ||
|
||
+ (SFSDKTestCredentialsData *)authCredentialsFromJson:(id)jsonResponse initializeSdk:(BOOL)initializeSdk { | ||
NSAssert(jsonResponse != nil, @"Error parsing JSON from config file: %@", [SFJsonUtils lastError]); | ||
NSDictionary *dictResponse = (NSDictionary *)jsonResponse; | ||
SFSDKTestCredentialsData *credsData = [[SFSDKTestCredentialsData alloc] initWithDict:dictResponse]; | ||
|
@@ -65,12 +130,14 @@ + (SFSDKTestCredentialsData *)populateAuthCredentialsFromConfigFileForClass:(Cla | |
nil != credsData.identityUrl && | ||
nil != credsData.instanceUrl, @"config credentials are missing! %@", | ||
dictResponse); | ||
|
||
// check whether the test config file has never been edited | ||
NSAssert(![credsData.refreshToken isEqualToString:@"__INSERT_TOKEN_HERE__"], | ||
@"You need to obtain credentials for your test org and replace test_credentials.json"); | ||
[SalesforceSDKManager initializeSDK]; | ||
|
||
if (initializeSdk) { | ||
[SalesforceSDKManager initializeSDK]; | ||
} | ||
|
||
// Note: We need to fix this inconsistency for tests in the long run.There should be a clean way to refresh appConfigs for tests. The configs should apply across all components that need the config. | ||
SFSDKAppConfig *appconfig = [[SFSDKAppConfig alloc] init]; | ||
appconfig.oauthRedirectURI = credsData.redirectUri; | ||
|
@@ -98,41 +165,4 @@ + (SFSDKTestCredentialsData *)populateAuthCredentialsFromConfigFileForClass:(Cla | |
return credsData; | ||
} | ||
|
||
+ (void)synchronousAuthRefresh | ||
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 method didn't change, though Github marked it as a diff due to other logic moving. |
||
{ | ||
// All of the setup and validation of prerequisite auth state is done in populateAuthCredentialsFromConfigFile. | ||
// Make sure that method has run before this one. | ||
NSAssert(credentials!=nil, @"You must call populateAuthCredentialsFromConfigFileForClass before synchronousAuthRefresh"); | ||
__block SFSDKTestRequestListener *authListener = [[SFSDKTestRequestListener alloc] init]; | ||
__block SFUserAccount *user = nil; | ||
[[SFUserAccountManager sharedInstance] | ||
refreshCredentials:credentials | ||
completion:^(SFOAuthInfo *authInfo, SFUserAccount *userAccount) { | ||
authListener.returnStatus = kTestRequestStatusDidLoad; | ||
user = userAccount; | ||
// Ensure tests don't change/corrupt the current user credentials. | ||
if(user.credentials.refreshToken == nil) { | ||
user.credentials = credentials; | ||
} | ||
} failure:^(SFOAuthInfo *authInfo, NSError *error) { | ||
authListener.lastError = error; | ||
authListener.returnStatus = kTestRequestStatusDidFail; | ||
}]; | ||
[authListener waitForCompletion]; | ||
[[SFUserAccountManager sharedInstance] setCurrentUserInternal:user]; | ||
NSAssert([authListener.returnStatus isEqualToString:kTestRequestStatusDidLoad], @"After auth attempt, expected status '%@', got '%@'", | ||
kTestRequestStatusDidLoad, | ||
authListener.returnStatus); | ||
} | ||
|
||
+ (SFOAuthCredentials *)newClientCredentials { | ||
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 method didn't change, though Github marked it as a diff due to other logic moving. |
||
|
||
NSString *identifier = [[SFUserAccountManager sharedInstance] uniqueUserAccountIdentifier:[SFUserAccountManager sharedInstance].oauthClientId]; | ||
SFOAuthCredentials *creds = [[SFOAuthCredentials alloc] initWithIdentifier:identifier clientId:[SFUserAccountManager sharedInstance].oauthClientId encrypted:YES]; | ||
creds.clientId = [SFUserAccountManager sharedInstance].oauthClientId; | ||
creds.redirectUri = [SFUserAccountManager sharedInstance].oauthCompletionUrl; | ||
creds.domain = [SFUserAccountManager sharedInstance].loginHost; | ||
creds.accessToken = nil; | ||
return creds; | ||
} | ||
@end |
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.
@bbirman - Now we have Local Dev Instant Login hosted in
SalesforceSDKManager.init
so we can avoid usingload
. Notice the two new boolean parameters on these two statements which allowTestSetupUtils
to execute correctly here ininitializeSDK
while still running exactly the same in existing tests.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.
nice!