Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
mockGetUser,
} from 'support/intercepts/account';
import { mockGetEvents, mockGetNotifications } from 'support/intercepts/events';
import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags';
import { mockAllApiRequests } from 'support/intercepts/general';
import {
mockGetRolePermissionsError,
Expand Down Expand Up @@ -151,6 +152,10 @@ const mockAlternateChildAccountToken = appTokenFactory.build({
const mockErrorMessage = 'An unknown error has occurred.';

describe('Parent/Child account switching', () => {
beforeEach(() => {
// Disable IAM delegation to use legacy child accounts flow for all tests
mockAppendFeatureFlags({ iamDelegation: false });
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jdamore-linode, quick question: for the failing E2E tests, I turned off the IAM delegation flag in the test. Does that look okay, or should we fix this another way?

Copy link
Contributor

Choose a reason for hiding this comment

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

@mpolotsk-akamai it appears the tests are still failing either way? @jdamore-linode would you mind checking? thx!

});
/*
* Tests to confirm that Parent account users can switch to Child accounts as expected.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ export const SwitchAccountButton = (props: ButtonProps) => {
},
font: theme.tokens.alias.Typography.Label.Semibold.S,
marginTop: theme.tokens.spacing.S4,
...(isDelegateUserType && {
'&.MuiButton-root': {
textTransform: 'none',
},
}),
})}
{...props}
>
{isDelegateUserType ? 'Switch back to your account' : 'Switch Account'}
{isDelegateUserType ? 'Switch Back to Your Account' : 'Switch Account'}
</Button>
);
};
102 changes: 54 additions & 48 deletions packages/manager/src/features/Account/SwitchAccountDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,18 @@ export const SwitchAccountDrawer = (props: Props) => {
userType: isIAMDelegationEnabled ? 'delegate' : 'proxy',
});
onClose(event);
location.replace('/linodes');

// Only redirect to /linodes for IAM delegate users
if (isIAMDelegationEnabled) {
location.replace('/linodes');
} else {
location.reload();
}
} catch {
// Error is handled by createTokenError.
}
},
[createToken, isProxyUserType, updateCurrentToken, revokeToken]
[createToken, updateCurrentToken, revokeToken, isIAMDelegationEnabled]
);

const [isSwitchingChildAccounts, setIsSwitchingChildAccounts] =
Expand Down Expand Up @@ -243,7 +249,7 @@ export const SwitchAccountDrawer = (props: Props) => {
.
</Typography>

{hasError && (
{hasError ? (
<Stack alignItems="center" gap={1} justifyContent="center">
<ErrorStateCloud />
<Typography>Unable to load data.</Typography>
Expand All @@ -260,8 +266,7 @@ export const SwitchAccountDrawer = (props: Props) => {
Try again
</Button>
</Stack>
)}
{!hasError && (
) : (
<>
<DebouncedSearchTextField
clearable
Expand All @@ -287,51 +292,52 @@ export const SwitchAccountDrawer = (props: Props) => {
No search results
</Typography>
)}

{isIAMDelegationEnabled && (
<ChildAccountsTable
childAccounts={childAccounts}
currentTokenWithBearer={
isProxyOrDelegateUserType
? currentParentTokenWithBearer
: currentTokenWithBearer
}
filter={filter}
isLoading={isLoading}
isSwitchingChildAccounts={isSwitchingChildAccounts}
onClose={onClose}
onPageChange={handlePageChange}
onPageSizeChange={handlePageSizeChange}
onSwitchAccount={handleSwitchToChildAccount}
page={page}
pageSize={pageSize}
setIsSwitchingChildAccounts={setIsSwitchingChildAccounts}
totalResults={delegatedChildAccounts?.results || 0}
userType={userType}
/>
)}
{!isIAMDelegationEnabled && (
<ChildAccountList
childAccounts={childAccounts}
currentTokenWithBearer={
isProxyOrDelegateUserType
? currentParentTokenWithBearer
: currentTokenWithBearer
}
fetchNextPage={fetchNextPage}
filter={filter}
hasNextPage={hasNextPage}
isFetchingNextPage={isFetchingNextPage}
isLoading={isLoading}
isSwitchingChildAccounts={isSwitchingChildAccounts}
onClose={onClose}
onSwitchAccount={handleSwitchToChildAccount}
refetchFn={refetchFn}
setIsSwitchingChildAccounts={setIsSwitchingChildAccounts}
userType={userType}
/>
)}
</>
)}
{isIAMDelegationEnabled && (
<ChildAccountsTable
childAccounts={childAccounts}
currentTokenWithBearer={
isProxyOrDelegateUserType
? currentParentTokenWithBearer
: currentTokenWithBearer
}
filter={filter}
isLoading={isLoading}
isSwitchingChildAccounts={isSwitchingChildAccounts}
onClose={onClose}
onPageChange={handlePageChange}
onPageSizeChange={handlePageSizeChange}
onSwitchAccount={handleSwitchToChildAccount}
page={page}
pageSize={pageSize}
setIsSwitchingChildAccounts={setIsSwitchingChildAccounts}
totalResults={delegatedChildAccounts?.results || 0}
userType={userType}
/>
)}
{!isIAMDelegationEnabled && (
<ChildAccountList
childAccounts={childAccounts}
currentTokenWithBearer={
isProxyOrDelegateUserType
? currentParentTokenWithBearer
: currentTokenWithBearer
}
fetchNextPage={fetchNextPage}
filter={filter}
hasNextPage={hasNextPage}
isFetchingNextPage={isFetchingNextPage}
isLoading={isLoading}
isSwitchingChildAccounts={isSwitchingChildAccounts}
onClose={onClose}
onSwitchAccount={handleSwitchToChildAccount}
refetchFn={refetchFn}
setIsSwitchingChildAccounts={setIsSwitchingChildAccounts}
userType={userType}
/>
)}
</Drawer>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ export const useSwitchToParentAccount = ({
}

onClose?.();
location.reload();

// For switch back to parent, always redirect to /linodes for delegate users
if (isDelegateUserType) {
location.replace('/linodes');
} else {
location.reload();
}
} catch (error) {
setSubmitting(false);
throw error;
Expand Down
7 changes: 4 additions & 3 deletions packages/manager/src/features/TopMenu/UserMenu/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@ export const UserMenu = React.memo(() => {
setStorage('is_delegate_user_type', 'true');
}

enqueueSnackbar(`Account switched to ${companyNameOrEmail}.`, {
variant: 'success',
});
const message = companyNameOrEmail
? `Account switched to ${companyNameOrEmail}.`
: 'Account switched.';
enqueueSnackbar(message, { variant: 'success' });
}
}, [
isProxyOrDelegateUserType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,11 @@ export const UserMenuPopover = (props: UserMenuPopoverProps) => {
gap={(theme) => theme.tokens.spacing.S16}
minWidth={250}
>
<Stack display="flex" gap={(theme) => theme.tokens.spacing.S8}>
{canSwitchBetweenParentOrProxyAccount && (
<Stack
display="flex"
gap={(theme) => (companyNameOrEmail ? theme.tokens.spacing.S8 : 0)}
>
{canSwitchBetweenParentOrProxyAccount && companyNameOrEmail && (
<Typography
sx={(theme) => ({
color: theme.tokens.alias.Content.Text.Primary.Default,
Expand All @@ -254,8 +257,8 @@ export const UserMenuPopover = (props: UserMenuPopoverProps) => {
overflowWrap: 'break-word',
})}
>
{canSwitchBetweenParentOrProxyAccount && companyNameOrEmail
? companyNameOrEmail
{canSwitchBetweenParentOrProxyAccount
? companyNameOrEmail || null
: userName}
</Typography>
{canSwitchBetweenParentOrProxyAccount && (
Expand Down