Fix auditor access to people

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2026-02-23 13:46:36 +01:00
parent 71b01bf20e
commit 86e4c2eada
3 changed files with 38 additions and 30 deletions

View File

@@ -1,12 +1,15 @@
import { getAssignableRoles } from "@probo/helpers";
import { useTranslate } from "@probo/i18n";
import { Tbody, Td, Th, Thead, Tr } from "@probo/ui";
import type { ComponentProps } from "react";
import { use } from "react";
import { ConnectionHandler, graphql, usePaginationFragment } from "react-relay";
import type { PeopleListFragment$key } from "#/__generated__/iam/PeopleListFragment.graphql";
import type { PeopleListFragment_RefetchQuery } from "#/__generated__/iam/PeopleListFragment_RefetchQuery.graphql";
import { type Order, SortableTable, SortableTh } from "#/components/SortableTable";
import { useOrganizationId } from "#/hooks/useOrganizationId";
import { CurrentUser } from "#/providers/CurrentUser";
import { PeopleListItem } from "./PeopleListItem";
@@ -50,6 +53,8 @@ export function PeopleList(props: {
const organizationId = useOrganizationId();
const { __ } = useTranslate();
const { role } = use(CurrentUser);
const canManageRoles = getAssignableRoles(role).length > 0;
const peoplePagination = usePaginationFragment<
PeopleListFragment_RefetchQuery,
@@ -85,7 +90,7 @@ export function PeopleList(props: {
<SortableTh field="FULL_NAME" onOrderChange={handleOrderChange}>{__("Name")}</SortableTh>
<SortableTh field="STATE">{__("Status")}</SortableTh>
<SortableTh field="EMAIL_ADDRESS" onOrderChange={handleOrderChange}>{__("Email")}</SortableTh>
<SortableTh field="ROLE" onOrderChange={handleOrderChange}>{__("Role")}</SortableTh>
{canManageRoles && <SortableTh field="ROLE" onOrderChange={handleOrderChange}>{__("Role")}</SortableTh>}
<SortableTh field="CREATED_AT" onOrderChange={handleOrderChange}>{__("Created on")}</SortableTh>
<Th></Th>
</Tr>

View File

@@ -213,36 +213,38 @@ export function PeopleListItem(props: {
<Badge variant="info">{profile.source}</Badge>
</div>
</Td>
<Td
noLink
className={clsx(
"pr-4",
isRemoving && "opacity-60 pointer-events-none",
isInactive && "opacity-50",
)}
>
<Select
disabled={!profile.membership.canUpdate || isUpdatingRole}
value={profile.membership.role}
onValueChange={role => void handleUpdateRole(role)}
{availableRoles.length > 0 && (
<Td
noLink
className={clsx(
"pr-4",
isRemoving && "opacity-60 pointer-events-none",
isInactive && "opacity-50",
)}
>
{availableRoles.includes("OWNER") && (
<Option value="OWNER">{__("Owner")}</Option>
)}
{availableRoles.includes("ADMIN") && (
<Option value="ADMIN">{__("Admin")}</Option>
)}
{availableRoles.includes("VIEWER") && (
<Option value="VIEWER">{__("Viewer")}</Option>
)}
{availableRoles.includes("AUDITOR") && (
<Option value="AUDITOR">{__("Auditor")}</Option>
)}
{availableRoles.includes("EMPLOYEE") && (
<Option value="EMPLOYEE">{__("Employee")}</Option>
)}
</Select>
</Td>
<Select
disabled={!profile.membership.canUpdate || isUpdatingRole}
value={profile.membership.role}
onValueChange={role => void handleUpdateRole(role)}
>
{availableRoles.includes("OWNER") && (
<Option value="OWNER">{__("Owner")}</Option>
)}
{availableRoles.includes("ADMIN") && (
<Option value="ADMIN">{__("Admin")}</Option>
)}
{availableRoles.includes("VIEWER") && (
<Option value="VIEWER">{__("Viewer")}</Option>
)}
{availableRoles.includes("AUDITOR") && (
<Option value="AUDITOR">{__("Auditor")}</Option>
)}
{availableRoles.includes("EMPLOYEE") && (
<Option value="EMPLOYEE">{__("Employee")}</Option>
)}
</Select>
</Td>
)}
<Td className={clsx(
isRemoving && "opacity-60 pointer-events-none",
isInactive && "opacity-50",

View File

@@ -318,6 +318,7 @@ var IAMViewerPolicy = policy.NewPolicy(
policy.Allow(
ActionOrganizationGet,
ActionMembershipList,
ActionInvitationList,
).
WithSID("org-viewer-access").
When(policy.Equals("principal.organization_id", "resource.organization_id")),