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

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<3ed9b93b29f7a5117adbb33ad359f34e>>
* @generated SignedSource<<e94787d44108bcbebaaa3ad6bbdab13b>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -191,6 +191,19 @@ return {
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
{
"alias": "canDelete",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:evidence:delete"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:evidence:delete\")"
}
],
"storageKey": null
@@ -220,12 +233,12 @@ return {
]
},
"params": {
"cacheID": "4224b79c60bb9be5f4768da436659656",
"cacheID": "2fb329c16bcc54a40b95c0204469975c",
"id": null,
"metadata": {},
"name": "CreateEvidenceDialogUploadMutation",
"operationKind": "mutation",
"text": "mutation CreateEvidenceDialogUploadMutation(\n $input: UploadMeasureEvidenceInput!\n) {\n uploadMeasureEvidence(input: $input) {\n evidenceEdge {\n node {\n id\n ...MeasureEvidencesTabFragment_evidence\n }\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment_evidence on Evidence {\n id\n file {\n fileName\n mimeType\n size\n id\n }\n type\n createdAt\n}\n"
"text": "mutation CreateEvidenceDialogUploadMutation(\n $input: UploadMeasureEvidenceInput!\n) {\n uploadMeasureEvidence(input: $input) {\n evidenceEdge {\n node {\n id\n ...MeasureEvidencesTabFragment_evidence\n }\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment_evidence on Evidence {\n id\n file {\n fileName\n mimeType\n size\n id\n }\n type\n createdAt\n canDelete: permission(action: \"core:evidence:delete\")\n}\n"
}
};
})();

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<7d62dd9f271d13ca9220c8e54b79fa06>>
* @generated SignedSource<<3afe17784c8b08b2dd0db14b26d0058f>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -237,6 +237,32 @@ return {
"plural": false,
"selections": [
(v14/*: any*/),
{
"alias": "canCreateMeasureMapping",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:control:create-measure-mapping"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:control:create-measure-mapping\")"
},
{
"alias": "canDeleteMeasureMapping",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:control:delete-measure-mapping"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:control:delete-measure-mapping\")"
},
(v16/*: any*/),
{
"alias": null,
@@ -348,16 +374,16 @@ return {
]
},
"params": {
"cacheID": "a7984d29c1f4c4274e71f939d6a313fe",
"cacheID": "61b16a84cb9903560d86e0b5ee031abe",
"id": null,
"metadata": {},
"name": "MeasureControlsTabControlsQuery",
"operationKind": "query",
"text": "query MeasureControlsTabControlsQuery(\n $after: CursorKey\n $before: CursorKey = null\n $filter: ControlFilter = null\n $first: Int = 20\n $last: Int = null\n $order: ControlOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...MeasureControlsTabFragment_4cFWzS\n id\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n id\n name\n }\n}\n\nfragment MeasureControlsTabFragment_4cFWzS on Measure {\n id\n controls(first: $first, after: $after, last: $last, before: $before, orderBy: $order, filter: $filter) {\n edges {\n node {\n id\n ...LinkedControlsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n"
"text": "query MeasureControlsTabControlsQuery(\n $after: CursorKey\n $before: CursorKey = null\n $filter: ControlFilter = null\n $first: Int = 20\n $last: Int = null\n $order: ControlOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...MeasureControlsTabFragment_4cFWzS\n id\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n id\n name\n }\n}\n\nfragment MeasureControlsTabFragment_4cFWzS on Measure {\n id\n controls(first: $first, after: $after, last: $last, before: $before, orderBy: $order, filter: $filter) {\n edges {\n node {\n id\n canCreateMeasureMapping: permission(action: \"core:control:create-measure-mapping\")\n canDeleteMeasureMapping: permission(action: \"core:control:delete-measure-mapping\")\n ...LinkedControlsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n"
}
};
})();
(node as any).hash = "a9a268e40cc503e7e11fca8464f3e62c";
(node as any).hash = "6cd1d286921188abc2a9fdc1c1e0ed08";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<08d4e9940fe4265f66568c81985cb591>>
* @generated SignedSource<<414658fc55873606e711cc4571e9fd9b>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -15,6 +15,8 @@ export type MeasureControlsTabFragment$data = {
readonly __id: string;
readonly edges: ReadonlyArray<{
readonly node: {
readonly canCreateMeasureMapping: boolean;
readonly canDeleteMeasureMapping: boolean;
readonly id: string;
readonly " $fragmentSpreads": FragmentRefs<"LinkedControlsCardFragment">;
};
@@ -145,6 +147,32 @@ return {
"plural": false,
"selections": [
(v1/*: any*/),
{
"alias": "canCreateMeasureMapping",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:control:create-measure-mapping"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:control:create-measure-mapping\")"
},
{
"alias": "canDeleteMeasureMapping",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:control:delete-measure-mapping"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:control:delete-measure-mapping\")"
},
{
"args": null,
"kind": "FragmentSpread",
@@ -230,6 +258,6 @@ return {
};
})();
(node as any).hash = "a9a268e40cc503e7e11fca8464f3e62c";
(node as any).hash = "6cd1d286921188abc2a9fdc1c1e0ed08";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<95a549108a1a26ccfaf2d8aae42cea73>>
* @generated SignedSource<<d189402d5d6f47a0b2a3e303436e8a74>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -11,6 +11,7 @@
import { ReaderFragment } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type MeasureEvidencesTabFragment$data = {
readonly canUploadEvidence: boolean;
readonly evidences: {
readonly __id: string;
readonly edges: ReadonlyArray<{
@@ -109,6 +110,19 @@ return {
"name": "MeasureEvidencesTabFragment",
"selections": [
(v1/*: any*/),
{
"alias": "canUploadEvidence",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:measure:upload-evidence"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:measure:upload-evidence\")"
},
{
"alias": "evidences",
"args": [
@@ -257,6 +271,6 @@ return {
};
})();
(node as any).hash = "c80a159cbb4ac8b8855875eff00d1255";
(node as any).hash = "b281a36db45b03e86ec56097b6b9b296";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<0fb98c755d9aacac0ef1d508af9e7edc>>
* @generated SignedSource<<e4f324b614d93555afbc7055f63c534a>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -12,6 +12,7 @@ import { ReaderFragment } from 'relay-runtime';
export type EvidenceType = "FILE" | "LINK";
import { FragmentRefs } from "relay-runtime";
export type MeasureEvidencesTabFragment_evidence$data = {
readonly canDelete: boolean;
readonly createdAt: any;
readonly file: {
readonly fileName: string;
@@ -85,12 +86,25 @@ const node: ReaderFragment = {
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
{
"alias": "canDelete",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:evidence:delete"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:evidence:delete\")"
}
],
"type": "Evidence",
"abstractKey": null
};
(node as any).hash = "441ff1dd2dd62fea27050c5f550b27ea";
(node as any).hash = "af214cdfe077ad77326c65f33ce3ca1f";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<b182b11e656579608aba8fb03faa0ef6>>
* @generated SignedSource<<3f6cce4a7258adac62eab83f233b1a80>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -187,6 +187,19 @@ return {
{
"kind": "InlineFragment",
"selections": [
{
"alias": "canUploadEvidence",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:measure:upload-evidence"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:measure:upload-evidence\")"
},
{
"alias": null,
"args": (v13/*: any*/),
@@ -259,6 +272,19 @@ return {
"name": "createdAt",
"storageKey": null
},
{
"alias": "canDelete",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:evidence:delete"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:evidence:delete\")"
},
(v11/*: any*/)
],
"storageKey": null
@@ -348,16 +374,16 @@ return {
]
},
"params": {
"cacheID": "45ba257dabcf1cc7dd4aa05b699c280e",
"cacheID": "61235868d1100317d143c9510c047558",
"id": null,
"metadata": {},
"name": "MeasureEvidencesTabQuery",
"operationKind": "query",
"text": "query MeasureEvidencesTabQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: EvidenceOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...MeasureEvidencesTabFragment_16fISc\n id\n }\n}\n\nfragment MeasureEvidencesTabFragment_16fISc on Measure {\n id\n evidences(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n file {\n fileName\n mimeType\n size\n id\n }\n ...MeasureEvidencesTabFragment_evidence\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment_evidence on Evidence {\n id\n file {\n fileName\n mimeType\n size\n id\n }\n type\n createdAt\n}\n"
"text": "query MeasureEvidencesTabQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: EvidenceOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...MeasureEvidencesTabFragment_16fISc\n id\n }\n}\n\nfragment MeasureEvidencesTabFragment_16fISc on Measure {\n id\n canUploadEvidence: permission(action: \"core:measure:upload-evidence\")\n evidences(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n file {\n fileName\n mimeType\n size\n id\n }\n ...MeasureEvidencesTabFragment_evidence\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment_evidence on Evidence {\n id\n file {\n fileName\n mimeType\n size\n id\n }\n type\n createdAt\n canDelete: permission(action: \"core:evidence:delete\")\n}\n"
}
};
})();
(node as any).hash = "c80a159cbb4ac8b8855875eff00d1255";
(node as any).hash = "b281a36db45b03e86ec56097b6b9b296";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<68d7a7680b2d8573d9f05e2c33e2e516>>
* @generated SignedSource<<bf973ac1452f812480abe7160f4529e8>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -378,6 +378,32 @@ return {
"plural": false,
"selections": [
(v2/*: any*/),
{
"alias": "canCreateMeasureMapping",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:risk:create-measure-mapping"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:risk:create-measure-mapping\")"
},
{
"alias": "canDeleteMeasureMapping",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:risk:delete-measure-mapping"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:risk:delete-measure-mapping\")"
},
(v3/*: any*/),
{
"alias": null,
@@ -452,6 +478,32 @@ return {
"plural": false,
"selections": [
(v2/*: any*/),
{
"alias": "canCreateMeasureMapping",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:control:create-measure-mapping"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:control:create-measure-mapping\")"
},
{
"alias": "canDeleteMeasureMapping",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:control:delete-measure-mapping"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:control:delete-measure-mapping\")"
},
(v3/*: any*/),
{
"alias": null,
@@ -498,6 +550,19 @@ return {
"kind": "LinkedHandle",
"name": "controls"
},
{
"alias": "canUploadEvidence",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:measure:upload-evidence"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:measure:upload-evidence\")"
},
{
"alias": null,
"args": (v23/*: any*/),
@@ -570,6 +635,19 @@ return {
"name": "createdAt",
"storageKey": null
},
{
"alias": "canDelete",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:evidence:delete"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:evidence:delete\")"
},
(v15/*: any*/)
],
"storageKey": null
@@ -604,12 +682,12 @@ return {
]
},
"params": {
"cacheID": "e168532dd6888e5d7ddfaca1dc5f188e",
"cacheID": "d8ac1210636ffd91eacb1bfe3452e26c",
"id": null,
"metadata": {},
"name": "MeasureGraphNodeQuery",
"operationKind": "query",
"text": "query MeasureGraphNodeQuery(\n $measureId: ID!\n) {\n node(id: $measureId) {\n __typename\n ... on Measure {\n id\n name\n description\n state\n category\n canUpdate: permission(action: \"core:measure:update\")\n canDelete: permission(action: \"core:measure:delete\")\n canListTasks: permission(action: \"core:task:list\")\n evidencesInfos: evidences(first: 0) {\n totalCount\n }\n risksInfos: risks(first: 0) {\n totalCount\n }\n controlsInfos: controls(first: 0) {\n totalCount\n }\n ...MeasureRisksTabFragment\n ...MeasureControlsTabFragment\n ...MeasureFormDialogMeasureFragment\n ...MeasureEvidencesTabFragment\n }\n id\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n id\n name\n }\n}\n\nfragment LinkedRisksCardFragment on Risk {\n id\n name\n inherentRiskScore\n residualRiskScore\n}\n\nfragment MeasureControlsTabFragment on Measure {\n id\n controls(first: 20) {\n edges {\n node {\n id\n ...LinkedControlsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment on Measure {\n id\n evidences(first: 50) {\n edges {\n node {\n id\n file {\n fileName\n mimeType\n size\n id\n }\n ...MeasureEvidencesTabFragment_evidence\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment_evidence on Evidence {\n id\n file {\n fileName\n mimeType\n size\n id\n }\n type\n createdAt\n}\n\nfragment MeasureFormDialogMeasureFragment on Measure {\n id\n description\n name\n category\n state\n}\n\nfragment MeasureRisksTabFragment on Measure {\n id\n risks(first: 100) {\n edges {\n node {\n id\n ...LinkedRisksCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n"
"text": "query MeasureGraphNodeQuery(\n $measureId: ID!\n) {\n node(id: $measureId) {\n __typename\n ... on Measure {\n id\n name\n description\n state\n category\n canUpdate: permission(action: \"core:measure:update\")\n canDelete: permission(action: \"core:measure:delete\")\n canListTasks: permission(action: \"core:task:list\")\n evidencesInfos: evidences(first: 0) {\n totalCount\n }\n risksInfos: risks(first: 0) {\n totalCount\n }\n controlsInfos: controls(first: 0) {\n totalCount\n }\n ...MeasureRisksTabFragment\n ...MeasureControlsTabFragment\n ...MeasureFormDialogMeasureFragment\n ...MeasureEvidencesTabFragment\n }\n id\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n id\n name\n }\n}\n\nfragment LinkedRisksCardFragment on Risk {\n id\n name\n inherentRiskScore\n residualRiskScore\n}\n\nfragment MeasureControlsTabFragment on Measure {\n id\n controls(first: 20) {\n edges {\n node {\n id\n canCreateMeasureMapping: permission(action: \"core:control:create-measure-mapping\")\n canDeleteMeasureMapping: permission(action: \"core:control:delete-measure-mapping\")\n ...LinkedControlsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment on Measure {\n id\n canUploadEvidence: permission(action: \"core:measure:upload-evidence\")\n evidences(first: 50) {\n edges {\n node {\n id\n file {\n fileName\n mimeType\n size\n id\n }\n ...MeasureEvidencesTabFragment_evidence\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment_evidence on Evidence {\n id\n file {\n fileName\n mimeType\n size\n id\n }\n type\n createdAt\n canDelete: permission(action: \"core:evidence:delete\")\n}\n\nfragment MeasureFormDialogMeasureFragment on Measure {\n id\n description\n name\n category\n state\n}\n\nfragment MeasureRisksTabFragment on Measure {\n id\n risks(first: 100) {\n edges {\n node {\n id\n canCreateMeasureMapping: permission(action: \"core:risk:create-measure-mapping\")\n canDeleteMeasureMapping: permission(action: \"core:risk:delete-measure-mapping\")\n ...LinkedRisksCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n"
}
};
})();

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<caa6c09d5f08c92e9e1083e0e6691713>>
* @generated SignedSource<<4f367882dc2cd7bb8a8605d9192cd7f5>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -16,6 +16,8 @@ export type MeasureRisksTabFragment$data = {
readonly __id: string;
readonly edges: ReadonlyArray<{
readonly node: {
readonly canCreateMeasureMapping: boolean;
readonly canDeleteMeasureMapping: boolean;
readonly id: string;
readonly " $fragmentSpreads": FragmentRefs<"LinkedRisksCardFragment">;
};
@@ -79,6 +81,32 @@ return {
"plural": false,
"selections": [
(v0/*: any*/),
{
"alias": "canCreateMeasureMapping",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:risk:create-measure-mapping"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:risk:create-measure-mapping\")"
},
{
"alias": "canDeleteMeasureMapping",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:risk:delete-measure-mapping"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:risk:delete-measure-mapping\")"
},
{
"args": null,
"kind": "FragmentSpread",
@@ -150,6 +178,6 @@ return {
};
})();
(node as any).hash = "1d73bd64b1a01fed76eac68d83d4d4c1";
(node as any).hash = "a837a187026f5c75c67efcb4831d0b76";
export default node;

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 = {