Skip to content

Commit

Permalink
feat(HMS-2721): add rbac control to every page
Browse files Browse the repository at this point in the history
This change leverage the rbac hook so it is checked
the permissions when a page is loaded. Out of the
scope is custom enable/disable controls for each
page.

Signed-off-by: Alejandro Visiedo <[email protected]>
  • Loading branch information
avisiedo committed May 30, 2024
1 parent 1745852 commit e4930ce
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/Components/CenteredSpinner/CenteredSpinner.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import '~@redhat-cloud-services/frontend-components-utilities/styles/variables';
15 changes: 15 additions & 0 deletions src/Components/CenteredSpinner/CenteredSpinner.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { render } from '@testing-library/react';
import CenteredSpinner from './CenteredSpinner';
import '@testing-library/jest-dom';
import { Bullseye, Spinner } from '@patternfly/react-core';

test('expect CenteredSpinner to render', () => {
expect(render(<CenteredSpinner />).container).toEqual(
render(
<Bullseye>
<Spinner />
</Bullseye>
).container
);
});
17 changes: 17 additions & 0 deletions src/Components/CenteredSpinner/CenteredSpinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Bullseye, Spinner } from '@patternfly/react-core';
import './CenteredSpinner.scss';
import React from 'react';

/**
* Component to show a Spineer centered in the available fragment
* of the screen.
*/
const CenteredSpinner = () => {
return (
<Bullseye>
<Spinner />
</Bullseye>
);
};

export default CenteredSpinner;
20 changes: 14 additions & 6 deletions src/Routes/DefaultPage/DefaultPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
PageGroup,
PageSection,
Pagination,
Spinner,
Stack,
StackItem,
Toolbar,
Expand All @@ -30,6 +29,7 @@ import Section from '@redhat-cloud-services/frontend-components/Section';
import { Domain, ResourcesApiFactory } from '../../Api/idmsvc';
import { DomainList } from '../../Components/DomainList/DomainList';
import { AppContext } from '../../AppContext';
import CenteredSpinner from '../../Components/CenteredSpinner/CenteredSpinner';

const Header = () => {
const linkLearnMoreAbout = 'https://access.redhat.com/articles/1586893';
Expand Down Expand Up @@ -185,10 +185,20 @@ const DefaultPage = () => {
const [perPage, setPerPage] = useState<number>(10);
const offset = (page - 1) * perPage;
const [isLoading, setIsLoading] = useState<boolean>(true);
const navigate = useNavigate();

console.log('INFO:DefaultPage render');

useEffect(() => {
if (appContext.rbac.isLoading) {
setIsLoading(true);
return;
}
if (!appContext.rbac.permissions.hasDomainsList) {
console.error('rbac no list permission');
navigate('/no-permissions', { replace: true });
return;
}
setIsLoading(true);
resources_api
.listDomains(undefined, offset, perPage, undefined)
Expand All @@ -203,7 +213,7 @@ const DefaultPage = () => {
console.log(reason);
setIsLoading(false);
});
}, [page, perPage]);
}, [page, perPage, appContext.rbac.isLoading]);

