Skip to content
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

upcoming: [M3-7430] - Implement Account Switching Functionality #10064

Merged
merged 17 commits into from
Jan 23, 2024

Conversation

jaalah-akamai
Copy link
Contributor

@jaalah-akamai jaalah-akamai commented Jan 12, 2024

Description πŸ“

Presently, there's no way for resellers to seamlessly log into indirect customer accounts. To overcome this obstacle, we aim to introduce a new feature. This feature allows users within the reseller account to choose an indirect customer account, obtaining the EUUID (Entity Unique User ID) in the process. Subsequently, this EUUID becomes instrumental in making a necessary endpoint call, triggering the generation of an ephemeral token allowing for the reseller to authenticate into a proxy account within the main indirect reseller's account. The primary goal of this token is to streamline the transition, providing reseller users with a frictionless experience when logging into the proxy account.

Changes πŸ”„

  • Moved the rendering of child accounts into a new component called ChildAccountList.tsx
  • Implemented functionality / logic to:
    • Request ephemeral token to log into the proxy account of a specific indirect customer account.
    • Set both reseller and proxy token in local storage to allow for account switching, utilizing the original /authentication/ token as the active account.
    • Account for loading and error states if requests fail or tokens expire.
  • Added unit test for SwitchAccountButton.tsx

Preview πŸ“·

Note

All PAT in this demo have been revoked. πŸ‘Œ

Fetch Proxy Token, Set Storage, Switch Accounts
parent-account-switching.mp4

Note

We will most likely be removing the toast when some of the errors are shown (as in not to show both a notice and a toast). While this is still in draft, I wanted to get some UX input.

Description Preview
Loading of indirect customer accounts Screenshot 2024-01-12 at 11 31 06 AM
Error in loading indirect customer accounts Screenshot 2024-01-11 at 12 52 02 PM
No indirect customer accounts Screenshot 2024-01-12 at 3 38 18 PM
Error switching to indirect customer accounts
error-switching-to-child.mp4
- Success toast when logging into proxy account
- Error if parent token is expired
indirect-customer-login-and-expiry.mp4

How to test πŸ§ͺ

Important

You won't see any actual UI changes when performing the switch account feature until we're off mocks.

Prerequisites

(How to setup test environment)

  • Add REACT_APP_PROXY_PAT to your .env file with a temporary PAT that you've created (could be the same account for testing)
  • Enable Parent / Child Account feature flag
  • Turn on Mock Service Worker (MSW)
  • Open dev tools > Application > and clear local storage
  • Ensure that { user_type: 'parent' } in serverHandlers.ts

Reproduction & Verification steps

(How to reproduce the issue, if applicable)

⭐ Parent View

  • Open dev tools > Application > and make note of payload under authentication/token
  • Open user menu in Cloud Manager and click/press "Switch Account"
  • Select any child account in the list
  • Observe that tokens have been created for parent/proxy accounts and that:
    • Original token has been stored under authentication/parent_token/token
    • authentication/token and authentication/proxy_token/token contain the same token indicating we've switched to a proxy account.

⭐ Proxy View: Switching Into Another Proxy

  • Open dev tools > Application > and make note of token value under authentication/token
  • Open user menu in Cloud Manager and click/press "Switch Account"
  • Select any child account in the list
  • Observe that:
    • authentication/parent_token/token remains the same
    • authentication/token and authentication/proxy_token/token have new token values

⭐ Proxy View: Switching Back to Parent

  • Open dev tools > Application > and make note of token value under authentication/token (should still mirror proxy token)
  • Update user type { user_type: 'proxy' } in serverHandlers.ts
  • Open user menu in Cloud Manager and click/press "Switch Account"
  • Select "switch back to your account"
  • Observe that authentication/token token value matches authentication/parent_token/token

As an Author I have considered πŸ€”

Check all that apply

  • πŸ‘€ Doing a self review
  • ❔ Our contribution guidelines
  • 🀏 Splitting feature into small PRs
  • βž• Adding a changeset
  • πŸ§ͺ Providing/Improving test coverage
  • πŸ” Removing all sensitive information from the code and PR description
  • 🚩 Using a feature flag to protect the release
  • πŸ‘£ Providing comprehensive reproduction steps
  • πŸ“‘ Providing or updating our documentation
  • πŸ•› Scheduling a pair reviewing session
  • πŸ“± Providing mobile support
  • β™Ώ Providing accessibility support

Comment on lines 94 to 97
const proxyToken = await getProxyToken({ euuid, headers });

// We don't need to worry about this if we're a proxy user.
if (!isProxyUser) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor/nit: the readability of this sequence could be improved slightly IMO– I was confused how we could get a proxy token AS another proxy user. (It became clearer once I saw how the headers argument was used).

Conceptually, maybe the getProxyToken function itself should decide what the headers should be based on whether it's a parent/sibling account? (Instead of taking in arbitrary headers).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great suggestion - I like that idea! πŸ‘

});
} catch (error) {
setIsProxyTokenError(error as APIError[]);
throw error;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will cause the try block in handleSwitchToChildAccount to error.

euuid,
token: isProxyUser
? getStorage('authentication/parent_token/token')
: currentTokenWithBearer,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For 'proxy' userType, use the stored parent token in the request. Otherwise, if 'parent' use current token.

}, [childAccounts, error, isLoading]);
updateCurrentTokenBasedOnUserType({ userType: 'parent' });
handleClose();
}, [handleClose, isProxyUser]);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Switching back to parent is simpler. Validate parent token in local storage and swap to it.

