diff --git a/frontend/src/component/admin/users/AccessMatrix/AccessMatrix.tsx b/frontend/src/component/admin/users/AccessOverview/AccessOverview.tsx similarity index 84% rename from frontend/src/component/admin/users/AccessMatrix/AccessMatrix.tsx rename to frontend/src/component/admin/users/AccessOverview/AccessOverview.tsx index a10aa9dcdd..f012ffab32 100644 --- a/frontend/src/component/admin/users/AccessMatrix/AccessMatrix.tsx +++ b/frontend/src/component/admin/users/AccessOverview/AccessOverview.tsx @@ -2,7 +2,7 @@ import { PageContent } from 'component/common/PageContent/PageContent'; import { PageHeader } from 'component/common/PageHeader/PageHeader'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import useUserInfo from 'hooks/api/getters/useUserInfo/useUserInfo'; -import { PermissionsTable } from './PermissionsTable'; +import { AccessOverviewTable } from './AccessOverviewTable'; import { styled, useMediaQuery } from '@mui/material'; import { useEffect, useState } from 'react'; import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments'; @@ -10,8 +10,8 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit import theme from 'themes/theme'; import { StringParam, useQueryParams } from 'use-query-params'; import useProjects from 'hooks/api/getters/useProjects/useProjects'; -import { AccessMatrixSelect } from './AccessMatrixSelect'; -import { useUserAccessMatrix } from 'hooks/api/getters/useUserAccessMatrix/useUserAccessMatrix'; +import { AccessOverviewSelect } from './AccessOverviewSelect'; +import { useUserAccessOverview } from 'hooks/api/getters/useUserAccessOverview/useUserAccessOverview'; const StyledActionsContainer = styled('div')(({ theme }) => ({ display: 'flex', @@ -28,7 +28,7 @@ const StyledTitle = styled('h2')(({ theme }) => ({ margin: theme.spacing(2, 0), })); -export const AccessMatrix = () => { +export const AccessOverview = () => { const id = useRequiredPathParam('id'); const [query, setQuery] = useQueryParams({ project: StringParam, @@ -45,7 +45,7 @@ export const AccessMatrix = () => { query.environment ?? undefined, ); - const { matrix, rootRole, projectRoles } = useUserAccessMatrix( + const { overview, rootRole, projectRoles } = useUserAccessOverview( id, project, environment, @@ -63,14 +63,14 @@ export const AccessMatrix = () => { const AccessActions = ( - option?.name ?? ''} value={projects.find(({ id }) => id === project)} setValue={(value) => setProject(value?.id ?? '')} /> - @@ -89,7 +89,7 @@ export const AccessMatrix = () => { isLoading={loading} header={ { Root permissions for role {rootRole?.name} - + Project permissions for project {project} with project roles [ {projectRoles?.map((role: any) => role.name).join(', ')}] - + Environment permissions for environment {environment} - + ); }; diff --git a/frontend/src/component/admin/users/AccessMatrix/AccessMatrixSelect.tsx b/frontend/src/component/admin/users/AccessOverview/AccessOverviewSelect.tsx similarity index 82% rename from frontend/src/component/admin/users/AccessMatrix/AccessMatrixSelect.tsx rename to frontend/src/component/admin/users/AccessOverview/AccessOverviewSelect.tsx index 1052c4bef5..f4ef50a2d1 100644 --- a/frontend/src/component/admin/users/AccessMatrix/AccessMatrixSelect.tsx +++ b/frontend/src/component/admin/users/AccessOverview/AccessOverviewSelect.tsx @@ -1,6 +1,6 @@ import { Autocomplete, type AutocompleteProps, TextField } from '@mui/material'; -interface IAccessMatrixSelectProps +interface IAccessOverviewSelectProps extends Partial> { label: string; options: T[]; @@ -8,13 +8,13 @@ interface IAccessMatrixSelectProps setValue: (role: T | null) => void; } -export const AccessMatrixSelect = ({ +export const AccessOverviewSelect = ({ label, options, value, setValue, ...rest -}: IAccessMatrixSelectProps) => ( +}: IAccessOverviewSelectProps) => ( { const columns = useMemo( () => [ diff --git a/frontend/src/component/admin/users/UsersAdmin.tsx b/frontend/src/component/admin/users/UsersAdmin.tsx index 12213b50fe..1f1e016656 100644 --- a/frontend/src/component/admin/users/UsersAdmin.tsx +++ b/frontend/src/component/admin/users/UsersAdmin.tsx @@ -5,7 +5,7 @@ import { Route, Routes } from 'react-router-dom'; import EditUser from './EditUser/EditUser'; import NotFound from 'component/common/NotFound/NotFound'; import { InactiveUsersList } from './InactiveUsersList/InactiveUsersList'; -import { AccessMatrix } from './AccessMatrix/AccessMatrix'; +import { AccessOverview } from './AccessOverview/AccessOverview'; import { PremiumFeature } from '../../common/PremiumFeature/PremiumFeature'; import { ConditionallyRender } from '../../common/ConditionallyRender/ConditionallyRender'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; @@ -25,7 +25,7 @@ export const UsersAdmin = () => { } /> } /> - } /> + } /> { const { action: actionName, executionParams, error } = action; const projectId = useRequiredPathParam('projectId'); - const { permissions } = useServiceAccountAccessMatrix( + const { permissions } = useServiceAccountAccessOverview( actorId, projectId, executionParams.environment as string, diff --git a/frontend/src/hooks/api/getters/useServiceAccountAccessMatrix/useServiceAccountAccessMatrix.ts b/frontend/src/hooks/api/getters/useServiceAccountAccessOverview/useServiceAccountAccessOverview.ts similarity index 67% rename from frontend/src/hooks/api/getters/useServiceAccountAccessMatrix/useServiceAccountAccessMatrix.ts rename to frontend/src/hooks/api/getters/useServiceAccountAccessOverview/useServiceAccountAccessOverview.ts index af04bb8dc1..e10d015d02 100644 --- a/frontend/src/hooks/api/getters/useServiceAccountAccessMatrix/useServiceAccountAccessMatrix.ts +++ b/frontend/src/hooks/api/getters/useServiceAccountAccessOverview/useServiceAccountAccessOverview.ts @@ -3,49 +3,49 @@ import { formatApiPath } from 'utils/formatPath'; import handleErrorResponses from '../httpErrorResponseHandler'; import type { IRole } from 'interfaces/role'; import type { IServiceAccount } from 'interfaces/service-account'; -import type { IMatrixPermission } from 'interfaces/permissions'; +import type { IAccessOverviewPermission } from 'interfaces/permissions'; import type { IPermission } from 'interfaces/user'; import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR'; -interface IServiceAccountAccessMatrix { - root: IMatrixPermission[]; - project: IMatrixPermission[]; - environment: IMatrixPermission[]; +interface IServiceAccountAccessOverview { + root: IAccessOverviewPermission[]; + project: IAccessOverviewPermission[]; + environment: IAccessOverviewPermission[]; } -interface IServiceAccountAccessMatrixResponse { - matrix: IServiceAccountAccessMatrix; +interface IServiceAccountAccessOverviewResponse { + overview: IServiceAccountAccessOverview; projectRoles: IRole[]; rootRole: IRole; serviceAccount: IServiceAccount; permissions: IPermission[]; } -interface IServiceAccountAccessMatrixOutput - extends Partial { +interface IServiceAccountAccessOverviewOutput + extends Partial { permissions: IPermission[]; loading: boolean; refetch: () => void; error?: Error; } -export const useServiceAccountAccessMatrix = ( +export const useServiceAccountAccessOverview = ( id?: number, project?: string, environment?: string, -): IServiceAccountAccessMatrixOutput => { +): IServiceAccountAccessOverviewOutput => { const queryParams = `${project ? `?project=${project}` : ''}${ environment ? `${project ? '&' : '?'}environment=${environment}` : '' }`; const url = `api/admin/service-account/${id}/permissions${queryParams}`; const { data, error, mutate } = useConditionalSWR< - IServiceAccountAccessMatrixResponse | undefined + IServiceAccountAccessOverviewResponse | undefined >(Boolean(id), undefined, formatApiPath(url), fetcher); return useMemo( () => ({ - matrix: data?.matrix, + overview: data?.overview, projectRoles: data?.projectRoles, rootRole: data?.rootRole, serviceAccount: data?.serviceAccount, @@ -60,6 +60,6 @@ export const useServiceAccountAccessMatrix = ( const fetcher = (path: string) => { return fetch(path) - .then(handleErrorResponses('Service account access matrix')) + .then(handleErrorResponses('Service account access overview')) .then((res) => res.json()); }; diff --git a/frontend/src/hooks/api/getters/useUserAccessMatrix/useUserAccessMatrix.ts b/frontend/src/hooks/api/getters/useUserAccessOverview/useUserAccessOverview.ts similarity index 67% rename from frontend/src/hooks/api/getters/useUserAccessMatrix/useUserAccessMatrix.ts rename to frontend/src/hooks/api/getters/useUserAccessOverview/useUserAccessOverview.ts index 4dcc004d5e..a0b467bd4b 100644 --- a/frontend/src/hooks/api/getters/useUserAccessMatrix/useUserAccessMatrix.ts +++ b/frontend/src/hooks/api/getters/useUserAccessOverview/useUserAccessOverview.ts @@ -4,45 +4,46 @@ import handleErrorResponses from '../httpErrorResponseHandler'; import useSWR from 'swr'; import type { IRole } from 'interfaces/role'; import type { IUser } from 'interfaces/user'; -import type { IMatrixPermission } from 'interfaces/permissions'; +import type { IAccessOverviewPermission } from 'interfaces/permissions'; -interface IUserAccessMatrix { - root: IMatrixPermission[]; - project: IMatrixPermission[]; - environment: IMatrixPermission[]; +interface IUserAccessOverview { + root: IAccessOverviewPermission[]; + project: IAccessOverviewPermission[]; + environment: IAccessOverviewPermission[]; } -interface IUserAccessMatrixResponse { - matrix: IUserAccessMatrix; +interface IUserAccessOverviewResponse { + overview: IUserAccessOverview; projectRoles: IRole[]; rootRole: IRole; user: IUser; } -interface IUserAccessMatrixOutput extends Partial { +interface IUserAccessOverviewOutput + extends Partial { loading: boolean; refetch: () => void; error?: Error; } -export const useUserAccessMatrix = ( +export const useUserAccessOverview = ( id: string, project?: string, environment?: string, -): IUserAccessMatrixOutput => { +): IUserAccessOverviewOutput => { const queryParams = `${project ? `?project=${project}` : ''}${ environment ? `${project ? '&' : '?'}environment=${environment}` : '' }`; const url = `api/admin/user-admin/${id}/permissions${queryParams}`; - const { data, error, mutate } = useSWR( + const { data, error, mutate } = useSWR( formatApiPath(url), fetcher, ); return useMemo( () => ({ - matrix: data?.matrix, + overview: data?.overview, projectRoles: data?.projectRoles, rootRole: data?.rootRole, user: data?.user, diff --git a/frontend/src/interfaces/permissions.ts b/frontend/src/interfaces/permissions.ts index b8330f8e06..7157068813 100644 --- a/frontend/src/interfaces/permissions.ts +++ b/frontend/src/interfaces/permissions.ts @@ -37,6 +37,6 @@ export interface IPermissionCategory { permissions: IPermission[]; } -export interface IMatrixPermission extends IPermission { +export interface IAccessOverviewPermission extends IPermission { hasPermission: boolean; } diff --git a/src/lib/routes/admin-api/user-admin.ts b/src/lib/routes/admin-api/user-admin.ts index 986f759c5f..4d285e95e2 100644 --- a/src/lib/routes/admin-api/user-admin.ts +++ b/src/lib/routes/admin-api/user-admin.ts @@ -741,7 +741,7 @@ export default class UserAdminController extends Controller { ), ); } - const matrix = await this.accessService.permissionsMatrixForUser( + const overview = await this.accessService.getAccessOverviewForUser( user, project, environment, @@ -749,7 +749,7 @@ export default class UserAdminController extends Controller { // TODO add response validation based on the schema res.status(200).json({ - matrix, + overview, user, rootRole, projectRoles, diff --git a/src/lib/services/access-service.ts b/src/lib/services/access-service.ts index af05b9a772..cb28076b3b 100644 --- a/src/lib/services/access-service.ts +++ b/src/lib/services/access-service.ts @@ -63,13 +63,13 @@ const PROJECT_ADMIN = [ export type IdPermissionRef = Pick; export type NamePermissionRef = Pick; export type PermissionRef = IdPermissionRef | NamePermissionRef; -type MatrixPermission = IPermission & { +type AccessOverviewPermission = IPermission & { hasPermission: boolean; }; -type PermissionMatrix = { - root: MatrixPermission[]; - project: MatrixPermission[]; - environment: MatrixPermission[]; +type AccessOverview = { + root: AccessOverviewPermission[]; + project: AccessOverviewPermission[]; + environment: AccessOverviewPermission[]; }; type APIUser = Pick & { isAPI: true }; @@ -244,14 +244,14 @@ export class AccessService { * Provided a project, project permissions will be checked against that project. * Provided an environment, environment permissions will be checked against that environment (and project). */ - async permissionsMatrixForUser( + async getAccessOverviewForUser( user: APIUser | NonAPIUser, projectId?: string, environment?: string, - ): Promise { + ): Promise { const permissions = await this.getPermissions(); const userP = await this.getPermissionsForUser(user); - const matrix: PermissionMatrix = { + const overview: AccessOverview = { root: permissions.root.map((p) => ({ ...p, hasPermission: this.meetsAllPermissions(userP, [p.name]), @@ -278,7 +278,7 @@ export class AccessService { })) ?? [], }; - return matrix; + return overview; } async getPermissionsForUser(