Fix measure pages permissions handling

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2025-12-31 18:09:17 +01:00
committed by Bryan Frimin
parent 095254a73d
commit 4d6b33203d
11 changed files with 278 additions and 45 deletions

View File

@@ -3,8 +3,6 @@ import { useOutletContext } from "react-router";
import { LinkedControlsCard } from "/components/controls/LinkedControlsCard";
import type { MeasureControlsTabFragment$key } from "/__generated__/core/MeasureControlsTabFragment.graphql";
import { useMutationWithIncrement } from "/hooks/useMutationWithIncrement";
import { use } from "react";
import { PermissionsContext } from "/providers/PermissionsContext";
export const controlsFragment = graphql`
fragment MeasureControlsTabFragment on Measure
@@ -30,6 +28,12 @@ export const controlsFragment = graphql`
edges {
node {
id
canCreateMeasureMapping: permission(
action: "core:control:create-measure-mapping"
)
canDeleteMeasureMapping: permission(
action: "core:control:delete-measure-mapping"
)
...LinkedControlsCardFragment
}
}
@@ -71,12 +75,12 @@ export default function MeasureControlsTab() {
const [data, refetch] = useRefetchableFragment(controlsFragment, measure);
const connectionId = data.controls.__id;
const controls = data.controls?.edges?.map((edge) => edge.node) ?? [];
const { isAuthorized } = use(PermissionsContext);
const canLinkControl = isAuthorized("Control", "createControlMeasureMapping");
const canUnlinkControl = isAuthorized(
"Control",
"deleteControlMeasureMapping",
const canLinkControl = controls.some(
({ canCreateMeasureMapping }) => canCreateMeasureMapping,
);
const canUnlinkControl = controls.some(
({ canDeleteMeasureMapping }) => canDeleteMeasureMapping,
);
const readOnly = !canLinkControl && !canUnlinkControl;

View File

@@ -29,11 +29,10 @@ import { fileSize, fileType, sprintf, formatDate } from "@probo/helpers";
import { EvidencePreviewDialog } from "../dialog/EvidencePreviewDialog";
import { useOrganizationId } from "/hooks/useOrganizationId";
import { CreateEvidenceDialog } from "../dialog/CreateEvidenceDialog";
import { use, useState } from "react";
import { useState } from "react";
import { EvidenceDownloadDialog } from "../dialog/EvidenceDownloadDialog";
import { updateStoreCounter } from "/hooks/useMutationWithIncrement";
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
import { PermissionsContext } from "/providers/PermissionsContext";
export const evidencesFragment = graphql`
fragment MeasureEvidencesTabFragment on Measure
@@ -46,6 +45,7 @@ export const evidencesFragment = graphql`
last: { type: "Int", defaultValue: null }
) {
id
canUploadEvidence: permission(action: "core:measure:upload-evidence")
evidences(
first: $first
after: $after
@@ -79,6 +79,7 @@ export const evidenceFragment = graphql`
}
type
createdAt
canDelete: permission(action: "core:evidence:delete")
}
`;
@@ -111,10 +112,6 @@ export default function MeasureEvidencesTab() {
const organizationId = useOrganizationId();
const dialogRef = useDialogRef();
const isSnapshotMode = Boolean(snapshotId);
const { isAuthorized } = use(PermissionsContext);
const canAddEvidence = isAuthorized("Measure", "uploadMeasureEvidence");
const canDeleteEvidence = isAuthorized("Evidence", "deleteEvidence");
usePageTitle(measure.name + " - " + __("Evidences"));
@@ -139,11 +136,10 @@ export default function MeasureEvidencesTab() {
organizationId={organizationId}
connectionId={connectionId}
hideActions={isSnapshotMode}
canDelete={canDeleteEvidence}
snapshotId={snapshotId}
/>
))}
{!isSnapshotMode && canAddEvidence && (
{!isSnapshotMode && pagination.data.canUploadEvidence && (
<TrButton
colspan={5}
onClick={() => dialogRef.current?.open()}
@@ -167,7 +163,7 @@ export default function MeasureEvidencesTab() {
filename={evidence.file?.fileName || ""}
/>
)}
{!isSnapshotMode && canAddEvidence && (
{!isSnapshotMode && pagination.data.canUploadEvidence && (
<CreateEvidenceDialog
ref={dialogRef}
measureId={measure.id}
@@ -184,7 +180,6 @@ function EvidenceRow(props: {
organizationId: string;
connectionId: string;
hideActions?: boolean;
canDelete?: boolean;
snapshotId?: string;
}) {
const evidence = useFragment(evidenceFragment, props.evidenceKey);
@@ -267,7 +262,7 @@ function EvidenceRow(props: {
<IconArrowInbox size={16} />
{__("Download")}
</DropdownItem>
{props.canDelete && (
{evidence.canDelete && (
<DropdownItem
variant="danger"
icon={IconTrashCan}

View File

@@ -3,8 +3,6 @@ import type { MeasureRisksTabFragment$key } from "/__generated__/core/MeasureRis
import { useOutletContext } from "react-router";
import { LinkedRisksCard } from "/components/risks/LinkedRisksCard";
import { useMutationWithIncrement } from "/hooks/useMutationWithIncrement";
import { use } from "react";
import { PermissionsContext } from "/providers/PermissionsContext";
export const risksFragment = graphql`
fragment MeasureRisksTabFragment on Measure {
@@ -14,6 +12,12 @@ export const risksFragment = graphql`
edges {
node {
id
canCreateMeasureMapping: permission(
action: "core:risk:create-measure-mapping"
)
canDeleteMeasureMapping: permission(
action: "core:risk:delete-measure-mapping"
)
...LinkedRisksCardFragment
}
}
@@ -55,10 +59,13 @@ export default function MeasureRisksTab() {
const data = useFragment(risksFragment, measure);
const connectionId = data.risks.__id;
const risks = data.risks?.edges?.map((edge) => edge.node) ?? [];
const { isAuthorized } = use(PermissionsContext);
const canLinkRisk = isAuthorized("Risk", "createRiskMeasureMapping");
const canUnlinkRisk = isAuthorized("Risk", "deleteRiskMeasureMapping");
const canLinkRisk = risks.some(
({ canCreateMeasureMapping }) => canCreateMeasureMapping,
);
const canUnlinkRisk = risks.some(
({ canDeleteMeasureMapping }) => canDeleteMeasureMapping,
);
const readOnly = !canLinkRisk && !canUnlinkRisk;
const incrementOptions = {