diff --git a/apps/console/src/__generated__/core/AuditGraphCreateMutation.graphql.ts b/apps/console/src/__generated__/core/AuditGraphCreateMutation.graphql.ts index 97ce18bb5..c5810bf74 100644 --- a/apps/console/src/__generated__/core/AuditGraphCreateMutation.graphql.ts +++ b/apps/console/src/__generated__/core/AuditGraphCreateMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<5cef509d4e44e0e0064c79fc7c3bf2e3>> * @lightSyntaxTransform * @nogrep */ @@ -28,6 +28,8 @@ export type AuditGraphCreateMutation$data = { readonly createAudit: { readonly auditEdge: { readonly node: { + readonly canDelete: boolean; + readonly canUpdate: boolean; readonly createdAt: any; readonly framework: { readonly id: string; @@ -160,6 +162,32 @@ v5 = { "kind": "ScalarField", "name": "createdAt", "storageKey": null + }, + { + "alias": "canUpdate", + "args": [ + { + "kind": "Literal", + "name": "action", + "value": "core:audit:update" + } + ], + "kind": "ScalarField", + "name": "permission", + "storageKey": "permission(action:\"core:audit:update\")" + }, + { + "alias": "canDelete", + "args": [ + { + "kind": "Literal", + "name": "action", + "value": "core:audit:delete" + } + ], + "kind": "ScalarField", + "name": "permission", + "storageKey": "permission(action:\"core:audit:delete\")" } ], "storageKey": null @@ -233,16 +261,16 @@ return { ] }, "params": { - "cacheID": "04d44dfd419c2cde11b0138ca175203f", + "cacheID": "d5155df01b8fe2fb74b49b953d49aed7", "id": null, "metadata": {}, "name": "AuditGraphCreateMutation", "operationKind": "mutation", - "text": "mutation AuditGraphCreateMutation(\n $input: CreateAuditInput!\n) {\n createAudit(input: $input) {\n auditEdge {\n node {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n }\n state\n framework {\n id\n name\n }\n createdAt\n }\n }\n }\n}\n" + "text": "mutation AuditGraphCreateMutation(\n $input: CreateAuditInput!\n) {\n createAudit(input: $input) {\n auditEdge {\n node {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n }\n state\n framework {\n id\n name\n }\n createdAt\n canUpdate: permission(action: \"core:audit:update\")\n canDelete: permission(action: \"core:audit:delete\")\n }\n }\n }\n}\n" } }; })(); -(node as any).hash = "4d014b16e02353df354085a151ccfe06"; +(node as any).hash = "dcca4ebf33522ad6ef45456612fad03f"; export default node; diff --git a/apps/console/src/__generated__/core/AuditGraphListQuery.graphql.ts b/apps/console/src/__generated__/core/AuditGraphListQuery.graphql.ts index 8c6d530b8..0be7a07d0 100644 --- a/apps/console/src/__generated__/core/AuditGraphListQuery.graphql.ts +++ b/apps/console/src/__generated__/core/AuditGraphListQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<145565eb150c67f2f1b3c70fe6f6e748>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -15,6 +15,7 @@ export type AuditGraphListQuery$variables = { }; export type AuditGraphListQuery$data = { readonly node: { + readonly canCreateAudit?: boolean; readonly " $fragmentSpreads": FragmentRefs<"AuditsPageFragment">; }; }; @@ -39,27 +40,40 @@ v1 = [ } ], v2 = { + "alias": "canCreateAudit", + "args": [ + { + "kind": "Literal", + "name": "action", + "value": "core:audit:create" + } + ], + "kind": "ScalarField", + "name": "permission", + "storageKey": "permission(action:\"core:audit:create\")" +}, +v3 = { "alias": null, "args": null, "kind": "ScalarField", "name": "__typename", "storageKey": null }, -v3 = { +v4 = { "alias": null, "args": null, "kind": "ScalarField", "name": "id", "storageKey": null }, -v4 = [ +v5 = [ { "kind": "Literal", "name": "first", "value": 10 } ], -v5 = { +v6 = { "alias": null, "args": null, "kind": "ScalarField", @@ -84,6 +98,7 @@ return { { "kind": "InlineFragment", "selections": [ + (v2/*: any*/), { "args": null, "kind": "FragmentSpread", @@ -114,14 +129,15 @@ return { "name": "node", "plural": false, "selections": [ - (v2/*: any*/), (v3/*: any*/), + (v4/*: any*/), { "kind": "InlineFragment", "selections": [ + (v2/*: any*/), { "alias": null, - "args": (v4/*: any*/), + "args": (v5/*: any*/), "concreteType": "AuditConnection", "kind": "LinkedField", "name": "audits", @@ -143,8 +159,8 @@ return { "name": "node", "plural": false, "selections": [ - (v3/*: any*/), - (v5/*: any*/), + (v4/*: any*/), + (v6/*: any*/), { "alias": null, "args": null, @@ -167,7 +183,7 @@ return { "name": "report", "plural": false, "selections": [ - (v3/*: any*/), + (v4/*: any*/), { "alias": null, "args": null, @@ -193,8 +209,8 @@ return { "name": "framework", "plural": false, "selections": [ - (v3/*: any*/), - (v5/*: any*/) + (v4/*: any*/), + (v6/*: any*/) ], "storageKey": null }, @@ -205,7 +221,33 @@ return { "name": "createdAt", "storageKey": null }, - (v2/*: any*/) + { + "alias": "canUpdate", + "args": [ + { + "kind": "Literal", + "name": "action", + "value": "core:audit:update" + } + ], + "kind": "ScalarField", + "name": "permission", + "storageKey": "permission(action:\"core:audit:update\")" + }, + { + "alias": "canDelete", + "args": [ + { + "kind": "Literal", + "name": "action", + "value": "core:audit:delete" + } + ], + "kind": "ScalarField", + "name": "permission", + "storageKey": "permission(action:\"core:audit:delete\")" + }, + (v3/*: any*/) ], "storageKey": null }, @@ -275,7 +317,7 @@ return { }, { "alias": null, - "args": (v4/*: any*/), + "args": (v5/*: any*/), "filters": [ "orderBy" ], @@ -294,16 +336,16 @@ return { ] }, "params": { - "cacheID": "d96d2332efb5f43e2dcb09669173ad7e", + "cacheID": "441524ada7aa614fb611f3d64812314f", "id": null, "metadata": {}, "name": "AuditGraphListQuery", "operationKind": "query", - "text": "query AuditGraphListQuery(\n $organizationId: ID!\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n ...AuditsPageFragment\n }\n id\n }\n}\n\nfragment AuditsPageFragment on Organization {\n audits(first: 10) {\n edges {\n node {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n }\n state\n framework {\n id\n name\n }\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n" + "text": "query AuditGraphListQuery(\n $organizationId: ID!\n) {\n node(id: $organizationId) {\n __typename\n ... on Organization {\n canCreateAudit: permission(action: \"core:audit:create\")\n ...AuditsPageFragment\n }\n id\n }\n}\n\nfragment AuditsPageFragment on Organization {\n audits(first: 10) {\n edges {\n node {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n }\n state\n framework {\n id\n name\n }\n createdAt\n canUpdate: permission(action: \"core:audit:update\")\n canDelete: permission(action: \"core:audit:delete\")\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n" } }; })(); -(node as any).hash = "3a082303ae15c8982a08c3bae8312846"; +(node as any).hash = "fc989e08b0d6411aac7ca6b1a0125edc"; export default node; diff --git a/apps/console/src/__generated__/core/AuditGraphNodeQuery.graphql.ts b/apps/console/src/__generated__/core/AuditGraphNodeQuery.graphql.ts index 196fd6a35..666933361 100644 --- a/apps/console/src/__generated__/core/AuditGraphNodeQuery.graphql.ts +++ b/apps/console/src/__generated__/core/AuditGraphNodeQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -15,6 +15,8 @@ export type AuditGraphNodeQuery$variables = { }; export type AuditGraphNodeQuery$data = { readonly node: { + readonly canDelete?: boolean; + readonly canUpdate?: boolean; readonly createdAt?: any; readonly framework?: { readonly darkLogoURL: string | null | undefined; @@ -199,6 +201,32 @@ v12 = { "kind": "ScalarField", "name": "updatedAt", "storageKey": null +}, +v13 = { + "alias": "canUpdate", + "args": [ + { + "kind": "Literal", + "name": "action", + "value": "core:audit:update" + } + ], + "kind": "ScalarField", + "name": "permission", + "storageKey": "permission(action:\"core:audit:update\")" +}, +v14 = { + "alias": "canDelete", + "args": [ + { + "kind": "Literal", + "name": "action", + "value": "core:audit:delete" + } + ], + "kind": "ScalarField", + "name": "permission", + "storageKey": "permission(action:\"core:audit:delete\")" }; return { "fragment": { @@ -228,7 +256,9 @@ return { (v10/*: any*/), (v11/*: any*/), (v6/*: any*/), - (v12/*: any*/) + (v12/*: any*/), + (v13/*: any*/), + (v14/*: any*/) ], "type": "Audit", "abstractKey": null @@ -274,7 +304,9 @@ return { (v10/*: any*/), (v11/*: any*/), (v6/*: any*/), - (v12/*: any*/) + (v12/*: any*/), + (v13/*: any*/), + (v14/*: any*/) ], "type": "Audit", "abstractKey": null @@ -285,16 +317,16 @@ return { ] }, "params": { - "cacheID": "af5fde4e1522c98b908630fdf1451ae9", + "cacheID": "c9d41c45b625f17ccf291ae2c027a027", "id": null, "metadata": {}, "name": "AuditGraphNodeQuery", "operationKind": "query", - "text": "query AuditGraphNodeQuery(\n $auditId: ID!\n) {\n node(id: $auditId) {\n __typename\n ... on Audit {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n mimeType\n size\n downloadUrl\n createdAt\n }\n reportUrl\n state\n framework {\n id\n name\n lightLogoURL\n darkLogoURL\n }\n organization {\n id\n name\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n" + "text": "query AuditGraphNodeQuery(\n $auditId: ID!\n) {\n node(id: $auditId) {\n __typename\n ... on Audit {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n mimeType\n size\n downloadUrl\n createdAt\n }\n reportUrl\n state\n framework {\n id\n name\n lightLogoURL\n darkLogoURL\n }\n organization {\n id\n name\n }\n createdAt\n updatedAt\n canUpdate: permission(action: \"core:audit:update\")\n canDelete: permission(action: \"core:audit:delete\")\n }\n id\n }\n}\n" } }; })(); -(node as any).hash = "db92119c6d6f000963a0ff3d0fb74dfd"; +(node as any).hash = "3195b5564b2cf8a21536ebf89f0f5c82"; export default node; diff --git a/apps/console/src/__generated__/core/AuditsListQuery.graphql.ts b/apps/console/src/__generated__/core/AuditsListQuery.graphql.ts index dbb587bcd..3a7b0517c 100644 --- a/apps/console/src/__generated__/core/AuditsListQuery.graphql.ts +++ b/apps/console/src/__generated__/core/AuditsListQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<0010416e8a5bda346d415bd80fd70dc8>> + * @generated SignedSource<<36758d66ccb0304442a2a59898fe95a0>> * @lightSyntaxTransform * @nogrep */ @@ -266,6 +266,32 @@ return { "name": "createdAt", "storageKey": null }, + { + "alias": "canUpdate", + "args": [ + { + "kind": "Literal", + "name": "action", + "value": "core:audit:update" + } + ], + "kind": "ScalarField", + "name": "permission", + "storageKey": "permission(action:\"core:audit:update\")" + }, + { + "alias": "canDelete", + "args": [ + { + "kind": "Literal", + "name": "action", + "value": "core:audit:delete" + } + ], + "kind": "ScalarField", + "name": "permission", + "storageKey": "permission(action:\"core:audit:delete\")" + }, (v8/*: any*/) ], "storageKey": null @@ -355,16 +381,16 @@ return { ] }, "params": { - "cacheID": "9d185e504f8c34d5c3fd7211d4e8a2a2", + "cacheID": "7804de168f5c2484d6beb2f4d19287b0", "id": null, "metadata": {}, "name": "AuditsListQuery", "operationKind": "query", - "text": "query AuditsListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 10\n $last: Int = null\n $orderBy: AuditOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...AuditsPageFragment_sdb03\n id\n }\n}\n\nfragment AuditsPageFragment_sdb03 on Organization {\n audits(first: $first, after: $after, last: $last, before: $before, orderBy: $orderBy) {\n edges {\n node {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n }\n state\n framework {\n id\n name\n }\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n" + "text": "query AuditsListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 10\n $last: Int = null\n $orderBy: AuditOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...AuditsPageFragment_sdb03\n id\n }\n}\n\nfragment AuditsPageFragment_sdb03 on Organization {\n audits(first: $first, after: $after, last: $last, before: $before, orderBy: $orderBy) {\n edges {\n node {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n }\n state\n framework {\n id\n name\n }\n createdAt\n canUpdate: permission(action: \"core:audit:update\")\n canDelete: permission(action: \"core:audit:delete\")\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n" } }; })(); -(node as any).hash = "be8d1f1d8015c16539886bc79c8026f7"; +(node as any).hash = "4013ec4e657ef7fb9d13afbd572ea9e5"; export default node; diff --git a/apps/console/src/__generated__/core/AuditsPageFragment.graphql.ts b/apps/console/src/__generated__/core/AuditsPageFragment.graphql.ts index 10b921035..17be72e77 100644 --- a/apps/console/src/__generated__/core/AuditsPageFragment.graphql.ts +++ b/apps/console/src/__generated__/core/AuditsPageFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<8c09163f7cf7b3953aed77791b0d3dd1>> + * @generated SignedSource<<075733c8694be657990e9fb8399c1ae6>> * @lightSyntaxTransform * @nogrep */ @@ -16,6 +16,8 @@ export type AuditsPageFragment$data = { readonly __id: string; readonly edges: ReadonlyArray<{ readonly node: { + readonly canDelete: boolean; + readonly canUpdate: boolean; readonly createdAt: any; readonly framework: { readonly id: string; @@ -215,6 +217,32 @@ return { "name": "createdAt", "storageKey": null }, + { + "alias": "canUpdate", + "args": [ + { + "kind": "Literal", + "name": "action", + "value": "core:audit:update" + } + ], + "kind": "ScalarField", + "name": "permission", + "storageKey": "permission(action:\"core:audit:update\")" + }, + { + "alias": "canDelete", + "args": [ + { + "kind": "Literal", + "name": "action", + "value": "core:audit:delete" + } + ], + "kind": "ScalarField", + "name": "permission", + "storageKey": "permission(action:\"core:audit:delete\")" + }, { "alias": null, "args": null, @@ -296,6 +324,6 @@ return { }; })(); -(node as any).hash = "be8d1f1d8015c16539886bc79c8026f7"; +(node as any).hash = "4013ec4e657ef7fb9d13afbd572ea9e5"; export default node; diff --git a/apps/console/src/hooks/graph/AuditGraph.ts b/apps/console/src/hooks/graph/AuditGraph.ts index 4696aa95f..4a6135ea6 100644 --- a/apps/console/src/hooks/graph/AuditGraph.ts +++ b/apps/console/src/hooks/graph/AuditGraph.ts @@ -9,6 +9,7 @@ export const auditsQuery = graphql` query AuditGraphListQuery($organizationId: ID!) { node(id: $organizationId) { ... on Organization { + canCreateAudit: permission(action: "core:audit:create") ...AuditsPageFragment } } @@ -45,6 +46,8 @@ export const auditNodeQuery = graphql` } createdAt updatedAt + canUpdate: permission(action: "core:audit:update") + canDelete: permission(action: "core:audit:delete") } } } @@ -72,6 +75,8 @@ export const createAuditMutation = graphql` name } createdAt + canUpdate: permission(action: "core:audit:update") + canDelete: permission(action: "core:audit:delete") } } } @@ -115,7 +120,7 @@ export const deleteAuditMutation = graphql` export const useDeleteAudit = ( audit: { id: string; framework: { name: string } }, connectionId: string, - onSuccess?: () => void + onSuccess?: () => void, ) => { const { __ } = useTranslate(); const [mutate] = useMutationWithToasts(deleteAuditMutation, { @@ -140,11 +145,11 @@ export const useDeleteAudit = ( { message: sprintf( __( - "This will permanently delete the audit for %s. This action cannot be undone." + "This will permanently delete the audit for %s. This action cannot be undone.", ), - audit.framework.name + audit.framework.name, ), - } + }, ); }; }; diff --git a/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx b/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx index 3eea78c59..5901de0fe 100644 --- a/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx +++ b/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx @@ -44,8 +44,6 @@ import { type GraphQLError, } from "@probo/helpers"; import type { AuditGraphNodeQuery } from "/__generated__/core/AuditGraphNodeQuery.graphql"; -import { use } from "react"; -import { PermissionsContext } from "/providers/PermissionsContext"; import { useNavigate } from "react-router"; const updateAuditSchema = z.object({ @@ -73,7 +71,6 @@ export default function AuditDetailsPage(props: Props) { const auditEntry = audit.node; const { __ } = useTranslate(); const organizationId = useOrganizationId(); - const { isAuthorized } = use(PermissionsContext); const navigate = useNavigate(); const deleteAudit = useDeleteAudit( @@ -178,7 +175,7 @@ export default function AuditDetailsPage(props: Props) { - {isAuthorized("Audit", "deleteAudit") && ( + {auditEntry.canDelete && (
- {formState.isDirty && isAuthorized("Audit", "updateAudit") && ( + {formState.isDirty && auditEntry.canUpdate && ( diff --git a/apps/console/src/pages/organizations/audits/AuditsPage.tsx b/apps/console/src/pages/organizations/audits/AuditsPage.tsx index 13fb855b8..6e99172ea 100644 --- a/apps/console/src/pages/organizations/audits/AuditsPage.tsx +++ b/apps/console/src/pages/organizations/audits/AuditsPage.tsx @@ -35,8 +35,6 @@ import type { AuditsPageFragment$key, } from "/__generated__/core/AuditsPageFragment.graphql"; import { SortableTable } from "/components/SortableTable"; -import { PermissionsContext } from "/providers/PermissionsContext"; -import { use } from "react"; const paginatedAuditsFragment = graphql` fragment AuditsPageFragment on Organization @@ -72,6 +70,8 @@ const paginatedAuditsFragment = graphql` name } createdAt + canUpdate: permission(action: "core:audit:update") + canDelete: permission(action: "core:audit:delete") } } } @@ -87,7 +87,6 @@ type Props = { export default function AuditsPage(props: Props) { const { __ } = useTranslate(); const organizationId = useOrganizationId(); - const { isAuthorized } = use(PermissionsContext); const data = usePreloadedQuery(auditsQuery, props.queryRef); const pagination = usePaginationFragment( @@ -99,9 +98,9 @@ export default function AuditsPage(props: Props) { usePageTitle(__("Audits")); - const hasAnyAction = - isAuthorized("Audit", "updateAudit") || - isAuthorized("Audit", "deleteAudit"); + const hasAnyAction = audits.some( + (audit) => audit.canDelete || audit.canUpdate, + ); return (
@@ -111,7 +110,7 @@ export default function AuditsPage(props: Props) { "Manage your organization's compliance audits and their progress.", )} > - {isAuthorized("Organization", "createAudit") && ( + {data.node.canCreateAudit && ( @@ -184,7 +182,7 @@ function AuditRow({ {hasAnyAction && ( - {isAuthorized("Audit", "deleteAudit") && ( + {entry.canDelete && (