Fix permissions handling with react context

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2025-12-02 17:11:02 +04:00
parent accc8292b5
commit e65097f248
57 changed files with 609 additions and 840 deletions

View File

@@ -14,11 +14,11 @@ import {
} from "@probo/ui";
import { useTranslate } from "@probo/i18n";
import { useFragment } from "react-relay";
import { useMemo, useState, useCallback, useEffect } from "react";
import { useMemo, useState, useCallback, useEffect, use } from "react";
import { sprintf, getAuditStateVariant, getAuditStateLabel, formatDate, getTrustCenterVisibilityOptions } from "@probo/helpers";
import { useOrganizationId } from "/hooks/useOrganizationId";
import type { TrustCenterAuditsCardFragment$key } from "./__generated__/TrustCenterAuditsCardFragment.graphql";
import { isAuthorized } from "/permissions";
import { PermissionsContext } from "/providers/PermissionsContext";
const trustCenterAuditFragment = graphql`
fragment TrustCenterAuditsCardFragment on Audit {
@@ -124,8 +124,8 @@ function AuditRow(props: {
const organizationId = useOrganizationId();
const { __ } = useTranslate();
const [optimisticValue, setOptimisticValue] = useState<string | null>(null);
const canUpdate = organizationId ? isAuthorized(organizationId, "TrustCenter", "updateTrustCenter") : false;
const { isAuthorized } = use(PermissionsContext);
const canUpdate = organizationId ? isAuthorized("TrustCenter", "updateTrustCenter") : false;
const handleValueChange = useCallback((value: string | {}) => {
const stringValue = typeof value === 'string' ? value : '';

View File

@@ -17,10 +17,10 @@ import {
import { useTranslate } from "@probo/i18n";
import type { TrustCenterDocumentsCardFragment$key } from "./__generated__/TrustCenterDocumentsCardFragment.graphql";
import { useFragment } from "react-relay";
import { useMemo, useState, useCallback, useEffect } from "react";
import { useMemo, useState, useCallback, useEffect, use } from "react";
import { sprintf, getTrustCenterVisibilityOptions } from "@probo/helpers";
import { useOrganizationId } from "/hooks/useOrganizationId";
import { isAuthorized } from "/permissions";
import { PermissionsContext } from "/providers/PermissionsContext";
const trustCenterDocumentFragment = graphql`
fragment TrustCenterDocumentsCardFragment on Document {
@@ -129,8 +129,8 @@ function DocumentRow(props: {
const organizationId = useOrganizationId();
const { __ } = useTranslate();
const [optimisticValue, setOptimisticValue] = useState<string | null>(null);
const canUpdate = organizationId ? isAuthorized(organizationId, "TrustCenter", "updateTrustCenter") : false;
const { isAuthorized } = use(PermissionsContext);
const canUpdate = isAuthorized("TrustCenter", "updateTrustCenter");
const handleValueChange = useCallback((value: string | {}) => {
const stringValue = typeof value === 'string' ? value : '';

View File

@@ -18,12 +18,10 @@ import {
import { useTranslate } from "@probo/i18n";
import type { TrustCenterFilesCardFragment$key, TrustCenterFilesCardFragment$data } from "./__generated__/TrustCenterFilesCardFragment.graphql";
import { useFragment } from "react-relay";
import { useMemo, useState, useCallback, useEffect } from "react";
import { useMemo, useState, useCallback, useEffect, use } from "react";
import { sprintf, getTrustCenterVisibilityOptions } from "@probo/helpers";
import { formatDate } from "@probo/helpers";
import { Authorized } from "/permissions";
import { isAuthorized } from "/permissions";
import { useParams } from "react-router";
import { PermissionsContext } from "/providers/PermissionsContext";
const trustCenterFileFragment = graphql`
fragment TrustCenterFilesCardFragment on TrustCenterFile {
@@ -150,9 +148,8 @@ function FileRow(props: {
const file = props.file;
const { __ } = useTranslate();
const [optimisticValue, setOptimisticValue] = useState<string | null>(null);
const { organizationId } = useParams();
const canUpdate = organizationId ? isAuthorized(organizationId, "TrustCenter", "updateTrustCenter") : false;
const { isAuthorized } = use(PermissionsContext);
const canUpdate = isAuthorized("TrustCenter", "updateTrustCenter");
const handleValueChange = useCallback((value: string | {}) => {
const stringValue = typeof value === 'string' ? value : '';
@@ -207,7 +204,7 @@ function FileRow(props: {
onClick={() => window.open(file.fileUrl, '_blank', 'noopener,noreferrer')}
title={__("Download")}
/>
<Authorized entity="TrustCenterFile" action="updateTrustCenterFile">
{isAuthorized("TrustCenterFile", "updateTrustCenterFile") && (
<Button
variant="secondary"
icon={IconPencil}
@@ -215,8 +212,8 @@ function FileRow(props: {
disabled={props.disabled}
title={__("Edit")}
/>
</Authorized>
<Authorized entity="TrustCenterFile" action="deleteTrustCenterFile">
)}
{isAuthorized("TrustCenterFile", "deleteTrustCenterFile") && (
<Button
variant="danger"
icon={IconTrashCan}
@@ -224,7 +221,7 @@ function FileRow(props: {
disabled={props.disabled}
title={__("Delete")}
/>
</Authorized>
)}
</div>
</Td>
</Tr>

View File

@@ -14,14 +14,14 @@ import {
IconPencil,
IconArrowLink,
} from "@probo/ui";
import { type ReactNode, useRef, useState } from "react";
import { type ReactNode, useRef, useState, use } from "react";
import {
useTrustCenterReferences,
useUpdateTrustCenterReferenceRankMutation,
} from "/hooks/graph/TrustCenterReferenceGraph";
import { TrustCenterReferenceDialog, type TrustCenterReferenceDialogRef } from "./TrustCenterReferenceDialog";
import { DeleteTrustCenterReferenceDialog } from "./DeleteTrustCenterReferenceDialog";
import { Authorized } from "/permissions";
import { PermissionsContext } from "/providers/PermissionsContext";
type Props = {
trustCenterId: string;
@@ -41,6 +41,7 @@ type Reference = {
export function TrustCenterReferencesSection({ trustCenterId }: Props) {
const { __ } = useTranslate();
const { isAuthorized } = use(PermissionsContext);
const dialogRef = useRef<TrustCenterReferenceDialogRef>(null);
const [draggedIndex, setDraggedIndex] = useState<number | null>(null);
const [dragOverIndex, setDragOverIndex] = useState<number | null>(null);
@@ -112,14 +113,14 @@ export function TrustCenterReferencesSection({ trustCenterId }: Props) {
{__("Showcase your customers and partners on your trust center")}
</p>
</div>
<Authorized entity="TrustCenter" action="createTrustCenterReference">
{isAuthorized("TrustCenter", "createTrustCenterReference") && (
<Button
icon={IconPlusLarge}
onClick={handleCreate}
>
{__("Add Reference")}
</Button>
</Authorized>
)}
</div>
<Table>
@@ -190,6 +191,7 @@ function ReferenceRow({
onDrop,
}: ReferenceRowProps) {
const [isMouseDown, setIsMouseDown] = useState(false);
const { isAuthorized } = use(PermissionsContext);
const className = [
isDragging && "opacity-50 cursor-grabbing",
@@ -231,14 +233,14 @@ function ReferenceRow({
icon={IconArrowLink}
onClick={onVisitWebsite}
/>
<Authorized entity="TrustCenterReference" action="updateTrustCenterReference">
{isAuthorized("TrustCenterReference", "updateTrustCenterReference") && (
<Button
variant="secondary"
icon={IconPencil}
onClick={onEdit}
/>
</Authorized>
<Authorized entity="TrustCenterReference" action="deleteTrustCenterReference">
)}
{isAuthorized("TrustCenterReference", "deleteTrustCenterReference") && (
<DeleteTrustCenterReferenceDialog
referenceId={reference.id}
referenceName={reference.name}
@@ -249,7 +251,7 @@ function ReferenceRow({
icon={IconTrashCan}
/>
</DeleteTrustCenterReferenceDialog>
</Authorized>
)}
</div>
</Td>
</Tr>

View File

@@ -14,11 +14,11 @@ import {
} from "@probo/ui";
import { useTranslate } from "@probo/i18n";
import { useFragment } from "react-relay";
import { useMemo, useState, useEffect } from "react";
import { useMemo, useState, use } from "react";
import { sprintf } from "@probo/helpers";
import { useOrganizationId } from "/hooks/useOrganizationId";
import { isAuthorized } from "/permissions/permissions";
import type { TrustCenterVendorsCardFragment$key } from "./__generated__/TrustCenterVendorsCardFragment.graphql";
import { PermissionsContext } from "/providers/PermissionsContext";
const trustCenterVendorFragment = graphql`
fragment TrustCenterVendorsCardFragment on Vendor {
@@ -49,44 +49,14 @@ type Props<Params> = {
export function TrustCenterVendorsCard<Params>(props: Props<Params>) {
const { __ } = useTranslate();
const organizationId = useOrganizationId();
const [limit, setLimit] = useState<number | null>(100);
const [canUpdate, setCanUpdate] = useState<boolean>(false);
const { isAuthorized } = use(PermissionsContext);
const canUpdate = isAuthorized("Vendor", "updateVendor");
const vendors = useMemo(() => {
return limit ? props.vendors.slice(0, limit) : props.vendors;
}, [props.vendors, limit]);
const showMoreButton = limit !== null && props.vendors.length > limit;
useEffect(() => {
if (!organizationId) {
setCanUpdate(false);
return;
}
try {
const authorized = isAuthorized(organizationId, "Vendor", "updateVendor");
setCanUpdate(authorized);
} catch (promise) {
if (promise instanceof Promise) {
promise
.then(() => {
try {
const authorized = isAuthorized(organizationId, "Vendor", "updateVendor");
setCanUpdate(authorized);
} catch {
setCanUpdate(false);
}
})
.catch(() => {
setCanUpdate(false);
});
} else {
setCanUpdate(false);
}
}
}, [organizationId]);
const onToggleVisibility = (vendorId: string, showOnTrustCenter: boolean) => {
props.onToggleVisibility({
variables: {