@jaalah-akamai jaalah-akamai marked this pull request as ready for review January 17, 2024 04:30
@jaalah-akamai jaalah-akamai requested a review from a team as a code owner January 17, 2024 04:30
@jaalah-akamai jaalah-akamai requested review from jdamore-linode and carrillo-erik and removed request for a team January 17, 2024 04:30
Copy link
Contributor

@mjac0bs mjac0bs left a comment

Choose a reason for hiding this comment

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

Here's some more feedback; I will give this an additional pass through to make sure that all loading and error states are addressed once this stuff is addressed.

Noteworthy:

  • Without a page reload, I don't think we can actually account switch, even if we were off mocks. Updating local storage isn't enough without a refresh. Is that not the case?
  • We lost a feature flag in canSwitchBetweenParentOrProxyAccount and so there's still a regression in the user menu.

Looks like there's a failure on SwitchAccountDrawer.test.tsx that probably came about when ChildAccountList was pulled out into its own component:

image

packages/manager/src/features/Account/utils.ts Outdated Show resolved Hide resolved
Comment on lines +72 to +76
if (userToken) {
setStorage('authentication/token', userToken);
setStorage('authentication/scopes', userScope);
setStorage('authentication/expire', userExpiry);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

In the POC, after swapping the tokens in local storage, we then had to trigger a page reload in order for the account switch to occur. Wouldn't that still be the case here (even though we can't test this yet easily without API returning a valid user_type)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mjac0bs I'm using the useHistory as to not force an entire page refresh. We'll have to test this when the API is ready.

Copy link
Contributor

Choose a reason for hiding this comment

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

I gave that a try back in my old POC branch to try account switching with real accounts off mocks and see what would happen, and wasn't able to successfully account switch so not sure about this. But I've forgotten exactly why it was that we needed the refresh for the new token to take affect, so if you want to leave as is until we can test for certain in the dev environment, that's fine.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for adding this!

Comment on lines +89 to +91
const userName =
(hasParentChildAccountAccess && isProxyUser ? parentProfile : profile)
?.username ?? '';
Copy link
Contributor

Choose a reason for hiding this comment

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

Much cleaner than the function that was doing this before - thanks!

jaalah-akamai and others added 4 commits January 18, 2024 13:11
Co-authored-by: Mariah Jacobs <114685994+mjac0bs@users.noreply.github.com>
Co-authored-by: Mariah Jacobs <114685994+mjac0bs@users.noreply.github.com>
…untList.tsx

Co-authored-by: Mariah Jacobs <114685994+mjac0bs@users.noreply.github.com>
Co-authored-by: Mariah Jacobs <114685994+mjac0bs@users.noreply.github.com>
Copy link

github-actions bot commented Jan 18, 2024

Coverage Report: βœ…
Base Coverage: 79.95%
Current Coverage: 79.95%

@carrillo-erik
Copy link
Contributor

I've verified the switch account flow as described in the reproduction steps. I was able to observe the updates to the authentication/token, authentication/parent_token/token, and authentication/proxy_token/token upon switching accounts. Also, after changing the user_type I verified that authentication/token matched the authentication/parent_token/token.

Regarding the note on the error states, I'm all for removing the toast in favor of displaying an error notice.

@jaalah-akamai
Copy link
Contributor Author

Toasts should be removed for error states πŸ‘

Copy link
Contributor

@mjac0bs mjac0bs left a comment

Choose a reason for hiding this comment

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

Thanks for addressing all the little pieces of feedback! πŸ™ŒπŸΌ

Confirmed:

  • When feature flag is off, no regressions in user menu.
  • When feature flag is on with user_type: null, no regressions in user menu.
  • When feature flag is on with user_type: child, no regressions in user menu.
  • When feature flag is on with user_type: parent, user menu displays the parent's company name with a clickable Switch Account button, which opens the Switch Account drawer. Clicking a child account swaps the proxy token into local storage active token as saves the current token as the local storage parent token.
  • When feature flag is on with user_type: proxy, user menu displays the child's company name with a clickable Switch Account button, which opens the Switch Account drawer. Drawer allows user to select another proxy account or switch back to parent account (swapping parent token into local storage active token).
  • Switch Account drawer gracefully handles an error when switching to a child account (shows error notice in drawer).
  • Switch Account drawer gracefully handles loading state and error loading child accounts (shows error copy and Try Again button in drawer, which tries to load accounts again when clicked).
  • Switch Account drawer gracefully handles error with expired parent token when switching back to parent account from proxy (shows error notice in drawer).
  • Same behavior as above for the Switch Account button on the Account Landing page.

Notes:

  • I don't think we have any loading state when clicking a child account and completing the account switch. May be worth adding as a follow up.

This LGTM. I'm still not certain the actual switching will work as expected, as I commented, but we know token swapping is. Looking forward to re-confirming all this with actual API data.

@mjac0bs mjac0bs added the Add'tl Approval Needed Waiting on another approval! label Jan 19, 2024
@jaalah-akamai
Copy link
Contributor Author

jaalah-akamai commented Jan 19, 2024

I don't think we have any loading state when clicking a child account and completing the account switch. May be worth adding as a follow up.

I'll make a note, it may get lost with the refresh / switch itself, but something we can test against API.

@mjac0bs mjac0bs added Approved Multiple approvals and ready to merge! and removed Add'tl Approval Needed Waiting on another approval! Ready for Review labels Jan 23, 2024
@jaalah-akamai jaalah-akamai merged commit b84275a into linode:develop Jan 23, 2024
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Approved Multiple approvals and ready to merge! Parent / Child Account
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants