Fix SOA permissions handling + add scope conditions

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-01-21 13:30:41 +04:00
parent ff65303a1a
commit 7ce73bbcfa
12 changed files with 272 additions and 201 deletions

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<7f57391fcdf09c326854f1cc2e0008c2>>
* @generated SignedSource<<3db987ede3a3aa1dfa570e76a00ef224>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -15,6 +15,7 @@ export type FrameworkDetailPageFragment$data = {
readonly canCreateControl: boolean;
readonly canDelete: boolean;
readonly canExport: boolean;
readonly canGenerateSOA: boolean;
readonly canUpdate: boolean;
readonly controls: {
readonly __id: string;
@@ -140,6 +141,19 @@ return {
"name": "permission",
"storageKey": "permission(action:\"core:control:create\")"
},
{
"alias": "canGenerateSOA",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:framework:generate-state-of-applicability"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:framework:generate-state-of-applicability\")"
},
{
"alias": null,
"args": null,
@@ -247,6 +261,6 @@ return {
};
})();
(node as any).hash = "c88994d5f1872bfe21cfe65e1911b76a";
(node as any).hash = "a3eb8b9d80c69d7faa83eae88e3b986b";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<bbc7e1cc0c5c3f72d0297ff14a1dff77>>
* @generated SignedSource<<a493a708fe8353db1159647a455582ad>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -189,6 +189,19 @@ return {
"name": "permission",
"storageKey": "permission(action:\"core:control:create\")"
},
{
"alias": "canGenerateSOA",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:framework:generate-state-of-applicability"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:framework:generate-state-of-applicability\")"
},
{
"alias": null,
"args": null,
@@ -301,12 +314,12 @@ return {
]
},
"params": {
"cacheID": "2a82ae6447b93b0fa6b570571694052b",
"cacheID": "58485d98106169267addab7729095131",
"id": null,
"metadata": {},
"name": "FrameworkGraphNodeQuery",
"operationKind": "query",
"text": "query FrameworkGraphNodeQuery(\n $frameworkId: ID!\n) {\n node(id: $frameworkId) {\n __typename\n ... on Framework {\n id\n name\n ...FrameworkDetailPageFragment\n }\n id\n }\n}\n\nfragment FrameworkDetailPageFragment on Framework {\n id\n name\n description\n lightLogoURL\n darkLogoURL\n canExport: permission(action: \"core:franework:export\")\n canUpdate: permission(action: \"core:framework:update\")\n canDelete: permission(action: \"core:framework:delete\")\n canCreateControl: permission(action: \"core:control:create\")\n organization {\n name\n id\n }\n controls(first: 250, orderBy: {field: SECTION_TITLE, direction: ASC}) {\n edges {\n node {\n id\n sectionTitle\n name\n status\n exclusionJustification\n bestPractice\n }\n }\n }\n}\n"
"text": "query FrameworkGraphNodeQuery(\n $frameworkId: ID!\n) {\n node(id: $frameworkId) {\n __typename\n ... on Framework {\n id\n name\n ...FrameworkDetailPageFragment\n }\n id\n }\n}\n\nfragment FrameworkDetailPageFragment on Framework {\n id\n name\n description\n lightLogoURL\n darkLogoURL\n canExport: permission(action: \"core:franework:export\")\n canUpdate: permission(action: \"core:framework:update\")\n canDelete: permission(action: \"core:framework:delete\")\n canCreateControl: permission(action: \"core:control:create\")\n canGenerateSOA: permission(action: \"core:framework:generate-state-of-applicability\")\n organization {\n name\n id\n }\n controls(first: 250, orderBy: {field: SECTION_TITLE, direction: ASC}) {\n edges {\n node {\n id\n sectionTitle\n name\n status\n exclusionJustification\n bestPractice\n }\n }\n }\n}\n"
}
};
})();

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<f3564b51cac1482be5c6c4443a9030cf>>
* @generated SignedSource<<4c350f48aeb8f51c9716aed4eeadc735>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -16,6 +16,7 @@ export type StateOfApplicabilityGraphNodeQuery$variables = {
export type StateOfApplicabilityGraphNodeQuery$data = {
readonly node: {
readonly canDelete?: boolean;
readonly canExport?: boolean;
readonly canUpdate?: boolean;
readonly createdAt?: string;
readonly id?: string;
@@ -122,6 +123,19 @@ v9 = {
"storageKey": "permission(action:\"core:state-of-applicability:delete\")"
},
v10 = {
"alias": "canExport",
"args": [
{
"kind": "Literal",
"name": "action",
"value": "core:state-of-applicability:export"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:state-of-applicability:export\")"
},
v11 = {
"alias": null,
"args": null,
"concreteType": "Organization",
@@ -133,7 +147,7 @@ v10 = {
],
"storageKey": null
},
v11 = {
v12 = {
"alias": null,
"args": null,
"concreteType": "People",
@@ -180,6 +194,7 @@ return {
(v9/*: any*/),
(v10/*: any*/),
(v11/*: any*/),
(v12/*: any*/),
{
"args": null,
"kind": "FragmentSpread",
@@ -230,6 +245,7 @@ return {
(v9/*: any*/),
(v10/*: any*/),
(v11/*: any*/),
(v12/*: any*/),
{
"alias": "controlsInfo",
"args": [
@@ -386,16 +402,16 @@ return {
]
},
"params": {
"cacheID": "6189c0ca41e3327629d744a658cbe6f1",
"cacheID": "529e47a135ba24716b749998d1181d9a",
"id": null,
"metadata": {},
"name": "StateOfApplicabilityGraphNodeQuery",
"operationKind": "query",
"text": "query StateOfApplicabilityGraphNodeQuery(\n $stateOfApplicabilityId: ID!\n) {\n node(id: $stateOfApplicabilityId) {\n __typename\n ... on StateOfApplicability {\n id\n name\n sourceId\n snapshotId\n createdAt\n updatedAt\n canUpdate: permission(action: \"core:state-of-applicability:update\")\n canDelete: permission(action: \"core:state-of-applicability:delete\")\n organization {\n id\n }\n owner {\n id\n fullName\n }\n ...StateOfApplicabilityControlsTabFragment\n }\n id\n }\n}\n\nfragment StateOfApplicabilityControlsTabFragment on StateOfApplicability {\n id\n controlsInfo: controls(first: 0) {\n totalCount\n }\n canCreateStateOfApplicabilityControlMapping: permission(action: \"core:state-of-applicability-control-mapping:create\")\n canDeleteStateOfApplicabilityControlMapping: permission(action: \"core:state-of-applicability-control-mapping:delete\")\n availableControls {\n controlId\n sectionTitle\n name\n frameworkId\n frameworkName\n organizationId\n stateOfApplicabilityId\n applicability\n justification\n bestPractice\n regulatory\n contractual\n riskAssessment\n }\n}\n"
"text": "query StateOfApplicabilityGraphNodeQuery(\n $stateOfApplicabilityId: ID!\n) {\n node(id: $stateOfApplicabilityId) {\n __typename\n ... on StateOfApplicability {\n id\n name\n sourceId\n snapshotId\n createdAt\n updatedAt\n canUpdate: permission(action: \"core:state-of-applicability:update\")\n canDelete: permission(action: \"core:state-of-applicability:delete\")\n canExport: permission(action: \"core:state-of-applicability:export\")\n organization {\n id\n }\n owner {\n id\n fullName\n }\n ...StateOfApplicabilityControlsTabFragment\n }\n id\n }\n}\n\nfragment StateOfApplicabilityControlsTabFragment on StateOfApplicability {\n id\n controlsInfo: controls(first: 0) {\n totalCount\n }\n canCreateStateOfApplicabilityControlMapping: permission(action: \"core:state-of-applicability-control-mapping:create\")\n canDeleteStateOfApplicabilityControlMapping: permission(action: \"core:state-of-applicability-control-mapping:delete\")\n availableControls {\n controlId\n sectionTitle\n name\n frameworkId\n frameworkName\n organizationId\n stateOfApplicabilityId\n applicability\n justification\n bestPractice\n regulatory\n contractual\n riskAssessment\n }\n}\n"
}
};
})();
(node as any).hash = "1a1f3480b9c66597d146c48ed1b00bd1";
(node as any).hash = "5ea300f4dd399cafd7985072c2013dbe";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<c1333ad749a9c6aaf8f6f671bc578c04>>
* @generated SignedSource<<63f008ba2b41fba49ba0c3145874aa72>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -76,12 +76,12 @@ const node: ReaderFragment = {
{
"kind": "Literal",
"name": "action",
"value": "core:measures:list"
"value": "core:measure:list"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:measures:list\")"
"storageKey": "permission(action:\"core:measure:list\")"
},
{
"alias": "canListRisks",
@@ -102,12 +102,12 @@ const node: ReaderFragment = {
{
"kind": "Literal",
"name": "action",
"value": "core:frameworks:list"
"value": "core:framework:list"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:frameworks:list\")"
"storageKey": "permission(action:\"core:framework:list\")"
},
{
"alias": "canListPeople",
@@ -309,6 +309,6 @@ const node: ReaderFragment = {
"abstractKey": null
};
(node as any).hash = "3a7071a1d9ed4ffc115f5bc22e283a50";
(node as any).hash = "6d640139997b2c7561699c1efb668650";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<d089cfdf5c585ba8fcb83456438efe62>>
* @generated SignedSource<<0f5d74875ad984071d92f1d0e3cfce12>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -352,12 +352,12 @@ return {
{
"kind": "Literal",
"name": "action",
"value": "core:measures:list"
"value": "core:measure:list"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:measures:list\")"
"storageKey": "permission(action:\"core:measure:list\")"
},
{
"alias": "canListRisks",
@@ -378,12 +378,12 @@ return {
{
"kind": "Literal",
"name": "action",
"value": "core:frameworks:list"
"value": "core:framework:list"
}
],
"kind": "ScalarField",
"name": "permission",
"storageKey": "permission(action:\"core:frameworks:list\")"
"storageKey": "permission(action:\"core:framework:list\")"
},
{
"alias": "canListPeople",
@@ -618,12 +618,12 @@ return {
]
},
"params": {
"cacheID": "d7e0b080876472d059c97bf57818c697",
"cacheID": "f380d0fe83b6d660c61c379af4d2eb7d",
"id": null,
"metadata": {},
"name": "ViewerMembershipLayoutQuery",
"operationKind": "query",
"text": "query ViewerMembershipLayoutQuery(\n $organizationId: ID!\n $hideSidebar: Boolean!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n ...MembershipsDropdown_organizationFragment\n ...ViewerMembershipDropdownFragment\n ...SidebarFragment @skip(if: $hideSidebar)\n viewerMembership {\n role\n profile {\n fullName\n id\n }\n id\n }\n }\n id\n }\n viewer {\n email\n ...MembershipsDropdown_viewerFragment\n pendingInvitations {\n totalCount\n }\n id\n }\n}\n\nfragment MembershipsDropdown_organizationFragment on Organization {\n name\n}\n\nfragment MembershipsDropdown_viewerFragment on Identity {\n pendingInvitations {\n totalCount\n }\n}\n\nfragment SidebarFragment on Organization {\n canListMeetings: permission(action: \"core:meeting:list\")\n canListTasks: permission(action: \"core:task:list\")\n canListMeasures: permission(action: \"core:measures:list\")\n canListRisks: permission(action: \"core:risk:list\")\n canListFrameworks: permission(action: \"core:frameworks:list\")\n canListPeople: permission(action: \"core:people:list\")\n canListVendors: permission(action: \"core:vendor:list\")\n canListDocuments: permission(action: \"core:document:list\")\n canListAssets: permission(action: \"core:asset:list\")\n canListData: permission(action: \"core:datum:list\")\n canListAudits: permission(action: \"core:audit:list\")\n canListNonconformities: permission(action: \"core:nonconformity:list\")\n canListObligations: permission(action: \"core:obligation:list\")\n canListContinualImprovements: permission(action: \"core:continual-improvement:list\")\n canListProcessingActivities: permission(action: \"core:processing-activity:list\")\n canListRightsRequests: permission(action: \"core:rights-request:list\")\n canListSnapshots: permission(action: \"core:snapshot:list\")\n canGetTrustCenter: permission(action: \"core:trust-center:get\")\n canUpdateOrganization: permission(action: \"iam:organization:update\")\n canListStatesOfApplicability: permission(action: \"core:state-of-applicability:list\")\n}\n\nfragment ViewerMembershipDropdownFragment on Organization {\n viewerMembership {\n identity {\n email\n canListAPIKeys: permission(action: \"iam:personal-api-key:list\")\n id\n }\n profile {\n fullName\n id\n }\n id\n }\n}\n"
"text": "query ViewerMembershipLayoutQuery(\n $organizationId: ID!\n $hideSidebar: Boolean!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n ...MembershipsDropdown_organizationFragment\n ...ViewerMembershipDropdownFragment\n ...SidebarFragment @skip(if: $hideSidebar)\n viewerMembership {\n role\n profile {\n fullName\n id\n }\n id\n }\n }\n id\n }\n viewer {\n email\n ...MembershipsDropdown_viewerFragment\n pendingInvitations {\n totalCount\n }\n id\n }\n}\n\nfragment MembershipsDropdown_organizationFragment on Organization {\n name\n}\n\nfragment MembershipsDropdown_viewerFragment on Identity {\n pendingInvitations {\n totalCount\n }\n}\n\nfragment SidebarFragment on Organization {\n canListMeetings: permission(action: \"core:meeting:list\")\n canListTasks: permission(action: \"core:task:list\")\n canListMeasures: permission(action: \"core:measure:list\")\n canListRisks: permission(action: \"core:risk:list\")\n canListFrameworks: permission(action: \"core:framework:list\")\n canListPeople: permission(action: \"core:people:list\")\n canListVendors: permission(action: \"core:vendor:list\")\n canListDocuments: permission(action: \"core:document:list\")\n canListAssets: permission(action: \"core:asset:list\")\n canListData: permission(action: \"core:datum:list\")\n canListAudits: permission(action: \"core:audit:list\")\n canListNonconformities: permission(action: \"core:nonconformity:list\")\n canListObligations: permission(action: \"core:obligation:list\")\n canListContinualImprovements: permission(action: \"core:continual-improvement:list\")\n canListProcessingActivities: permission(action: \"core:processing-activity:list\")\n canListRightsRequests: permission(action: \"core:rights-request:list\")\n canListSnapshots: permission(action: \"core:snapshot:list\")\n canGetTrustCenter: permission(action: \"core:trust-center:get\")\n canUpdateOrganization: permission(action: \"iam:organization:update\")\n canListStatesOfApplicability: permission(action: \"core:state-of-applicability:list\")\n}\n\nfragment ViewerMembershipDropdownFragment on Organization {\n viewerMembership {\n identity {\n email\n canListAPIKeys: permission(action: \"iam:personal-api-key:list\")\n id\n }\n profile {\n fullName\n id\n }\n id\n }\n}\n"
}
};
})();