diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AccessController.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AccessController.java index b6522647b4..b4ec05f6bb 100644 --- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AccessController.java +++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/controller/AccessController.java @@ -36,7 +36,7 @@ public class AccessController implements AuthorizationApi { .map(user -> accessControlService.getRoles() .stream() .filter(role -> user.groups().contains(role.getName())) - .map(role -> mapPermissions(role.getPermissions(), role.getClusters())) + .map(role -> mapPermissions(role.getName(), role.getPermissions(), role.getClusters())) .flatMap(Collection::stream) .collect(Collectors.toList()) ) @@ -57,11 +57,12 @@ public class AccessController implements AuthorizationApi { .map(ResponseEntity::ok); } - private List mapPermissions(List permissions, List clusters) { + private List mapPermissions(String name, List permissions, List clusters) { return permissions .stream() .map(permission -> { UserPermissionDTO dto = new UserPermissionDTO(); + dto.setRoleName(name); dto.setClusters(clusters); dto.setResource(ResourceTypeDTO.fromValue(permission.getResource().toString().toUpperCase())); dto.setValue(permission.getValue()); diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/model/rbac/Permission.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/model/rbac/Permission.java index 56b0a09802..4e34610be4 100644 --- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/model/rbac/Permission.java +++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/model/rbac/Permission.java @@ -37,11 +37,18 @@ public class Permission { Resource resource; List actions; + String roleName; + @Nullable String value; @Nullable transient Pattern compiledValuePattern; + @SuppressWarnings("unused") + public void setRoleName(String roleName) { + this.roleName = roleName; + } + @SuppressWarnings("unused") public void setResource(String resource) { this.resource = Resource.fromString(resource.toUpperCase()); diff --git a/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml b/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml index 306c3fd2dd..bb6e6855a3 100644 --- a/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml +++ b/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml @@ -3554,6 +3554,8 @@ components: UserPermission: type: object properties: + roleName: + type: string clusters: type: array items: diff --git a/kafka-ui-react-app/src/components/NavBar/UserInfo/UserInfo.styled.ts b/kafka-ui-react-app/src/components/NavBar/UserInfo/UserInfo.styled.ts index 85154d7679..ade5379813 100644 --- a/kafka-ui-react-app/src/components/NavBar/UserInfo/UserInfo.styled.ts +++ b/kafka-ui-react-app/src/components/NavBar/UserInfo/UserInfo.styled.ts @@ -9,8 +9,18 @@ export const Wrapper = styled.div` position: relative; } `; - export const Text = styled.div( + ({ theme }) => css` + color: ${theme.menu.color.normal}; + ` +); +export const HeaderText = styled.div( + ({ theme }) => css` + color: ${theme.menu.titleColor}; + ` +); + +export const LinkText = styled.div( ({ theme }) => css` color: ${theme.button.primary.invertedColors.normal}; ` diff --git a/kafka-ui-react-app/src/components/NavBar/UserInfo/UserInfo.tsx b/kafka-ui-react-app/src/components/NavBar/UserInfo/UserInfo.tsx index dae43364c4..73a593e9fe 100644 --- a/kafka-ui-react-app/src/components/NavBar/UserInfo/UserInfo.tsx +++ b/kafka-ui-react-app/src/components/NavBar/UserInfo/UserInfo.tsx @@ -7,18 +7,49 @@ import { useUserInfo } from 'lib/hooks/useUserInfo'; import * as S from './UserInfo.styled'; const UserInfo = () => { - const { username } = useUserInfo(); + const { username, roles } = useUserInfo(); + + const roleNames = roles + ? Array.from(roles.values()) + .map((value) => { + const types = Array.from(value.values()).map((r) => r); + const names = new Set( + types.map((u) => u.map((a) => a.roleName)).flat() + ); + + return Array.from(names); + }) + .flat() + : []; return username ? ( - {username} + {username} } > + {roleNames.length > 0 && ( + <> + + Assigned roles + + + {roleNames.map((name) => ( + + {name} + + ))} + + +
+
+ + )} + Log out diff --git a/kafka-ui-react-app/src/components/NavBar/UserInfo/__tests__/UserInfo.spec.tsx b/kafka-ui-react-app/src/components/NavBar/UserInfo/__tests__/UserInfo.spec.tsx index 2231b09a25..974a0ba947 100644 --- a/kafka-ui-react-app/src/components/NavBar/UserInfo/__tests__/UserInfo.spec.tsx +++ b/kafka-ui-react-app/src/components/NavBar/UserInfo/__tests__/UserInfo.spec.tsx @@ -59,4 +59,27 @@ describe('UserInfo', () => { renderComponent(); expect(screen.queryByRole('listbox')).not.toBeInTheDocument(); }); + + it('should render the role names with correct data', () => { + const map = new Map(); + map.set( + 'someCluster', + new Map([ + ['CONFIG', [{ roleName: 'someRole1' }, { roleName: 'someRole2' }]], + ]) + ); + + (useUserInfo as jest.Mock).mockImplementation(() => ({ + username: 'someName', + roles: map, + })); + + renderComponent(); + + expect(screen.getByText('someName')).toBeInTheDocument(); + expect(screen.getByText('Assigned roles')).toBeInTheDocument(); + expect(screen.getByText('someRole1')).toBeInTheDocument(); + expect(screen.getByText('someRole2')).toBeInTheDocument(); + expect(screen.getByText('Log out')).toBeInTheDocument(); + }); });