1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-08 01:15:49 +02:00
unleash.unleash/frontend/src/component/admin/apiToken/ApiTokenPage/ApiTokenPage.tsx
Gastón Fournier 89cf16f915
Feat/more granular permissions check in create apitoken (#4072)
## About the changes
This PR enables or disables create API token button based on the
permissions.

**Note:** the button is only displayed if you have READ permissions on
some API token. This is a minor limitation as having CREATE permissions
should also grant READ permissions, but right now this is up to the user
to set up the custom role with the correct permissions

**Note 2:** Project-specific API tokens are also ruled by the
project-specific permission to create API tokens in a project (just
having the root permissions to create a client token or frontend token
does not grant access to create a project-specific API token). The
permissions to access the creation of a project-specific API token then
rely on the root permissions to allow the user to create either a client
token or a frontend token.

---------

Co-authored-by: David Leek <david@getunleash.io>
2023-06-23 10:57:08 +02:00

122 lines
4.8 KiB
TypeScript

import { useContext } from 'react';
import AccessContext from 'contexts/AccessContext';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { AdminAlert } from 'component/common/AdminAlert/AdminAlert';
import { ApiTokenTable } from 'component/common/ApiTokenTable/ApiTokenTable';
import { PageContent } from 'component/common/PageContent/PageContent';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import { CreateApiTokenButton } from 'component/common/ApiTokenTable/CreateApiTokenButton/CreateApiTokenButton';
import { Search } from 'component/common/Search/Search';
import { useApiTokenTable } from 'component/common/ApiTokenTable/useApiTokenTable';
import { useApiTokens } from 'hooks/api/getters/useApiTokens/useApiTokens';
import { ActionCell } from 'component/common/Table/cells/ActionCell/ActionCell';
import { CopyApiTokenButton } from 'component/common/ApiTokenTable/CopyApiTokenButton/CopyApiTokenButton';
import { RemoveApiTokenButton } from 'component/common/ApiTokenTable/RemoveApiTokenButton/RemoveApiTokenButton';
import useApiTokensApi from 'hooks/api/actions/useApiTokensApi/useApiTokensApi';
import {
ADMIN,
DELETE_CLIENT_API_TOKEN,
DELETE_FRONTEND_API_TOKEN,
READ_CLIENT_API_TOKEN,
READ_FRONTEND_API_TOKEN,
CREATE_CLIENT_API_TOKEN,
CREATE_FRONTEND_API_TOKEN,
} from '@server/types/permissions';
export const ApiTokenPage = () => {
const { hasAccess } = useContext(AccessContext);
const { tokens, loading, refetch } = useApiTokens();
const { deleteToken } = useApiTokensApi();
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
state: { globalFilter },
setGlobalFilter,
setHiddenColumns,
columns,
} = useApiTokenTable(tokens, props => {
const READ_PERMISSION =
props.row.original.type === 'client'
? READ_CLIENT_API_TOKEN
: props.row.original.type === 'frontend'
? READ_FRONTEND_API_TOKEN
: ADMIN;
const DELETE_PERMISSION =
props.row.original.type === 'client'
? DELETE_CLIENT_API_TOKEN
: props.row.original.type === 'frontend'
? DELETE_FRONTEND_API_TOKEN
: ADMIN;
return (
<ActionCell>
<CopyApiTokenButton
token={props.row.original}
permission={READ_PERMISSION}
/>
<RemoveApiTokenButton
token={props.row.original}
permission={DELETE_PERMISSION}
onRemove={async () => {
await deleteToken(props.row.original.secret);
refetch();
}}
/>
</ActionCell>
);
});
return (
<ConditionallyRender
condition={hasAccess([
READ_CLIENT_API_TOKEN,
READ_FRONTEND_API_TOKEN,
ADMIN,
])}
show={() => (
<PageContent
header={
<PageHeader
title={`API access (${rows.length})`}
actions={
<>
<Search
initialValue={globalFilter}
onChange={setGlobalFilter}
/>
<PageHeader.Divider />
<CreateApiTokenButton
permission={[
CREATE_FRONTEND_API_TOKEN,
CREATE_CLIENT_API_TOKEN,
ADMIN,
]}
path="/admin/api/create-token"
/>
</>
}
/>
}
>
<ApiTokenTable
loading={loading}
headerGroups={headerGroups}
setHiddenColumns={setHiddenColumns}
prepareRow={prepareRow}
getTableBodyProps={getTableBodyProps}
getTableProps={getTableProps}
rows={rows}
columns={columns}
globalFilter={globalFilter}
/>
</PageContent>
)}
elseShow={() => <AdminAlert />}
/>
);
};