Fix snapshot pages permissions handling

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2026-01-02 11:52:00 +01:00
committed by Bryan Frimin
parent 9cc6d143f6
commit ea2438e345
9 changed files with 982 additions and 847 deletions

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<14e03b23c216da916e36cecb49aefa6d>> * @generated SignedSource<<5c57612f8793f7b056bf0046febe42ca>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -17,6 +17,9 @@ export type ProcessingActivityGraphListQuery$variables = {
export type ProcessingActivityGraphListQuery$data = { export type ProcessingActivityGraphListQuery$data = {
readonly node: { readonly node: {
readonly canCreateProcessingActivity?: boolean; readonly canCreateProcessingActivity?: boolean;
readonly canExportDataProtectionImpactAssessments?: boolean;
readonly canExportProcessingActivities?: boolean;
readonly canExportTransferImpactAssessments?: boolean;
readonly " $fragmentSpreads": FragmentRefs<"ProcessingActivitiesPageDPIAFragment" | "ProcessingActivitiesPageFragment" | "ProcessingActivitiesPageTIAFragment">; readonly " $fragmentSpreads": FragmentRefs<"ProcessingActivitiesPageDPIAFragment" | "ProcessingActivitiesPageFragment" | "ProcessingActivitiesPageTIAFragment">;
}; };
}; };
@@ -58,30 +61,69 @@ v2 = {
"name": "permission", "name": "permission",
"storageKey": "permission(action:\"core:processing-activity:create\")" "storageKey": "permission(action:\"core:processing-activity:create\")"
}, },
v3 = [ v3 = {
"alias": "canExportProcessingActivities",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:processing-activity:export"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:processing-activity:export\")"
},
v4 = {
"alias": "canExportDataProtectionImpactAssessments",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:data-protection-impact-assessment:export"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:data-protection-impact-assessment:export\")"
},
v5 = {
"alias": "canExportTransferImpactAssessments",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:transfer-impact-assessment:export"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:transfer-impact-assessment:export\")"
},
v6 = [
{ {
"kind": "Variable", "kind": "Variable",
"name": "snapshotId", "name": "snapshotId",
"variableName": "snapshotId" "variableName": "snapshotId"
} }
], ],
v4 = { v7 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "__typename", "name": "__typename",
"storageKey": null "storageKey": null
}, },
v5 = { v8 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "id", "name": "id",
"storageKey": null "storageKey": null
}, },
v6 = [ v9 = [
{ {
"fields": (v3/*: any*/), "fields": (v6/*: any*/),
"kind": "ObjectValue", "kind": "ObjectValue",
"name": "filter" "name": "filter"
}, },
@@ -91,42 +133,42 @@ v6 = [
"value": 10 "value": 10
} }
], ],
v7 = { v10 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "totalCount", "name": "totalCount",
"storageKey": null "storageKey": null
}, },
v8 = { v11 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "name", "name": "name",
"storageKey": null "storageKey": null
}, },
v9 = { v12 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "createdAt", "name": "createdAt",
"storageKey": null "storageKey": null
}, },
v10 = { v13 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "updatedAt", "name": "updatedAt",
"storageKey": null "storageKey": null
}, },
v11 = { v14 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "cursor", "name": "cursor",
"storageKey": null "storageKey": null
}, },
v12 = { v15 = {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PageInfo", "concreteType": "PageInfo",
@@ -151,7 +193,7 @@ v12 = {
], ],
"storageKey": null "storageKey": null
}, },
v13 = { v16 = {
"kind": "ClientExtension", "kind": "ClientExtension",
"selections": [ "selections": [
{ {
@@ -163,10 +205,10 @@ v13 = {
} }
] ]
}, },
v14 = [ v17 = [
"filter" "filter"
], ],
v15 = { v18 = {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "ProcessingActivity", "concreteType": "ProcessingActivity",
@@ -174,8 +216,8 @@ v15 = {
"name": "processingActivity", "name": "processingActivity",
"plural": false, "plural": false,
"selections": [ "selections": [
(v5/*: any*/), (v8/*: any*/),
(v8/*: any*/) (v11/*: any*/)
], ],
"storageKey": null "storageKey": null
}; };
@@ -198,18 +240,21 @@ return {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
(v2/*: any*/), (v2/*: any*/),
(v3/*: any*/),
(v4/*: any*/),
(v5/*: any*/),
{ {
"args": (v3/*: any*/), "args": (v6/*: any*/),
"kind": "FragmentSpread", "kind": "FragmentSpread",
"name": "ProcessingActivitiesPageFragment" "name": "ProcessingActivitiesPageFragment"
}, },
{ {
"args": (v3/*: any*/), "args": (v6/*: any*/),
"kind": "FragmentSpread", "kind": "FragmentSpread",
"name": "ProcessingActivitiesPageDPIAFragment" "name": "ProcessingActivitiesPageDPIAFragment"
}, },
{ {
"args": (v3/*: any*/), "args": (v6/*: any*/),
"kind": "FragmentSpread", "kind": "FragmentSpread",
"name": "ProcessingActivitiesPageTIAFragment" "name": "ProcessingActivitiesPageTIAFragment"
} }
@@ -238,21 +283,24 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v4/*: any*/), (v7/*: any*/),
(v5/*: any*/), (v8/*: any*/),
{ {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
(v2/*: any*/), (v2/*: any*/),
(v3/*: any*/),
(v4/*: any*/),
(v5/*: any*/),
{ {
"alias": null, "alias": null,
"args": (v6/*: any*/), "args": (v9/*: any*/),
"concreteType": "ProcessingActivityConnection", "concreteType": "ProcessingActivityConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "processingActivities", "name": "processingActivities",
"plural": false, "plural": false,
"selections": [ "selections": [
(v7/*: any*/), (v10/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -269,7 +317,7 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v5/*: any*/), (v8/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -284,7 +332,7 @@ return {
"name": "sourceId", "name": "sourceId",
"storageKey": null "storageKey": null
}, },
(v8/*: any*/), (v11/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -327,8 +375,8 @@ return {
"name": "internationalTransfers", "name": "internationalTransfers",
"storageKey": null "storageKey": null
}, },
(v9/*: any*/), (v12/*: any*/),
(v10/*: any*/), (v13/*: any*/),
{ {
"alias": "canUpdate", "alias": "canUpdate",
"args": [ "args": [
@@ -355,23 +403,23 @@ return {
"name": "permission", "name": "permission",
"storageKey": "permission(action:\"core:processing-activity:delete\")" "storageKey": "permission(action:\"core:processing-activity:delete\")"
}, },
(v4/*: any*/) (v7/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v11/*: any*/) (v14/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v12/*: any*/), (v15/*: any*/),
(v13/*: any*/) (v16/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
{ {
"alias": null, "alias": null,
"args": (v6/*: any*/), "args": (v9/*: any*/),
"filters": (v14/*: any*/), "filters": (v17/*: any*/),
"handle": "connection", "handle": "connection",
"key": "ProcessingActivitiesPage_processingActivities", "key": "ProcessingActivitiesPage_processingActivities",
"kind": "LinkedHandle", "kind": "LinkedHandle",
@@ -379,13 +427,13 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v6/*: any*/), "args": (v9/*: any*/),
"concreteType": "DataProtectionImpactAssessmentConnection", "concreteType": "DataProtectionImpactAssessmentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "dataProtectionImpactAssessments", "name": "dataProtectionImpactAssessments",
"plural": false, "plural": false,
"selections": [ "selections": [
(v7/*: any*/), (v10/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -402,7 +450,7 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v5/*: any*/), (v8/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -424,26 +472,26 @@ return {
"name": "residualRisk", "name": "residualRisk",
"storageKey": null "storageKey": null
}, },
(v15/*: any*/), (v18/*: any*/),
(v9/*: any*/), (v12/*: any*/),
(v10/*: any*/), (v13/*: any*/),
(v4/*: any*/) (v7/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v11/*: any*/) (v14/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v12/*: any*/), (v15/*: any*/),
(v13/*: any*/) (v16/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
{ {
"alias": null, "alias": null,
"args": (v6/*: any*/), "args": (v9/*: any*/),
"filters": (v14/*: any*/), "filters": (v17/*: any*/),
"handle": "connection", "handle": "connection",
"key": "ProcessingActivitiesPage_dataProtectionImpactAssessments", "key": "ProcessingActivitiesPage_dataProtectionImpactAssessments",
"kind": "LinkedHandle", "kind": "LinkedHandle",
@@ -451,13 +499,13 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v6/*: any*/), "args": (v9/*: any*/),
"concreteType": "TransferImpactAssessmentConnection", "concreteType": "TransferImpactAssessmentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "transferImpactAssessments", "name": "transferImpactAssessments",
"plural": false, "plural": false,
"selections": [ "selections": [
(v7/*: any*/), (v10/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -474,7 +522,7 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v5/*: any*/), (v8/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -496,26 +544,26 @@ return {
"name": "localLawRisk", "name": "localLawRisk",
"storageKey": null "storageKey": null
}, },
(v15/*: any*/), (v18/*: any*/),
(v9/*: any*/), (v12/*: any*/),
(v10/*: any*/), (v13/*: any*/),
(v4/*: any*/) (v7/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v11/*: any*/) (v14/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v12/*: any*/), (v15/*: any*/),
(v13/*: any*/) (v16/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
{ {
"alias": null, "alias": null,
"args": (v6/*: any*/), "args": (v9/*: any*/),
"filters": (v14/*: any*/), "filters": (v17/*: any*/),
"handle": "connection", "handle": "connection",
"key": "ProcessingActivitiesPage_transferImpactAssessments", "key": "ProcessingActivitiesPage_transferImpactAssessments",
"kind": "LinkedHandle", "kind": "LinkedHandle",
@@ -531,16 +579,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "1d48f2badad2cfdbc1d36a06756a9ec7", "cacheID": "84a26e65e3de62f76f034786cf174f80",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "ProcessingActivityGraphListQuery", "name": "ProcessingActivityGraphListQuery",
"operationKind": "query", "operationKind": "query",
"text": "query ProcessingActivityGraphListQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n canCreateProcessingActivity: permission(action: \"core:processing-activity:create\")\n ...ProcessingActivitiesPageFragment_3iomuz\n ...ProcessingActivitiesPageDPIAFragment_3iomuz\n ...ProcessingActivitiesPageTIAFragment_3iomuz\n }\n id\n }\n}\n\nfragment ProcessingActivitiesPageDPIAFragment_3iomuz on Organization {\n id\n dataProtectionImpactAssessments(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n description\n potentialRisk\n residualRisk\n processingActivity {\n id\n name\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n\nfragment ProcessingActivitiesPageFragment_3iomuz on Organization {\n id\n processingActivities(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n snapshotId\n sourceId\n name\n purpose\n dataSubjectCategory\n personalDataCategory\n lawfulBasis\n location\n internationalTransfers\n createdAt\n updatedAt\n canUpdate: permission(action: \"core:processing-activity:update\")\n canDelete: permission(action: \"core:processing-activity:delete\")\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n\nfragment ProcessingActivitiesPageTIAFragment_3iomuz on Organization {\n id\n transferImpactAssessments(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n dataSubjects\n transfer\n localLawRisk\n processingActivity {\n id\n name\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n" "text": "query ProcessingActivityGraphListQuery(\n $organizationId: ID!\n $snapshotId: ID\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n canCreateProcessingActivity: permission(action: \"core:processing-activity:create\")\n canExportProcessingActivities: permission(action: \"core:processing-activity:export\")\n canExportDataProtectionImpactAssessments: permission(action: \"core:data-protection-impact-assessment:export\")\n canExportTransferImpactAssessments: permission(action: \"core:transfer-impact-assessment:export\")\n ...ProcessingActivitiesPageFragment_3iomuz\n ...ProcessingActivitiesPageDPIAFragment_3iomuz\n ...ProcessingActivitiesPageTIAFragment_3iomuz\n }\n id\n }\n}\n\nfragment ProcessingActivitiesPageDPIAFragment_3iomuz on Organization {\n id\n dataProtectionImpactAssessments(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n description\n potentialRisk\n residualRisk\n processingActivity {\n id\n name\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n\nfragment ProcessingActivitiesPageFragment_3iomuz on Organization {\n id\n processingActivities(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n snapshotId\n sourceId\n name\n purpose\n dataSubjectCategory\n personalDataCategory\n lawfulBasis\n location\n internationalTransfers\n createdAt\n updatedAt\n canUpdate: permission(action: \"core:processing-activity:update\")\n canDelete: permission(action: \"core:processing-activity:delete\")\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n\nfragment ProcessingActivitiesPageTIAFragment_3iomuz on Organization {\n id\n transferImpactAssessments(first: 10, filter: {snapshotId: $snapshotId}) {\n totalCount\n edges {\n node {\n id\n dataSubjects\n transfer\n localLawRisk\n processingActivity {\n id\n name\n }\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "7a0d589abac7bbd3710a0caad37d6273"; (node as any).hash = "6efb688e3142c0eceb054ded9df044de";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<7d676ad166c7c858dc8dbc909ed500ea>> * @generated SignedSource<<8fe6c01dea59b2ae2d04050e3cb959d1>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -24,6 +24,7 @@ export type SnapshotFormDialogCreateMutation$data = {
readonly createSnapshot: { readonly createSnapshot: {
readonly snapshotEdge: { readonly snapshotEdge: {
readonly node: { readonly node: {
readonly canDelete: boolean;
readonly createdAt: string; readonly createdAt: string;
readonly description: string | null | undefined; readonly description: string | null | undefined;
readonly id: string; readonly id: string;
@@ -106,6 +107,19 @@ v3 = {
"kind": "ScalarField", "kind": "ScalarField",
"name": "createdAt", "name": "createdAt",
"storageKey": null "storageKey": null
},
{
"alias": "canDelete",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:snapshot:delete"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:snapshot:delete\")"
} }
], ],
"storageKey": null "storageKey": null
@@ -179,16 +193,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "e60d598bc7f5c4958168405725664334", "cacheID": "5165891e3f49f2b9e3d1a0b29a0f8bf6",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "SnapshotFormDialogCreateMutation", "name": "SnapshotFormDialogCreateMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation SnapshotFormDialogCreateMutation(\n $input: CreateSnapshotInput!\n) {\n createSnapshot(input: $input) {\n snapshotEdge {\n node {\n id\n name\n description\n type\n createdAt\n }\n }\n }\n}\n" "text": "mutation SnapshotFormDialogCreateMutation(\n $input: CreateSnapshotInput!\n) {\n createSnapshot(input: $input) {\n snapshotEdge {\n node {\n id\n name\n description\n type\n createdAt\n canDelete: permission(action: \"core:snapshot:delete\")\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "b03087e1699a90953aad7cdedaeee1a4"; (node as any).hash = "1a844eb9af4ea94b194deaf65ba068a0";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<f4a719bca36d682b094afe419b9129e8>> * @generated SignedSource<<55bde95f500bc2496ce224e275e49984>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -15,6 +15,7 @@ export type SnapshotGraphListQuery$variables = {
}; };
export type SnapshotGraphListQuery$data = { export type SnapshotGraphListQuery$data = {
readonly organization: { readonly organization: {
readonly canCreateSnapshot?: boolean;
readonly " $fragmentSpreads": FragmentRefs<"SnapshotsPageFragment">; readonly " $fragmentSpreads": FragmentRefs<"SnapshotsPageFragment">;
}; };
}; };
@@ -39,20 +40,33 @@ v1 = [
} }
], ],
v2 = { v2 = {
"alias": "canCreateSnapshot",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:snapshot:create"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:snapshot:create\")"
},
v3 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "__typename", "name": "__typename",
"storageKey": null "storageKey": null
}, },
v3 = [ v4 = [
{ {
"kind": "Literal", "kind": "Literal",
"name": "first", "name": "first",
"value": 100 "value": 100
} }
], ],
v4 = { v5 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
@@ -77,6 +91,7 @@ return {
{ {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
(v2/*: any*/),
{ {
"args": null, "args": null,
"kind": "FragmentSpread", "kind": "FragmentSpread",
@@ -107,13 +122,14 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v2/*: any*/), (v3/*: any*/),
{ {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
(v2/*: any*/),
{ {
"alias": null, "alias": null,
"args": (v3/*: any*/), "args": (v4/*: any*/),
"concreteType": "SnapshotConnection", "concreteType": "SnapshotConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "snapshots", "name": "snapshots",
@@ -135,7 +151,7 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v4/*: any*/), (v5/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -164,7 +180,20 @@ return {
"name": "createdAt", "name": "createdAt",
"storageKey": null "storageKey": null
}, },
(v2/*: any*/) {
"alias": "canDelete",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:snapshot:delete"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:snapshot:delete\")"
},
(v3/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
@@ -220,7 +249,7 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v3/*: any*/), "args": (v4/*: any*/),
"filters": null, "filters": null,
"handle": "connection", "handle": "connection",
"key": "SnapshotsGraphListQuery__snapshots", "key": "SnapshotsGraphListQuery__snapshots",
@@ -231,23 +260,23 @@ return {
"type": "Organization", "type": "Organization",
"abstractKey": null "abstractKey": null
}, },
(v4/*: any*/) (v5/*: any*/)
], ],
"storageKey": null "storageKey": null
} }
] ]
}, },
"params": { "params": {
"cacheID": "eda538d8a5e4e94551012bbb6b8da92f", "cacheID": "5925e1c6f87d598008baeef50bf620c7",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "SnapshotGraphListQuery", "name": "SnapshotGraphListQuery",
"operationKind": "query", "operationKind": "query",
"text": "query SnapshotGraphListQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n ...SnapshotsPageFragment\n }\n id\n }\n}\n\nfragment SnapshotsPageFragment on Organization {\n snapshots(first: 100) {\n edges {\n node {\n id\n name\n description\n type\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n" "text": "query SnapshotGraphListQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n canCreateSnapshot: permission(action: \"core:snapshot:create\")\n ...SnapshotsPageFragment\n }\n id\n }\n}\n\nfragment SnapshotsPageFragment on Organization {\n snapshots(first: 100) {\n edges {\n node {\n id\n name\n description\n type\n createdAt\n canDelete: permission(action: \"core:snapshot:delete\")\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "0f264bca502a59b7f8b8ec729d0ce1ff"; (node as any).hash = "18d12720fafef47af62376e8461fd19f";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<8aa2e602e0b579ac6a320207afa7c558>> * @generated SignedSource<<a4f24e8f6dd08074e60067f638eacfd9>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -16,6 +16,7 @@ export type SnapshotsPageFragment$data = {
readonly __id: string; readonly __id: string;
readonly edges: ReadonlyArray<{ readonly edges: ReadonlyArray<{
readonly node: { readonly node: {
readonly canDelete: boolean;
readonly createdAt: string; readonly createdAt: string;
readonly description: string | null | undefined; readonly description: string | null | undefined;
readonly id: string; readonly id: string;
@@ -107,6 +108,19 @@ const node: ReaderFragment = {
"name": "createdAt", "name": "createdAt",
"storageKey": null "storageKey": null
}, },
{
"alias": "canDelete",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:snapshot:delete"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:snapshot:delete\")"
},
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -172,6 +186,6 @@ const node: ReaderFragment = {
"abstractKey": null "abstractKey": null
}; };
(node as any).hash = "700dede55fd00f2b57dbbb6ed2e2613d"; (node as any).hash = "d924051b479e33aa7fb627e7ad8ad664";
export default node; export default node;

View File

@@ -19,6 +19,15 @@ export const processingActivitiesQuery = graphql`
canCreateProcessingActivity: permission( canCreateProcessingActivity: permission(
action: "core:processing-activity:create" action: "core:processing-activity:create"
) )
canExportProcessingActivities: permission(
action: "core:processing-activity:export"
)
canExportDataProtectionImpactAssessments: permission(
action: "core:data-protection-impact-assessment:export"
)
canExportTransferImpactAssessments: permission(
action: "core:transfer-impact-assessment:export"
)
...ProcessingActivitiesPageFragment @arguments(snapshotId: $snapshotId) ...ProcessingActivitiesPageFragment @arguments(snapshotId: $snapshotId)
...ProcessingActivitiesPageDPIAFragment ...ProcessingActivitiesPageDPIAFragment
@arguments(snapshotId: $snapshotId) @arguments(snapshotId: $snapshotId)

View File

@@ -11,6 +11,7 @@ export const snapshotsQuery = graphql`
query SnapshotGraphListQuery($organizationId: ID!) { query SnapshotGraphListQuery($organizationId: ID!) {
organization: node(id: $organizationId) { organization: node(id: $organizationId) {
... on Organization { ... on Organization {
canCreateSnapshot: permission(action: "core:snapshot:create")
...SnapshotsPageFragment ...SnapshotsPageFragment
} }
} }
@@ -67,7 +68,7 @@ export const deleteSnapshotMutation = graphql`
export const useDeleteSnapshot = ( export const useDeleteSnapshot = (
snapshot: { id: string; name: string }, snapshot: { id: string; name: string },
connectionId: string connectionId: string,
) => { ) => {
const { __ } = useTranslate(); const { __ } = useTranslate();
const [mutate] = useMutationWithToasts(deleteSnapshotMutation, { const [mutate] = useMutationWithToasts(deleteSnapshotMutation, {
@@ -90,11 +91,11 @@ export const useDeleteSnapshot = (
{ {
message: sprintf( message: sprintf(
__( __(
"This will permanently delete the snapshot %s. This action cannot be undone." "This will permanently delete the snapshot %s. This action cannot be undone.",
), ),
snapshot.name snapshot.name,
), ),
} },
); );
}; };
}; };

View File

@@ -35,8 +35,6 @@ import type { NodeOf } from "/types";
import SnapshotFormDialog from "./dialog/SnapshotFormDialog"; import SnapshotFormDialog from "./dialog/SnapshotFormDialog";
import { usePageTitle } from "@probo/hooks"; import { usePageTitle } from "@probo/hooks";
import { useOrganizationId } from "/hooks/useOrganizationId"; import { useOrganizationId } from "/hooks/useOrganizationId";
import { PermissionsContext } from "/providers/PermissionsContext";
import { use } from "react";
type Props = { type Props = {
queryRef: PreloadedQuery<SnapshotGraphListQuery>; queryRef: PreloadedQuery<SnapshotGraphListQuery>;
@@ -54,6 +52,7 @@ const snapshotsFragment = graphql`
description description
type type
createdAt createdAt
canDelete: permission(action: "core:snapshot:delete")
} }
} }
} }
@@ -73,10 +72,9 @@ export default function SnapshotsPage(props: Props) {
); );
const connectionId = data.snapshots.__id; const connectionId = data.snapshots.__id;
const snapshots = data.snapshots.edges.map((edge) => edge.node); const snapshots = data.snapshots.edges.map((edge) => edge.node);
const { isAuthorized } = use(PermissionsContext);
usePageTitle(__("Snapshots")); usePageTitle(__("Snapshots"));
const hasAnyAction = isAuthorized("Snapshot", "deleteSnapshot"); const hasAnyAction = snapshots.some(({ canDelete }) => canDelete);
return ( return (
<div className="space-y-6"> <div className="space-y-6">
@@ -86,7 +84,7 @@ export default function SnapshotsPage(props: Props) {
"Snapshots capture point-in-time views of your organization's compliance state. Create snapshots to track progress over time.", "Snapshots capture point-in-time views of your organization's compliance state. Create snapshots to track progress over time.",
)} )}
> >
{isAuthorized("Organization", "createSnapshot") && ( {organization.canCreateSnapshot && (
<SnapshotFormDialog connection={connectionId}> <SnapshotFormDialog connection={connectionId}>
<Button variant="primary" icon={IconPlusLarge}> <Button variant="primary" icon={IconPlusLarge}>
{__("New snapshot")} {__("New snapshot")}
@@ -142,7 +140,6 @@ type SnapshotRowProps = {
function SnapshotRow(props: SnapshotRowProps) { function SnapshotRow(props: SnapshotRowProps) {
const { __ } = useTranslate(); const { __ } = useTranslate();
const deleteSnapshot = useDeleteSnapshot(props.snapshot, props.connectionId); const deleteSnapshot = useDeleteSnapshot(props.snapshot, props.connectionId);
const { isAuthorized } = use(PermissionsContext);
const typePath = getSnapshotTypeUrlPath(props.snapshot.type); const typePath = getSnapshotTypeUrlPath(props.snapshot.type);
return ( return (
@@ -164,7 +161,7 @@ function SnapshotRow(props: SnapshotRowProps) {
{props.hasAnyAction && ( {props.hasAnyAction && (
<Td noLink width={50} className="text-end"> <Td noLink width={50} className="text-end">
<ActionDropdown> <ActionDropdown>
{isAuthorized("Snapshot", "deleteSnapshot") && ( {props.snapshot.canDelete && (
<DropdownItem <DropdownItem
onClick={deleteSnapshot} onClick={deleteSnapshot}
variant="danger" variant="danger"

View File

@@ -34,6 +34,7 @@ const snapshotCreateMutation = graphql`
description description
type type
createdAt createdAt
canDelete: permission(action: "core:snapshot:delete")
} }
} }
} }
@@ -60,14 +61,19 @@ export default function SnapshotFormDialog(props: Props) {
errorMessage: __("Failed to create snapshot"), errorMessage: __("Failed to create snapshot"),
}); });
const { handleSubmit, register, reset, control, formState: { errors } } = const {
useFormWithSchema(snapshotSchema, { handleSubmit,
defaultValues: { register,
name: "", reset,
description: "", control,
type: "DATA", formState: { errors },
}, } = useFormWithSchema(snapshotSchema, {
}); defaultValues: {
name: "",
description: "",
type: "DATA",
},
});
const onSubmit = handleSubmit(async (data) => { const onSubmit = handleSubmit(async (data) => {
await mutate({ await mutate({
@@ -89,14 +95,7 @@ export default function SnapshotFormDialog(props: Props) {
<Dialog <Dialog
ref={dialogRef} ref={dialogRef}
trigger={props.children} trigger={props.children}
title={ title={<Breadcrumb items={[__("Snapshots"), __("New Snapshot")]} />}
<Breadcrumb
items={[
__("Snapshots"),
__("New Snapshot"),
]}
/>
}
> >
<form onSubmit={onSubmit}> <form onSubmit={onSubmit}>
<DialogContent className="grid grid-cols-[1fr_420px]"> <DialogContent className="grid grid-cols-[1fr_420px]">
@@ -125,20 +124,14 @@ export default function SnapshotFormDialog(props: Props) {
label={__("Type")} label={__("Type")}
error={errors.type?.message} error={errors.type?.message}
> >
<ControlledField <ControlledField control={control} name="type" type="select">
control={control}
name="type"
type="select"
>
<SnapshotTypeOptions /> <SnapshotTypeOptions />
</ControlledField> </ControlledField>
</PropertyRow> </PropertyRow>
</div> </div>
</DialogContent> </DialogContent>
<DialogFooter> <DialogFooter>
<Button type="submit"> <Button type="submit">{__("Create snapshot")}</Button>
{__("Create snapshot")}
</Button>
</DialogFooter> </DialogFooter>
</form> </form>
</Dialog> </Dialog>