diff --git a/packages/manager/.changeset/pr-10248-upcoming-features-1709325591286.md b/packages/manager/.changeset/pr-10248-upcoming-features-1709325591286.md
new file mode 100644
index 00000000000..a235d89664f
--- /dev/null
+++ b/packages/manager/.changeset/pr-10248-upcoming-features-1709325591286.md
@@ -0,0 +1,5 @@
+---
+"@linode/manager": Upcoming Features
+---
+
+Display parent email in user menu for restricted parent users without access to company name ([#10248](https://github.com/linode/manager/pull/10248))
diff --git a/packages/manager/src/features/TopMenu/UserMenu/UserMenu.test.tsx b/packages/manager/src/features/TopMenu/UserMenu/UserMenu.test.tsx
index a4424eabad5..9254b677082 100644
--- a/packages/manager/src/features/TopMenu/UserMenu/UserMenu.test.tsx
+++ b/packages/manager/src/features/TopMenu/UserMenu/UserMenu.test.tsx
@@ -197,4 +197,48 @@ describe('UserMenu', () => {
expect(within(userMenuPopover).getByText('Child Company')).toBeVisible();
expect(within(userMenuPopover).getByText('Switch Account')).toBeVisible();
});
+
+ it('shows the parent email for a parent user if their company name is not set', async () => {
+ // Mock a forbidden request to the /account endpoint, which happens if Billing (Account) Access is None.
+ server.use(
+ rest.get('*/account/users/*/grants', (req, res, ctx) => {
+ return res(
+ ctx.json(
+ grantsFactory.build({
+ global: {
+ account_access: null,
+ },
+ })
+ )
+ );
+ }),
+ rest.get('*/account', (req, res, ctx) => {
+ return res(ctx.status(403));
+ }),
+ rest.get('*/profile', (req, res, ctx) => {
+ return res(
+ ctx.json(
+ profileFactory.build({
+ email: 'parent@parent.com',
+ user_type: 'parent',
+ username: 'parent-username',
+ })
+ )
+ );
+ })
+ );
+
+ const { findByLabelText, findByTestId } = renderWithTheme(, {
+ flags: { parentChildAccountAccess: true },
+ });
+
+ const userMenuButton = await findByLabelText('Profile & Account');
+ fireEvent.click(userMenuButton);
+
+ const userMenuPopover = await findByTestId('user-menu-popover');
+
+ expect(
+ within(userMenuPopover).getByText('parent@parent.com')
+ ).toBeVisible();
+ });
});
diff --git a/packages/manager/src/features/TopMenu/UserMenu/UserMenu.tsx b/packages/manager/src/features/TopMenu/UserMenu/UserMenu.tsx
index 3f72af54be6..2adb6aa411b 100644
--- a/packages/manager/src/features/TopMenu/UserMenu/UserMenu.tsx
+++ b/packages/manager/src/features/TopMenu/UserMenu/UserMenu.tsx
@@ -80,12 +80,16 @@ export const UserMenu = React.memo(() => {
((!isChildAccountAccessRestricted && isParentUser) || isProxyUser);
const open = Boolean(anchorEl);
const id = open ? 'user-menu-popover' : undefined;
- const companyName =
- (hasParentChildAccountAccess &&
- profile?.user_type !== 'default' &&
- account?.company) ??
- '';
- const showCompanyName = hasParentChildAccountAccess && companyName;
+
+ // If there is no company name to identify an account, fall back on the email.
+ // Covers an edge case in which a restricted parent user without `account_access` cannot access the account company.
+ const companyNameOrEmail =
+ hasParentChildAccountAccess &&
+ profile?.user_type !== 'default' &&
+ account?.company
+ ? account.company
+ : profile?.email;
+
const { isParentTokenExpired } = useParentTokenManagement({ isProxyUser });
// Used for fetching parent profile and account data by making a request with the parent's token.
@@ -119,11 +123,11 @@ export const UserMenu = React.memo(() => {
if (isProxyUser && !getStorage('proxy_user')) {
setStorage('proxy_user', 'true');
- enqueueSnackbar(`Account switched to ${companyName}.`, {
+ enqueueSnackbar(`Account switched to ${companyNameOrEmail}.`, {
variant: 'success',
});
}
- }, [isProxyUser, companyName, enqueueSnackbar]);
+ }, [isProxyUser, companyNameOrEmail, enqueueSnackbar]);
const accountLinks: MenuLink[] = React.useMemo(
() => [
@@ -225,19 +229,19 @@ export const UserMenu = React.memo(() => {
{userName}
- {showCompanyName && (
+ {companyNameOrEmail && (
({
fontFamily: theme.font.bold,
fontSize: '0.875rem',
})}
>
- {companyName}
+ {companyNameOrEmail}
)}
@@ -275,7 +279,9 @@ export const UserMenu = React.memo(() => {
fontSize="1.1rem"
>
- {canSwitchBetweenParentOrProxyAccount ? companyName : userName}
+ {canSwitchBetweenParentOrProxyAccount && companyNameOrEmail
+ ? companyNameOrEmail
+ : userName}
{canSwitchBetweenParentOrProxyAccount && (
@@ -291,23 +297,11 @@ export const UserMenu = React.memo(() => {
My Profile
-
-
+
+
{profileLinks.slice(0, 4).map(renderLink)}
-
+
{profileLinks.slice(4).map(renderLink)}