diff --git a/src/app/AccessManagement/CreateRole.tsx b/src/app/AccessManagement/CreateRole.tsx index 5d1ff86dd..7581b09cc 100644 --- a/src/app/AccessManagement/CreateRole.tsx +++ b/src/app/AccessManagement/CreateRole.tsx @@ -26,27 +26,24 @@ import { useTranslation } from 'react-i18next'; import formUtils, { IField } from '@services/formUtils'; import { AddCircleOIcon, ExclamationCircleIcon, TimesIcon } from '@patternfly/react-icons'; import { useCreateRole, useFetchAvailableRoles } from '@app/services/rolesHook'; +import { PERMISSIONS_MAP } from '@services/infinispanRefData'; const CreateRole = (props: { isModalOpen: boolean; submitModal: () => void; closeModal: () => void }) => { const { t } = useTranslation(); const { roles } = useFetchAvailableRoles(); - const brandname = t('brandname.brandname'); - const initialSelectOptions: SelectOptionProps[] = [ - { value: 'ALL', children: 'ALL', description: t('access-management.roles.permission-all') }, - { value: 'ADMIN', children: 'ADMIN', description: t('access-management.roles.permission-admin') }, - { value: 'ALL_READ', children: 'ALL_READ', description: t('access-management.roles.permission-all-read') }, - { value: 'READ', children: 'READ', description: t('access-management.roles.permission-read') }, - { value: 'BULK_READ', children: 'BULK_READ', description: t('access-management.roles.permission-bulk-read') }, - { value: 'ALL_WRITE', children: 'ALL_WRITE', description: t('access-management.roles.permission-all-write') }, - { value: 'WRITE', children: 'WRITE', description: t('access-management.roles.permission-write') }, - { value: 'BULK_WRITE', children: 'BULK_WRITE', description: t('access-management.roles.permission-bulk-write') }, - { value: 'MONITOR', children: 'MONITOR', description: t('access-management.roles.permission-monitor') }, - { value: 'CREATE', children: 'CREATE', description: t('access-management.roles.permission-create') }, - { value: 'EXEC', children: 'EXEC', description: t('access-management.roles.permission-exec') }, - { value: 'LISTEN', children: 'LISTEN', description: t('access-management.roles.permission-listen') }, - { value: 'LIFECYCLE', children: 'LIFECYCLE', description: t('access-management.roles.permission-lifecycle') }, - { value: 'NONE', children: 'NONE', description: t('access-management.roles.permission-none') } - ]; + const initPermissions = () => { + let array: SelectOptionProps[] = []; + PERMISSIONS_MAP.forEach((value, key, map) => { + array.push({ + value: key, + children: key, + description: value + }) + }) + return array; + }; + const initialSelectOptions: SelectOptionProps[] = initPermissions(); + const roleNameInitialState: IField = { value: '', isValid: false, @@ -247,7 +244,7 @@ const CreateRole = (props: { isModalOpen: boolean; submitModal: () => void; clos {t('access-management.roles.modal-save-action')} , ]} > @@ -322,7 +319,7 @@ const CreateRole = (props: { isModalOpen: boolean; submitModal: () => void; clos {...option} hasCheckbox isSelected={selectedPermissions.includes(option.value)} - description={option.description} + description={t(option.description as string)} ref={null} /> ))} diff --git a/src/app/AccessManagement/RoleDetail.tsx b/src/app/AccessManagement/RoleDetail.tsx new file mode 100644 index 000000000..6d275c036 --- /dev/null +++ b/src/app/AccessManagement/RoleDetail.tsx @@ -0,0 +1,95 @@ +import React, { useEffect, useState } from 'react'; +import { + Card, + CardBody, + Nav, + NavItem, + NavList, + PageSection, + PageSectionVariants, + Text, + TextContent, + TextVariants +} from '@patternfly/react-core'; +import { useTranslation } from 'react-i18next'; +import { DataContainerBreadcrumb } from '@app/Common/DataContainerBreadcrumb'; +import { global_spacer_md, global_spacer_sm } from '@patternfly/react-tokens'; +import { RoleGeneral } from '@app/AccessManagement/RoleDetailContent/RoleGeneral'; +import { RolePermissions } from '@app/AccessManagement/RoleDetailContent/RolePermissions'; + +const RoleDetail = (props) => { + const roleName = decodeURIComponent(props.computedMatch.params.roleName); + const { t } = useTranslation(); + const brandname = t('brandname.brandname'); + const [activeTabKey, setActiveTabKey] = useState('0'); + const [showGeneralDescription, setShowGeneralDescription] = useState(true); + const [showPermissions, setShowPermissions] = useState(false); + const [showCaches, setShowCaches] = useState(false); + + useEffect(() => { + setShowGeneralDescription(activeTabKey === '0'); + setShowPermissions(activeTabKey === '1'); + setShowCaches(activeTabKey === '2'); + }, [activeTabKey]); + + interface AccessTab { + key: string; + name: string; + } + + const handleTabClick = (event, nav) => { + setActiveTabKey(nav.itemId); + }; + + const tabs: AccessTab[] = [ + { name: t('access-management.role.tab-general'), key: '0' }, + { name: t('access-management.role.tab-permissions'), key: '1' }, + // { name: t('access-management.role.tab-caches'), key: '2' } + ]; + + const buildTabs = () => { + return ( + + ); + }; + + const buildSelectedContent = ( + + + {showGeneralDescription && } + {showPermissions && } + {/*{showCaches && }*/} + + + ); + + return ( + <> + + + + {roleName} + + {buildTabs()} + + {buildSelectedContent} + + ); +}; + +export { RoleDetail }; diff --git a/src/app/AccessManagement/RoleDetailContent/RoleCaches.tsx b/src/app/AccessManagement/RoleDetailContent/RoleCaches.tsx new file mode 100644 index 000000000..dc795c660 --- /dev/null +++ b/src/app/AccessManagement/RoleDetailContent/RoleCaches.tsx @@ -0,0 +1,12 @@ +import { useTranslation } from 'react-i18next'; + +const RoleCaches = () => { + const { t } = useTranslation(); + const brandname = t('brandname.brandname'); + + return ( + "Caches" + ) +}; + +export { RoleCaches }; diff --git a/src/app/AccessManagement/RoleDetailContent/RoleGeneral.tsx b/src/app/AccessManagement/RoleDetailContent/RoleGeneral.tsx new file mode 100644 index 000000000..0148cb051 --- /dev/null +++ b/src/app/AccessManagement/RoleDetailContent/RoleGeneral.tsx @@ -0,0 +1,174 @@ +import { useTranslation } from 'react-i18next'; +import { useDescribeRole } from '@app/services/rolesHook'; +import { + ActionGroup, + Alert, + Button, + ButtonVariant, + EmptyState, + EmptyStateActions, + EmptyStateBody, + EmptyStateFooter, + EmptyStateHeader, + EmptyStateIcon, + EmptyStateVariant, + Form, + FormGroup, + FormHelperText, + HelperText, + HelperTextItem, + Spinner, + TextInput +} from '@patternfly/react-core'; +import * as React from 'react'; +import { useEffect, useState } from 'react'; +import { ExclamationCircleIcon } from '@patternfly/react-icons'; +import { global_danger_color_200 } from '@patternfly/react-tokens'; +import { Link } from 'react-router-dom'; +import formUtils, { IField } from '@services/formUtils'; + +const RoleGeneral= (props: { name: string }) => { + const roleNameInitialState: IField = { + value: '', + isValid: false, + validated: 'default' + }; + + const roleDescriptionInitialState: IField = { + value: '', + isValid: false, + validated: 'default' + }; + + const { t } = useTranslation(); + const {role, loading, error, setLoading} = useDescribeRole(props.name); + const brandname = t('brandname.brandname'); + const [roleName, setRoleName] = useState(roleNameInitialState); + const [roleDescription, setRoleDescription] = useState(roleDescriptionInitialState); + const [isImplicit, setIsImplicit] = useState(false); + + useEffect(() => { + if (role) { + setRoleName({ + ...roleName, + value: role.name + }); + setRoleDescription({ + ...roleDescription, + value: role.description + }) + setIsImplicit(role.implicit); + } + }, [role]); + + const buildDetailContent = () => { + if (loading && !role) { + return ( + + ); + } + + if (error !== '') { + return ( + + } + headingLevel="h2" + /> + {error} + + + + + + + + + ) + } + + const displayImplicitRoleMessage = () => { + return role?.implicit && ( + + ); + } + return ( +
{ + e.preventDefault(); + }} + > + {displayImplicitRoleMessage()} + + + formUtils.validateRequiredField(value, t('access-management.roles.modal-role-name'), setRoleName) + } + aria-label="role-name-input" + /> + {roleName.validated === 'error' && ( + + + }> + {roleName.invalidText} + + + + )} + + + + formUtils.validateRequiredField( + value, + t('access-management.roles.modal-role-description'), + setRoleDescription + ) + } + aria-label="role-description-input" + /> + {roleDescription.validated === 'error' && ( + + + }> + {roleDescription.invalidText} + + + + )} + + + + + +
+ ) + } + + return buildDetailContent(); +}; + +export { RoleGeneral }; diff --git a/src/app/AccessManagement/RoleDetailContent/RolePermissions.tsx b/src/app/AccessManagement/RoleDetailContent/RolePermissions.tsx new file mode 100644 index 000000000..01e69e2e1 --- /dev/null +++ b/src/app/AccessManagement/RoleDetailContent/RolePermissions.tsx @@ -0,0 +1,196 @@ +import { useTranslation } from 'react-i18next'; +import { + Bullseye, + Button, + ButtonVariant, EmptyState, EmptyStateBody, EmptyStateIcon, EmptyStateVariant, + Pagination, + SearchInput, Title, + Toolbar, + ToolbarContent, + ToolbarGroup, + ToolbarItem, + ToolbarItemVariant +} from '@patternfly/react-core'; +import React, { useEffect, useState } from 'react'; +import { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; +import { useDescribeRole } from '@app/services/rolesHook'; +import { PERMISSIONS_MAP } from '@services/infinispanRefData'; +import { TableErrorState } from '@app/Common/TableErrorState'; +import { TableLoadingState } from '@app/Common/TableLoadingState'; +import { SearchIcon } from '@patternfly/react-icons'; + +const RolePermissions = (props: { name: string }) => { + const { t } = useTranslation(); + const {role, loading, error, setLoading} = useDescribeRole(props.name); + const [pagination, setPagination] = useState({ + page: 1, + perPage: 5 + }); + const [searchValue, setSearchValue] = useState(''); + const [permissionRows, setPermissionRows] = useState([]); + const [filteredPermissions, setFilteredPermissions] = useState([]); + + useEffect(() => { + if (!role) { + return; + } + + if (searchValue.trim() !== '') { + setFilteredPermissions(role.permissions.filter((perm) => perm.toLowerCase().includes(searchValue.toLowerCase())).sort()); + } else { + setFilteredPermissions(role.permissions.sort()); + } + + setPagination({ + ...pagination, + page: 1 + }); + }, [role, searchValue]); + + useEffect(() => { + if (!role) { + return; + } + const initSlice = (pagination.page - 1) * pagination.perPage; + setPermissionRows(filteredPermissions.slice(initSlice, initSlice + pagination.perPage)); + }, [filteredPermissions, pagination]); + + const columnNames = { + name: t('access-management.role.permission-name'), + description: t('access-management.role.permission-description'), + }; + + const onSetPage = (_event, pageNumber) => { + setPagination({ + ...pagination, + page: pageNumber + }); + }; + + const onPerPageSelect = (_event, perPage) => { + setPagination({ + page: 1, + perPage: perPage + }); + }; + + const onSearchChange = (value: string) => { + setSearchValue(value); + }; + + const paginationComponent = ( + + ); + + const displayRows = () => { + if (!role || permissionRows.length == 0) { + return ( + + + + + + + {t('access-management.role.no-permissions-found')} + + + {t('access-management.role.no-filtered-permissions-body')} + + + + + + ) + } + + return ( + + {permissionRows.map((row) => ( + + {row} + {PERMISSIONS_MAP.get(row)? t(PERMISSIONS_MAP.get(row) as string): row } + + ))} + + ); + }; + + const addPermissionButton = () => { + if (!role || role.implicit) { + return; + } + + return ( + + ); + } + + if (loading) { + return ( + + ); + } + + if (error) { + return ( + + ); + } + + return ( + + + + + + onSearchChange(value)} + onSearch={(_event, value) => onSearchChange(value)} + onClear={() => setSearchValue('')} + /> + + + {addPermissionButton()} + + + + {paginationComponent} + + + + + + + + + + + {displayRows()} +
+ {columnNames.name} + {columnNames.description}
+ + {paginationComponent} + +
+ ); +}; + +export { RolePermissions }; diff --git a/src/app/AccessManagement/RoleTableDisplay.tsx b/src/app/AccessManagement/RoleTableDisplay.tsx index 3597e56fb..fae3d3ff1 100644 --- a/src/app/AccessManagement/RoleTableDisplay.tsx +++ b/src/app/AccessManagement/RoleTableDisplay.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useState } from 'react'; +import { Link } from 'react-router-dom'; import { Bullseye, Button, @@ -14,13 +15,13 @@ import { Icon, Pagination, SearchInput, - Spinner, Title, Toolbar, ToolbarContent, ToolbarGroup, ToolbarItem, - ToolbarItemVariant + ToolbarItemVariant, + Spinner } from '@patternfly/react-core'; import { ActionsColumn, IAction, Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; import { useTranslation } from 'react-i18next'; @@ -29,6 +30,8 @@ import { useFetchAvailableRoles } from '@app/services/rolesHook'; import { CreateRole } from '@app/AccessManagement/CreateRole'; import { global_spacer_sm, global_spacer_xl } from '@patternfly/react-tokens'; import { DeleteRole } from '@app/AccessManagement/DeleteRole'; +import { TableErrorState } from '@app/Common/TableErrorState'; +import { TableLoadingState } from '@app/Common/TableLoadingState'; const RoleTableDisplay = () => { const { t } = useTranslation(); @@ -89,7 +92,7 @@ const RoleTableDisplay = () => { const pagination = ( { )} - {row.name} + {row.name} + { @@ -155,7 +163,7 @@ const RoleTableDisplay = () => { {roles.length == 0 - ? t('access-management.roles.no-roles-body') + ? t('access-management.roles.no-roles-body', {brandname: brandname}) : t('access-management.roles.no-filtered-roles-body')} @@ -164,6 +172,7 @@ const RoleTableDisplay = () => { ); }; + const createRoleButtonHelper = (isEmptyPage?: boolean) => { const emptyPageButtonProp = { style: { marginTop: global_spacer_xl.value } }; const normalPageButtonProps = { style: { marginLeft: global_spacer_sm.value } }; @@ -180,34 +189,6 @@ const RoleTableDisplay = () => { ); }; - if (loading) { - return ( - - - {t('access-management.roles.loading-roles')}} - icon={} - headingLevel="h4" - /> - - - ); - } - - if (error) { - return ( - - - {t('access-management.roles.loading-roles-error')}} - icon={} - headingLevel="h4" - /> - - - ); - } - const displayContent = () => { if (roles.length === 0) { return ( @@ -222,6 +203,19 @@ const RoleTableDisplay = () => { ); } + + if (loading) { + return ( + + ); + } + + if (error) { + return ( + + ); + } + return ( @@ -258,7 +252,7 @@ const RoleTableDisplay = () => { } }} > - {columnNames.name} + {columnNames.name} {columnNames.permissions} {columnNames.description} diff --git a/src/app/Caches/Create/CreateCacheWizard.tsx b/src/app/Caches/Create/CreateCacheWizard.tsx index 6601becb2..7e3463bd4 100644 --- a/src/app/Caches/Create/CreateCacheWizard.tsx +++ b/src/app/Caches/Create/CreateCacheWizard.tsx @@ -245,7 +245,7 @@ const CreateCacheWizard = (props: { cacheManager: CacheManager; create: boolean onClick={(event) => getPreviousStep(event, activeStep, onBack)} data-cy="wizardBackButton" > - {t('caches.create.back-button-label')} + {t('common.actions.back')} ); diff --git a/src/app/Caches/DetailCache.tsx b/src/app/Caches/DetailCache.tsx index 71ff568e2..9ec501597 100644 --- a/src/app/Caches/DetailCache.tsx +++ b/src/app/Caches/DetailCache.tsx @@ -183,7 +183,7 @@ const DetailCache = (props: { cacheName: string }) => { search: location.search }} > - + diff --git a/src/app/Common/DataContainerBreadcrumb.tsx b/src/app/Common/DataContainerBreadcrumb.tsx index 35eb1b5c2..8b86bb3d1 100644 --- a/src/app/Common/DataContainerBreadcrumb.tsx +++ b/src/app/Common/DataContainerBreadcrumb.tsx @@ -1,8 +1,10 @@ import { Breadcrumb, BreadcrumbItem } from '@patternfly/react-core'; import { Link } from 'react-router-dom'; import * as React from 'react'; +import { useTranslation } from 'react-i18next'; -const DataContainerBreadcrumb = (props: { currentPage: string; cacheName?: string }) => { +const DataContainerBreadcrumb = (props: { currentPage: string; parentPage?: string, cacheName?: string, label?: string }) => { + const { t } = useTranslation(); const addCacheName = () => { if (props.cacheName) { return ( @@ -20,17 +22,17 @@ const DataContainerBreadcrumb = (props: { currentPage: string; cacheName?: strin } return; }; - + const label = props.label? props.label : 'cache-managers.title'; return ( - + - Data container + {t(label)} {addCacheName()} diff --git a/src/app/Common/TableErrorState.tsx b/src/app/Common/TableErrorState.tsx index 9f1855a14..ad8bfff7e 100644 --- a/src/app/Common/TableErrorState.tsx +++ b/src/app/Common/TableErrorState.tsx @@ -2,9 +2,9 @@ import { Bullseye, EmptyState, EmptyStateBody, + EmptyStateHeader, EmptyStateIcon, - EmptyStateVariant, - EmptyStateHeader + EmptyStateVariant } from '@patternfly/react-core'; import { ExclamationCircleIcon } from '@patternfly/react-icons'; import { global_danger_color_200 } from '@patternfly/react-tokens'; @@ -12,17 +12,15 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; const TableErrorState = (props: { error: string; detail?: string }) => { + const { t } = useTranslation(); const displayErrorBody = () => { if (props.detail) { return props.detail as string; } else { - return 'There was an error retrieving data.\n' + ' Check your connection and try again.'; + return t('common.loading-error-message'); } }; - const { t } = useTranslation(); - const brandname = t('brandname.brandname'); - return ( diff --git a/src/app/Common/TableLoadingState.tsx b/src/app/Common/TableLoadingState.tsx new file mode 100644 index 000000000..666fb13e9 --- /dev/null +++ b/src/app/Common/TableLoadingState.tsx @@ -0,0 +1,24 @@ +import { + Bullseye, + EmptyState, + EmptyStateHeader, + EmptyStateIcon, + EmptyStateVariant, + Spinner +} from '@patternfly/react-core'; +import * as React from 'react'; + +const TableLoadingState = (props: { message: string }) => { + return ( + + + } + headingLevel="h4" + /> + + + ); +}; +export { TableLoadingState }; diff --git a/src/app/IndexManagement/IndexManagement.tsx b/src/app/IndexManagement/IndexManagement.tsx index b93c5f206..fdda93eea 100644 --- a/src/app/IndexManagement/IndexManagement.tsx +++ b/src/app/IndexManagement/IndexManagement.tsx @@ -169,7 +169,7 @@ const IndexManagement = (props) => { }} > diff --git a/src/app/assets/languages/en.json b/src/app/assets/languages/en.json index 22c0aa2fb..b88a13e00 100644 --- a/src/app/assets/languages/en.json +++ b/src/app/assets/languages/en.json @@ -7,6 +7,14 @@ "configuration-docs-link": "https://infinispan.org/docs/stable/titles/configuring/configuring.html", "default-roles-docs-link": "https://infinispan.org/docs/stable/titles/server/server.html#default-user-roles_server-getting-started" }, + "common" : { + "actions" : { + "back": "Back", + "cancel": "Cancel", + "save": "Save" + }, + "loading-error-message": "There was an error retrieving data. Check your connection and try again." + }, "layout": { "console-name": "Server Management Console", "skip-to-content": "Skip to Content", @@ -219,7 +227,6 @@ "templates-placeholder": "Select a cache template", "create-button-label": "Create", "next-button-label": "Next", - "back-button-label": "Back", "cancel-button-label": "Cancel", "download-button-label": "Download", "getting-started": { @@ -534,8 +541,7 @@ "action-see-less": "See fewer cache details", "action-see-more": "See more cache details", "action-manage-indexes": "Manage indexes", - "refresh": "Refresh", - "back": "Back" + "refresh": "Refresh" }, "entries": { "action-edit": "Edit", @@ -642,8 +648,7 @@ "size": "Index size in bytes", "indexing-status": "Indexing", "button-clear": "Clear index", - "button-rebuild": "Rebuild index", - "button-back-to-cache-detail": "Back" + "button-rebuild": "Rebuild index" }, "rebalancing": { "rebalancing": "Rebalancing", @@ -853,6 +858,7 @@ "no-filtered-roles-body": "No roles match your search criteria.", "roles-hint-link": "Learn more in the {{brandname}} documentation", "loading-roles": "Loading roles", + "loading-roles-error": "Unexpected error loading roles", "create-button": "Create role", "delete-action": "Delete", "no-roles-status": "No roles", @@ -886,6 +892,21 @@ "modal-delete-description-2": "You can always recreate the role.", "delete-success": "Role {{name}} has been deleted", "delete-error": "Unexpected error deleting the role {{name}}" + }, + "role" : { + "breadcrumb": "Detail of role {{roleName}}", + "tab-general": "General settings", + "tab-permissions": "Permissions", + "tab-caches": "Accessible caches", + "loading": "Loading role {{roleName}}", + "error": "An error occurred while retrieving the role {{roleName}}", + "implicit-warning": "The general settings for predefined roles are not editable.", + "permission-name": "Permission name", + "permission-description": "Description", + "add-permission-button": "Add permission", + "permissions-search-placeholder": "Filter by name", + "no-permissions-found": "No permission found", + "no-filtered-permissions-body": "No permission match your search criteria." } } } diff --git a/src/app/routes.tsx b/src/app/routes.tsx index b30efe4ef..8f165749d 100644 --- a/src/app/routes.tsx +++ b/src/app/routes.tsx @@ -19,6 +19,7 @@ import { ConsoleServices } from '@services/ConsoleServices'; import { ConsoleACL } from '@services/securityService'; import { NotAuthorized } from '@app/NotAuthorized/NotAuthorized'; import { NotFound } from '@app/NotFound/NotFound'; +import { RoleDetail } from '@app/AccessManagement/RoleDetail'; let routeFocusTimer: number; @@ -186,7 +187,16 @@ const routes: IAppRoute[] = [ title: 'Connected Clients', menu: true, admin: true - } + }, + { + component: RoleDetail, + exact: true, + label: 'Role detail', + path: '/role/:roleName', + title: 'Role detail', + menu: false, + admin: true + }, ]; const AppRoutes = (props: { init: string }) => { diff --git a/src/app/services/rolesHook.ts b/src/app/services/rolesHook.ts index 750fb099b..8b7dd8a56 100644 --- a/src/app/services/rolesHook.ts +++ b/src/app/services/rolesHook.ts @@ -77,3 +77,29 @@ export function useDeleteRole(roleName: string, call: () => void) { onDeleteRole }; } + +export function useDescribeRole(roleName: string) { + const [role, setRole] = useState(); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(''); + + useEffect(() => { + if (loading) { + ConsoleServices.security() + .describeRole( + roleName + ) + .then((either) => { + if (either.isRight()) { + setRole(either.value); + } else { + setError(either.value.message); + } + }).finally(() => setLoading(false)); + } + }, [loading]) + + return { + role, loading, error, setLoading + }; +} diff --git a/src/services/displayUtils.ts b/src/services/displayUtils.ts index 44b8664b1..d5a592f89 100644 --- a/src/services/displayUtils.ts +++ b/src/services/displayUtils.ts @@ -465,12 +465,12 @@ class DisplayUtils { return featureChipGroup; } - public formatContentToDisplay(content: any, contentType?: ContentType): string { + public formatContentToDisplay(content: never, contentType?: ContentType): string { if (!contentType || contentType == ContentType.JSON || contentType == ContentType.customType) { // Try parse and stringify try { return JSON.stringify(JSON.parse(content), null, 2); - } catch (err) {} + } catch (err) { /* empty */ } } return content as string; diff --git a/src/services/infinispanRefData.ts b/src/services/infinispanRefData.ts index 65ccb08c7..dfe520e3a 100644 --- a/src/services/infinispanRefData.ts +++ b/src/services/infinispanRefData.ts @@ -1,11 +1,4 @@ -import { - fileStore, - jdbcStore, - querySqlStore, - remoteStore, - rocksDB, - tableSqlStore -} from '@app/utils/persistentStorageTemplate'; +import { fileStore, jdbcStore, querySqlStore, remoteStore, tableSqlStore } from '@app/utils/persistentStorageTemplate'; export enum ComponentHealth { HEALTHY = 'HEALTHY', @@ -247,3 +240,24 @@ export enum RoleFilterOption { cacheManagerPermissions = 'Cache Manager Permissions', cachePermissions = 'Cache Permissions' } + +export enum Permission { + ALL = 'all', +} + +export const PERMISSIONS_MAP = new Map([ + ["ALL", "access-management.roles.permission-all"], + ["ADMIN", "access-management.roles.permission-admin"], + ["ALL_READ", "access-management.roles.permission-all-read"], + ["READ", "access-management.roles.permission-read"], + ["BULK_READ", "access-management.roles.permission-bulk-read"], + ["ALL_WRITE", "access-management.roles.permission-all-write"], + ["WRITE", "access-management.roles.permission-write"], + ["BULK_WRITE", "access-management.roles.permission-bulk-write"], + ["MONITOR", "access-management.roles.permission-monitor"], + ["CREATE", "access-management.roles.permission-create"], + ["EXEC", "access-management.roles.permission-exec"], + ["LISTEN", "access-management.roles.permission-listen"], + ["LIFECYCLE", "access-management.roles.permission-lifecycle"], + ["NONE", "access-management.roles.permission-none"], +]); diff --git a/src/services/securityService.ts b/src/services/securityService.ts index 9a62a4b72..61f2b3096 100644 --- a/src/services/securityService.ts +++ b/src/services/securityService.ts @@ -178,6 +178,21 @@ export class SecurityService { ); } + /** + * Retrieve security roles + * + */ + public async describeRole(roleName: string): Promise> { + return this.fetchCaller.get(this.endpoint + '/permissions/' + roleName, (data) => + { + name: roleName, + description: data.description, + permissions: data.permissions, + implicit: data.implicit + } + ); + } + /** * Created a new role * @param roleName