Skip to content

Commit

Permalink
Merge branch 'feature/ZKUI-356' into tmp/octopus/w/2.0/feature/ZKUI-356
Browse files Browse the repository at this point in the history
  • Loading branch information
bert-e committed May 30, 2023
2 parents f24c3ae + 7359cc8 commit 593108d
Show file tree
Hide file tree
Showing 19 changed files with 283 additions and 686 deletions.
68 changes: 35 additions & 33 deletions src/react/DataServiceRoleProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createContext, useContext, useMemo, useState } from 'react';
import { useParams } from 'react-router-dom';
import { useLocation, useParams, useRouteMatch } from 'react-router-dom';
import { noopBasedEventDispatcher, regexArn, useAccounts } from './utils/hooks';
import {
getRoleArnStored,
Expand All @@ -12,6 +12,7 @@ import {
useAssumeRoleQuery,
useS3ConfigFromAssumeRoleResult,
} from './next-architecture/ui/S3ClientProvider';
import Loader from './ui-elements/Loader';

export const _DataServiceRoleContext = createContext<null | {
role: { roleArn: string };
Expand Down Expand Up @@ -43,32 +44,22 @@ export const useSetAssumedRole = () => {
};

export const useCurrentAccount = () => {
const { accountName } = useParams<{ accountName: string }>();
const storedRoleArn = getRoleArnStored();
const accountId = storedRoleArn
? regexArn.exec(storedRoleArn)?.groups?.['account_id']
const { accountName } = useParams<{
accountName: string;
}>();
const { roleArn } = useDataServiceRole();
const accountId = roleArn
? regexArn.exec(roleArn)?.groups?.['account_id']
: '';
const { accounts } = useAccounts(noopBasedEventDispatcher); //TODO: use a real event dispatcher

// invalide the stored ARN if it's not in the list accountsWithRoles
useMemo(() => {
const isStoredArnValide = accounts.find((account) => {
return account.Roles.find((role) => {
return role.Arn === storedRoleArn;
});
});
if (!isStoredArnValide && storedRoleArn && accounts.length) {
removeRoleArnStored();
}
}, [storedRoleArn, JSON.stringify(accounts)]);

const account = useMemo(() => {
return accounts.find((account) => {
if (accountName) return account.Name === accountName;
else if (accountId) return account.id === accountId;
else return true;
});
}, [storedRoleArn, JSON.stringify(accounts)]);
}, [accountId, JSON.stringify(accounts)]);

return {
account,
Expand All @@ -77,22 +68,29 @@ export const useCurrentAccount = () => {

const DataServiceRoleProvider = ({ children }: { children: JSX.Element }) => {
const [role, setRoleState] = useState<{ roleArn: string }>({
roleArn: getRoleArnStored(),
roleArn: '',
});

const { account } = useCurrentAccount();
const storedAccountID = regexArn.exec(role.roleArn)?.groups?.['account_id'];

const roleArn = useMemo(() => {
if (!role.roleArn || account?.id !== storedAccountID) {
// If the account is not the same as the one stored in the localstorage or it's empty, asssume the first Role in the list.
const defaultAssumedRoleArn = account?.Roles[0].Arn;
if (defaultAssumedRoleArn) setRoleArnStored(defaultAssumedRoleArn);
return defaultAssumedRoleArn || '';
} else {
return role.roleArn;
const { accounts } = useAccounts(noopBasedEventDispatcher); //TODO: use a real event dispatcher

// invalide the stored ARN if it's not in the list accountsWithRoles
useMemo(() => {
const storedRole = getRoleArnStored();
if (!role.roleArn && storedRole && accounts.length) {
const isStoredArnValide = accounts.find((account) => {
return account.Roles.find((r) => {
return r.Arn === storedRole;
});
});
if (isStoredArnValide) {
setRoleState({ roleArn: storedRole });
} else {
setRoleState({ roleArn: accounts[0].Roles[0].Arn });
}
} else if (!storedRole && !role.roleArn && accounts.length) {
setRoleState({ roleArn: accounts[0].Roles[0].Arn });
}
}, [role.roleArn, JSON.stringify(account)]);
}, [role.roleArn, JSON.stringify(accounts)]);

const { getQuery } = useAssumeRoleQuery();
const assumeRoleMutation = useMutation({
Expand All @@ -107,7 +105,11 @@ const DataServiceRoleProvider = ({ children }: { children: JSX.Element }) => {
assumeRoleMutation.mutate(role.roleArn);
};

const { data: assumeRoleResult } = useQuery(getQuery(roleArn));
const { data: assumeRoleResult, status } = useQuery(getQuery(role.roleArn));

if (status === 'idle') {
return <Loader>Loading...</Loader>;
}

return (
<S3ClientProvider
Expand All @@ -119,7 +121,7 @@ const DataServiceRoleProvider = ({ children }: { children: JSX.Element }) => {
>
<_DataServiceRoleContext.Provider
value={{
role: { roleArn },
role,
setRole,
}}
>
Expand Down
4 changes: 3 additions & 1 deletion src/react/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ function useLoginEffect(navbarRef: { current: NavbarWebComponent | null }) {
const navbarElement = navbarRef.current;

const onAuthenticated = (evt: Event) => {
if (evt.detail && evt.detail.profile) {
if (evt.detail && evt.detail.profile && evt.detail.access_token) {
setUser(evt.detail);
dispatch(addOIDCUser(evt.detail));
dispatch(setOIDCLogout(navbarElement.logOut || null));
} else if (evt.detail && evt.detail.profile && !evt.detail.access_token) {
navbarElement.logOut(true);
}
};

Expand Down
53 changes: 28 additions & 25 deletions src/react/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import NoMatch from './NoMatch';
import ManagementProvider from './ManagementProvider';
import DataServiceRoleProvider, {
useCurrentAccount,
useDataServiceRole,
} from './DataServiceRoleProvider';
import BucketCreate from './databrowser/buckets/BucketCreate';
import makeMgtClient from '../js/managementClient';
Expand All @@ -38,6 +39,7 @@ import { push } from 'connected-react-router';
import { AppContainer, Layout2 } from '@scality/core-ui';
import { Locations } from './locations/Locations';
import ReauthDialog from './ui-elements/ReauthDialog';
import { useAuthGroups } from './utils/hooks';

export const RemoveTrailingSlash = ({ ...rest }) => {
const location = useLocation();
Expand Down Expand Up @@ -84,11 +86,7 @@ const RedirectToAccount = () => {
</EmptyStateContainer>
);
} else {
return (
<Loader>
<div>Loading</div>
</Loader>
);
return <ErrorPage401 />;
}
};

Expand Down Expand Up @@ -197,6 +195,7 @@ function Routes() {
);
const history = useHistory();
const location = useLocation();
const { isStorageManager } = useAuthGroups();

const doesRouteMatch = useCallback(
(paths: RouteProps | RouteProps[]) => {
Expand Down Expand Up @@ -289,26 +288,30 @@ function Routes() {
path: '/accounts/:accountName/workflows',
}),
},
{
label: 'Locations',
icon: <Icon name="Location" />,
onClick: () => {
history.push('/locations');
},
active: doesRouteMatch({
path: '/locations',
}),
},
{
label: 'Data Services',
icon: <Icon name="Cubes" />,
onClick: () => {
history.push('/dataservices');
},
active: doesRouteMatch({
path: '/dataservices',
}),
},
...(isStorageManager
? [
{
label: 'Locations',
icon: <Icon name="Location" />,
onClick: () => {
history.push('/locations');
},
active: doesRouteMatch({
path: '/locations',
}),
},
{
label: 'Data Services',
icon: <Icon name="Cubes" />,
onClick: () => {
history.push('/dataservices');
},
active: doesRouteMatch({
path: '/dataservices',
}),
},
]
: []),
],
};

Expand Down
50 changes: 30 additions & 20 deletions src/react/account/AccountList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import { Table } from '@scality/core-ui/dist/components/tablev2/Tablev2.componen
import { formatSimpleDate } from '../utils';
import { NameLinkContaner } from '../ui-elements/NameLink';
import { AppState } from '../../types/state';
import { Icon } from '@scality/core-ui';
import { Icon, Link } from '@scality/core-ui';
import { useMetricsAdapter } from '../next-architecture/ui/MetricsAdapterProvider';
import { useAccountLatestUsedCapacity } from '../next-architecture/domain/business/accounts';
import { Account } from '../next-architecture/domain/entities/account';
import { CellProps, CoreUIColumn } from 'react-table';
import { UsedCapacityInlinePromiseResult } from '../next-architecture/ui/metrics/LatestUsedCapacity';
import { useSetAssumedRole } from '../DataServiceRoleProvider';
import { useAuthGroups } from '../utils/hooks';

const TableAction = styled.div`
display: flex;
Expand All @@ -28,17 +29,24 @@ function AccountList({ accounts }: { accounts: Account[] }) {
(state: AppState) => state.oidc.user?.profile?.groups || [],
);

const { isStorageManager } = useAuthGroups();

const nameCell = ({ value, row }: CellProps<Account, string>) => {
const setRole = useSetAssumedRole();
if (!row.original.canManageAccount) {
return value;
}

return (
<NameLinkContaner
<Link
href="#"
onClick={() => {
setRole({ roleArn: row.original.preferredAssumableRoleArn });
dispatch(push(`/accounts/${value}`));
}}
>
{value}
</NameLinkContaner>
</Link>
);
};

Expand All @@ -65,25 +73,27 @@ function AccountList({ accounts }: { accounts: Account[] }) {
},
Cell: (value: CellProps<Account, string>) => createDateCell(value),
},
{
Header: 'Data Used',
accessor: 'usedCapacity',
cellStyle: {
textAlign: 'right',
minWidth: '7rem',
},
Cell: ({ row }) => {
const metricsAdapter = useMetricsAdapter();
isStorageManager
? {
Header: 'Data Used',
accessor: 'usedCapacity',
cellStyle: {
textAlign: 'right',
minWidth: '7rem',
},
Cell: ({ row }) => {
const metricsAdapter = useMetricsAdapter();

const { usedCapacity } = useAccountLatestUsedCapacity({
accountCanonicalId: row.original.canonicalId,
metricsAdapter: metricsAdapter,
});
const { usedCapacity } = useAccountLatestUsedCapacity({
accountCanonicalId: row.original.canonicalId,
metricsAdapter: metricsAdapter,
});

return <UsedCapacityInlinePromiseResult result={usedCapacity} />;
},
},
];
return <UsedCapacityInlinePromiseResult result={usedCapacity} />;
},
}
: undefined,
].filter((e) => e);
}, [nameCell]);

return (
Expand Down
12 changes: 2 additions & 10 deletions src/react/account/AccountRoleSelectButtonAndModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@ import { Stack, Tooltip, Wrap } from '@scality/core-ui';
import { spacing } from '@scality/core-ui/dist/style/theme';
import { SpacedBox } from '@scality/core-ui/dist/components/spacedbox/SpacedBox';
import { CustomModal as Modal, ModalBody } from '../ui-elements/Modal';
import {
regexArn,
SCALITY_INTERNAL_ROLES,
useAccounts,
useRedirectDataConsumers,
} from '../utils/hooks';
import { regexArn, SCALITY_INTERNAL_ROLES, useAccounts } from '../utils/hooks';
import {
useCurrentAccount,
useDataServiceRole,
Expand All @@ -35,7 +30,6 @@ export function AccountRoleSelectButtonAndModal({
const [isModalOpen, setIsModalOpen] = useState(false);
const accountName = account?.Name;
const [assumedAccount, setAssumedAccount] = useState(accountName);
const redirectDataConsummers = useRedirectDataConsumers();
const setRole = useSetAssumedRole();
const history = useHistory();

Expand Down Expand Up @@ -74,15 +68,13 @@ export function AccountRoleSelectButtonAndModal({
icon={<Icon name="Arrow-right" />}
variant="primary"
onClick={() => {
const parsedArn = regexArn.exec(assumedRoleArn);
const roleName = parsedArn?.groups?.name || '';
setRole({ roleArn: assumedRoleArn });
history.push(
generatePath(path, {
accountName: assumedAccount,
}),
);
redirectDataConsummers([{ Name: roleName }], handleClose);
handleClose();
}}
label="Continue"
disabled={assumedRoleArn === roleArn}
Expand Down
18 changes: 17 additions & 1 deletion src/react/account/Accounts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ import AccountList from './AccountList';
import { BreadcrumbAccount } from '../ui-elements/Breadcrumb';
import Header from '../ui-elements/EntityHeader';
import { MultiAccountsIcon } from './MultiAccountsIcon';
import { AppContainer, ErrorPage500, Icon } from '@scality/core-ui';
import {
AppContainer,
ErrorPage401,
ErrorPage500,
Icon,
} from '@scality/core-ui';
import { useListAccounts } from '../next-architecture/domain/business/accounts';
import { useMetricsAdapter } from '../next-architecture/ui/MetricsAdapterProvider';
import { useAccessibleAccountsAdapter } from '../next-architecture/ui/AccessibleAccountsAdapterProvider';
import { EmptyStateContainer } from '../ui-elements/Container';
import { Warning } from '../ui-elements/Warning';
import { useAuthGroups } from '../utils/hooks';

const Accounts = () => {
const { pathname } = useLocation();
Expand All @@ -21,6 +27,16 @@ const Accounts = () => {
});
const history = useHistory();

const { isStorageManager } = useAuthGroups();

if (
accounts.status == 'success' &&
accounts.value.length === 0 &&
!isStorageManager
) {
return <ErrorPage401 />;
}

return (
<>
<AppContainer.ContextContainer>
Expand Down
Loading

0 comments on commit 593108d

Please sign in to comment.