1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-26 13:48:33 +02:00

chore: rename access matrix to access overview (#9531)

https://linear.app/unleash/issue/2-3344/new-name-access-overview-instead-of-access-matrix

Renames Access Matrix to Access Overview, both internally (code) and
externally (UI).
This commit is contained in:
Nuno Góis 2025-03-13 15:23:58 +00:00 committed by GitHub
parent dadda7b648
commit 0d0530b61c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 60 additions and 59 deletions

View File

@ -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 = (
<StyledActionsContainer>
<AccessMatrixSelect
<AccessOverviewSelect
label='Project'
options={projects}
getOptionLabel={(option) => option?.name ?? ''}
value={projects.find(({ id }) => id === project)}
setValue={(value) => setProject(value?.id ?? '')}
/>
<AccessMatrixSelect
<AccessOverviewSelect
label='Environment'
options={environments}
getOptionLabel={(option) =>
@ -89,7 +89,7 @@ export const AccessMatrix = () => {
isLoading={loading}
header={
<PageHeader
title={`Access for ${user.name ?? user.username}`}
title={`Access overview for ${user.name ?? user.username}`}
actions={
<ConditionallyRender
condition={!isSmallScreen}
@ -107,16 +107,16 @@ export const AccessMatrix = () => {
<StyledTitle>
Root permissions for role {rootRole?.name}
</StyledTitle>
<PermissionsTable permissions={matrix?.root ?? []} />
<AccessOverviewTable permissions={overview?.root ?? []} />
<StyledTitle>
Project permissions for project {project} with project roles [
{projectRoles?.map((role: any) => role.name).join(', ')}]
</StyledTitle>
<PermissionsTable permissions={matrix?.project ?? []} />
<AccessOverviewTable permissions={overview?.project ?? []} />
<StyledTitle>
Environment permissions for environment {environment}
</StyledTitle>
<PermissionsTable permissions={matrix?.environment ?? []} />
<AccessOverviewTable permissions={overview?.environment ?? []} />
</PageContent>
);
};

View File

@ -1,6 +1,6 @@
import { Autocomplete, type AutocompleteProps, TextField } from '@mui/material';
interface IAccessMatrixSelectProps<T>
interface IAccessOverviewSelectProps<T>
extends Partial<AutocompleteProps<T, false, false, false>> {
label: string;
options: T[];
@ -8,13 +8,13 @@ interface IAccessMatrixSelectProps<T>
setValue: (role: T | null) => void;
}
export const AccessMatrixSelect = <T,>({
export const AccessOverviewSelect = <T,>({
label,
options,
value,
setValue,
...rest
}: IAccessMatrixSelectProps<T>) => (
}: IAccessOverviewSelectProps<T>) => (
<Autocomplete
options={options}
value={value}

View File

@ -7,12 +7,12 @@ import { IconCell } from 'component/common/Table/cells/IconCell/IconCell';
import Check from '@mui/icons-material/Check';
import Close from '@mui/icons-material/Close';
import { Box } from '@mui/material';
import type { IMatrixPermission } from 'interfaces/permissions';
import type { IAccessOverviewPermission } from 'interfaces/permissions';
export const PermissionsTable = ({
export const AccessOverviewTable = ({
permissions,
}: {
permissions: IMatrixPermission[];
permissions: IAccessOverviewPermission[];
}) => {
const columns = useMemo(
() => [

View File

@ -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 = () => {
}
/>
<Route path=':id/edit' element={<EditUser />} />
<Route path=':id/access' element={<AccessMatrix />} />
<Route path=':id/access' element={<AccessOverview />} />
<Route
path='inactive'
element={

View File

@ -4,7 +4,7 @@ import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import type { ActionsActionState } from '../../useProjectActionsForm';
import { ProjectActionsFormItem } from '../ProjectActionsFormItem';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useServiceAccountAccessMatrix } from 'hooks/api/getters/useServiceAccountAccessMatrix/useServiceAccountAccessMatrix';
import { useServiceAccountAccessOverview } from 'hooks/api/getters/useServiceAccountAccessOverview/useServiceAccountAccessOverview';
import { useEffect, useMemo } from 'react';
import { ProjectActionsActionParameter } from './ProjectActionsActionParameter/ProjectActionsActionParameter';
import type { ActionConfigurations } from 'interfaces/action';
@ -51,7 +51,7 @@ export const ProjectActionsActionItem = ({
}: IProjectActionsItemProps) => {
const { action: actionName, executionParams, error } = action;
const projectId = useRequiredPathParam('projectId');
const { permissions } = useServiceAccountAccessMatrix(
const { permissions } = useServiceAccountAccessOverview(
actorId,
projectId,
executionParams.environment as string,

View File

@ -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<IServiceAccountAccessMatrixResponse> {
interface IServiceAccountAccessOverviewOutput
extends Partial<IServiceAccountAccessOverviewResponse> {
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());
};

View File

@ -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<IUserAccessMatrixResponse> {
interface IUserAccessOverviewOutput
extends Partial<IUserAccessOverviewResponse> {
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<IUserAccessMatrixResponse>(
const { data, error, mutate } = useSWR<IUserAccessOverviewResponse>(
formatApiPath(url),
fetcher,
);
return useMemo(
() => ({
matrix: data?.matrix,
overview: data?.overview,
projectRoles: data?.projectRoles,
rootRole: data?.rootRole,
user: data?.user,

View File

@ -37,6 +37,6 @@ export interface IPermissionCategory {
permissions: IPermission[];
}
export interface IMatrixPermission extends IPermission {
export interface IAccessOverviewPermission extends IPermission {
hasPermission: boolean;
}

View File

@ -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,

View File

@ -63,13 +63,13 @@ const PROJECT_ADMIN = [
export type IdPermissionRef = Pick<IPermission, 'id' | 'environment'>;
export type NamePermissionRef = Pick<IPermission, 'name' | 'environment'>;
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<IUser, 'id' | 'permissions'> & { 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<PermissionMatrix> {
): Promise<AccessOverview> {
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(