const changePageSize = (size: number) => {
setPerPage(size);
Expand All @@ -227,13 +237,11 @@ const DefaultPage = () => {
const loadingContent = (
<>
<Header />
<Bullseye>
<Spinner />
</Bullseye>
<CenteredSpinner />
</>
);

if (isLoading) {
if (appContext.rbac.isLoading || isLoading) {
return loadingContent;
}
const content = appContext.totalDomains <= 0 ? emptyContent : listContent;
Expand Down
10 changes: 9 additions & 1 deletion src/Routes/DetailPage/DetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { DetailServers } from './Components/DetailServers/DetailServers';
import ConfirmDeleteDomain from '../../Components/ConfirmDeleteDomain/ConfirmDeleteDomain';
import useNotification from '../../Hooks/useNotification';
import { buildDeleteFailedNotification, buildDeleteSuccessNotification } from './detailNotifications';
import CenteredSpinner from '../../Components/CenteredSpinner/CenteredSpinner';

/**
* It represents the detail page to show the information about a
Expand Down Expand Up @@ -55,8 +56,15 @@ const DetailPage = () => {

console.log('INFO:DetailPage render:domain_id=' + domain_id);

if (appContext.rbac.isLoading) {
return <CenteredSpinner />;
}

// Load Domain to display
useEffect(() => {
if (!appContext.rbac.permissions.hasDomainsRead) {
navigate('/no-permissions', { replace: true });
}
if (domain_id) {
resources_api
.readDomain(domain_id)
Expand All @@ -72,7 +80,7 @@ const DetailPage = () => {
navigate('/domains', { replace: true });
});
}
}, [domain_id]);
}, [domain_id, appContext.rbac.isLoading]);

// Kebab menu
const [isKebabOpen, setIsKebabOpen] = useState<boolean>(false);
Expand Down
23 changes: 22 additions & 1 deletion src/Routes/NoPermissionsPage/NoPermissionsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,36 @@ import React, { useEffect } from 'react';

import { Main } from '@redhat-cloud-services/frontend-components/Main';
import { NotAuthorized } from '@redhat-cloud-services/frontend-components/NotAuthorized';
import { Button } from '@patternfly/react-core';
import useChrome from '@redhat-cloud-services/frontend-components/useChrome';

const NoPermissionsPage = () => {
useEffect(() => {
insights?.chrome?.appAction?.('no-permissions');
}, []);

const { isBeta } = useChrome();
const prefix = isBeta() ? '/beta' : '/preview';
const linkMyUserAccess = prefix + '/iam/my-user-access';

return (
<Main>
<NotAuthorized serviceName="Sample app" />
<NotAuthorized
serviceName="Directory and Domain"
showReturnButton
title="Access permissions needed"
description={
<>
To access identity domains, contact your organization <br />
administrator. Aternatively, visit
<br />
<Button component="a" variant="link" isInline iconPosition="right" href={linkMyUserAccess} ouiaId="LinkNoPermissionsMyUserAccess">
My User Access
</Button>{' '}
to learn more about your permissions.
</>
}
/>
</Main>
);
};
Expand Down
18 changes: 17 additions & 1 deletion src/Routes/WizardPage/WizardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* The goal is provide the steps to register and add
* a new domain service.
*/
import React, { useContext, useState } from 'react';
import React, { useContext, useEffect, useState } from 'react';
import { ExternalLinkAltIcon } from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon';

import { Button, Modal, ModalVariant, PageGroup, PageSection, PageSectionVariants, Text, Wizard, WizardStep } from '@patternfly/react-core';
Expand All @@ -22,6 +22,7 @@ import PagePreparation from './Components/PagePreparation/PagePreparation';
import PageServiceRegistration from './Components/PageServiceRegistration/PageServiceRegistration';
import PageServiceDetails from './Components/PageServiceDetails/PageServiceDetails';
import PageReview from './Components/PageReview/PageReview';
import CenteredSpinner from '../../Components/CenteredSpinner/CenteredSpinner';

/**
* Wizard page to register a new domain into the service.
Expand All @@ -43,6 +44,21 @@ const WizardPage = () => {
const linkLearnMoreAbout = 'https://access.redhat.com/articles/1586893';
const linkLearnMoreAboutRemovingDirectoryAndDomainServices = 'https://access.redhat.com/articles/1586893';

if (appContext.rbac.isLoading) {
return <CenteredSpinner />;
}

useEffect(() => {
if (!appContext.rbac.permissions.hasTokenCreate) {
navigate('/no-permissions', { replace: true });
return;
}
if (!appContext.rbac.permissions.hasDomainsUpdate) {
navigate('/no-permissions', { replace: true });
return;
}
}, [appContext.rbac.isLoading]);

const notifyNotCompleted = () => {
const notificationID = 'domain-registration-cancelled-notification';
notifyError({
Expand Down

0 comments on commit e4930ce

Please sign in to comment.