diff --git a/CHANGELOG.md b/CHANGELOG.md index ab993002e..7f949f091 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- New risk treatment strategy options: Mitigate, Accept, Avoid, Transfer + ## [0.7.0] - 2025-04-12 ### Added diff --git a/apps/console/src/pages/organizations/Routes.tsx b/apps/console/src/pages/organizations/Routes.tsx index aae0977b3..a0741ca67 100644 --- a/apps/console/src/pages/organizations/Routes.tsx +++ b/apps/console/src/pages/organizations/Routes.tsx @@ -24,7 +24,7 @@ import { PolicyListPage } from "./policies/PolicyListPage"; import { PolicyPage } from "./policies/PolicyPage"; import { EditRiskPage } from "./risks/EditRiskPage"; import { NewRiskPage } from "./risks/NewRiskPage"; -import { RiskListPage } from "./risks/RiskListPage"; +import { ListRiskPage } from "./risks/ListRiskPage"; import ShowRiskView from "./risks/ShowRiskView"; import { VendorListPage } from "./vendors/VendorListPage"; import { VendorPage } from "./vendors/VendorPage"; @@ -60,7 +60,7 @@ export function OrganizationsRoutes() { } /> } /> } /> - } /> + } /> } /> } /> } /> diff --git a/apps/console/src/pages/organizations/risks/EditRiskView.tsx b/apps/console/src/pages/organizations/risks/EditRiskView.tsx index 5cb58f77f..00981bea9 100644 --- a/apps/console/src/pages/organizations/risks/EditRiskView.tsx +++ b/apps/console/src/pages/organizations/risks/EditRiskView.tsx @@ -34,6 +34,7 @@ import { Suspense } from "react"; import { EditRiskViewSkeleton } from "./EditRiskPage"; import type { EditRiskViewQuery } from "./__generated__/EditRiskViewQuery.graphql"; import type { EditRiskViewUpdateRiskMutation } from "./__generated__/EditRiskViewUpdateRiskMutation.graphql"; +import type { RiskTreatment } from "./__generated__/EditRiskViewUpdateRiskMutation.graphql"; // Query to get risk details const editRiskViewQuery = graphql` @@ -47,6 +48,7 @@ const editRiskViewQuery = graphql` inherentImpact residualLikelihood residualImpact + treatment } } } @@ -64,6 +66,7 @@ const updateRiskMutation = graphql` inherentImpact residualLikelihood residualImpact + treatment updatedAt } } @@ -94,6 +97,7 @@ function EditRiskViewContent({ const [residualLikelihood, setResidualLikelihood] = useState("MEDIUM"); const [residualImpact, setResidualImpact] = useState("MEDIUM"); + const [treatment, setTreatment] = useState("MITIGATED"); const [isSubmitting, setIsSubmitting] = useState(false); const [updateRisk, isInFlight] = @@ -161,6 +165,7 @@ function EditRiskViewContent({ setInherentImpact(floatToImpact(risk.inherentImpact || 0.5)); setResidualLikelihood(floatToLikelihood(risk.residualLikelihood || 0.5)); setResidualImpact(floatToImpact(risk.residualImpact || 0.5)); + setTreatment(risk.treatment || "MITIGATED"); } }, [risk]); @@ -186,6 +191,7 @@ function EditRiskViewContent({ inherentImpact: impactToFloat(inherentImpact), residualLikelihood: likelihoodToFloat(residualLikelihood), residualImpact: impactToFloat(residualImpact), + treatment, }; updateRisk({ @@ -308,6 +314,29 @@ function EditRiskViewContent({ +
+ + +

+ Choose how you plan to address this risk +

+
+ + +

Residual Risk

