diff --git a/apps/console/src/pages/organizations/Routes.tsx b/apps/console/src/pages/organizations/Routes.tsx index a8bc6bc21..c59fb8671 100644 --- a/apps/console/src/pages/organizations/Routes.tsx +++ b/apps/console/src/pages/organizations/Routes.tsx @@ -24,6 +24,7 @@ import { VendorPage } from "./vendors/VendorPage"; import { MitigationNewPage } from "./mitigations/MitigationNewPage"; import { RiskListPage } from "./risks/RiskListPage"; import { NewRiskPage } from "./risks/NewRiskPage"; +import ShowRiskView from "./risks/ShowRiskView"; export function OrganizationsRoutes() { return ( @@ -57,6 +58,7 @@ export function OrganizationsRoutes() { /> } /> } /> + } /> } /> } /> diff --git a/apps/console/src/pages/organizations/frameworks/controls/ControlView.tsx b/apps/console/src/pages/organizations/frameworks/controls/ControlView.tsx index 159530b22..6682fba31 100644 --- a/apps/console/src/pages/organizations/frameworks/controls/ControlView.tsx +++ b/apps/console/src/pages/organizations/frameworks/controls/ControlView.tsx @@ -33,6 +33,14 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; +import { + ControlViewLinkedMitigationsQuery, + ControlViewLinkedMitigationsQuery$data, +} from "./__generated__/ControlViewLinkedMitigationsQuery.graphql"; +import { + ControlViewOrganizationMitigationsQuery, + ControlViewOrganizationMitigationsQuery$data, +} from "./__generated__/ControlViewOrganizationMitigationsQuery.graphql"; const controlViewQuery = graphql` query ControlViewQuery($controlId: ID!) { @@ -115,38 +123,6 @@ const deleteMitigationMappingMutation = graphql` } `; -// Add type definitions for the GraphQL responses -interface MitigationNode { - id: string; - name: string; - description: string; - category: string; - importance: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL"; - state: "NOT_STARTED" | "IN_PROGRESS" | "IMPLEMENTED" | "NOT_APPLICABLE"; -} - -interface LinkedMitigationsData { - control?: { - id: string; - mitigations?: { - edges: Array<{ - node: MitigationNode; - }>; - }; - }; -} - -interface OrganizationMitigationsData { - organization?: { - id: string; - mitigations?: { - edges: Array<{ - node: MitigationNode; - }>; - }; - }; -} - export function Control({ control, }: { @@ -163,9 +139,9 @@ export function Control({ const [isMitigationMappingDialogOpen, setIsMitigationMappingDialogOpen] = useState(false); const [linkedMitigationsData, setLinkedMitigationsData] = - useState(null); + useState(null); const [organizationMitigationsData, setOrganizationMitigationsData] = - useState(null); + useState(null); const [mitigationSearchQuery, setMitigationSearchQuery] = useState(""); const [isLoadingMitigations, setIsLoadingMitigations] = useState(false); const [isLinkingMitigation, setIsLinkingMitigation] = useState(false); @@ -184,11 +160,15 @@ export function Control({ useEffect(() => { if (control.id) { setIsLoadingMitigations(true); - fetchQuery(environment, linkedMitigationsQuery, { - controlId: control.id, - }).subscribe({ + fetchQuery( + environment, + linkedMitigationsQuery, + { + controlId: control.id, + } + ).subscribe({ next: (data) => { - setLinkedMitigationsData(data as LinkedMitigationsData); + setLinkedMitigationsData(data); setIsLoadingMitigations(false); }, error: (error: Error) => { @@ -206,19 +186,27 @@ export function Control({ setIsLoadingMitigations(true); // Fetch all mitigations for the organization - fetchQuery(environment, organizationMitigationsQuery, { - organizationId, - }).subscribe({ + fetchQuery( + environment, + organizationMitigationsQuery, + { + organizationId, + } + ).subscribe({ next: (data) => { - setOrganizationMitigationsData(data as OrganizationMitigationsData); + setOrganizationMitigationsData(data); }, complete: () => { // Fetch linked mitigations for this control - fetchQuery(environment, linkedMitigationsQuery, { - controlId: control.id, - }).subscribe({ + fetchQuery( + environment, + linkedMitigationsQuery, + { + controlId: control.id, + } + ).subscribe({ next: (data) => { - setLinkedMitigationsData(data as LinkedMitigationsData); + setLinkedMitigationsData(data); setIsLoadingMitigations(false); }, error: (error: Error) => { @@ -337,11 +325,15 @@ export function Control({ } // Refresh linked mitigations data - fetchQuery(environment, linkedMitigationsQuery, { - controlId: control.id, - }).subscribe({ + fetchQuery( + environment, + linkedMitigationsQuery, + { + controlId: control.id, + } + ).subscribe({ next: (data) => { - setLinkedMitigationsData(data as LinkedMitigationsData); + setLinkedMitigationsData(data); }, error: (error: Error) => { console.error("Error refreshing linked mitigations:", error); @@ -394,11 +386,15 @@ export function Control({ } // Refresh linked mitigations data - fetchQuery(environment, linkedMitigationsQuery, { - controlId: control.id, - }).subscribe({ + fetchQuery( + environment, + linkedMitigationsQuery, + { + controlId: control.id, + } + ).subscribe({ next: (data) => { - setLinkedMitigationsData(data as LinkedMitigationsData); + setLinkedMitigationsData(data); }, error: (error: Error) => { console.error("Error refreshing linked mitigations:", error); @@ -589,85 +585,81 @@ export function Control({ - {filteredMitigations().map( - (mitigation: MitigationNode) => { - const isLinked = isMitigationLinked( - mitigation.id - ); - return ( - - -
- {mitigation.name} + {filteredMitigations().map((mitigation) => { + const isLinked = isMitigationLinked(mitigation.id); + return ( + + +
+ {mitigation.name} +
+ {mitigation.description && ( +
+ {mitigation.description}
- {mitigation.description && ( -
- {mitigation.description} -
- )} - - -
+ +
+ {formatImportance(mitigation.importance)} +
+ + +
+ {formatState(mitigation.state)} +
+ + + {isLinked ? ( +
- - -
+ ) : ( + + )} + Unlink + + ) : ( +
- - - {isLinked ? ( - - ) : ( - - )} - - - ); - } - )} + {isLinkingMitigation ? ( + + ) : ( + + )} + Link + + )} + + + ); + })} )} @@ -720,68 +712,66 @@ export function Control({ - {getLinkedMitigations().map( - (mitigation: MitigationNode) => ( - - -
{mitigation.name}
- {mitigation.description && ( -
- {mitigation.description} -
- )} - - -
( + + +
{mitigation.name}
+ {mitigation.description && ( +
+ {mitigation.description} +
+ )} + + +
+ {formatImportance(mitigation.importance)} +
+ + +
+ {formatState(mitigation.state)} +
+ + +
+
- - -
+ View + + +
- - -
- - -
- - - ) - )} + Unlink + +
+ + + ))}
diff --git a/apps/console/src/pages/organizations/risks/RiskListView.tsx b/apps/console/src/pages/organizations/risks/RiskListView.tsx index 0863ae680..0974f6bb5 100644 --- a/apps/console/src/pages/organizations/risks/RiskListView.tsx +++ b/apps/console/src/pages/organizations/risks/RiskListView.tsx @@ -318,21 +318,35 @@ function RiskListViewContent({ key={risk.id} className="border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted cursor-pointer" > - - {risk.name} + + + {risk.name} + - - {floatToProbabilityText(risk.probability)} + + + {floatToProbabilityText(risk.probability)} + - - {floatToImpactText(risk.impact)} + + + {floatToImpactText(risk.impact)} + + + {risk.mitigations?.edges?.length && + risk.mitigations?.edges?.length > 0 ? ( +
+ + + + Mitigation + Actions + + + + {risk.mitigations?.edges.map(({ node: mitigation }) => ( + + + + {mitigation.name} + + + + + + + ))} + +
+
+ ) : ( +
+

No mitigations associated with this risk.

+
+ )} + + + + + +
+
+

+ Full Description +

+

{risk.description}

+
+
+

+ Last Updated +

+

{formatDate(risk.updatedAt!)}

+
+
+
+
+
+ + + {/* Dialog for linking mitigations */} + + + +
+
+ Link Mitigation to Risk + + Select a mitigation to link to this risk. + +
+ +
+
+ +
+
+
+
+ + setMitigationSearchQuery(e.target.value)} + /> +
+
+ +
+ +
+ {isLoadingMitigations ? ( +
Loading mitigations...
+ ) : filteredMitigations().length === 0 ? ( +
No mitigations found.
+ ) : ( +
+ {filteredMitigations().map((mitigation) => { + // For each render, recalculate linked status directly against the current risk data + const isLinked = risk.mitigations?.edges?.some( + (edge) => edge.node.id === mitigation.id + ); + + const isProcessing = + (isLinkingMitigation && + currentMitigationId === mitigation.id) || + (isUnlinkingMitigation && + currentMitigationId === mitigation.id); + + return ( +
+
+
+

{mitigation.name}

+
+ +
+
+ ); + })} +
+ )} +
+
+ + + + +
+
+ + + ); +} + +export default function ShowRiskView() { + const { riskId } = useParams(); + const [queryRef, loadQuery] = + useQueryLoader(showRiskViewQuery); + + useEffect(() => { + loadQuery({ riskId: riskId! }); + }, [loadQuery, riskId]); + + if (!queryRef) { + return ; + } + + return ( + }> + + + ); +} diff --git a/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewCreateRiskMappingMutation.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewCreateRiskMappingMutation.graphql.ts new file mode 100644 index 000000000..1ea6837b1 --- /dev/null +++ b/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewCreateRiskMappingMutation.graphql.ts @@ -0,0 +1,95 @@ +/** + * @generated SignedSource<<16f4621b72343a04c88df9d0b137c9fd>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +export type CreateRiskMappingInput = { + impact: number; + mitigationId: string; + probability: number; + riskId: string; +}; +export type ShowRiskViewCreateRiskMappingMutation$variables = { + input: CreateRiskMappingInput; +}; +export type ShowRiskViewCreateRiskMappingMutation$data = { + readonly createRiskMapping: { + readonly success: boolean; + }; +}; +export type ShowRiskViewCreateRiskMappingMutation = { + response: ShowRiskViewCreateRiskMappingMutation$data; + variables: ShowRiskViewCreateRiskMappingMutation$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "input" + } +], +v1 = [ + { + "alias": null, + "args": [ + { + "kind": "Variable", + "name": "input", + "variableName": "input" + } + ], + "concreteType": "CreateRiskMappingPayload", + "kind": "LinkedField", + "name": "createRiskMapping", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "success", + "storageKey": null + } + ], + "storageKey": null + } +]; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "ShowRiskViewCreateRiskMappingMutation", + "selections": (v1/*: any*/), + "type": "Mutation", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "ShowRiskViewCreateRiskMappingMutation", + "selections": (v1/*: any*/) + }, + "params": { + "cacheID": "32dfd9049a8c6c1d404528bac1316346", + "id": null, + "metadata": {}, + "name": "ShowRiskViewCreateRiskMappingMutation", + "operationKind": "mutation", + "text": "mutation ShowRiskViewCreateRiskMappingMutation(\n $input: CreateRiskMappingInput!\n) {\n createRiskMapping(input: $input) {\n success\n }\n}\n" + } +}; +})(); + +(node as any).hash = "02f82b14cc6cf7c2e39dad4613e9d191"; + +export default node; diff --git a/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewDeleteRiskMappingMutation.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewDeleteRiskMappingMutation.graphql.ts new file mode 100644 index 000000000..8e1c60b07 --- /dev/null +++ b/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewDeleteRiskMappingMutation.graphql.ts @@ -0,0 +1,93 @@ +/** + * @generated SignedSource<<45a4aca30e16d598cd188f3cbc041a0d>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +export type DeleteRiskMappingInput = { + mitigationId: string; + riskId: string; +}; +export type ShowRiskViewDeleteRiskMappingMutation$variables = { + input: DeleteRiskMappingInput; +}; +export type ShowRiskViewDeleteRiskMappingMutation$data = { + readonly deleteRiskMapping: { + readonly success: boolean; + }; +}; +export type ShowRiskViewDeleteRiskMappingMutation = { + response: ShowRiskViewDeleteRiskMappingMutation$data; + variables: ShowRiskViewDeleteRiskMappingMutation$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "input" + } +], +v1 = [ + { + "alias": null, + "args": [ + { + "kind": "Variable", + "name": "input", + "variableName": "input" + } + ], + "concreteType": "DeleteRiskMappingPayload", + "kind": "LinkedField", + "name": "deleteRiskMapping", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "success", + "storageKey": null + } + ], + "storageKey": null + } +]; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "ShowRiskViewDeleteRiskMappingMutation", + "selections": (v1/*: any*/), + "type": "Mutation", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "ShowRiskViewDeleteRiskMappingMutation", + "selections": (v1/*: any*/) + }, + "params": { + "cacheID": "847faec465a30f457c57c5c1524a707d", + "id": null, + "metadata": {}, + "name": "ShowRiskViewDeleteRiskMappingMutation", + "operationKind": "mutation", + "text": "mutation ShowRiskViewDeleteRiskMappingMutation(\n $input: DeleteRiskMappingInput!\n) {\n deleteRiskMapping(input: $input) {\n success\n }\n}\n" + } +}; +})(); + +(node as any).hash = "41aa62a4185b1e6061bd7e06abbec85d"; + +export default node; diff --git a/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewOrganizationMitigationsQuery.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewOrganizationMitigationsQuery.graphql.ts new file mode 100644 index 000000000..42af7f455 --- /dev/null +++ b/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewOrganizationMitigationsQuery.graphql.ts @@ -0,0 +1,280 @@ +/** + * @generated SignedSource<<771e7ea5d1af4e722dc5790db8abd623>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +export type MitigationImportance = "ADVANCED" | "MANDATORY" | "PREFERRED"; +export type MitigationState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED"; +export type ShowRiskViewOrganizationMitigationsQuery$variables = { + organizationId: string; +}; +export type ShowRiskViewOrganizationMitigationsQuery$data = { + readonly organization: { + readonly id: string; + readonly mitigations?: { + readonly edges: ReadonlyArray<{ + readonly node: { + readonly category: string; + readonly description: string; + readonly id: string; + readonly importance: MitigationImportance; + readonly name: string; + readonly state: MitigationState; + }; + }>; + }; + }; +}; +export type ShowRiskViewOrganizationMitigationsQuery = { + response: ShowRiskViewOrganizationMitigationsQuery$data; + variables: ShowRiskViewOrganizationMitigationsQuery$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "organizationId" + } +], +v1 = [ + { + "kind": "Variable", + "name": "id", + "variableName": "organizationId" + } +], +v2 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v3 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null +}, +v4 = [ + { + "alias": null, + "args": null, + "concreteType": "MitigationEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Mitigation", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "description", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "category", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "importance", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "state", + "storageKey": null + }, + (v3/*: any*/) + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "cursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "PageInfo", + "kind": "LinkedField", + "name": "pageInfo", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "endCursor", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasNextPage", + "storageKey": null + } + ], + "storageKey": null + } +], +v5 = [ + { + "kind": "Literal", + "name": "first", + "value": 100 + } +]; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "ShowRiskViewOrganizationMitigationsQuery", + "selections": [ + { + "alias": "organization", + "args": (v1/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v2/*: any*/), + { + "kind": "InlineFragment", + "selections": [ + { + "alias": "mitigations", + "args": null, + "concreteType": "MitigationConnection", + "kind": "LinkedField", + "name": "__Organization__mitigations_connection", + "plural": false, + "selections": (v4/*: any*/), + "storageKey": null + } + ], + "type": "Organization", + "abstractKey": null + } + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "ShowRiskViewOrganizationMitigationsQuery", + "selections": [ + { + "alias": "organization", + "args": (v1/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v3/*: any*/), + (v2/*: any*/), + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": (v5/*: any*/), + "concreteType": "MitigationConnection", + "kind": "LinkedField", + "name": "mitigations", + "plural": false, + "selections": (v4/*: any*/), + "storageKey": "mitigations(first:100)" + }, + { + "alias": null, + "args": (v5/*: any*/), + "filters": null, + "handle": "connection", + "key": "Organization__mitigations", + "kind": "LinkedHandle", + "name": "mitigations" + } + ], + "type": "Organization", + "abstractKey": null + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "ac4f3fc31facab3cb2b9455751a4a528", + "id": null, + "metadata": { + "connection": [ + { + "count": null, + "cursor": null, + "direction": "forward", + "path": [ + "organization", + "mitigations" + ] + } + ] + }, + "name": "ShowRiskViewOrganizationMitigationsQuery", + "operationKind": "query", + "text": "query ShowRiskViewOrganizationMitigationsQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n mitigations(first: 100) {\n edges {\n node {\n id\n name\n description\n category\n importance\n state\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n" + } +}; +})(); + +(node as any).hash = "608bcf7b0e53529673b25ac7762627e2"; + +export default node; diff --git a/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewQuery.graphql.ts b/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewQuery.graphql.ts new file mode 100644 index 000000000..b2fd2b503 --- /dev/null +++ b/apps/console/src/pages/organizations/risks/__generated__/ShowRiskViewQuery.graphql.ts @@ -0,0 +1,246 @@ +/** + * @generated SignedSource<> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ +/* eslint-disable */ +// @ts-nocheck + +import { ConcreteRequest } from 'relay-runtime'; +export type MitigationImportance = "ADVANCED" | "MANDATORY" | "PREFERRED"; +export type MitigationState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED"; +export type ShowRiskViewQuery$variables = { + riskId: string; +}; +export type ShowRiskViewQuery$data = { + readonly node: { + readonly createdAt?: string; + readonly description?: string; + readonly id: string; + readonly impact?: number; + readonly mitigations?: { + readonly edges: ReadonlyArray<{ + readonly node: { + readonly category: string; + readonly description: string; + readonly id: string; + readonly importance: MitigationImportance; + readonly name: string; + readonly state: MitigationState; + }; + }>; + }; + readonly name?: string; + readonly probability?: number; + readonly updatedAt?: string; + }; +}; +export type ShowRiskViewQuery = { + response: ShowRiskViewQuery$data; + variables: ShowRiskViewQuery$variables; +}; + +const node: ConcreteRequest = (function(){ +var v0 = [ + { + "defaultValue": null, + "kind": "LocalArgument", + "name": "riskId" + } +], +v1 = [ + { + "kind": "Variable", + "name": "id", + "variableName": "riskId" + } +], +v2 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v3 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null +}, +v4 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "description", + "storageKey": null +}, +v5 = { + "kind": "InlineFragment", + "selections": [ + (v3/*: any*/), + (v4/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "probability", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "impact", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "createdAt", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "updatedAt", + "storageKey": null + }, + { + "alias": null, + "args": [ + { + "kind": "Literal", + "name": "first", + "value": 100 + } + ], + "concreteType": "MitigationConnection", + "kind": "LinkedField", + "name": "mitigations", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "MitigationEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Mitigation", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v2/*: any*/), + (v3/*: any*/), + (v4/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "category", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "importance", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "state", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": "mitigations(first:100)" + } + ], + "type": "Risk", + "abstractKey": null +}; +return { + "fragment": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Fragment", + "metadata": null, + "name": "ShowRiskViewQuery", + "selections": [ + { + "alias": null, + "args": (v1/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v2/*: any*/), + (v5/*: any*/) + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": (v0/*: any*/), + "kind": "Operation", + "name": "ShowRiskViewQuery", + "selections": [ + { + "alias": null, + "args": (v1/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null + }, + (v2/*: any*/), + (v5/*: any*/) + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "1fa87a20a3f945fa7da2f72e5b4fa52f", + "id": null, + "metadata": {}, + "name": "ShowRiskViewQuery", + "operationKind": "query", + "text": "query ShowRiskViewQuery(\n $riskId: ID!\n) {\n node(id: $riskId) {\n __typename\n id\n ... on Risk {\n name\n description\n probability\n impact\n createdAt\n updatedAt\n mitigations(first: 100) {\n edges {\n node {\n id\n name\n description\n category\n importance\n state\n }\n }\n }\n }\n }\n}\n" + } +}; +})(); + +(node as any).hash = "824859cf39078da910b00879c17a2a9d"; + +export default node; diff --git a/pkg/coredata/migrations/20250401T082800Z.sql b/pkg/coredata/migrations/20250401T082800Z.sql new file mode 100644 index 000000000..4d6c4b72a --- /dev/null +++ b/pkg/coredata/migrations/20250401T082800Z.sql @@ -0,0 +1 @@ +ALTER TABLE risks_mitigations ADD COLUMN tenant_id TEXT NOT NULL; \ No newline at end of file diff --git a/pkg/coredata/migrations/20250401T082900Z.sql b/pkg/coredata/migrations/20250401T082900Z.sql new file mode 100644 index 000000000..514aaa0b7 --- /dev/null +++ b/pkg/coredata/migrations/20250401T082900Z.sql @@ -0,0 +1 @@ +ALTER TABLE risks_mitigations ADD COLUMN created_at TIMESTAMP NOT NULL; \ No newline at end of file