Skip to content

Commit

Permalink
ISPN-15125 Error page is shown for non-admin user if accesses cache t…
Browse files Browse the repository at this point in the history
…o which has permission
  • Loading branch information
karesti committed Oct 3, 2023
1 parent f37cb89 commit e073cd1
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 100 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/no-empty-function": "off",
"prettier/prettier": "off",
"import/no-unresolved": "off",
"import/extensions": "off",
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pull_requests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
docker exec $(docker ps -q -l) /opt/infinispan/bin/cli.sh install org.ow2.asm:asm-tree:9.4
docker exec $(docker ps -q -l) /opt/infinispan/bin/cli.sh install org.ow2.asm:asm-util:9.4
- name: Restarting Infnispan Server After Nashorn Installation
- name: Restarting Infinispan Server After Nashorn Installation
run: |
docker restart $(docker ps -q -l)
# Wait for server to startup
Expand Down
3 changes: 0 additions & 3 deletions cypress/e2e/data-container.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,10 @@ describe('Data Container Overview', () => {
cy.get('[data-cy=cacheFilterSelect]').click();
cy.get('[data-cy=cacheFilterSelectExpanded]').should('exist');
cy.get('[id$="Invalidated"]').click(); //Filtering invalidated caches
cy.get('[id$="Scattered"]').click(); //Filtering scattered caches
cy.get('[data-cy=cacheFilterSelect]').click(); //Closing filter selectbox

//Verifying that only replicated,invalidated and scattered caches are shown
cy.contains('jboss-cache');
cy.contains('invalidationCache');
cy.contains('scattered-cache');
cy.get('[data-cy=cachesTable] tr').should('have.length', 4); //4 including header row

//Clears all filters
Expand Down
27 changes: 19 additions & 8 deletions cypress/e2e/rbac_func.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ describe('RBAC Functionlity Tests', () => {
cy.get('[data-cy=cacheManagerStatus]').should('exist');
cy.get('[data-cy=navigationTabs]').should('exist');
cy.contains(/^\d+ Caches$/);

cy.contains('10 Counters');
if (isMonitor) {
cy.contains('1 Tasks').should('not.exist');
Expand Down Expand Up @@ -153,10 +153,15 @@ describe('RBAC Functionlity Tests', () => {
cy.get('[data-cy=queriesTab]').should('exist');
}

//Checking cache configuration page
cy.get('[data-cy=cacheConfigurationTab]').click();
cy.contains('authorization');
cy.contains(roleName);
if (isSuperAdmin) {
//Checking cache configuration page
cy.get('[data-cy=cacheConfigurationTab]').click();
cy.contains('authorization');
cy.contains(roleName);
} else {
cy.get('[data-cy=cacheConfigurationTab]').should('not.exist');
}

cy.get('[data-cy=manageIndexesLink]').click();
if (isSuperAdmin) {
cy.get('[data-cy=clearIndexButton]').should('exist');
Expand Down Expand Up @@ -247,9 +252,15 @@ describe('RBAC Functionlity Tests', () => {
cy.get('[data-cy=clearAllButton]').click();
cy.get('[data-cy=deleteButton]').click();
cy.wait(1500); //Waiting till the whole page is loaded
//Checking cache configuration page
cy.get('[data-cy=cacheConfigurationTab]').click();
cy.contains('authorization').should('not.exist');

if (isSuperAdmin) {
//Checking cache configuration page
cy.get('[data-cy=cacheConfigurationTab]').click();
cy.contains('authorization').should('not.exist');
} else {
cy.get('[data-cy=cacheConfigurationTab]').should('not.exist');
}

cy.get('[data-cy=manageIndexesLink]').click();
if (isSuperAdmin) {
cy.get('[data-cy=clearIndexButton]').should('exist');
Expand Down
17 changes: 6 additions & 11 deletions src/app/CacheManagers/CacheTableDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ const CacheTableDisplay = (props: { cmName: string; setCachesCount: (count: numb
setChipsCacheType([]);
} else {
// From the select, extract each category
let filterStatus = extract(selectedFilters, cacheStatus);
let filterFeatures = extract(selectedFilters, cacheFeatures);
let filterCacheType = extract(selectedFilters, cacheTypes);
const filterStatus = extract(selectedFilters, cacheStatus);
const filterFeatures = extract(selectedFilters, cacheFeatures);
const filterCacheType = extract(selectedFilters, cacheTypes);
// Update chips
setChipsCacheStatus(filterStatus);
setChipsCacheFeature(filterFeatures);
Expand Down Expand Up @@ -185,7 +185,7 @@ const CacheTableDisplay = (props: { cmName: string; setCachesCount: (count: numb

const actionResolver = (rowData: IRowData, extraData: IExtraData) => {
// @ts-ignore
let cacheName: string = rowData.cells[0].cacheName as string;
const cacheName: string = rowData.cells[0].cacheName as string;

if (!cacheName) {
return [];
Expand Down Expand Up @@ -213,7 +213,7 @@ const CacheTableDisplay = (props: { cmName: string; setCachesCount: (count: numb
];
}

let actions = [
const actions = [
{
'data-cy': 'deleteCacheAction',
title: t('cache-managers.delete'),
Expand Down Expand Up @@ -256,14 +256,10 @@ const CacheTableDisplay = (props: { cmName: string; setCachesCount: (count: numb
};

const closeIgnoreModal = (ignoreDone: boolean) => {
if (ignoreDone) {
}
setCacheAction({ cacheName: '', action: '' });
};

const closeAvailableModal = (ignoreDone: boolean) => {
if (ignoreDone) {
}
setCacheAction({ cacheName: '', action: '' });
};

Expand Down Expand Up @@ -485,7 +481,7 @@ const CacheTableDisplay = (props: { cmName: string; setCachesCount: (count: numb
};

const onDeleteChip = (chip) => {
let actualSelection = selectedFilters.filter((item) => item !== chip);
const actualSelection = selectedFilters.filter((item) => item !== chip);
setSelectedFilters(actualSelection);
};

Expand Down Expand Up @@ -569,7 +565,6 @@ const CacheTableDisplay = (props: { cmName: string; setCachesCount: (count: numb
<SelectOption key={1} value={t('cache-managers.mode-repl')} />
<SelectOption key={2} value={t('cache-managers.mode-dist')} />
<SelectOption key={3} value={t('cache-managers.mode-invalid')} />
<SelectOption key={4} value={t('cache-managers.mode-scattered')} />
</SelectGroup>
<SelectGroup label={t('cache-managers.cache-filter-feature-label')} key="group2">
<SelectOption key={5} value={t('cache-managers.cache-filter-feature-bounded')} />
Expand Down
46 changes: 28 additions & 18 deletions src/app/Caches/CacheMetrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,36 +28,44 @@ import { useTranslation } from 'react-i18next';
import { StorageType } from '@services/infinispanRefData';
import { DataAccessChart } from './DataAccessChart';
import { useCacheDetail } from '@app/services/cachesHook';
import { ConsoleACL } from '@services/securityService';
import { ConsoleServices } from '@services/ConsoleServices';
import { useConnectedUser } from '@app/services/userManagementHook';

const CacheMetrics = (props: { cacheName: string; display: boolean }) => {
const { connectedUser } = useConnectedUser();
const { cache, error, loading } = useCacheDetail();
const [stats, setStats] = useState<CacheStats | undefined>(cache.stats);
const [displayQueryStats, setDisplayQueryStats] = useState<boolean>(false);
const [memory, setMemory] = useState<string | undefined>(undefined);
const { t } = useTranslation();
const brandname = t('brandname.brandname');
const [displayDataDistribution, setDisplayDataDistribution] = useState<boolean>(false);

useEffect(() => {
const loadMemory = JSON.parse(cache.configuration.config)[props.cacheName];
const cacheMode = Object.keys(loadMemory)[0];
if (loadMemory[cacheMode].memory) {
if (loadMemory[cacheMode].memory.storage === 'HEAP' && loadMemory[cacheMode].memory['max-size'])
setMemory(loadMemory[cacheMode].memory.storage);
else if (loadMemory[cacheMode].memory.storage === 'OFF_HEAP') setMemory(loadMemory[cacheMode].memory.storage);
} else {
setMemory('HEAP');
if (ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)) {
// Data distrib is for admin
setDisplayDataDistribution(true);
const loadMemory = cache.configuration ? JSON.parse(cache.configuration.config)[props.cacheName] : undefined;
if (loadMemory) {
const cacheMode = Object.keys(loadMemory)[0];
if (loadMemory[cacheMode].memory) {
if (loadMemory[cacheMode].memory.storage === 'HEAP' && loadMemory[cacheMode].memory['max-size'])
setMemory(loadMemory[cacheMode].memory.storage);
else if (loadMemory[cacheMode].memory.storage === 'OFF_HEAP') setMemory(loadMemory[cacheMode].memory.storage);
} else {
setMemory('HEAP');
}
} else {
setMemory('HEAP');
}
}

setStats(cache.stats);
let loadQueryStats = cache.stats != undefined && cache.stats.enabled && cache.features.indexed;
const loadQueryStats = cache.stats != undefined && cache.stats.enabled && cache.features.indexed;
setDisplayQueryStats(loadQueryStats);
}, [cache, error]);

useEffect(() => {
if (props.display) {
}
}, []);

const buildOperationsPerformanceCard = () => {
if (!stats) {
return '';
Expand Down Expand Up @@ -262,13 +270,15 @@ const CacheMetrics = (props: { cacheName: string; display: boolean }) => {
<GridItem span={4}>{buildEntriesCard()}</GridItem>
<GridItem span={4}>{buildMemoryCard()}</GridItem>
<GridItem span={4}>{buildOperationsPerformanceCard()}</GridItem>
<GridItem span={7}>
<DataDistributionChart cacheName={props.cacheName} />
</GridItem>
{displayDataDistribution &&
<GridItem span={7}>
<DataDistributionChart cacheName={props.cacheName} />
</GridItem>
}
<GridItem span={5}>
<DataAccessChart stats={stats} />
</GridItem>
<GridItem span={12}>{buildQueryStats()}</GridItem>
<GridItem span={displayDataDistribution ? 12 : 7}>{buildQueryStats()}</GridItem>
</Grid>
);
};
Expand Down
90 changes: 48 additions & 42 deletions src/app/Caches/DetailCache.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,18 @@ const DetailCache = (props: { cacheName: string }) => {
if (!ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser)) {
return '';
}
const encoding = CacheConfigUtils.toEncoding(cache.configuration.config);
const encodingKey = CacheConfigUtils.toEncoding(cache.encoding.key);
const encodingValue = CacheConfigUtils.toEncoding(cache.encoding.value);

if (encoding == EncodingType.Java || encoding == EncodingType.JBoss) {
if (encodingKey == EncodingType.Java || encodingKey == EncodingType.JBoss ||
encodingValue == EncodingType.Java || encodingValue == EncodingType.JBoss) {
return (
<Card isCompact>
<CardBody>
<Alert
isPlain
isInline
title={t('caches.configuration.pojo-encoding', { brandname: brandname, encoding: encoding.toString() })}
title={t('caches.configuration.pojo-encoding', { brandname: brandname, encodingKey: encodingKey.toString(), encodingValue: encodingValue.toString() })}
variant={AlertVariant.info}
actionLinks={
<AlertActionLink onClick={() => window.open(encodingDocs, '_blank')}>
Expand Down Expand Up @@ -145,29 +147,6 @@ const DetailCache = (props: { cacheName: string }) => {
);
};

const encodingMessage = () => {
if (loading || !cache || error) {
return '';
}

const encodingType = CacheConfigUtils.toEncoding(cache.configuration.config);
if (encodingType == EncodingType.Protobuf) {
return '';
}
return (
<Alert
isExpandable
title={t('caches.configuration.no-query-encoding', { encoding: encodingType.toString() })}
variant={AlertVariant.info}
actionLinks={
<AlertActionLink onClick={() => window.open(encodingDocs, '_blank')}>
{t('caches.configuration.encoding-docs-message')}
</AlertActionLink>
}
/>
);
};

const buildDetailContent = () => {
if (error.length > 0) {
return (
Expand Down Expand Up @@ -205,19 +184,34 @@ const DetailCache = (props: { cacheName: string }) => {
);
}

const displayEntries: boolean = cache.editable &&
ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser);

const displayConf: boolean = ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser);

if (
activeTabKey1 == 0 &&
cache.editable &&
ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser)
) {
activeTabKey1 == 0 && displayEntries) {
return <React.Fragment>{buildEntriesTabContent(cache.queryable)}</React.Fragment>;
} else if (activeTabKey1 == 2) {
return <CacheMetrics cacheName={cacheName} display={activeTabKey1 == 2} />;
} else {
}

if (displayConf && (activeTabKey1 == 1 || (!displayEntries && activeTabKey1 == 0))) {
return (
cache.configuration && <CacheConfiguration cacheName={cache.name} editable={cache.editable} config={cache.configuration.config} />
);
}
let metricsKey = 2;
if (!displayConf) {
metricsKey --;
}
if (!displayEntries) {
metricsKey--;
}
if (activeTabKey1 == metricsKey) {
return (
<CacheConfiguration cacheName={cache.name} editable={cache.editable} config={cache.configuration.config} />
<CacheMetrics cacheName={cacheName} display={activeTabKey1 == metricsKey} />
);
}
return '';
};

const buildBackupsManage = () => {
Expand Down Expand Up @@ -406,9 +400,13 @@ const DetailCache = (props: { cacheName: string }) => {
};

const displayConfiguration = () => {
if (!ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)) {
return ;
}

let eventKey = 1;
if (!ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser) || !cache.editable) {
eventKey = 0;
eventKey--;
}

return <Tab data-cy="cacheConfigurationTab" eventKey={eventKey} title={t('caches.tabs.configuration')} />;
Expand All @@ -419,10 +417,19 @@ const DetailCache = (props: { cacheName: string }) => {
return '';
}

let eventKey = 2;
if (!ConsoleServices.security().hasCacheConsoleACL(ConsoleACL.READ, cacheName, connectedUser) || !cache.editable) {
eventKey--;
}

if (!ConsoleServices.security().hasConsoleACL(ConsoleACL.ADMIN, connectedUser)) {
eventKey--;
}

return (
<Tab
data-cy="cacheMetricsTab"
eventKey={2}
eventKey={eventKey}
title={cache.stats?.enabled ? t('caches.tabs.metrics-enabled') : t('caches.tabs.metrics-disabled')}
/>
);
Expand Down Expand Up @@ -471,9 +478,11 @@ const DetailCache = (props: { cacheName: string }) => {
<Text component={TextVariants.h1}>{cache.name}</Text>
</TextContent>
</ToolbarItem>
<ToolbarItem>
<CacheTypeBadge cacheType={cache.type} small={false} cacheName={cache.name} />
</ToolbarItem>
{cache.type !== 'Unknown' &&
<ToolbarItem>`
<CacheTypeBadge cacheType={cache.type} small={false} cacheName={cache.name} />
</ToolbarItem>
}
{buildShowMoreHeader()}
</ToolbarContent>
</ToolbarGroup>
Expand All @@ -486,9 +495,6 @@ const DetailCache = (props: { cacheName: string }) => {
component={TabsComponent.nav}
onSelect={(event, tabIndex) => {
setActiveTabKey1(tabIndex);
if (tabIndex == 0 || tabIndex == 2) {
loadCache(cacheName);
}
}}
>
{displayCacheEntries()}
Expand Down
Loading

0 comments on commit e073cd1

Please sign in to comment.