@@ -357,6 +386,8 @@ function EditRiskViewContent({

+ +
+
+ + +

+ Choose how you plan to address this risk +

+
+
diff --git a/apps/console/src/pages/organizations/risks/__generated__/EditRiskViewQuery.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/EditRiskViewQuery.graphql.ts index 4eb993909..2c4491103 100644 --- a/apps/console/src/pages/organizations/risks/__generated__/EditRiskViewQuery.graphql.ts +++ b/apps/console/src/pages/organizations/risks/__generated__/EditRiskViewQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<5ae729150c7f534725306ecd1cf786af>> * @lightSyntaxTransform * @nogrep */ @@ -9,6 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; +export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED"; export type EditRiskViewQuery$variables = { riskId: string; }; @@ -21,6 +22,7 @@ export type EditRiskViewQuery$data = { readonly name?: string; readonly residualImpact?: number; readonly residualLikelihood?: number; + readonly treatment?: RiskTreatment; }; }; export type EditRiskViewQuery = { @@ -91,6 +93,13 @@ v8 = { "kind": "ScalarField", "name": "residualImpact", "storageKey": null +}, +v9 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "treatment", + "storageKey": null }; return { "fragment": { @@ -116,7 +125,8 @@ return { (v5/*: any*/), (v6/*: any*/), (v7/*: any*/), - (v8/*: any*/) + (v8/*: any*/), + (v9/*: any*/) ], "type": "Risk", "abstractKey": null @@ -158,7 +168,8 @@ return { (v5/*: any*/), (v6/*: any*/), (v7/*: any*/), - (v8/*: any*/) + (v8/*: any*/), + (v9/*: any*/) ], "type": "Risk", "abstractKey": null @@ -169,16 +180,16 @@ return { ] }, "params": { - "cacheID": "0cf5e4b47335aeb1fe04520d137942d1", + "cacheID": "cd7c9a0e53b9c1a2291e488756da9908", "id": null, "metadata": {}, "name": "EditRiskViewQuery", "operationKind": "query", - "text": "query EditRiskViewQuery(\n $riskId: ID!\n) {\n risk: node(id: $riskId) {\n __typename\n ... on Risk {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n }\n id\n }\n}\n" + "text": "query EditRiskViewQuery(\n $riskId: ID!\n) {\n risk: node(id: $riskId) {\n __typename\n ... on Risk {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n treatment\n }\n id\n }\n}\n" } }; })(); -(node as any).hash = "d057f56759426d63136cef80269dc8a3"; +(node as any).hash = "cce4cb6856fe45d8ab37fe690ac8c720"; export default node; diff --git a/apps/console/src/pages/organizations/risks/__generated__/EditRiskViewUpdateRiskMutation.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/EditRiskViewUpdateRiskMutation.graphql.ts index 7fb27298e..3246c7acf 100644 --- a/apps/console/src/pages/organizations/risks/__generated__/EditRiskViewUpdateRiskMutation.graphql.ts +++ b/apps/console/src/pages/organizations/risks/__generated__/EditRiskViewUpdateRiskMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<92886e4193283cb894a864edc361a575>> * @lightSyntaxTransform * @nogrep */ @@ -9,6 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; +export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED"; export type UpdateRiskInput = { description?: string | null | undefined; id: string; @@ -17,6 +18,7 @@ export type UpdateRiskInput = { name?: string | null | undefined; residualImpact?: number | null | undefined; residualLikelihood?: number | null | undefined; + treatment?: RiskTreatment | null | undefined; }; export type EditRiskViewUpdateRiskMutation$variables = { input: UpdateRiskInput; @@ -31,6 +33,7 @@ export type EditRiskViewUpdateRiskMutation$data = { readonly name: string; readonly residualImpact: number; readonly residualLikelihood: number; + readonly treatment: RiskTreatment; readonly updatedAt: string; }; }; @@ -120,6 +123,13 @@ v1 = [ "name": "residualImpact", "storageKey": null }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "treatment", + "storageKey": null + }, { "alias": null, "args": null, @@ -152,16 +162,16 @@ return { "selections": (v1/*: any*/) }, "params": { - "cacheID": "1fb9a7f1a9a6dc2fd8b1c3235336324b", + "cacheID": "e1bdac5dea224d79834ac952692a9bda", "id": null, "metadata": {}, "name": "EditRiskViewUpdateRiskMutation", "operationKind": "mutation", - "text": "mutation EditRiskViewUpdateRiskMutation(\n $input: UpdateRiskInput!\n) {\n updateRisk(input: $input) {\n risk {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n updatedAt\n }\n }\n}\n" + "text": "mutation EditRiskViewUpdateRiskMutation(\n $input: UpdateRiskInput!\n) {\n updateRisk(input: $input) {\n risk {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n treatment\n updatedAt\n }\n }\n}\n" } }; })(); -(node as any).hash = "75f21269b0c81f77ce4e3547010059ee"; +(node as any).hash = "6394ecc50b1e1f039b11ecdcf2724571"; export default node; diff --git a/apps/console/src/pages/organizations/risks/__generated__/RiskListViewDeleteMutation.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/ListRiskViewDeleteMutation.graphql.ts similarity index 79% rename from apps/console/src/pages/organizations/risks/__generated__/RiskListViewDeleteMutation.graphql.ts rename to apps/console/src/pages/organizations/risks/__generated__/ListRiskViewDeleteMutation.graphql.ts index 9a33faea6..884857cc7 100644 --- a/apps/console/src/pages/organizations/risks/__generated__/RiskListViewDeleteMutation.graphql.ts +++ b/apps/console/src/pages/organizations/risks/__generated__/ListRiskViewDeleteMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<349d62a3a4ed3ea1d83c12f0c61437dd>> + * @generated SignedSource<<4d228ebd230765e4ef84981f18bcd705>> * @lightSyntaxTransform * @nogrep */ @@ -12,18 +12,18 @@ import { ConcreteRequest } from 'relay-runtime'; export type DeleteRiskInput = { riskId: string; }; -export type RiskListViewDeleteMutation$variables = { +export type ListRiskViewDeleteMutation$variables = { connections: ReadonlyArray; input: DeleteRiskInput; }; -export type RiskListViewDeleteMutation$data = { +export type ListRiskViewDeleteMutation$data = { readonly deleteRisk: { readonly deletedRiskId: string; }; }; -export type RiskListViewDeleteMutation = { - response: RiskListViewDeleteMutation$data; - variables: RiskListViewDeleteMutation$variables; +export type ListRiskViewDeleteMutation = { + response: ListRiskViewDeleteMutation$data; + variables: ListRiskViewDeleteMutation$variables; }; const node: ConcreteRequest = (function(){ @@ -59,7 +59,7 @@ return { ], "kind": "Fragment", "metadata": null, - "name": "RiskListViewDeleteMutation", + "name": "ListRiskViewDeleteMutation", "selections": [ { "alias": null, @@ -84,7 +84,7 @@ return { (v0/*: any*/) ], "kind": "Operation", - "name": "RiskListViewDeleteMutation", + "name": "ListRiskViewDeleteMutation", "selections": [ { "alias": null, @@ -117,16 +117,16 @@ return { ] }, "params": { - "cacheID": "525011737d0920883b3942d2603dc31f", + "cacheID": "d6c6ab49ae59bc29ee4b1a33c4a36181", "id": null, "metadata": {}, - "name": "RiskListViewDeleteMutation", + "name": "ListRiskViewDeleteMutation", "operationKind": "mutation", - "text": "mutation RiskListViewDeleteMutation(\n $input: DeleteRiskInput!\n) {\n deleteRisk(input: $input) {\n deletedRiskId\n }\n}\n" + "text": "mutation ListRiskViewDeleteMutation(\n $input: DeleteRiskInput!\n) {\n deleteRisk(input: $input) {\n deletedRiskId\n }\n}\n" } }; })(); -(node as any).hash = "4aee92e5abfd6733b44588bf01276560"; +(node as any).hash = "0c83d35fb68cb67f5980df027c0d1051"; export default node; diff --git a/apps/console/src/pages/organizations/risks/__generated__/RiskListViewPaginationQuery.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/ListRiskViewPaginationQuery.graphql.ts similarity index 86% rename from apps/console/src/pages/organizations/risks/__generated__/RiskListViewPaginationQuery.graphql.ts rename to apps/console/src/pages/organizations/risks/__generated__/ListRiskViewPaginationQuery.graphql.ts index f82a6a4b0..af56efbd0 100644 --- a/apps/console/src/pages/organizations/risks/__generated__/RiskListViewPaginationQuery.graphql.ts +++ b/apps/console/src/pages/organizations/risks/__generated__/ListRiskViewPaginationQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<121c9ad6ab399476692b98d1838f70d7>> * @lightSyntaxTransform * @nogrep */ @@ -10,21 +10,21 @@ import { ConcreteRequest } from 'relay-runtime'; import { FragmentRefs } from "relay-runtime"; -export type RiskListViewPaginationQuery$variables = { +export type ListRiskViewPaginationQuery$variables = { after?: string | null | undefined; before?: string | null | undefined; first?: number | null | undefined; id: string; last?: number | null | undefined; }; -export type RiskListViewPaginationQuery$data = { +export type ListRiskViewPaginationQuery$data = { readonly node: { - readonly " $fragmentSpreads": FragmentRefs<"RiskListView_risks">; + readonly " $fragmentSpreads": FragmentRefs<"ListRiskView_risks">; }; }; -export type RiskListViewPaginationQuery = { - response: RiskListViewPaginationQuery$data; - variables: RiskListViewPaginationQuery$variables; +export type ListRiskViewPaginationQuery = { + response: ListRiskViewPaginationQuery$data; + variables: ListRiskViewPaginationQuery$variables; }; const node: ConcreteRequest = (function(){ @@ -107,7 +107,7 @@ return { ], "kind": "Fragment", "metadata": null, - "name": "RiskListViewPaginationQuery", + "name": "ListRiskViewPaginationQuery", "selections": [ { "alias": null, @@ -120,7 +120,7 @@ return { { "args": (v6/*: any*/), "kind": "FragmentSpread", - "name": "RiskListView_risks" + "name": "ListRiskView_risks" } ], "storageKey": null @@ -139,7 +139,7 @@ return { (v3/*: any*/) ], "kind": "Operation", - "name": "RiskListViewPaginationQuery", + "name": "ListRiskViewPaginationQuery", "selections": [ { "alias": null, @@ -214,6 +214,13 @@ return { "name": "residualImpact", "storageKey": null }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "treatment", + "storageKey": null + }, { "alias": null, "args": null, @@ -308,7 +315,7 @@ return { "args": (v6/*: any*/), "filters": null, "handle": "connection", - "key": "RiskListView_risks", + "key": "ListRiskView_risks", "kind": "LinkedHandle", "name": "risks" } @@ -322,16 +329,16 @@ return { ] }, "params": { - "cacheID": "afcf1c15c2ed7722673da85d53acfef3", + "cacheID": "402fdc7c2f504ba8640e2ecd2f8f2cb8", "id": null, "metadata": {}, - "name": "RiskListViewPaginationQuery", + "name": "ListRiskViewPaginationQuery", "operationKind": "query", - "text": "query RiskListViewPaginationQuery(\n $after: CursorKey\n $before: CursorKey\n $first: Int\n $last: Int\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...RiskListView_risks_pbnwq\n id\n }\n}\n\nfragment RiskListView_risks_pbnwq on Organization {\n risks(first: $first, after: $after, last: $last, before: $before) {\n edges {\n node {\n id\n name\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n description\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n id\n}\n" + "text": "query ListRiskViewPaginationQuery(\n $after: CursorKey\n $before: CursorKey\n $first: Int\n $last: Int\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...ListRiskView_risks_pbnwq\n id\n }\n}\n\nfragment ListRiskView_risks_pbnwq on Organization {\n risks(first: $first, after: $after, last: $last, before: $before) {\n edges {\n node {\n id\n name\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n treatment\n description\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n id\n}\n" } }; })(); -(node as any).hash = "7da0a3d5e4fb09ce7f6b7ddf233702ab"; +(node as any).hash = "a5f7d6424459d2a3b471bb0a4f0a4169"; export default node; diff --git a/apps/console/src/pages/organizations/risks/__generated__/RiskListViewQuery.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/ListRiskViewQuery.graphql.ts similarity index 87% rename from apps/console/src/pages/organizations/risks/__generated__/RiskListViewQuery.graphql.ts rename to apps/console/src/pages/organizations/risks/__generated__/ListRiskViewQuery.graphql.ts index 22e36633f..25c78ebf4 100644 --- a/apps/console/src/pages/organizations/risks/__generated__/RiskListViewQuery.graphql.ts +++ b/apps/console/src/pages/organizations/risks/__generated__/ListRiskViewQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<5301e57ef0b2621712f4c8ca693afdeb>> + * @generated SignedSource<<677eff2bfb212e672f0d95b56adeebe7>> * @lightSyntaxTransform * @nogrep */ @@ -10,22 +10,22 @@ import { ConcreteRequest } from 'relay-runtime'; import { FragmentRefs } from "relay-runtime"; -export type RiskListViewQuery$variables = { +export type ListRiskViewQuery$variables = { after?: string | null | undefined; before?: string | null | undefined; first?: number | null | undefined; last?: number | null | undefined; organizationId: string; }; -export type RiskListViewQuery$data = { +export type ListRiskViewQuery$data = { readonly organization: { readonly id: string; - readonly " $fragmentSpreads": FragmentRefs<"RiskListView_risks">; + readonly " $fragmentSpreads": FragmentRefs<"ListRiskView_risks">; }; }; -export type RiskListViewQuery = { - response: RiskListViewQuery$data; - variables: RiskListViewQuery$variables; +export type ListRiskViewQuery = { + response: ListRiskViewQuery$data; + variables: ListRiskViewQuery$variables; }; const node: ConcreteRequest = (function(){ @@ -108,7 +108,7 @@ return { ], "kind": "Fragment", "metadata": null, - "name": "RiskListViewQuery", + "name": "ListRiskViewQuery", "selections": [ { "alias": "organization", @@ -122,7 +122,7 @@ return { { "args": (v7/*: any*/), "kind": "FragmentSpread", - "name": "RiskListView_risks" + "name": "ListRiskView_risks" } ], "storageKey": null @@ -141,7 +141,7 @@ return { (v1/*: any*/) ], "kind": "Operation", - "name": "RiskListViewQuery", + "name": "ListRiskViewQuery", "selections": [ { "alias": "organization", @@ -216,6 +216,13 @@ return { "name": "residualImpact", "storageKey": null }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "treatment", + "storageKey": null + }, { "alias": null, "args": null, @@ -310,7 +317,7 @@ return { "args": (v7/*: any*/), "filters": null, "handle": "connection", - "key": "RiskListView_risks", + "key": "ListRiskView_risks", "kind": "LinkedHandle", "name": "risks" } @@ -324,16 +331,16 @@ return { ] }, "params": { - "cacheID": "56ddd15a8a41c48c01bf0be667569473", + "cacheID": "fcdb0ca740c0a11d5e4961407baadffa", "id": null, "metadata": {}, - "name": "RiskListViewQuery", + "name": "ListRiskViewQuery", "operationKind": "query", - "text": "query RiskListViewQuery(\n $organizationId: ID!\n $first: Int\n $after: CursorKey\n $last: Int\n $before: CursorKey\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ...RiskListView_risks_pbnwq\n }\n}\n\nfragment RiskListView_risks_pbnwq on Organization {\n risks(first: $first, after: $after, last: $last, before: $before) {\n edges {\n node {\n id\n name\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n description\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n id\n}\n" + "text": "query ListRiskViewQuery(\n $organizationId: ID!\n $first: Int\n $after: CursorKey\n $last: Int\n $before: CursorKey\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ...ListRiskView_risks_pbnwq\n }\n}\n\nfragment ListRiskView_risks_pbnwq on Organization {\n risks(first: $first, after: $after, last: $last, before: $before) {\n edges {\n node {\n id\n name\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n treatment\n description\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n id\n}\n" } }; })(); -(node as any).hash = "0fff20fd656047e6df52818ccf0a0f3b"; +(node as any).hash = "8f1ba48e6663d5f1e473aa52b70c7a67"; export default node; diff --git a/apps/console/src/pages/organizations/risks/__generated__/RiskListView_risks.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/ListRiskView_risks.graphql.ts similarity index 88% rename from apps/console/src/pages/organizations/risks/__generated__/RiskListView_risks.graphql.ts rename to apps/console/src/pages/organizations/risks/__generated__/ListRiskView_risks.graphql.ts index 0fdf9a915..020650ae1 100644 --- a/apps/console/src/pages/organizations/risks/__generated__/RiskListView_risks.graphql.ts +++ b/apps/console/src/pages/organizations/risks/__generated__/ListRiskView_risks.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<9a0b8102088652729e5c161730fe26a9>> * @lightSyntaxTransform * @nogrep */ @@ -9,8 +9,9 @@ // @ts-nocheck import { ReaderFragment } from 'relay-runtime'; +export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED"; import { FragmentRefs } from "relay-runtime"; -export type RiskListView_risks$data = { +export type ListRiskView_risks$data = { readonly id: string; readonly risks: { readonly __id: string; @@ -24,6 +25,7 @@ export type RiskListView_risks$data = { readonly name: string; readonly residualImpact: number; readonly residualLikelihood: number; + readonly treatment: RiskTreatment; readonly updatedAt: string; }; }>; @@ -34,11 +36,11 @@ export type RiskListView_risks$data = { readonly startCursor: string | null | undefined; }; }; - readonly " $fragmentType": "RiskListView_risks"; + readonly " $fragmentType": "ListRiskView_risks"; }; -export type RiskListView_risks$key = { - readonly " $data"?: RiskListView_risks$data; - readonly " $fragmentSpreads": FragmentRefs<"RiskListView_risks">; +export type ListRiskView_risks$key = { + readonly " $data"?: ListRiskView_risks$data; + readonly " $fragmentSpreads": FragmentRefs<"ListRiskView_risks">; }; const node: ReaderFragment = (function(){ @@ -100,21 +102,21 @@ return { "fragmentPathInResult": [ "node" ], - "operation": require('./RiskListViewPaginationQuery.graphql'), + "operation": require('./ListRiskViewPaginationQuery.graphql'), "identifierInfo": { "identifierField": "id", "identifierQueryVariableName": "id" } } }, - "name": "RiskListView_risks", + "name": "ListRiskView_risks", "selections": [ { "alias": "risks", "args": null, "concreteType": "RiskConnection", "kind": "LinkedField", - "name": "__RiskListView_risks_connection", + "name": "__ListRiskView_risks_connection", "plural": false, "selections": [ { @@ -169,6 +171,13 @@ return { "name": "residualImpact", "storageKey": null }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "treatment", + "storageKey": null + }, { "alias": null, "args": null, @@ -271,6 +280,6 @@ return { }; })(); -(node as any).hash = "7da0a3d5e4fb09ce7f6b7ddf233702ab"; +(node as any).hash = "a5f7d6424459d2a3b471bb0a4f0a4169"; export default node; diff --git a/apps/console/src/pages/organizations/risks/__generated__/NewRiskViewCreateRiskMutation.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/NewRiskViewCreateRiskMutation.graphql.ts index b76e05a02..80feb9c43 100644 --- a/apps/console/src/pages/organizations/risks/__generated__/NewRiskViewCreateRiskMutation.graphql.ts +++ b/apps/console/src/pages/organizations/risks/__generated__/NewRiskViewCreateRiskMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<63841b5a52846eba02cc6d442cfd4133>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -9,6 +9,7 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; +export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED"; export type CreateRiskInput = { description: string; inherentImpact: number; @@ -17,6 +18,7 @@ export type CreateRiskInput = { organizationId: string; residualImpact?: number | null | undefined; residualLikelihood?: number | null | undefined; + treatment: RiskTreatment; }; export type NewRiskViewCreateRiskMutation$variables = { connections: ReadonlyArray; @@ -34,6 +36,7 @@ export type NewRiskViewCreateRiskMutation$data = { readonly name: string; readonly residualImpact: number; readonly residualLikelihood: number; + readonly treatment: RiskTreatment; readonly updatedAt: string; }; }; @@ -127,6 +130,13 @@ v3 = { "name": "residualImpact", "storageKey": null }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "treatment", + "storageKey": null + }, { "alias": null, "args": null, @@ -213,16 +223,16 @@ return { ] }, "params": { - "cacheID": "86d84d72c424807216edf39eb8f0c34f", + "cacheID": "9f296661d12f36362aeecd2a1fd4aa63", "id": null, "metadata": {}, "name": "NewRiskViewCreateRiskMutation", "operationKind": "mutation", - "text": "mutation NewRiskViewCreateRiskMutation(\n $input: CreateRiskInput!\n) {\n createRisk(input: $input) {\n riskEdge {\n node {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n createdAt\n updatedAt\n }\n }\n }\n}\n" + "text": "mutation NewRiskViewCreateRiskMutation(\n $input: CreateRiskInput!\n) {\n createRisk(input: $input) {\n riskEdge {\n node {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n treatment\n createdAt\n updatedAt\n }\n }\n }\n}\n" } }; })(); -(node as any).hash = "7ad6c27c192e419839b8105eb2ca9ae7"; +(node as any).hash = "7f70a20771d9f05f62e952a59c5484e3"; export default node; diff --git a/pkg/coredata/migrations/20250412T100700Z.sql b/pkg/coredata/migrations/20250412T100700Z.sql new file mode 100644 index 000000000..7a633aef2 --- /dev/null +++ b/pkg/coredata/migrations/20250412T100700Z.sql @@ -0,0 +1,4 @@ +CREATE TYPE risk_treatment AS ENUM ('MITIGATED', 'TRANSFERRED', 'AVOIDED', 'ACCEPTED'); + +ALTER TABLE risks ADD COLUMN treatment risk_treatment NOT NULL DEFAULT 'MITIGATED'; +ALTER TABLE risks ALTER COLUMN treatment DROP DEFAULT; \ No newline at end of file diff --git a/pkg/coredata/risk.go b/pkg/coredata/risk.go index 28a2b59b4..4d7fd0772 100644 --- a/pkg/coredata/risk.go +++ b/pkg/coredata/risk.go @@ -28,16 +28,17 @@ import ( type ( Risk struct { - ID gid.GID `db:"id"` - OrganizationID gid.GID `db:"organization_id"` - Name string `db:"name"` - Description string `db:"description"` - InherentLikelihood float64 `db:"inherent_likelihood"` - InherentImpact float64 `db:"inherent_impact"` - ResidualLikelihood float64 `db:"residual_likelihood"` - ResidualImpact float64 `db:"residual_impact"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt time.Time `db:"updated_at"` + ID gid.GID `db:"id"` + OrganizationID gid.GID `db:"organization_id"` + Name string `db:"name"` + Description string `db:"description"` + Treatment RiskTreatment `db:"treatment"` + InherentLikelihood float64 `db:"inherent_likelihood"` + InherentImpact float64 `db:"inherent_impact"` + ResidualLikelihood float64 `db:"residual_likelihood"` + ResidualImpact float64 `db:"residual_impact"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` } Risks []*Risk @@ -72,9 +73,9 @@ WITH rsks AS ( SELECT r.id, r.organization_id, - r.tenant_id, r.name, r.description, + r.treatment, r.inherent_likelihood, r.inherent_impact, r.residual_likelihood, @@ -93,6 +94,7 @@ SELECT organization_id, name, description, + treatment, inherent_likelihood, inherent_impact, residual_likelihood, @@ -137,6 +139,7 @@ SELECT organization_id, name, description, + treatment, inherent_likelihood, inherent_impact, residual_likelihood, @@ -180,6 +183,7 @@ SELECT organization_id, name, description, + treatment, inherent_likelihood, inherent_impact, residual_likelihood, @@ -217,8 +221,8 @@ func (r *Risk) Insert( scope Scoper, ) error { q := ` -INSERT INTO risks (id, tenant_id, organization_id, name, description, inherent_likelihood, inherent_impact, residual_likelihood, residual_impact, created_at, updated_at) -VALUES (@id, @tenant_id, @organization_id, @name, @description, @inherent_likelihood, @inherent_impact, @residual_likelihood, @residual_impact, @created_at, @updated_at) +INSERT INTO risks (id, tenant_id, organization_id, name, description, treatment, inherent_likelihood, inherent_impact, residual_likelihood, residual_impact, created_at, updated_at) +VALUES (@id, @tenant_id, @organization_id, @name, @description, @treatment, @inherent_likelihood, @inherent_impact, @residual_likelihood, @residual_impact, @created_at, @updated_at) ` args := pgx.StrictNamedArgs{ @@ -227,6 +231,7 @@ VALUES (@id, @tenant_id, @organization_id, @name, @description, @inherent_likeli "organization_id": r.OrganizationID, "name": r.Name, "description": r.Description, + "treatment": r.Treatment, "inherent_likelihood": r.InherentLikelihood, "inherent_impact": r.InherentImpact, "residual_likelihood": r.ResidualLikelihood, @@ -249,6 +254,7 @@ UPDATE risks SET name = @name, description = @description, + treatment = @treatment, inherent_likelihood = @inherent_likelihood, inherent_impact = @inherent_impact, residual_likelihood = @residual_likelihood, @@ -263,6 +269,7 @@ WHERE %s "risk_id": r.ID, "name": r.Name, "description": r.Description, + "treatment": r.Treatment, "inherent_likelihood": r.InherentLikelihood, "inherent_impact": r.InherentImpact, "residual_likelihood": r.ResidualLikelihood, diff --git a/pkg/coredata/risk_treatment.go b/pkg/coredata/risk_treatment.go new file mode 100644 index 000000000..d8bb13430 --- /dev/null +++ b/pkg/coredata/risk_treatment.go @@ -0,0 +1,84 @@ +// Copyright (c) 2025 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +package coredata + +import ( + "database/sql/driver" + "fmt" +) + +type ( + RiskTreatment string +) + +const ( + RiskTreatmentMitigated RiskTreatment = "MITIGATED" + RiskTreatmentAccepted RiskTreatment = "ACCEPTED" + RiskTreatmentAvoided RiskTreatment = "AVOIDED" + RiskTreatmentTransferred RiskTreatment = "TRANSFERRED" +) + +func (rt RiskTreatment) MarshalText() ([]byte, error) { + return []byte(rt.String()), nil +} + +func (rt *RiskTreatment) UnmarshalText(data []byte) error { + val := string(data) + + switch val { + case RiskTreatmentMitigated.String(): + *rt = RiskTreatmentMitigated + case RiskTreatmentAccepted.String(): + *rt = RiskTreatmentAccepted + case RiskTreatmentAvoided.String(): + *rt = RiskTreatmentAvoided + case RiskTreatmentTransferred.String(): + *rt = RiskTreatmentTransferred + default: + return fmt.Errorf("invalid RiskTreatment value: %q", val) + } + + return nil +} + +func (rt RiskTreatment) String() string { + var val string + + switch rt { + case RiskTreatmentMitigated: + val = "MITIGATED" + case RiskTreatmentAccepted: + val = "ACCEPTED" + case RiskTreatmentAvoided: + val = "AVOIDED" + case RiskTreatmentTransferred: + val = "TRANSFERRED" + } + + return val +} + +func (rt *RiskTreatment) Scan(value any) error { + val, ok := value.(string) + if !ok { + return fmt.Errorf("invalid scan source for RiskTreatment, expected string got %T", value) + } + + return rt.UnmarshalText([]byte(val)) +} + +func (rt RiskTreatment) Value() (driver.Value, error) { + return rt.String(), nil +} diff --git a/pkg/probo/risk_service.go b/pkg/probo/risk_service.go index d13427b82..71ff14c3e 100644 --- a/pkg/probo/risk_service.go +++ b/pkg/probo/risk_service.go @@ -34,6 +34,7 @@ type ( OrganizationID gid.GID Name string Description string + Treatment coredata.RiskTreatment InherentLikelihood float64 InherentImpact float64 ResidualLikelihood *float64 @@ -44,6 +45,7 @@ type ( ID gid.GID Name *string Description *string + Treatment *coredata.RiskTreatment InherentLikelihood *float64 InherentImpact *float64 ResidualLikelihood *float64 @@ -169,6 +171,7 @@ func (s RiskService) Create( Description: req.Description, InherentLikelihood: req.InherentLikelihood, InherentImpact: req.InherentImpact, + Treatment: req.Treatment, ResidualLikelihood: req.InherentLikelihood, ResidualImpact: req.InherentImpact, CreatedAt: now, @@ -254,6 +257,10 @@ func (s RiskService) Update( risk.ResidualImpact = *req.ResidualImpact } + if req.Treatment != nil { + risk.Treatment = *req.Treatment + } + risk.UpdatedAt = time.Now() if err := risk.Update(ctx, conn, s.svc.scope); err != nil { diff --git a/pkg/server/api/console/v1/schema.graphql b/pkg/server/api/console/v1/schema.graphql index 2d050da9c..b0fe2cc01 100644 --- a/pkg/server/api/console/v1/schema.graphql +++ b/pkg/server/api/console/v1/schema.graphql @@ -149,6 +149,26 @@ enum EvidenceType LINK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.EvidenceTypeLink") } +enum RiskTreatment + @goModel(model: "github.com/getprobo/probo/pkg/coredata.RiskTreatment") { + MITIGATED + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.RiskTreatmentMitigated" + ) + ACCEPTED + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.RiskTreatmentAccepted" + ) + AVOIDED + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.RiskTreatmentAvoided" + ) + TRANSFERRED + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.RiskTreatmentTransferred" + ) +} + # Order Field Enums enum UserOrderField @goModel(model: "github.com/getprobo/probo/pkg/coredata.UserOrderField") { @@ -608,6 +628,7 @@ type Risk implements Node { id: ID! name: String! description: String! + treatment: RiskTreatment! inherentLikelihood: Float! inherentImpact: Float! inherentSeverity: Float! @@ -1064,6 +1085,7 @@ input CreateRiskInput { organizationId: ID! name: String! description: String! + treatment: RiskTreatment! inherentLikelihood: Float! inherentImpact: Float! residualLikelihood: Float @@ -1074,6 +1096,7 @@ input UpdateRiskInput { id: ID! name: String description: String + treatment: RiskTreatment inherentLikelihood: Float inherentImpact: Float residualLikelihood: Float diff --git a/pkg/server/api/console/v1/schema/schema.go b/pkg/server/api/console/v1/schema/schema.go index 851742d73..05a9017fe 100644 --- a/pkg/server/api/console/v1/schema/schema.go +++ b/pkg/server/api/console/v1/schema/schema.go @@ -425,6 +425,7 @@ type ComplexityRoot struct { ResidualImpact func(childComplexity int) int ResidualLikelihood func(childComplexity int) int ResidualSeverity func(childComplexity int) int + Treatment func(childComplexity int) int UpdatedAt func(childComplexity int) int } @@ -2338,6 +2339,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Risk.ResidualSeverity(childComplexity), true + case "Risk.treatment": + if e.complexity.Risk.Treatment == nil { + break + } + + return e.complexity.Risk.Treatment(childComplexity), true + case "Risk.updatedAt": if e.complexity.Risk.UpdatedAt == nil { break @@ -3225,6 +3233,26 @@ enum EvidenceType LINK @goEnum(value: "github.com/getprobo/probo/pkg/coredata.EvidenceTypeLink") } +enum RiskTreatment + @goModel(model: "github.com/getprobo/probo/pkg/coredata.RiskTreatment") { + MITIGATED + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.RiskTreatmentMitigated" + ) + ACCEPTED + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.RiskTreatmentAccepted" + ) + AVOIDED + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.RiskTreatmentAvoided" + ) + TRANSFERRED + @goEnum( + value: "github.com/getprobo/probo/pkg/coredata.RiskTreatmentTransferred" + ) +} + # Order Field Enums enum UserOrderField @goModel(model: "github.com/getprobo/probo/pkg/coredata.UserOrderField") { @@ -3684,6 +3712,7 @@ type Risk implements Node { id: ID! name: String! description: String! + treatment: RiskTreatment! inherentLikelihood: Float! inherentImpact: Float! inherentSeverity: Float! @@ -4140,6 +4169,7 @@ input CreateRiskInput { organizationId: ID! name: String! description: String! + treatment: RiskTreatment! inherentLikelihood: Float! inherentImpact: Float! residualLikelihood: Float @@ -4150,6 +4180,7 @@ input UpdateRiskInput { id: ID! name: String description: String + treatment: RiskTreatment inherentLikelihood: Float inherentImpact: Float residualLikelihood: Float @@ -16772,6 +16803,50 @@ func (ec *executionContext) fieldContext_Risk_description(_ context.Context, fie return fc, nil } +func (ec *executionContext) _Risk_treatment(ctx context.Context, field graphql.CollectedField, obj *types.Risk) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Risk_treatment(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Treatment, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(coredata.RiskTreatment) + fc.Result = res + return ec.marshalNRiskTreatment2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Risk_treatment(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Risk", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type RiskTreatment does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _Risk_inherentLikelihood(ctx context.Context, field graphql.CollectedField, obj *types.Risk) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Risk_inherentLikelihood(ctx, field) if err != nil { @@ -17500,6 +17575,8 @@ func (ec *executionContext) fieldContext_RiskEdge_node(_ context.Context, field return ec.fieldContext_Risk_name(ctx, field) case "description": return ec.fieldContext_Risk_description(ctx, field) + case "treatment": + return ec.fieldContext_Risk_treatment(ctx, field) case "inherentLikelihood": return ec.fieldContext_Risk_inherentLikelihood(ctx, field) case "inherentImpact": @@ -18681,6 +18758,8 @@ func (ec *executionContext) fieldContext_UpdateRiskPayload_risk(_ context.Contex return ec.fieldContext_Risk_name(ctx, field) case "description": return ec.fieldContext_Risk_description(ctx, field) + case "treatment": + return ec.fieldContext_Risk_treatment(ctx, field) case "inherentLikelihood": return ec.fieldContext_Risk_inherentLikelihood(ctx, field) case "inherentImpact": @@ -23710,7 +23789,7 @@ func (ec *executionContext) unmarshalInputCreateRiskInput(ctx context.Context, o asMap[k] = v } - fieldsInOrder := [...]string{"organizationId", "name", "description", "inherentLikelihood", "inherentImpact", "residualLikelihood", "residualImpact"} + fieldsInOrder := [...]string{"organizationId", "name", "description", "treatment", "inherentLikelihood", "inherentImpact", "residualLikelihood", "residualImpact"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -23738,6 +23817,13 @@ func (ec *executionContext) unmarshalInputCreateRiskInput(ctx context.Context, o return it, err } it.Description = data + case "treatment": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("treatment")) + data, err := ec.unmarshalNRiskTreatment2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment(ctx, v) + if err != nil { + return it, err + } + it.Treatment = data case "inherentLikelihood": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("inherentLikelihood")) data, err := ec.unmarshalNFloat2float64(ctx, v) @@ -25233,7 +25319,7 @@ func (ec *executionContext) unmarshalInputUpdateRiskInput(ctx context.Context, o asMap[k] = v } - fieldsInOrder := [...]string{"id", "name", "description", "inherentLikelihood", "inherentImpact", "residualLikelihood", "residualImpact"} + fieldsInOrder := [...]string{"id", "name", "description", "treatment", "inherentLikelihood", "inherentImpact", "residualLikelihood", "residualImpact"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -25261,6 +25347,13 @@ func (ec *executionContext) unmarshalInputUpdateRiskInput(ctx context.Context, o return it, err } it.Description = data + case "treatment": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("treatment")) + data, err := ec.unmarshalORiskTreatment2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment(ctx, v) + if err != nil { + return it, err + } + it.Treatment = data case "inherentLikelihood": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("inherentLikelihood")) data, err := ec.unmarshalOFloat2ᚖfloat64(ctx, v) @@ -29294,6 +29387,11 @@ func (ec *executionContext) _Risk(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { atomic.AddUint32(&out.Invalids, 1) } + case "treatment": + out.Values[i] = ec._Risk_treatment(ctx, field, obj) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&out.Invalids, 1) + } case "inherentLikelihood": out.Values[i] = ec._Risk_inherentLikelihood(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -32999,6 +33097,37 @@ var ( } ) +func (ec *executionContext) unmarshalNRiskTreatment2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment(ctx context.Context, v any) (coredata.RiskTreatment, error) { + tmp, err := graphql.UnmarshalString(v) + res := unmarshalNRiskTreatment2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment[tmp] + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNRiskTreatment2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment(ctx context.Context, sel ast.SelectionSet, v coredata.RiskTreatment) graphql.Marshaler { + res := graphql.MarshalString(marshalNRiskTreatment2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment[v]) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +var ( + unmarshalNRiskTreatment2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment = map[string]coredata.RiskTreatment{ + "MITIGATED": coredata.RiskTreatmentMitigated, + "ACCEPTED": coredata.RiskTreatmentAccepted, + "AVOIDED": coredata.RiskTreatmentAvoided, + "TRANSFERRED": coredata.RiskTreatmentTransferred, + } + marshalNRiskTreatment2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment = map[coredata.RiskTreatment]string{ + coredata.RiskTreatmentMitigated: "MITIGATED", + coredata.RiskTreatmentAccepted: "ACCEPTED", + coredata.RiskTreatmentAvoided: "AVOIDED", + coredata.RiskTreatmentTransferred: "TRANSFERRED", + } +) + func (ec *executionContext) unmarshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality(ctx context.Context, v any) (coredata.ServiceCriticality, error) { tmp, err := graphql.UnmarshalString(v) res := unmarshalNServiceCriticality2githubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality[tmp] @@ -34317,6 +34446,38 @@ var ( } ) +func (ec *executionContext) unmarshalORiskTreatment2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment(ctx context.Context, v any) (*coredata.RiskTreatment, error) { + if v == nil { + return nil, nil + } + tmp, err := graphql.UnmarshalString(v) + res := unmarshalORiskTreatment2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment[tmp] + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalORiskTreatment2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment(ctx context.Context, sel ast.SelectionSet, v *coredata.RiskTreatment) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalString(marshalORiskTreatment2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment[*v]) + return res +} + +var ( + unmarshalORiskTreatment2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment = map[string]coredata.RiskTreatment{ + "MITIGATED": coredata.RiskTreatmentMitigated, + "ACCEPTED": coredata.RiskTreatmentAccepted, + "AVOIDED": coredata.RiskTreatmentAvoided, + "TRANSFERRED": coredata.RiskTreatmentTransferred, + } + marshalORiskTreatment2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐRiskTreatment = map[coredata.RiskTreatment]string{ + coredata.RiskTreatmentMitigated: "MITIGATED", + coredata.RiskTreatmentAccepted: "ACCEPTED", + coredata.RiskTreatmentAvoided: "AVOIDED", + coredata.RiskTreatmentTransferred: "TRANSFERRED", + } +) + func (ec *executionContext) unmarshalOServiceCriticality2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐServiceCriticality(ctx context.Context, v any) (*coredata.ServiceCriticality, error) { if v == nil { return nil, nil diff --git a/pkg/server/api/console/v1/types/risk.go b/pkg/server/api/console/v1/types/risk.go index da8de556f..6abd0aae7 100644 --- a/pkg/server/api/console/v1/types/risk.go +++ b/pkg/server/api/console/v1/types/risk.go @@ -48,6 +48,7 @@ func NewRisk(r *coredata.Risk) *Risk { ID: r.ID, Name: r.Name, Description: r.Description, + Treatment: r.Treatment, InherentLikelihood: r.InherentLikelihood, InherentImpact: r.InherentImpact, InherentSeverity: r.InherentSeverity(), diff --git a/pkg/server/api/console/v1/types/types.go b/pkg/server/api/console/v1/types/types.go index 5d5a5a8ed..874a32a06 100644 --- a/pkg/server/api/console/v1/types/types.go +++ b/pkg/server/api/console/v1/types/types.go @@ -147,13 +147,14 @@ type CreatePolicyPayload struct { } type CreateRiskInput struct { - OrganizationID gid.GID `json:"organizationId"` - Name string `json:"name"` - Description string `json:"description"` - InherentLikelihood float64 `json:"inherentLikelihood"` - InherentImpact float64 `json:"inherentImpact"` - ResidualLikelihood *float64 `json:"residualLikelihood,omitempty"` - ResidualImpact *float64 `json:"residualImpact,omitempty"` + OrganizationID gid.GID `json:"organizationId"` + Name string `json:"name"` + Description string `json:"description"` + Treatment coredata.RiskTreatment `json:"treatment"` + InherentLikelihood float64 `json:"inherentLikelihood"` + InherentImpact float64 `json:"inherentImpact"` + ResidualLikelihood *float64 `json:"residualLikelihood,omitempty"` + ResidualImpact *float64 `json:"residualImpact,omitempty"` } type CreateRiskMitigationMappingInput struct { @@ -554,20 +555,21 @@ type RequestEvidencePayload struct { } type Risk struct { - ID gid.GID `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - InherentLikelihood float64 `json:"inherentLikelihood"` - InherentImpact float64 `json:"inherentImpact"` - InherentSeverity float64 `json:"inherentSeverity"` - ResidualLikelihood float64 `json:"residualLikelihood"` - ResidualImpact float64 `json:"residualImpact"` - ResidualSeverity float64 `json:"residualSeverity"` - Mitigations *MitigationConnection `json:"mitigations"` - Policies *PolicyConnection `json:"policies"` - Controls *ControlConnection `json:"controls"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID gid.GID `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Treatment coredata.RiskTreatment `json:"treatment"` + InherentLikelihood float64 `json:"inherentLikelihood"` + InherentImpact float64 `json:"inherentImpact"` + InherentSeverity float64 `json:"inherentSeverity"` + ResidualLikelihood float64 `json:"residualLikelihood"` + ResidualImpact float64 `json:"residualImpact"` + ResidualSeverity float64 `json:"residualSeverity"` + Mitigations *MitigationConnection `json:"mitigations"` + Policies *PolicyConnection `json:"policies"` + Controls *ControlConnection `json:"controls"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } func (Risk) IsNode() {} @@ -680,13 +682,14 @@ type UpdatePolicyPayload struct { } type UpdateRiskInput struct { - ID gid.GID `json:"id"` - Name *string `json:"name,omitempty"` - Description *string `json:"description,omitempty"` - InherentLikelihood *float64 `json:"inherentLikelihood,omitempty"` - InherentImpact *float64 `json:"inherentImpact,omitempty"` - ResidualLikelihood *float64 `json:"residualLikelihood,omitempty"` - ResidualImpact *float64 `json:"residualImpact,omitempty"` + ID gid.GID `json:"id"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Treatment *coredata.RiskTreatment `json:"treatment,omitempty"` + InherentLikelihood *float64 `json:"inherentLikelihood,omitempty"` + InherentImpact *float64 `json:"inherentImpact,omitempty"` + ResidualLikelihood *float64 `json:"residualLikelihood,omitempty"` + ResidualImpact *float64 `json:"residualImpact,omitempty"` } type UpdateRiskPayload struct { diff --git a/pkg/server/api/console/v1/v1_resolver.go b/pkg/server/api/console/v1/v1_resolver.go index eef45621e..6b0b0e56e 100644 --- a/pkg/server/api/console/v1/v1_resolver.go +++ b/pkg/server/api/console/v1/v1_resolver.go @@ -726,6 +726,7 @@ func (r *mutationResolver) CreateRisk(ctx context.Context, input types.CreateRis OrganizationID: input.OrganizationID, Name: input.Name, Description: input.Description, + Treatment: input.Treatment, InherentLikelihood: input.InherentLikelihood, InherentImpact: input.InherentImpact, ResidualLikelihood: input.ResidualLikelihood, @@ -751,6 +752,7 @@ func (r *mutationResolver) UpdateRisk(ctx context.Context, input types.UpdateRis ID: input.ID, Name: input.Name, Description: input.Description, + Treatment: input.Treatment, InherentLikelihood: input.InherentLikelihood, InherentImpact: input.InherentImpact, ResidualLikelihood: input.ResidualLikelihood, @@ -1591,36 +1593,3 @@ type taskResolver struct{ *Resolver } type vendorResolver struct{ *Resolver } type vendorComplianceReportResolver struct{ *Resolver } type viewerResolver struct{ *Resolver } - -// !!! WARNING !!! -// The code below was going to be deleted when updating resolvers. It has been copied here so you have -// one last chance to move it out of harms way if you want. There are two reasons this happens: -// - When renaming or deleting a resolver the old code will be put in here. You can safely delete -// it when you're done. -// - You have helper methods in this file. Move them out to keep these resolver files clean. -/* - func (r *mutationResolver) CreateRiskControlMapping(ctx context.Context, input types.CreateRiskControlMappingInput) (*types.CreateRiskControlMappingPayload, error) { - svc := r.GetTenantServiceIfAuthorized(ctx, input.RiskID.TenantID()) - - err := svc.Risks.CreateControlMapping(ctx, input.RiskID, input.ControlID) - if err != nil { - panic(fmt.Errorf("cannot create risk control mapping: %w", err)) - } - - return &types.CreateRiskControlMappingPayload{ - Success: true, - }, nil -} -func (r *mutationResolver) DeleteRiskControlMapping(ctx context.Context, input types.DeleteRiskControlMappingInput) (*types.DeleteRiskControlMappingPayload, error) { - svc := r.GetTenantServiceIfAuthorized(ctx, input.RiskID.TenantID()) - - err := svc.Risks.DeleteControlMapping(ctx, input.RiskID, input.ControlID) - if err != nil { - panic(fmt.Errorf("cannot delete risk control mapping: %w", err)) - } - - return &types.DeleteRiskControlMappingPayload{ - Success: true, - }, nil -} -*/