Skip to content
Merged
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
6 changes: 6 additions & 0 deletions packages/api-v4/src/iam/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,12 @@ export type AccountAdmin =
| 'list_default_firewalls'
| 'list_delegate_users'
| 'list_enrolled_beta_programs'
| 'list_entities'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

wonder if we need to add AccountViewer to AccountAdmin as well, I assume that account_admin role includes all permissions from account_viewer, and now we have some duplicate permissions in that file

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

True - I will make a ticket to clean that up πŸ‘

| 'list_role_permissions'
| 'list_service_transfers'
| 'list_user_delegate_accounts'
| 'list_user_grants'
| 'list_user_permissions'
| 'revoke_profile_app'
| 'revoke_profile_device'
| 'send_profile_phone_number_verification_code'
Expand Down Expand Up @@ -254,8 +257,11 @@ export type AccountViewer =
| 'list_available_services'
| 'list_default_firewalls'
| 'list_enrolled_beta_programs'
| 'list_entities'
| 'list_role_permissions'
| 'list_service_transfers'
| 'list_user_grants'
| 'list_user_permissions'
| 'view_account'
| 'view_account_login'
| 'view_account_settings'
Expand Down
12 changes: 4 additions & 8 deletions packages/manager/src/features/IAM/Roles/Roles.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ describe('RolesLanding', () => {
const mockPermissions = accountRolesFactory.build();
queryMocks.usePermissions.mockReturnValue({
data: {
view_account: true,
is_account_admin: true,
list_role_permissions: true,
},
});
queryMocks.useAccountRoles.mockReturnValue({
Expand All @@ -76,8 +75,7 @@ describe('RolesLanding', () => {
it('should show an error message if user does not have permissions', () => {
queryMocks.usePermissions.mockReturnValue({
data: {
view_account: false,
is_account_admin: false,
list_role_permissions: false,
},
});

Expand All @@ -90,8 +88,7 @@ describe('RolesLanding', () => {
it('should not show the default roles panel for non-child accounts', () => {
queryMocks.usePermissions.mockReturnValue({
data: {
view_account: true,
is_account_admin: true,
list_role_permissions: true,
},
});
queryMocks.useProfile.mockReturnValue({ data: { user_type: 'parent' } });
Expand All @@ -109,8 +106,7 @@ describe('RolesLanding', () => {
it('should show the default roles panel for child accounts', () => {
queryMocks.usePermissions.mockReturnValue({
data: {
view_account: true,
is_account_admin: true,
list_role_permissions: true,
},
});
queryMocks.useProfile.mockReturnValue({ data: { user_type: 'child' } });
Expand Down
6 changes: 3 additions & 3 deletions packages/manager/src/features/IAM/Roles/Roles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import { DefaultRolesPanel } from './Defaults/DefaultRolesPanel';
export const RolesLanding = () => {
const { data: permissions, isLoading: isPermissionsLoading } = usePermissions(
'account',
['view_account', 'is_account_admin']
['list_role_permissions']
);
const { data: accountRoles, isLoading } = useAccountRoles(
permissions?.view_account
permissions?.list_role_permissions
);
const { isIAMDelegationEnabled } = useIsIAMDelegationEnabled();
const { isChildAccount, isProfileLoading } = useDelegationRole();
Expand All @@ -33,7 +33,7 @@ export const RolesLanding = () => {
return <CircleProgress />;
}

if (!(permissions?.view_account || permissions?.is_account_admin)) {
if (!permissions?.list_role_permissions) {
return (
<Notice variant="error">You do not have permission to view roles.</Notice>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const AssignedEntitiesTable = ({ username }: Props) => {
const { data: permissions } = usePermissions('account', [
'is_account_admin',
'update_default_delegate_access',
'list_entities',
]);

const { isDefaultDelegationRolesForChildAccount } =
Expand Down Expand Up @@ -106,7 +107,9 @@ export const AssignedEntitiesTable = ({ username }: Props) => {
data: entities,
error: entitiesError,
isLoading: entitiesLoading,
} = useAllAccountEntities({});
} = useAllAccountEntities({
enabled: permissions?.list_entities,
});

const {
data: assignedUserRoles,
Expand Down
27 changes: 15 additions & 12 deletions packages/manager/src/features/IAM/Users/UserDetails/UserProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,27 @@ import { UsernamePanel } from './UsernamePanel';
export const UserProfile = () => {
const { username } = useParams({ from: '/iam/users/$username' });
const { data: permissions } = usePermissions('account', [
'is_account_admin',
'view_account',
'view_user',
'update_user',
'delete_user',
'list_user_permissions',
]);

const isAccountAdmin = permissions?.is_account_admin;

const {
data: user,
error,
isLoading,
} = useAccountUser(
username ?? '',
isAccountAdmin || permissions?.view_account
);
} = useAccountUser(username ?? '', permissions?.view_user);
const { data: assignedRoles } = useUserRoles(
username ?? '',
isAccountAdmin || permissions?.view_account
permissions?.list_user_permissions
);

if (isLoading) {
return <CircleProgress />;
}

if (!(isAccountAdmin || permissions?.view_account)) {
if (!permissions?.view_user || !permissions?.list_user_permissions) {
return (
<Notice variant="error">
You do not have permission to view this user&apos;s details.
Expand All @@ -67,9 +64,15 @@ export const UserProfile = () => {
sx={(theme) => ({ marginTop: theme.tokens.spacing.S16 })}
>
<UserDetailsPanel activeUser={user} assignedRoles={assignedRoles} />
<UsernamePanel activeUser={user} canUpdateUser={isAccountAdmin} />
<UsernamePanel
activeUser={user}
canUpdateUser={permissions?.update_user}
/>
<UserEmailPanel activeUser={user} />
<DeleteUserPanel activeUser={user} canDeleteUser={isAccountAdmin} />
<DeleteUserPanel
activeUser={user}
canDeleteUser={permissions?.delete_user}
/>
</Stack>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('UserEntities', () => {
});
queryMocks.usePermissions.mockReturnValue({
data: {
is_account_admin: true,
list_entities: true,
},
});
});
Expand Down Expand Up @@ -155,8 +155,9 @@ describe('UserEntities', () => {
it('should not render if user does not have permissions', () => {
queryMocks.usePermissions.mockReturnValue({
data: {
is_account_admin: false,
view_account: false,
list_entities: false,
view_user: false,
list_role_permissions: false,
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,17 @@ export const UserEntities = () => {
const theme = useTheme();
const { username } = useParams({ from: '/iam/users/$username' });
const { data: permissions } = usePermissions('account', [
'is_account_admin',
'view_account',
'view_user',
'list_entities',
'list_user_permissions',
]);
const {
data: assignedRoles,
isLoading,
error: assignedRolesError,
} = useUserRoles(
username ?? '',
permissions?.is_account_admin || permissions?.view_account
);
} = useUserRoles(username ?? '', permissions?.list_user_permissions);

const { error } = useAccountUser(
username ?? '',
permissions?.is_account_admin || permissions?.view_account
);
const { error } = useAccountUser(username ?? '', permissions?.view_user);

const hasAssignedRoles = assignedRoles
? assignedRoles.entity_access.length > 0
Expand All @@ -49,7 +44,7 @@ export const UserEntities = () => {
return <CircleProgress />;
}

if (!(permissions?.is_account_admin || permissions?.view_account)) {
if (!permissions?.list_entities) {
return (
<Notice variant="error">
You do not have permission to view this user&apos;s entities.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe('UserRoles', () => {
});
queryMocks.usePermissions.mockReturnValue({
data: {
is_account_admin: true,
view_user: true,
},
});
});
Expand Down
15 changes: 5 additions & 10 deletions packages/manager/src/features/IAM/Users/UserRoles/UserRoles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,18 @@ export const UserRoles = () => {
const { username } = useParams({ from: '/iam/users/$username' });
const { data: permissions } = usePermissions('account', [
'is_account_admin',
'view_account',
'view_user',
'list_user_permissions',
]);
const theme = useTheme();

const {
data: assignedRoles,
isLoading,
error: assignedRolesError,
} = useUserRoles(
username ?? '',
permissions?.is_account_admin || permissions?.view_account
);
} = useUserRoles(username ?? '', permissions?.list_user_permissions);

const { error } = useAccountUser(
username ?? '',
permissions?.is_account_admin || permissions?.view_account
);
const { error } = useAccountUser(username ?? '', permissions?.view_user);

const hasAssignedRoles = assignedRoles
? assignedRoles.account_access.length > 0 ||
Expand All @@ -51,7 +46,7 @@ export const UserRoles = () => {
return <CircleProgress />;
}

if (!(permissions?.is_account_admin || permissions?.view_account)) {
if (!permissions?.view_user) {
return (
<Notice variant="error">
You do not have permission to view this user&apos;s roles.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ export const UserRow = ({ onDelete, user }: Props) => {
const { data: permissions } = usePermissions('account', [
'delete_user',
'is_account_admin',
'view_account',
'view_user',
]);

const { isIAMDelegationEnabled } = useIsIAMDelegationEnabled();
const canViewUser = permissions.view_account;
const canViewUser = permissions.view_user;

// Determine if the current user is a child account with isIAMDelegationEnabled enabled
// If so, we need to show the 'User type' column in the table
Expand Down
4 changes: 2 additions & 2 deletions packages/manager/src/features/IAM/Users/UsersTable/Users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const UsersLanding = () => {
const theme = useTheme();
const { data: permissions } = usePermissions('account', [
'create_user',
'view_account',
'view_user',
]);
const pagination = usePaginationV2({
currentRoute: '/iam/users',
Expand Down Expand Up @@ -166,7 +166,7 @@ export const UsersLanding = () => {
},
}}
debounceTime={250}
disabled={!permissions?.view_account}
disabled={!permissions?.view_user}
errorText={searchError?.message}
hideLabel
isSearching={isFetching}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('UsersActionMenu', () => {
permissions={{
is_account_admin: true,
delete_user: true,
view_account: true,
view_user: true,
}}
username="test_user"
/>
Expand Down Expand Up @@ -100,7 +100,7 @@ describe('UsersActionMenu', () => {
permissions={{
is_account_admin: true,
delete_user: true,
view_account: true,
view_user: true,
}}
username="current_user"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { PickPermissions, UserType } from '@linode/api-v4';
import type { Action } from 'src/components/ActionMenu/ActionMenu';

type UserActionMenuPermissions = PickPermissions<
'delete_user' | 'is_account_admin' | 'view_account'
'delete_user' | 'is_account_admin' | 'view_user'
>;

interface Props {
Expand All @@ -29,7 +29,7 @@ export const UsersActionMenu = (props: Props) => {
useDelegationRole();

const isAccountAdmin = permissions.is_account_admin;
const isAccountViewer = permissions.view_account;
const canViewUser = permissions.view_user;
const canDeleteUser = isAccountAdmin || permissions.delete_user;
const isDelegateUser = userType === 'delegate';

Expand All @@ -47,8 +47,8 @@ export const UsersActionMenu = (props: Props) => {
});
},
hidden: shouldHideForChildDelegate,
disabled: !isAccountViewer,
tooltip: !isAccountViewer
disabled: !canViewUser,
tooltip: !canViewUser
? 'You do not have permission to view user details.'
: undefined,
title: 'View User Details',
Expand All @@ -60,8 +60,8 @@ export const UsersActionMenu = (props: Props) => {
params: { username },
});
},
disabled: !isAccountViewer,
tooltip: !isAccountViewer
disabled: !canViewUser,
tooltip: !canViewUser
? 'You do not have permission to view assigned roles.'
: undefined,
title: 'View Assigned Roles',
Expand All @@ -73,8 +73,8 @@ export const UsersActionMenu = (props: Props) => {
params: { username },
});
},
disabled: !isAccountViewer,
tooltip: !isAccountViewer
disabled: !canViewUser,
tooltip: !canViewUser
? 'You do not have permission to view entity access.'
: undefined,
title: 'View Entity Access',
Expand Down