-
Notifications
You must be signed in to change notification settings - Fork 3
fix(davinci-client): return-url-from-external-idp #322
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
Conversation
🦋 Changeset detectedLatest commit: 609d381 The changes in this PR will be included in the next version bump. This PR includes changesets to release 9 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
View your CI Pipeline Execution ↗ for commit 609d381.
☁️ Nx Cloud last updated this comment at |
Codecov ReportAttention: Patch coverage is
❌ Your patch status has failed because the patch coverage (0.00%) is below the target coverage (40.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #322 +/- ##
==========================================
- Coverage 50.32% 48.16% -2.16%
==========================================
Files 29 29
Lines 1713 1715 +2
Branches 194 192 -2
==========================================
- Hits 862 826 -36
- Misses 851 889 +38
🚀 New features to boost your workflow:
|
|
Deployed f24f072 to https://ForgeRock.github.io/ping-javascript-sdk/pr-322/f24f0727cb1b2be2c4c5041aa51bcdd0bd63c408 branch gh-pages in ForgeRock/ping-javascript-sdk |
cerebrl
left a comment
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.
I'd like to suggest some pattern changes here:
I think it's best we preserve the aspect of the externalIdp method returning a "updater" function. This function is then called in the collector component like all the others. This keeps it consistent.
Within this "updater" function, we set the localStorage item. This means we only store it if a user selects the social login option. That way we don't dirty up the WebStorage if we don't have to.
This updater function can also return the URL, but it doesn't have to as the collector already has the URL on the object. Either way, we can return it as it doesn't hurt anything.
updating the api for the social login external idp method. Instead of redirecting for the application, we will return a url for the application to redirect to themselves.
5b5852b to
9a03632
Compare
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.
Okay, after thinking on this for a bit, re-reviewing this PR, and thinking about long-term patterns, I'd like to suggest something a bit different holistically.
Here's a few things:
- I think we should use the Storage Effect, rather than directly interact with
localStorage - I'd like the location of code that triggers the write to also trigger the read from storage
- I don't think
davinci.api.tsshould have to be aware of how to get what it needs to make the call - I'm thinking the
client.store.tsshould cover #2 above
Here's an example code for client.store.ts:
return {
// ...
externalIdp: (collector: IdpCollector): (() => string | InternalErrorResponse) => {
const rootState: RootState = store.getState();
const serverSlice = nodeSlice.selectors.selectServer(rootState);
return () => {
const error = setServerInfo(serverSlice, log);
const redirect = collector.output.url;
if (error) {
return error;
}
return redirect;
};
},
resume: async ({ continueToken }: { continueToken: string }) => {
const serverInfo = getServerInfo(log);
if (!serverInfo) {
return { /* some error */ };
}
await store.dispatch(davinciApi.endpoints.resume.initiate({ serverInfo, continueToken }));
const node = nodeSlice.selectSlice(store.getState());
return node;
},
// ...
};If the above doesn't make much sense, we can chat about it tomorrow.
| } | ||
|
|
||
| export function authorize( | ||
| export function returnRedirectUrlForSocialLogin( |
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.
I'd like to suggest we rename this function to selectIdp, since returning the URL is really secondary to the persisting the continue URL of the IdP.
| logger.error( | ||
| 'No Continue Url found, social login needs a continue url to be saved in localStorage', | ||
| ); | ||
| return { | ||
| error: { | ||
| message: | ||
| 'No Continue Url found, social login needs a continue url to be saved in localStorage', | ||
| type: 'network_error', | ||
| }, | ||
| type: 'internal_error', | ||
| }; |
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.
I'd like to suggest we use the pattern of handling errors first, then handling successes. You can see them in many instances throughout DaVinci Client, but good examples are client.store.ts and reducer.utils.ts here:
| .addCase(updateCollectorValues, (state, action) => { |
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.
I'm not sure if this is the right location for this functionality. This utils file is supposed to be tied to the davinci.api.ts file, which this function doesn't directly relate to it. I think we need to evaluate where this logic lives.
cerebrl
left a comment
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.
Just a few small comments, and I think we are done here. Thanks for putting up with me, Ryan :)
|
|
||
| const serverStorage = createStorage<ContinueNode['server']>( | ||
| { storeType: 'localStorage' }, | ||
| 'socialLoginUrl', |
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.
Let's update this to reflect what's now being stored: server info.
| }): Promise<InternalErrorResponse | NodeStates> => { | ||
| try { | ||
| const serverInfo = await serverStorage.get(); | ||
| if (serverInfo && '_links' in serverInfo) { |
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.
I get that you're narrowing here, but it feels a bit overkill for me since this very same check exists within the API module. Can we just do a cast here, and just check that truthiness of the value? We can then rely on the more strict check within the API module for the more detailed property needs.
| if ( | ||
| !links || | ||
| !('continue' in links) || | ||
| !('href' in links['continue']) || | ||
| !links['continue'].href | ||
| ) { |
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.
Yikes! Completely non-blocking, but it would be nice to have some sort of selector or lens to prevent this type of object path checking.
b81aec3 to
b90fccd
Compare
b90fccd to
8f642a8
Compare
cerebrl
left a comment
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.
Let's change this name to align with what's actually stored.
JIRA Ticket
https://pingidentity.atlassian.net/browse/SDKS-4107
Description
updating the api for the social login external idp method. Instead of redirecting for the application, we will return a url for the application to redirect to themselves.