Rename mitigation into mesure

Signed-off-by: gearnode <bryan@frimin.fr>
This commit is contained in:
gearnode
2025-04-12 21:09:49 -07:00
parent daff5e6670
commit 3711bb4bbb
80 changed files with 3397 additions and 3472 deletions

View File

@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
### Changed
- Rename "Mitigation" in "Mesure"
## [0.9.0] - 2025-04-12
### Added

View File

@@ -134,10 +134,10 @@ export function NavMain() {
function getNavItems(organizationId?: string): NavItem[] {
return [
{
title: "Mitigations",
title: "Mesures",
icon: ClipboardList,
url: organizationId
? `/organizations/${organizationId}/mitigations`
? `/organizations/${organizationId}/mesures`
: undefined,
},
{

View File

@@ -69,7 +69,7 @@ const SidebarProvider = React.forwardRef<
const [openMobile, setOpenMobile] = React.useState(false);
// This is the internal state of the sidebar.
// We use openProp and setOpenProp for mitigation from outside the component.
// We use openProp and setOpenProp for mesure from outside the component.
const [_open, _setOpen] = React.useState(defaultOpen);
const open = openProp ?? _open;
const setOpen = React.useCallback(

View File

@@ -2,5 +2,5 @@ import { Navigate, useParams } from "react-router";
export default function HomePage() {
const { organizationId } = useParams();
return <Navigate to={`/organizations/${organizationId}/mitigations`} />;
return <Navigate to={`/organizations/${organizationId}/mesures`} />;
}

View File

@@ -16,7 +16,7 @@ import { OrganizationBreadcrumbBreadcrumbPeopleOverviewQuery } from "./__generat
import { OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery.graphql";
import { OrganizationBreadcrumbBreadcrumbVendorOverviewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbVendorOverviewQuery.graphql";
import { OrganizationBreadcrumbOrganizationQuery } from "./__generated__/OrganizationBreadcrumbOrganizationQuery.graphql";
import { OrganizationBreadcrumbBreadcrumbMitigationViewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbMitigationViewQuery.graphql";
import { OrganizationBreadcrumbBreadcrumbMesureViewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbMesureViewQuery.graphql";
import { OrganizationBreadcrumbBreadcrumbControlQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbControlQuery.graphql";
import { OrganizationBreadcrumbBreadcrumbRiskShowQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbRiskShowQuery.graphql";
import ErrorBoundary from "@/components/ErrorBoundary";
@@ -314,15 +314,15 @@ function BreadcrumbPolicyOverview() {
);
}
function BreadcrumbMitigationList() {
function BreadcrumbMesureList() {
const { organizationId } = useParams();
return (
<>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbNavLink to={`/organizations/${organizationId}/mitigations`}>
Mitigations
<BreadcrumbNavLink to={`/organizations/${organizationId}/mesures`}>
Mesures
</BreadcrumbNavLink>
</BreadcrumbItem>
<Outlet />
@@ -330,24 +330,22 @@ function BreadcrumbMitigationList() {
);
}
function BreadcrumbMitigationView() {
const { organizationId, mitigationId } = useParams();
function BreadcrumbMesureView() {
const { organizationId, mesureId } = useParams();
const data =
useLazyLoadQuery<OrganizationBreadcrumbBreadcrumbMitigationViewQuery>(
useLazyLoadQuery<OrganizationBreadcrumbBreadcrumbMesureViewQuery>(
graphql`
query OrganizationBreadcrumbBreadcrumbMitigationViewQuery(
$mitigationId: ID!
) {
mitigation: node(id: $mitigationId) {
query OrganizationBreadcrumbBreadcrumbMesureViewQuery($mesureId: ID!) {
mesure: node(id: $mesureId) {
id
... on Mitigation {
... on Mesure {
name
category
}
}
}
`,
{ mitigationId: mitigationId! }
{ mesureId: mesureId! }
);
return (
@@ -355,17 +353,17 @@ function BreadcrumbMitigationView() {
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbNavLink
to={`/organizations/${organizationId}/mitigations#${data.mitigation.category}`}
to={`/organizations/${organizationId}/mesures#${data.mesure.category}`}
>
{data.mitigation.category}
{data.mesure.category}
</BreadcrumbNavLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbNavLink
to={`/organizations/${organizationId}/mitigations/${mitigationId}`}
to={`/organizations/${organizationId}/mesures/${mesureId}`}
>
{data.mitigation.name}
{data.mesure.name}
</BreadcrumbNavLink>
</BreadcrumbItem>
<Outlet />
@@ -463,13 +461,13 @@ export function BreadCrumb() {
</ErrorBoundary>
}
>
<Route path="mitigations" element={<BreadcrumbMitigationList />}>
<Route path="mesures" element={<BreadcrumbMesureList />}>
<Route path="new" element={<New />} />
<Route
path=":mitigationId"
path=":mesureId"
element={
<Suspense>
<BreadcrumbMitigationView />
<BreadcrumbMesureView />
</Suspense>
}
>

View File

@@ -11,10 +11,10 @@ import { FrameworkListPage } from "./frameworks/FrameworkListPage";
import { FrameworkPage } from "./frameworks/FrameworkPage";
import { NewFrameworkPage } from "./frameworks/NewFrameworkPage";
import { ControlPage } from "./frameworks/controls/ControlPage";
import { EditMitigationPage } from "./mitigations/EditMitigationPage";
import { MitigationListPage } from "./mitigations/MitigationListPage";
import { MitigationPage } from "./mitigations/MitigationPage";
import { NewMitigationPage } from "./mitigations/NewMitigationPage";
import { EditMesurePage } from "./mesures/EditMesurePage";
import { MesureListPage } from "./mesures/MesureListPage";
import { MesurePage } from "./mesures/MesurePage";
import { NewMesurePage } from "./mesures/NewMesurePage";
import { NewPeoplePage } from "./people/NewPeoplePage";
import { PeopleListPage } from "./people/PeopleListPage";
import { PeoplePage } from "./people/PeoplePage";
@@ -48,13 +48,10 @@ export function OrganizationsRoutes() {
<Route path="edit" element={<EditFrameworkPage />} />
<Route path="*" element={<NotFoundPage />} />
</Route>
<Route path="mitigations" element={<MitigationListPage />} />
<Route path="mitigations/new" element={<NewMitigationPage />} />
<Route path="mitigations/:mitigationId" element={<MitigationPage />} />
<Route
path="mitigations/:mitigationId/edit"
element={<EditMitigationPage />}
/>
<Route path="mesures" element={<MesureListPage />} />
<Route path="mesures/new" element={<NewMesurePage />} />
<Route path="mesures/:mesureId" element={<MesurePage />} />
<Route path="mesures/:mesureId/edit" element={<EditMesurePage />} />
<Route path="vendors/:vendorId" element={<VendorPage />} />
<Route path="policies" element={<PolicyListPage />} />
<Route path="policies/new" element={<NewPolicyPage />} />

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<5297fe6c58e18534c0e9684cfea6b319>>
* @generated SignedSource<<a8e66e7606187f54d173cddac8bcd316>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,19 +9,19 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type OrganizationBreadcrumbBreadcrumbMitigationViewQuery$variables = {
mitigationId: string;
export type OrganizationBreadcrumbBreadcrumbMesureViewQuery$variables = {
mesureId: string;
};
export type OrganizationBreadcrumbBreadcrumbMitigationViewQuery$data = {
readonly mitigation: {
export type OrganizationBreadcrumbBreadcrumbMesureViewQuery$data = {
readonly mesure: {
readonly category?: string;
readonly id: string;
readonly name?: string;
};
};
export type OrganizationBreadcrumbBreadcrumbMitigationViewQuery = {
response: OrganizationBreadcrumbBreadcrumbMitigationViewQuery$data;
variables: OrganizationBreadcrumbBreadcrumbMitigationViewQuery$variables;
export type OrganizationBreadcrumbBreadcrumbMesureViewQuery = {
response: OrganizationBreadcrumbBreadcrumbMesureViewQuery$data;
variables: OrganizationBreadcrumbBreadcrumbMesureViewQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -29,14 +29,14 @@ var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "mitigationId"
"name": "mesureId"
}
],
v1 = [
{
"kind": "Variable",
"name": "id",
"variableName": "mitigationId"
"variableName": "mesureId"
}
],
v2 = {
@@ -64,7 +64,7 @@ v3 = {
"storageKey": null
}
],
"type": "Mitigation",
"type": "Mesure",
"abstractKey": null
};
return {
@@ -72,10 +72,10 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "OrganizationBreadcrumbBreadcrumbMitigationViewQuery",
"name": "OrganizationBreadcrumbBreadcrumbMesureViewQuery",
"selections": [
{
"alias": "mitigation",
"alias": "mesure",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
@@ -95,10 +95,10 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "OrganizationBreadcrumbBreadcrumbMitigationViewQuery",
"name": "OrganizationBreadcrumbBreadcrumbMesureViewQuery",
"selections": [
{
"alias": "mitigation",
"alias": "mesure",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
@@ -120,16 +120,16 @@ return {
]
},
"params": {
"cacheID": "dcc05f69cfc1d38fae2488aa4740f109",
"cacheID": "f6183e3013438a1cff8e91c6ff80f452",
"id": null,
"metadata": {},
"name": "OrganizationBreadcrumbBreadcrumbMitigationViewQuery",
"name": "OrganizationBreadcrumbBreadcrumbMesureViewQuery",
"operationKind": "query",
"text": "query OrganizationBreadcrumbBreadcrumbMitigationViewQuery(\n $mitigationId: ID!\n) {\n mitigation: node(id: $mitigationId) {\n __typename\n id\n ... on Mitigation {\n name\n category\n }\n }\n}\n"
"text": "query OrganizationBreadcrumbBreadcrumbMesureViewQuery(\n $mesureId: ID!\n) {\n mesure: node(id: $mesureId) {\n __typename\n id\n ... on Mesure {\n name\n category\n }\n }\n}\n"
}
};
})();
(node as any).hash = "0b8d38ad84bd4c5a684711285c29e5a4";
(node as any).hash = "67fd3d426bbfcbe90457c3033dade1b3";
export default node;

View File

@@ -10,7 +10,7 @@ export function NewFrameworkViewSkeleton() {
return (
<PageTemplateSkeleton
title="Create Framework"
description="Create a new framework to organize your mitigations"
description="Create a new framework to organize your mesures"
>
<div className="max-w-2xl aspect-square bg-subtle-bg rounded-xl animate-pulse" />
</PageTemplateSkeleton>

View File

@@ -170,7 +170,7 @@ function NewFrameworkViewContent() {
return (
<PageTemplate
title="Create Framework"
description="Create a new framework to organize your mitigations"
description="Create a new framework to organize your mesures"
>
<Card className="max-w-2xl">
<form onSubmit={handleSubmit} className="p-6 space-y-6">

View File

@@ -26,13 +26,13 @@ import {
} from "react-relay";
import { useParams, Link } from "react-router";
import {
ControlLinkedMitigationsQuery$data,
ControlLinkedMitigationsQuery,
} from "./__generated__/ControlLinkedMitigationsQuery.graphql";
ControlLinkedMesuresQuery$data,
ControlLinkedMesuresQuery,
} from "./__generated__/ControlLinkedMesuresQuery.graphql";
import {
ControlOrganizationMitigationsQuery$data,
ControlOrganizationMitigationsQuery,
} from "./__generated__/ControlOrganizationMitigationsQuery.graphql";
ControlOrganizationMesuresQuery$data,
ControlOrganizationMesuresQuery,
} from "./__generated__/ControlOrganizationMesuresQuery.graphql";
import { ControlFragment_Control$key } from "./__generated__/ControlFragment_Control.graphql";
import {
ControlLinkedPoliciesQuery$data,
@@ -52,13 +52,13 @@ const controlFragment = graphql`
}
`;
// New query to fetch linked mitigations
const linkedMitigationsQuery = graphql`
query ControlLinkedMitigationsQuery($controlId: ID!) {
// New query to fetch linked mesures
const linkedMesuresQuery = graphql`
query ControlLinkedMesuresQuery($controlId: ID!) {
control: node(id: $controlId) {
id
... on Control {
mitigations(first: 100) @connection(key: "Control__mitigations") {
mesures(first: 100) @connection(key: "Control__mesures") {
edges {
node {
id
@@ -75,13 +75,13 @@ const linkedMitigationsQuery = graphql`
}
`;
// Query to fetch all mitigations for the organization
const organizationMitigationsQuery = graphql`
query ControlOrganizationMitigationsQuery($organizationId: ID!) {
// Query to fetch all mesures for the organization
const organizationMesuresQuery = graphql`
query ControlOrganizationMesuresQuery($organizationId: ID!) {
organization: node(id: $organizationId) {
id
... on Organization {
mitigations(first: 100) @connection(key: "Organization__mitigations") {
mesures(first: 100) @connection(key: "Organization__mesures") {
edges {
node {
id
@@ -142,23 +142,23 @@ const organizationPoliciesQuery = graphql`
}
`;
// Mutation to create a mapping between a control and a mitigation
const createMitigationMappingMutation = graphql`
mutation ControlCreateMitigationMappingMutation(
$input: CreateControlMitigationMappingInput!
// Mutation to create a mapping between a control and a mesure
const createMesureMappingMutation = graphql`
mutation ControlCreateMesureMappingMutation(
$input: CreateControlMesureMappingInput!
) {
createControlMitigationMapping(input: $input) {
createControlMesureMapping(input: $input) {
success
}
}
`;
// Mutation to delete a mapping between a control and a mitigation
const deleteMitigationMappingMutation = graphql`
mutation ControlDeleteMitigationMappingMutation(
$input: DeleteControlMitigationMappingInput!
// Mutation to delete a mapping between a control and a mesure
const deleteMesureMappingMutation = graphql`
mutation ControlDeleteMesureMappingMutation(
$input: DeleteControlMesureMappingInput!
) {
deleteControlMitigationMapping(input: $input) {
deleteControlMesureMapping(input: $input) {
success
}
}
@@ -199,17 +199,17 @@ export function Control({
const { toast } = useToast();
const environment = useRelayEnvironment();
// State for mitigation mapping
const [isMitigationMappingDialogOpen, setIsMitigationMappingDialogOpen] =
// State for mesure mapping
const [isMesureMappingDialogOpen, setIsMesureMappingDialogOpen] =
useState(false);
const [linkedMitigationsData, setLinkedMitigationsData] =
useState<ControlLinkedMitigationsQuery$data | null>(null);
const [organizationMitigationsData, setOrganizationMitigationsData] =
useState<ControlOrganizationMitigationsQuery$data | null>(null);
const [mitigationSearchQuery, setMitigationSearchQuery] = useState("");
const [isLoadingMitigations, setIsLoadingMitigations] = useState(false);
const [isLinkingMitigation, setIsLinkingMitigation] = useState(false);
const [isUnlinkingMitigation, setIsUnlinkingMitigation] = useState(false);
const [linkedMesuresData, setLinkedMesuresData] =
useState<ControlLinkedMesuresQuery$data | null>(null);
const [organizationMesuresData, setOrganizationMesuresData] =
useState<ControlOrganizationMesuresQuery$data | null>(null);
const [mesureSearchQuery, setMesureSearchQuery] = useState("");
const [isLoadingMesures, setIsLoadingMesures] = useState(false);
const [isLinkingMesure, setIsLinkingMesure] = useState(false);
const [isUnlinkingMesure, setIsUnlinkingMesure] = useState(false);
const [categoryFilter, setCategoryFilter] = useState<string | null>(null);
// Policy state
@@ -225,85 +225,73 @@ export function Control({
const [isUnlinkingPolicy, setIsUnlinkingPolicy] = useState(false);
// Create mutation hooks
const [commitCreateMitigationMapping] = useMutation(
createMitigationMappingMutation
);
const [commitDeleteMitigationMapping] = useMutation(
deleteMitigationMappingMutation
);
const [commitCreateMesureMapping] = useMutation(createMesureMappingMutation);
const [commitDeleteMesureMapping] = useMutation(deleteMesureMappingMutation);
const [commitCreatePolicyMapping] = useMutation(createPolicyMappingMutation);
const [commitDeletePolicyMapping] = useMutation(deletePolicyMappingMutation);
// Load initial linked mitigations data
// Load initial linked mesures data
useEffect(() => {
if (control.id) {
setIsLoadingMitigations(true);
fetchQuery<ControlLinkedMitigationsQuery>(
environment,
linkedMitigationsQuery,
{
controlId: control.id,
}
).subscribe({
setIsLoadingMesures(true);
fetchQuery<ControlLinkedMesuresQuery>(environment, linkedMesuresQuery, {
controlId: control.id,
}).subscribe({
next: (data) => {
setLinkedMitigationsData(data);
setIsLoadingMitigations(false);
setLinkedMesuresData(data);
setIsLoadingMesures(false);
},
error: (error: Error) => {
console.error("Error loading initial mitigations:", error);
setIsLoadingMitigations(false);
console.error("Error loading initial mesures:", error);
setIsLoadingMesures(false);
},
});
}
}, [control.id, environment]);
// Load mitigations data
const loadMitigationsData = useCallback(() => {
// Load mesures data
const loadMesuresData = useCallback(() => {
if (!organizationId || !control.id) return;
setIsLoadingMitigations(true);
setIsLoadingMesures(true);
// Fetch all mitigations for the organization
fetchQuery<ControlOrganizationMitigationsQuery>(
// Fetch all mesures for the organization
fetchQuery<ControlOrganizationMesuresQuery>(
environment,
organizationMitigationsQuery,
organizationMesuresQuery,
{
organizationId,
}
).subscribe({
next: (data) => {
setOrganizationMitigationsData(data);
setOrganizationMesuresData(data);
},
complete: () => {
// Fetch linked mitigations for this control
fetchQuery<ControlLinkedMitigationsQuery>(
environment,
linkedMitigationsQuery,
{
controlId: control.id,
}
).subscribe({
// Fetch linked mesures for this control
fetchQuery<ControlLinkedMesuresQuery>(environment, linkedMesuresQuery, {
controlId: control.id,
}).subscribe({
next: (data) => {
setLinkedMitigationsData(data);
setIsLoadingMitigations(false);
setLinkedMesuresData(data);
setIsLoadingMesures(false);
},
error: (error: Error) => {
console.error("Error fetching linked mitigations:", error);
setIsLoadingMitigations(false);
console.error("Error fetching linked mesures:", error);
setIsLoadingMesures(false);
toast({
title: "Error",
description: "Failed to load linked mitigations.",
description: "Failed to load linked mesures.",
variant: "destructive",
});
},
});
},
error: (error: Error) => {
console.error("Error fetching organization mitigations:", error);
setIsLoadingMitigations(false);
console.error("Error fetching organization mesures:", error);
setIsLoadingMesures(false);
toast({
title: "Error",
description: "Failed to load mitigations.",
description: "Failed to load mesures.",
variant: "destructive",
});
},
@@ -311,197 +299,190 @@ export function Control({
}, [control.id, environment, organizationId, toast]);
// Helper functions
const getMitigations = useCallback(() => {
if (!organizationMitigationsData?.organization?.mitigations?.edges)
return [];
return organizationMitigationsData.organization.mitigations.edges.map(
const getMesures = useCallback(() => {
if (!organizationMesuresData?.organization?.mesures?.edges) return [];
return organizationMesuresData.organization.mesures.edges.map(
(edge) => edge.node
);
}, [organizationMitigationsData]);
}, [organizationMesuresData]);
const getLinkedMitigations = useCallback(() => {
if (!linkedMitigationsData?.control?.mitigations?.edges) return [];
return linkedMitigationsData.control.mitigations.edges.map(
(edge) => edge.node
);
}, [linkedMitigationsData]);
const getLinkedMesures = useCallback(() => {
if (!linkedMesuresData?.control?.mesures?.edges) return [];
return linkedMesuresData.control.mesures.edges.map((edge) => edge.node);
}, [linkedMesuresData]);
const isMitigationLinked = useCallback(
(mitigationId: string) => {
const linkedMitigations = getLinkedMitigations();
return linkedMitigations.some(
(mitigation) => mitigation.id === mitigationId
);
const isMesureLinked = useCallback(
(mesureId: string) => {
const linkedMesures = getLinkedMesures();
return linkedMesures.some((mesure) => mesure.id === mesureId);
},
[getLinkedMitigations]
[getLinkedMesures]
);
const getMitigationCategories = useCallback(() => {
const mitigations = getMitigations();
const getMesureCategories = useCallback(() => {
const mesures = getMesures();
const categories = new Set<string>();
mitigations.forEach((mitigation) => {
if (mitigation.category) {
categories.add(mitigation.category);
mesures.forEach((mesure) => {
if (mesure.category) {
categories.add(mesure.category);
}
});
return Array.from(categories).sort();
}, [getMitigations]);
}, [getMesures]);
const filteredMitigations = useCallback(() => {
const mitigations = getMitigations();
if (!mitigationSearchQuery && !categoryFilter) return mitigations;
const filteredMesures = useCallback(() => {
const mesures = getMesures();
if (!mesureSearchQuery && !categoryFilter) return mesures;
return mitigations.filter((mitigation) => {
return mesures.filter((mesure) => {
// Filter by search query
const matchesSearch =
!mitigationSearchQuery ||
mitigation.name
.toLowerCase()
.includes(mitigationSearchQuery.toLowerCase()) ||
(mitigation.description &&
mitigation.description
!mesureSearchQuery ||
mesure.name.toLowerCase().includes(mesureSearchQuery.toLowerCase()) ||
(mesure.description &&
mesure.description
.toLowerCase()
.includes(mitigationSearchQuery.toLowerCase()));
.includes(mesureSearchQuery.toLowerCase()));
// Filter by category
const matchesCategory =
!categoryFilter ||
categoryFilter === "all" ||
mitigation.category === categoryFilter;
mesure.category === categoryFilter;
return matchesSearch && matchesCategory;
});
}, [categoryFilter, getMitigations, mitigationSearchQuery]);
}, [categoryFilter, getMesures, mesureSearchQuery]);
// Handle link/unlink functions
const handleLinkMitigation = useCallback(
(mitigationId: string) => {
const handleLinkMesure = useCallback(
(mesureId: string) => {
if (!control.id) return;
setIsLinkingMitigation(true);
setIsLinkingMesure(true);
commitCreateMitigationMapping({
commitCreateMesureMapping({
variables: {
input: {
controlId: control.id,
mitigationId: mitigationId,
mesureId: mesureId,
},
},
onCompleted: (_, errors) => {
setIsLinkingMitigation(false);
setIsLinkingMesure(false);
if (errors) {
console.error("Error linking mitigation:", errors);
console.error("Error linking mesure:", errors);
toast({
title: "Error",
description: "Failed to link mitigation. Please try again.",
description: "Failed to link mesure. Please try again.",
variant: "destructive",
});
return;
}
// Refresh linked mitigations data
fetchQuery<ControlLinkedMitigationsQuery>(
// Refresh linked mesures data
fetchQuery<ControlLinkedMesuresQuery>(
environment,
linkedMitigationsQuery,
linkedMesuresQuery,
{
controlId: control.id,
}
).subscribe({
next: (data) => {
setLinkedMitigationsData(data);
setLinkedMesuresData(data);
},
error: (error: Error) => {
console.error("Error refreshing linked mitigations:", error);
console.error("Error refreshing linked mesures:", error);
},
});
toast({
title: "Success",
description: "Mitigation successfully linked to control.",
description: "Mesure successfully linked to control.",
});
},
onError: (error) => {
setIsLinkingMitigation(false);
console.error("Error linking mitigation:", error);
setIsLinkingMesure(false);
console.error("Error linking mesure:", error);
toast({
title: "Error",
description: "Failed to link mitigation. Please try again.",
description: "Failed to link mesure. Please try again.",
variant: "destructive",
});
},
});
},
[commitCreateMitigationMapping, control.id, environment, toast]
[commitCreateMesureMapping, control.id, environment, toast]
);
const handleUnlinkMitigation = useCallback(
(mitigationId: string) => {
const handleUnlinkMesure = useCallback(
(mesureId: string) => {
if (!control.id) return;
setIsUnlinkingMitigation(true);
setIsUnlinkingMesure(true);
commitDeleteMitigationMapping({
commitDeleteMesureMapping({
variables: {
input: {
controlId: control.id,
mitigationId: mitigationId,
mesureId: mesureId,
},
},
onCompleted: (_, errors) => {
setIsUnlinkingMitigation(false);
setIsUnlinkingMesure(false);
if (errors) {
console.error("Error unlinking mitigation:", errors);
console.error("Error unlinking mesure:", errors);
toast({
title: "Error",
description: "Failed to unlink mitigation. Please try again.",
description: "Failed to unlink mesure. Please try again.",
variant: "destructive",
});
return;
}
// Refresh linked mitigations data
fetchQuery<ControlLinkedMitigationsQuery>(
// Refresh linked mesures data
fetchQuery<ControlLinkedMesuresQuery>(
environment,
linkedMitigationsQuery,
linkedMesuresQuery,
{
controlId: control.id,
}
).subscribe({
next: (data) => {
setLinkedMitigationsData(data);
setLinkedMesuresData(data);
},
error: (error: Error) => {
console.error("Error refreshing linked mitigations:", error);
console.error("Error refreshing linked mesures:", error);
},
});
toast({
title: "Success",
description: "Mitigation successfully unlinked from control.",
description: "Mesure successfully unlinked from control.",
});
},
onError: (error) => {
setIsUnlinkingMitigation(false);
console.error("Error unlinking mitigation:", error);
setIsUnlinkingMesure(false);
console.error("Error unlinking mesure:", error);
toast({
title: "Error",
description: "Failed to unlink mitigation. Please try again.",
description: "Failed to unlink mesure. Please try again.",
variant: "destructive",
});
},
});
},
[commitDeleteMitigationMapping, control.id, environment, toast]
[commitDeleteMesureMapping, control.id, environment, toast]
);
const handleOpenMitigationMappingDialog = useCallback(() => {
loadMitigationsData();
setIsMitigationMappingDialogOpen(true);
}, [loadMitigationsData]);
const handleOpenMesureMappingDialog = useCallback(() => {
loadMesuresData();
setIsMesureMappingDialogOpen(true);
}, [loadMesuresData]);
// Load initial linked policies data
useEffect(() => {
@@ -824,10 +805,10 @@ export function Control({
{/* Security Measures Section */}
<div className="mt-8">
{/* Mitigation Mapping Dialog */}
{/* Mesure Mapping Dialog */}
<Dialog
open={isMitigationMappingDialogOpen}
onOpenChange={setIsMitigationMappingDialogOpen}
open={isMesureMappingDialogOpen}
onOpenChange={setIsMesureMappingDialogOpen}
>
<DialogContent className="max-w-3xl max-h-[80vh] overflow-hidden flex flex-col">
<DialogHeader>
@@ -844,8 +825,8 @@ export function Control({
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-tertiary" />
<Input
placeholder="Search security measures by name or description..."
value={mitigationSearchQuery}
onChange={(e) => setMitigationSearchQuery(e.target.value)}
value={mesureSearchQuery}
onChange={(e) => setMesureSearchQuery(e.target.value)}
className="w-full pl-10"
/>
</div>
@@ -862,7 +843,7 @@ export function Control({
</SelectTrigger>
<SelectContent>
<SelectItem value="all">All categories</SelectItem>
{getMitigationCategories().map((category) => (
{getMesureCategories().map((category) => (
<SelectItem key={category} value={category}>
{category}
</SelectItem>
@@ -873,14 +854,14 @@ export function Control({
</div>
<div className="flex-1 overflow-hidden">
{isLoadingMitigations ? (
{isLoadingMesures ? (
<div className="flex items-center justify-center h-full">
<Loader2 className="w-8 h-8 animate-spin text-info" />
<span className="ml-2">Loading security measures...</span>
</div>
) : (
<div className="max-h-[50vh] overflow-y-auto pr-2">
{filteredMitigations().length === 0 ? (
{filteredMesures().length === 0 ? (
<div className="text-center py-8 text-secondary">
No security measures found. Try adjusting your search or
select a different category.
@@ -900,39 +881,39 @@ export function Control({
</tr>
</thead>
<tbody>
{filteredMitigations().map((mitigation) => {
const isLinked = isMitigationLinked(mitigation.id);
{filteredMesures().map((mesure) => {
const isLinked = isMesureLinked(mesure.id);
return (
<tr
key={mitigation.id}
key={mesure.id}
className="border-b hover:bg-invert-bg"
>
<td className="py-3 px-4">
<div className="font-medium">
{mitigation.name}
{mesure.name}
</div>
{mitigation.description && (
{mesure.description && (
<div className="text-xs text-secondary line-clamp-1 mt-0.5">
{mitigation.description}
{mesure.description}
</div>
)}
</td>
<td className="py-3 px-4">
<div
className={`px-2 py-0.5 rounded-full text-xs ${getImportanceColor(
mitigation.importance
mesure.importance
)} inline-block`}
>
{formatImportance(mitigation.importance)}
{formatImportance(mesure.importance)}
</div>
</td>
<td className="py-3 px-4">
<div
className={`px-2 py-0.5 rounded-full text-xs ${getStateColor(
mitigation.state
mesure.state
)} inline-block`}
>
{formatState(mitigation.state)}
{formatState(mesure.state)}
</div>
</td>
<td className="py-3 px-4 text-right whitespace-nowrap">
@@ -941,12 +922,12 @@ export function Control({
variant="outline"
size="sm"
onClick={() =>
handleUnlinkMitigation(mitigation.id)
handleUnlinkMesure(mesure.id)
}
disabled={isUnlinkingMitigation}
disabled={isUnlinkingMesure}
className="text-xs h-7 text-danger border-danger-b hover:bg-h-danger-bg"
>
{isUnlinkingMitigation ? (
{isUnlinkingMesure ? (
<Loader2 className="w-4 h-4 animate-spin" />
) : (
<X className="w-4 h-4" />
@@ -958,12 +939,12 @@ export function Control({
variant="secondary"
size="sm"
onClick={() =>
handleLinkMitigation(mitigation.id)
handleLinkMesure(mesure.id)
}
disabled={isLinkingMitigation}
disabled={isLinkingMesure}
className="text-xs h-7 text-info border-info-b hover:bg-h-info-bg"
>
{isLinkingMitigation ? (
{isLinkingMesure ? (
<Loader2 className="w-4 h-4 animate-spin" />
) : (
<LinkIcon className="w-4 h-4" />
@@ -983,14 +964,14 @@ export function Control({
</div>
<DialogFooter className="mt-4">
<Button onClick={() => setIsMitigationMappingDialogOpen(false)}>
<Button onClick={() => setIsMesureMappingDialogOpen(false)}>
Close
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
{/* Linked Mitigations List */}
{/* Linked Mesures List */}
<div>
<div className="flex justify-between items-center mb-4">
<h3 className="text-xl font-medium text-secondary">
@@ -1000,20 +981,20 @@ export function Control({
variant="outline"
size="sm"
className="flex items-center gap-1"
onClick={handleOpenMitigationMappingDialog}
onClick={handleOpenMesureMappingDialog}
>
<LinkIcon className="w-4 h-4" />
<span>Link Security Measures</span>
</Button>
</div>
{isLoadingMitigations ? (
{isLoadingMesures ? (
<div className="flex items-center justify-center h-24">
<Loader2 className="w-6 h-6 animate-spin text-info" />
<span className="ml-2">Loading security measures...</span>
</div>
) : linkedMitigationsData?.control?.mitigations?.edges &&
linkedMitigationsData.control.mitigations.edges.length > 0 ? (
) : linkedMesuresData?.control?.mesures?.edges &&
linkedMesuresData.control.mesures.edges.length > 0 ? (
<div className="overflow-x-auto border rounded-md">
<table className="w-full">
<thead>
@@ -1027,35 +1008,35 @@ export function Control({
</tr>
</thead>
<tbody>
{getLinkedMitigations().map((mitigation) => (
{getLinkedMesures().map((mesure) => (
<tr
key={mitigation.id}
key={mesure.id}
className="border-b hover:bg-invert-bg"
>
<td className="py-3 px-4">
<div className="font-medium">{mitigation.name}</div>
{mitigation.description && (
<div className="font-medium">{mesure.name}</div>
{mesure.description && (
<div className="text-xs text-secondary line-clamp-1 mt-0.5">
{mitigation.description}
{mesure.description}
</div>
)}
</td>
<td className="py-3 px-4">
<div
className={`px-2 py-0.5 rounded-full text-xs ${getImportanceColor(
mitigation.importance
mesure.importance
)} inline-block`}
>
{formatImportance(mitigation.importance)}
{formatImportance(mesure.importance)}
</div>
</td>
<td className="py-3 px-4">
<div
className={`px-2 py-0.5 rounded-full text-xs ${getStateColor(
mitigation.state
mesure.state
)} inline-block`}
>
{formatState(mitigation.state)}
{formatState(mesure.state)}
</div>
</td>
<td className="py-3 px-4 text-right whitespace-nowrap">
@@ -1067,7 +1048,7 @@ export function Control({
className="text-xs h-7"
>
<Link
to={`/organizations/${organizationId}/mitigations/${mitigation.id}`}
to={`/organizations/${organizationId}/mesures/${mesure.id}`}
>
View
</Link>
@@ -1075,10 +1056,8 @@ export function Control({
<Button
variant="outline"
size="sm"
onClick={() =>
handleUnlinkMitigation(mitigation.id)
}
disabled={isUnlinkingMitigation}
onClick={() => handleUnlinkMesure(mesure.id)}
disabled={isUnlinkingMesure}
className="text-xs h-7 text-danger border-danger-b hover:bg-h-danger-bg"
>
Unlink

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<53f255c3852774870c7d294d64e6808d>>
* @generated SignedSource<<aad63785dac93ad7f8db05ee4f219109>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,21 +9,21 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type CreateControlMitigationMappingInput = {
export type CreateControlMesureMappingInput = {
controlId: string;
mitigationId: string;
mesureId: string;
};
export type MitigationViewCreateControlMappingMutation$variables = {
input: CreateControlMitigationMappingInput;
export type ControlCreateMesureMappingMutation$variables = {
input: CreateControlMesureMappingInput;
};
export type MitigationViewCreateControlMappingMutation$data = {
readonly createControlMitigationMapping: {
export type ControlCreateMesureMappingMutation$data = {
readonly createControlMesureMapping: {
readonly success: boolean;
};
};
export type MitigationViewCreateControlMappingMutation = {
response: MitigationViewCreateControlMappingMutation$data;
variables: MitigationViewCreateControlMappingMutation$variables;
export type ControlCreateMesureMappingMutation = {
response: ControlCreateMesureMappingMutation$data;
variables: ControlCreateMesureMappingMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -44,9 +44,9 @@ v1 = [
"variableName": "input"
}
],
"concreteType": "CreateControlMitigationMappingPayload",
"concreteType": "CreateControlMesureMappingPayload",
"kind": "LinkedField",
"name": "createControlMitigationMapping",
"name": "createControlMesureMapping",
"plural": false,
"selections": [
{
@@ -65,7 +65,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewCreateControlMappingMutation",
"name": "ControlCreateMesureMappingMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
@@ -74,20 +74,20 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewCreateControlMappingMutation",
"name": "ControlCreateMesureMappingMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "fa46c5cf8b96b70117d12cf985247824",
"cacheID": "589fad9dec58fb2efe52e8e587c8ce85",
"id": null,
"metadata": {},
"name": "MitigationViewCreateControlMappingMutation",
"name": "ControlCreateMesureMappingMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewCreateControlMappingMutation(\n $input: CreateControlMitigationMappingInput!\n) {\n createControlMitigationMapping(input: $input) {\n success\n }\n}\n"
"text": "mutation ControlCreateMesureMappingMutation(\n $input: CreateControlMesureMappingInput!\n) {\n createControlMesureMapping(input: $input) {\n success\n }\n}\n"
}
};
})();
(node as any).hash = "af6e4d7933e5c428eec0e97cdf0b73dd";
(node as any).hash = "8974d4f4025f6e1eaba2a6b30e357486";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<f34a09cd4eda414409384386a4cea5b4>>
* @generated SignedSource<<272b7b4a8bc0c81baa4a8d8f3656be0c>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,21 +9,21 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type DeleteControlMitigationMappingInput = {
export type DeleteControlMesureMappingInput = {
controlId: string;
mitigationId: string;
mesureId: string;
};
export type MitigationViewDeleteControlMappingMutation$variables = {
input: DeleteControlMitigationMappingInput;
export type ControlDeleteMesureMappingMutation$variables = {
input: DeleteControlMesureMappingInput;
};
export type MitigationViewDeleteControlMappingMutation$data = {
readonly deleteControlMitigationMapping: {
export type ControlDeleteMesureMappingMutation$data = {
readonly deleteControlMesureMapping: {
readonly success: boolean;
};
};
export type MitigationViewDeleteControlMappingMutation = {
response: MitigationViewDeleteControlMappingMutation$data;
variables: MitigationViewDeleteControlMappingMutation$variables;
export type ControlDeleteMesureMappingMutation = {
response: ControlDeleteMesureMappingMutation$data;
variables: ControlDeleteMesureMappingMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -44,9 +44,9 @@ v1 = [
"variableName": "input"
}
],
"concreteType": "DeleteControlMitigationMappingPayload",
"concreteType": "DeleteControlMesureMappingPayload",
"kind": "LinkedField",
"name": "deleteControlMitigationMapping",
"name": "deleteControlMesureMapping",
"plural": false,
"selections": [
{
@@ -65,7 +65,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewDeleteControlMappingMutation",
"name": "ControlDeleteMesureMappingMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
@@ -74,20 +74,20 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewDeleteControlMappingMutation",
"name": "ControlDeleteMesureMappingMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "b18a11215ba33a6c770cc08c88a28769",
"cacheID": "66b2b12e57f8a150825f0e3f25494093",
"id": null,
"metadata": {},
"name": "MitigationViewDeleteControlMappingMutation",
"name": "ControlDeleteMesureMappingMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewDeleteControlMappingMutation(\n $input: DeleteControlMitigationMappingInput!\n) {\n deleteControlMitigationMapping(input: $input) {\n success\n }\n}\n"
"text": "mutation ControlDeleteMesureMappingMutation(\n $input: DeleteControlMesureMappingInput!\n) {\n deleteControlMesureMapping(input: $input) {\n success\n }\n}\n"
}
};
})();
(node as any).hash = "f4f01abb45a3288558d7e8a1d19ce1ed";
(node as any).hash = "64e6f03a12a22a87e4893a335e58379b";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<d03d81a6969d83d42491f33bcbd1fc00>>
* @generated SignedSource<<03360061cfc99eaa1ec9921a815f9fa0>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,31 +9,31 @@
// @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 ControlLinkedMitigationsQuery$variables = {
export type MesureImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type MesureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type ControlLinkedMesuresQuery$variables = {
controlId: string;
};
export type ControlLinkedMitigationsQuery$data = {
export type ControlLinkedMesuresQuery$data = {
readonly control: {
readonly id: string;
readonly mitigations?: {
readonly mesures?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly category: string;
readonly description: string;
readonly id: string;
readonly importance: MitigationImportance;
readonly importance: MesureImportance;
readonly name: string;
readonly state: MitigationState;
readonly state: MesureState;
};
}>;
};
};
};
export type ControlLinkedMitigationsQuery = {
response: ControlLinkedMitigationsQuery$data;
variables: ControlLinkedMitigationsQuery$variables;
export type ControlLinkedMesuresQuery = {
response: ControlLinkedMesuresQuery$data;
variables: ControlLinkedMesuresQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -69,7 +69,7 @@ v4 = [
{
"alias": null,
"args": null,
"concreteType": "MitigationEdge",
"concreteType": "MesureEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
@@ -77,7 +77,7 @@ v4 = [
{
"alias": null,
"args": null,
"concreteType": "Mitigation",
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "node",
"plural": false,
@@ -170,7 +170,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ControlLinkedMitigationsQuery",
"name": "ControlLinkedMesuresQuery",
"selections": [
{
"alias": "control",
@@ -185,11 +185,11 @@ return {
"kind": "InlineFragment",
"selections": [
{
"alias": "mitigations",
"alias": "mesures",
"args": null,
"concreteType": "MitigationConnection",
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "__Control__mitigations_connection",
"name": "__Control__mesures_connection",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": null
@@ -209,7 +209,7 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ControlLinkedMitigationsQuery",
"name": "ControlLinkedMesuresQuery",
"selections": [
{
"alias": "control",
@@ -227,21 +227,21 @@ return {
{
"alias": null,
"args": (v5/*: any*/),
"concreteType": "MitigationConnection",
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "mitigations",
"name": "mesures",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": "mitigations(first:100)"
"storageKey": "mesures(first:100)"
},
{
"alias": null,
"args": (v5/*: any*/),
"filters": null,
"handle": "connection",
"key": "Control__mitigations",
"key": "Control__mesures",
"kind": "LinkedHandle",
"name": "mitigations"
"name": "mesures"
}
],
"type": "Control",
@@ -253,7 +253,7 @@ return {
]
},
"params": {
"cacheID": "082617925f3db2937654823bd7dc8833",
"cacheID": "19d9240a60b26d765a93e00be9e1e83f",
"id": null,
"metadata": {
"connection": [
@@ -263,18 +263,18 @@ return {
"direction": "forward",
"path": [
"control",
"mitigations"
"mesures"
]
}
]
},
"name": "ControlLinkedMitigationsQuery",
"name": "ControlLinkedMesuresQuery",
"operationKind": "query",
"text": "query ControlLinkedMitigationsQuery(\n $controlId: ID!\n) {\n control: node(id: $controlId) {\n __typename\n id\n ... on Control {\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"
"text": "query ControlLinkedMesuresQuery(\n $controlId: ID!\n) {\n control: node(id: $controlId) {\n __typename\n id\n ... on Control {\n mesures(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 = "3d61e207c8a46a72f19e3414152438b8";
(node as any).hash = "acb01a862fb268c4b4b557edc3090a0e";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<3c11f3c5fa5a298493ba19d950baa7d2>>
* @generated SignedSource<<345a2b05f66a0bb630eea3c12f549e52>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,31 +9,31 @@
// @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 ControlOrganizationMitigationsQuery$variables = {
export type MesureImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type MesureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type ControlOrganizationMesuresQuery$variables = {
organizationId: string;
};
export type ControlOrganizationMitigationsQuery$data = {
export type ControlOrganizationMesuresQuery$data = {
readonly organization: {
readonly id: string;
readonly mitigations?: {
readonly mesures?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly category: string;
readonly description: string;
readonly id: string;
readonly importance: MitigationImportance;
readonly importance: MesureImportance;
readonly name: string;
readonly state: MitigationState;
readonly state: MesureState;
};
}>;
};
};
};
export type ControlOrganizationMitigationsQuery = {
response: ControlOrganizationMitigationsQuery$data;
variables: ControlOrganizationMitigationsQuery$variables;
export type ControlOrganizationMesuresQuery = {
response: ControlOrganizationMesuresQuery$data;
variables: ControlOrganizationMesuresQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -69,7 +69,7 @@ v4 = [
{
"alias": null,
"args": null,
"concreteType": "MitigationEdge",
"concreteType": "MesureEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
@@ -77,7 +77,7 @@ v4 = [
{
"alias": null,
"args": null,
"concreteType": "Mitigation",
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "node",
"plural": false,
@@ -170,7 +170,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ControlOrganizationMitigationsQuery",
"name": "ControlOrganizationMesuresQuery",
"selections": [
{
"alias": "organization",
@@ -185,11 +185,11 @@ return {
"kind": "InlineFragment",
"selections": [
{
"alias": "mitigations",
"alias": "mesures",
"args": null,
"concreteType": "MitigationConnection",
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "__Organization__mitigations_connection",
"name": "__Organization__mesures_connection",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": null
@@ -209,7 +209,7 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ControlOrganizationMitigationsQuery",
"name": "ControlOrganizationMesuresQuery",
"selections": [
{
"alias": "organization",
@@ -227,21 +227,21 @@ return {
{
"alias": null,
"args": (v5/*: any*/),
"concreteType": "MitigationConnection",
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "mitigations",
"name": "mesures",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": "mitigations(first:100)"
"storageKey": "mesures(first:100)"
},
{
"alias": null,
"args": (v5/*: any*/),
"filters": null,
"handle": "connection",
"key": "Organization__mitigations",
"key": "Organization__mesures",
"kind": "LinkedHandle",
"name": "mitigations"
"name": "mesures"
}
],
"type": "Organization",
@@ -253,7 +253,7 @@ return {
]
},
"params": {
"cacheID": "21e0815f3ed8b62621aa0d7824a93036",
"cacheID": "59ceb60db60754876774a3856686b35c",
"id": null,
"metadata": {
"connection": [
@@ -263,18 +263,18 @@ return {
"direction": "forward",
"path": [
"organization",
"mitigations"
"mesures"
]
}
]
},
"name": "ControlOrganizationMitigationsQuery",
"name": "ControlOrganizationMesuresQuery",
"operationKind": "query",
"text": "query ControlOrganizationMitigationsQuery(\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"
"text": "query ControlOrganizationMesuresQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n mesures(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 = "54b1b5a6966cf761d49739da3a988db8";
(node as any).hash = "cc43b07a1a1f5831f5d09fbd13d8805d";
export default node;

View File

@@ -4,26 +4,26 @@ import { lazy } from "@probo/react-lazy";
import { useLocation } from "react-router";
import { ErrorBoundaryWithLocation } from "../ErrorBoundary";
const NewMitigationView = lazy(() => import("./NewMitigationView"));
const EditMesureView = lazy(() => import("./EditMesureView"));
export function NewMitigationViewSkeleton() {
export function EditMesureViewSkeleton() {
return (
<PageTemplateSkeleton
title="New Mitigation"
description="Add a new mitigation. You will be able to link it to control and risks"
title="Edit Mesure"
description="Edit a Mesure. You will be able to link it to control and risks"
>
<div className="max-w-2xl aspect-square bg-subtle-bg rounded-xl animate-pulse" />
</PageTemplateSkeleton>
);
}
export function NewMitigationPage() {
export function EditMesurePage() {
const location = useLocation();
return (
<Suspense key={location.pathname} fallback={<NewMitigationViewSkeleton />}>
<Suspense key={location.pathname} fallback={<EditMesureViewSkeleton />}>
<ErrorBoundaryWithLocation>
<NewMitigationView />
<EditMesureView />
</ErrorBoundaryWithLocation>
</Suspense>
);

View File

@@ -9,19 +9,19 @@ import {
import { useParams, useNavigate } from "react-router";
import { PageTemplate } from "@/components/PageTemplate";
import { useToast } from "@/hooks/use-toast";
import { EditMitigationViewUpdateMitigationMutation } from "./__generated__/EditMitigationViewUpdateMitigationMutation.graphql";
import { EditMesureViewUpdateMesureMutation } from "./__generated__/EditMesureViewUpdateMesureMutation.graphql";
import { EditableField } from "@/components/EditableField";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { cn } from "@/lib/utils";
import { EditMitigationViewSkeleton } from "./EditMitigationPage";
import { EditMitigationViewQuery } from "./__generated__/EditMitigationViewQuery.graphql";
import { EditMesureViewSkeleton } from "./EditMesurePage";
import { EditMesureViewQuery } from "./__generated__/EditMesureViewQuery.graphql";
const editMitigationQuery = graphql`
query EditMitigationViewQuery($mitigationId: ID!) {
node(id: $mitigationId) {
... on Mitigation {
const editMesureQuery = graphql`
query EditMesureViewQuery($mesureId: ID!) {
node(id: $mesureId) {
... on Mesure {
id
name
description
@@ -32,12 +32,10 @@ const editMitigationQuery = graphql`
}
`;
const updateMitigationMutation = graphql`
mutation EditMitigationViewUpdateMitigationMutation(
$input: UpdateMitigationInput!
) {
updateMitigation(input: $input) {
mitigation {
const updateMesureMutation = graphql`
mutation EditMesureViewUpdateMesureMutation($input: UpdateMesureInput!) {
updateMesure(input: $input) {
mesure {
id
name
description
@@ -46,29 +44,27 @@ const updateMitigationMutation = graphql`
}
`;
function EditMitigationViewContent({
function EditMesureViewContent({
queryRef,
}: {
queryRef: PreloadedQuery<EditMitigationViewQuery>;
queryRef: PreloadedQuery<EditMesureViewQuery>;
}) {
const { organizationId } = useParams<{
organizationId: string;
}>();
const { mitigationId } = useParams();
const { mesureId } = useParams();
const navigate = useNavigate();
const { toast } = useToast();
const { node: mitigation } = usePreloadedQuery(editMitigationQuery, queryRef);
const { node: mesure } = usePreloadedQuery(editMesureQuery, queryRef);
const [formData, setFormData] = useState({
name: mitigation.name ?? "",
description: mitigation.description ?? "",
category: mitigation.category ?? "",
importance: mitigation.importance,
name: mesure.name ?? "",
description: mesure.description ?? "",
category: mesure.category ?? "",
importance: mesure.importance,
});
const [commit, isInFlight] =
useMutation<EditMitigationViewUpdateMitigationMutation>(
updateMitigationMutation
);
useMutation<EditMesureViewUpdateMesureMutation>(updateMesureMutation);
const handleFieldChange = (field: keyof typeof formData, value: unknown) => {
setFormData((prev) => ({
@@ -92,7 +88,7 @@ function EditMitigationViewContent({
commit({
variables: {
input: {
id: mitigationId!,
id: mesureId!,
name: formData.name,
description: formData.description,
category: formData.category,
@@ -103,7 +99,7 @@ function EditMitigationViewContent({
if (errors) {
toast({
title: "Error",
description: errors[0]?.message || "Failed to update mitigation",
description: errors[0]?.message || "Failed to update mesure",
variant: "destructive",
});
return;
@@ -111,12 +107,10 @@ function EditMitigationViewContent({
toast({
title: "Success",
description: "Mitigation updated successfully",
description: "Mesure updated successfully",
});
navigate(
`/organizations/${organizationId}/mitigations/${mitigationId}`
);
navigate(`/organizations/${organizationId}/mesures/${mesureId}`);
},
onError(error) {
toast({
@@ -130,8 +124,8 @@ function EditMitigationViewContent({
return (
<PageTemplate
title="Edit Mitigation"
description="Edit a mitigation. You will be able to link it to control and risks"
title="Edit Mesure"
description="Edit a mesure. You will be able to link it to control and risks"
>
<Card className="max-w-2xl">
<form onSubmit={handleSubmit} className="p-6 space-y-6">
@@ -148,7 +142,7 @@ function EditMitigationViewContent({
onChange={(value) => handleFieldChange("description", value)}
required
multiline
helpText="Provide a detailed description of the mitigation"
helpText="Provide a detailed description of the mesure"
/>
<EditableField
@@ -209,15 +203,13 @@ function EditMitigationViewContent({
type="button"
variant="outline"
onClick={() =>
navigate(
`/organizations/${organizationId}/mitigations/${mitigationId}`
)
navigate(`/organizations/${organizationId}/mesures/${mesureId}`)
}
>
Cancel
</Button>
<Button type="submit" disabled={isInFlight}>
{isInFlight ? "Updating..." : "Update Mitigation"}
{isInFlight ? "Updating..." : "Update Mesure"}
</Button>
</div>
</form>
@@ -226,24 +218,24 @@ function EditMitigationViewContent({
);
}
export default function EditMitigationView() {
const { mitigationId } = useParams();
export default function EditMesureView() {
const { mesureId } = useParams();
const [queryRef, loadQuery] =
useQueryLoader<EditMitigationViewQuery>(editMitigationQuery);
useQueryLoader<EditMesureViewQuery>(editMesureQuery);
useEffect(() => {
if (mitigationId) {
loadQuery({ mitigationId });
if (mesureId) {
loadQuery({ mesureId });
}
}, [mitigationId, loadQuery]);
}, [mesureId, loadQuery]);
if (!queryRef) {
return <EditMitigationViewSkeleton />;
return <EditMesureViewSkeleton />;
}
return (
<Suspense fallback={<EditMitigationViewSkeleton />}>
<EditMitigationViewContent queryRef={queryRef} />
<Suspense fallback={<EditMesureViewSkeleton />}>
<EditMesureViewContent queryRef={queryRef} />
</Suspense>
);
}

View File

@@ -4,13 +4,13 @@ import { lazy } from "@probo/react-lazy";
import { useLocation } from "react-router";
import { ErrorBoundaryWithLocation } from "../ErrorBoundary";
const MitigationListView = lazy(() => import("./MitigationListView"));
const MesureListView = lazy(() => import("./MesureListView"));
export function MitigationListViewSkeleton() {
export function MesureListViewSkeleton() {
return (
<PageTemplateSkeleton
title="Mitigations"
description="Mitigations are actions taken to reduce the risk of a risk."
title="Mesures"
description="Mesures are actions taken to reduce the risk of a risk."
>
<div className="space-y-6">
<div className="h-[72px] bg-subtle-bg animate-pulse rounded-xl" />
@@ -31,13 +31,13 @@ export function MitigationListViewSkeleton() {
);
}
export function MitigationListPage() {
export function MesureListPage() {
const location = useLocation();
return (
<Suspense key={location.pathname} fallback={<MitigationListViewSkeleton />}>
<Suspense key={location.pathname} fallback={<MesureListViewSkeleton />}>
<ErrorBoundaryWithLocation>
<MitigationListView />
<MesureListView />
</ErrorBoundaryWithLocation>
</Suspense>
);

View File

@@ -21,11 +21,11 @@ import {
} from "lucide-react";
import { PageTemplate } from "@/components/PageTemplate";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { MitigationListViewQuery as MitigationListViewQueryType } from "./__generated__/MitigationListViewQuery.graphql";
import { MitigationListViewSkeleton } from "./MitigationListPage";
import { MesureListViewQuery as MesureListViewQueryType } from "./__generated__/MesureListViewQuery.graphql";
import { MesureListViewSkeleton } from "./MesureListPage";
import { Button } from "@/components/ui/button";
import { useToast } from "@/hooks/use-toast";
import { MitigationListViewImportMitigationMutation as MitigationListViewImportMitigationMutationType } from "./__generated__/MitigationListViewImportMitigationMutation.graphql";
import { MesureListViewImportMesureMutation as MesureListViewImportMesureMutationType } from "./__generated__/MesureListViewImportMesureMutation.graphql";
import {
Tooltip,
TooltipContent,
@@ -38,13 +38,12 @@ import {
PopoverTrigger,
} from "@/components/ui/popover";
const mitigationListViewQuery = graphql`
query MitigationListViewQuery($organizationId: ID!, $first: Int) {
const mesureListViewQuery = graphql`
query MesureListViewQuery($organizationId: ID!, $first: Int) {
organization: node(id: $organizationId) {
id
... on Organization {
mitigations(first: $first)
@connection(key: "MitigationListView_mitigations") {
mesures(first: $first) @connection(key: "MesureListView_mesures") {
edges {
node {
id
@@ -63,13 +62,13 @@ const mitigationListViewQuery = graphql`
}
`;
const importMitigationMutation = graphql`
mutation MitigationListViewImportMitigationMutation(
$input: ImportMitigationInput!
const importMesureMutation = graphql`
mutation MesureListViewImportMesureMutation(
$input: ImportMesureInput!
$connections: [ID!]!
) {
importMitigation(input: $input) {
mitigationEdges @appendEdge(connections: $connections) {
importMesure(input: $input) {
mesureEdges @appendEdge(connections: $connections) {
node {
id
name
@@ -85,7 +84,7 @@ const importMitigationMutation = graphql`
}
`;
interface Mitigation {
interface Mesure {
id?: string;
name?: string;
description?: string;
@@ -102,7 +101,7 @@ interface Category {
name: string;
description: string;
progress: number;
mitigations: Mitigation[];
mesures: Mesure[];
doneCount: number;
totalCount: number;
}
@@ -110,21 +109,21 @@ interface Category {
interface OrganizationData {
organization: {
id: string;
mitigations?: {
mesures?: {
edges: Array<{
node: Mitigation;
node: Mesure;
}>;
};
};
}
function MitigationListContent({
function MesureListContent({
queryRef,
}: {
queryRef: PreloadedQuery<MitigationListViewQueryType>;
queryRef: PreloadedQuery<MesureListViewQueryType>;
}) {
const data = usePreloadedQuery<MitigationListViewQueryType>(
mitigationListViewQuery,
const data = usePreloadedQuery<MesureListViewQueryType>(
mesureListViewQuery,
queryRef
) as unknown as OrganizationData;
@@ -133,10 +132,8 @@ function MitigationListContent({
const [isImporting, setIsImporting] = useState(false);
const { toast } = useToast();
const [importMitigation] =
useMutation<MitigationListViewImportMitigationMutationType>(
importMitigationMutation
);
const [importMesure] =
useMutation<MesureListViewImportMesureMutationType>(importMesureMutation);
// Monitor URL hash for changes and update state accordingly
const [initialHashCategory] = useState(() =>
@@ -181,10 +178,10 @@ function MitigationListContent({
};
}, [expandedCategories]);
const mitigations =
data.organization.mitigations?.edges.map((edge) => edge.node) ?? [];
const mesures =
data.organization.mesures?.edges.map((edge) => edge.node) ?? [];
// Map mitigation state to status for the new design
// Map mesure state to status for the new design
const mapStateToStatus = (state?: string): string => {
if (!state) return "incomplete";
switch (state) {
@@ -201,48 +198,48 @@ function MitigationListContent({
}
};
const processedMitigations = mitigations.map((mitigation: Mitigation) => ({
...mitigation,
status: mapStateToStatus(mitigation.state),
const processedMesures = mesures.map((mesure: Mesure) => ({
...mesure,
status: mapStateToStatus(mesure.state),
}));
// Calculate global progress
const implementedCount = processedMitigations.filter(
(mitigation: Mitigation) => mitigation.status === "complete"
const implementedCount = processedMesures.filter(
(mesure: Mesure) => mesure.status === "complete"
).length;
const notApplicableCount = processedMitigations.filter(
(mitigation: Mitigation) => mitigation.status === "not-applicable"
const notApplicableCount = processedMesures.filter(
(mesure: Mesure) => mesure.status === "not-applicable"
).length;
const totalMitigations = processedMitigations.length;
const totalMesures = processedMesures.length;
// Include not-applicable as effectively "complete" for progress percentage
const effectiveCompletedCount = implementedCount + notApplicableCount;
const globalProgress = totalMitigations
? Math.round((effectiveCompletedCount / totalMitigations) * 100)
const globalProgress = totalMesures
? Math.round((effectiveCompletedCount / totalMesures) * 100)
: 0;
// Get global status counts
const globalStatusCounts = processedMitigations.reduce(
(acc: Record<string, number>, mitigation: Mitigation) => {
if (mitigation.status) {
acc[mitigation.status] = (acc[mitigation.status] || 0) + 1;
const globalStatusCounts = processedMesures.reduce(
(acc: Record<string, number>, mesure: Mesure) => {
if (mesure.status) {
acc[mesure.status] = (acc[mesure.status] || 0) + 1;
}
return acc;
},
{} as Record<string, number>
);
// Group mitigations by category
const mitigationsByCategory = processedMitigations.reduce(
(acc: Record<string, Mitigation[]>, mitigation: Mitigation) => {
if (!mitigation?.category) return acc;
if (!acc[mitigation.category]) {
acc[mitigation.category] = [];
// Group mesures by category
const mesuresByCategory = processedMesures.reduce(
(acc: Record<string, Mesure[]>, mesure: Mesure) => {
if (!mesure?.category) return acc;
if (!acc[mesure.category]) {
acc[mesure.category] = [];
}
acc[mitigation.category].push(mitigation);
acc[mesure.category].push(mesure);
return acc;
},
{} as Record<string, Mitigation[]>
{} as Record<string, Mesure[]>
);
// Function to toggle a category's expanded state
@@ -256,17 +253,17 @@ function MitigationListContent({
});
};
const categories: Category[] = Object.entries(mitigationsByCategory)
.map(([categoryName, categoryMitigations]: [string, Mitigation[]]) => {
const catImplementedCount = categoryMitigations.filter(
(mitigation) => mitigation.status === "complete"
const categories: Category[] = Object.entries(mesuresByCategory)
.map(([categoryName, categoryMesures]: [string, Mesure[]]) => {
const catImplementedCount = categoryMesures.filter(
(mesure) => mesure.status === "complete"
).length;
const catNotApplicableCount = categoryMitigations.filter(
(mitigation) => mitigation.status === "not-applicable"
const catNotApplicableCount = categoryMesures.filter(
(mesure) => mesure.status === "not-applicable"
).length;
// Consider both "complete" and "not-applicable" as done for category progress
const catDoneCount = catImplementedCount + catNotApplicableCount;
const catTotalCount = categoryMitigations.length;
const catTotalCount = categoryMesures.length;
const progress = catTotalCount
? Math.round((catDoneCount / catTotalCount) * 100)
: 0;
@@ -274,16 +271,16 @@ function MitigationListContent({
return {
id: categoryName,
name: categoryName,
description: `Mitigations related to ${categoryName.toLowerCase()}`,
description: `Mesures related to ${categoryName.toLowerCase()}`,
progress: progress,
mitigations: categoryMitigations.sort((a, b) =>
mesures: categoryMesures.sort((a, b) =>
(a.name || "").localeCompare(b.name || "")
),
doneCount: catDoneCount,
totalCount: catTotalCount,
};
})
.filter((category) => category.mitigations.length > 0)
.filter((category) => category.mesures.length > 0)
.sort((a, b) => a.name.localeCompare(b.name));
const getStatusIcon = (status: string) => {
@@ -309,12 +306,12 @@ function MitigationListContent({
setIsImporting(true);
importMitigation({
importMesure({
variables: {
connections: [
ConnectionHandler.getConnectionID(
data.organization.id,
"MitigationListView_mitigations"
"MesureListView_mesures"
),
],
input: {
@@ -328,8 +325,8 @@ function MitigationListContent({
onCompleted: () => {
setIsImporting(false);
toast({
title: "Mitigations imported",
description: "Mitigations have been imported successfully.",
title: "Mesures imported",
description: "Mesures have been imported successfully.",
variant: "default",
});
if (fileInputRef.current) {
@@ -339,7 +336,7 @@ function MitigationListContent({
onError: (error) => {
setIsImporting(false);
toast({
title: "Error importing mitigations",
title: "Error importing mesures",
description: error.message,
variant: "destructive",
});
@@ -349,8 +346,8 @@ function MitigationListContent({
return (
<PageTemplate
title="Mitigations"
description="Mitigations are actions taken to reduce the risk. Add them to track their implementation status."
title="Mesures"
description="Mesures are actions taken to reduce the risk. Add them to track their implementation status."
actions={
<div className="flex gap-4">
<Button
@@ -358,17 +355,17 @@ function MitigationListContent({
onClick={() => fileInputRef.current?.click()}
disabled={isImporting}
>
{isImporting ? "Importing..." : "Import Mitigations"}
{isImporting ? "Importing..." : "Import Mesures"}
</Button>
<Button asChild>
<Link to={`/organizations/${organizationId}/mitigations/new`}>
New Mitigation
<Link to={`/organizations/${organizationId}/mesures/new`}>
New Mesure
</Link>
</Button>
</div>
}
>
{/* Hidden file input for mitigation import */}
{/* Hidden file input for mesure import */}
<input
type="file"
ref={fileInputRef}
@@ -380,7 +377,7 @@ function MitigationListContent({
{/* Global Progress Summary */}
<div className="mb-8">
<div className="flex items-center justify-between mb-1">
<h3 className="text-lg font-medium">Mitigation Implementation</h3>
<h3 className="text-lg font-medium">Mesure Implementation</h3>
<span className="text-sm text-tertiary">
{globalProgress}% complete
</span>
@@ -396,7 +393,7 @@ function MitigationListContent({
className="bg-green-500 h-full"
style={{
width: `${
(globalStatusCounts.complete / totalMitigations) * 100
(globalStatusCounts.complete / totalMesures) * 100
}%`,
}}
/>
@@ -407,7 +404,7 @@ function MitigationListContent({
className="bg-blue-500 h-full"
style={{
width: `${
(globalStatusCounts["in-progress"] / totalMitigations) * 100
(globalStatusCounts["in-progress"] / totalMesures) * 100
}%`,
}}
/>
@@ -418,7 +415,7 @@ function MitigationListContent({
className="bg-red-500 h-full"
style={{
width: `${
(globalStatusCounts.incomplete / totalMitigations) * 100
(globalStatusCounts.incomplete / totalMesures) * 100
}%`,
}}
/>
@@ -429,8 +426,7 @@ function MitigationListContent({
className="bg-primary-bg h-full"
style={{
width: `${
(globalStatusCounts["not-applicable"] / totalMitigations) *
100
(globalStatusCounts["not-applicable"] / totalMesures) * 100
}%`,
}}
/>
@@ -441,7 +437,7 @@ function MitigationListContent({
className="bg-secondary h-full"
style={{
width: `${
(globalStatusCounts["not-started"] / totalMitigations) * 100
(globalStatusCounts["not-started"] / totalMesures) * 100
}%`,
}}
/>
@@ -521,7 +517,7 @@ function MitigationListContent({
{isExpanded && (
<CardContent className="p-0">
{category.mitigations.length > 0 ? (
{category.mesures.length > 0 ? (
<div className="w-full">
<table className="w-full">
<thead>
@@ -532,26 +528,24 @@ function MitigationListContent({
<th className="w-24 px-4 py-2 text-left">
Status
</th>
<th className="px-4 py-2 text-left">
Mitigation
</th>
<th className="px-4 py-2 text-left">Mesure</th>
</tr>
</thead>
<tbody className="divide-y">
{category.mitigations.map((mitigation) => (
{category.mesures.map((mesure) => (
<tr
key={mitigation.id || Math.random().toString()}
key={mesure.id || Math.random().toString()}
className="hover:bg-h-subtle-bg cursor-pointer"
>
<td className="w-24 px-4 py-3 align-middle">
<Badge variant="outline" className="text-xs">
{mitigation.importance}
{mesure.importance}
</Badge>
</td>
<td className="w-24 px-4 py-3 align-middle">
<div className="flex items-center justify-center">
{mitigation.status
? getStatusIcon(mitigation.status)
{mesure.status
? getStatusIcon(mesure.status)
: null}
</div>
</td>
@@ -561,11 +555,11 @@ function MitigationListContent({
<Tooltip>
<TooltipTrigger asChild>
<Link
to={`/organizations/${organizationId}/mitigations/${mitigation.id}`}
to={`/organizations/${organizationId}/mesures/${mesure.id}`}
className="font-medium group flex items-center relative"
>
<span className="mr-1">
{mitigation.name}
{mesure.name}
</span>
<span className="absolute bottom-0 left-0 w-full h-0.5 bg-primary-bg scale-x-0 group-hover:scale-x-100 transition-transform"></span>
</Link>
@@ -584,7 +578,7 @@ function MitigationListContent({
<Button
variant="ghost"
className="p-0 h-6 w-6 rounded-full hover:bg-primary-bg"
aria-label="Learn more about this mitigation"
aria-label="Learn more about this mesure"
>
<HelpCircle className="h-5 w-5 text-primary hover:text-primary" />
</Button>
@@ -597,26 +591,26 @@ function MitigationListContent({
<div className="space-y-3">
<div className="flex justify-between items-start">
<h4 className="font-bold text-md">
{mitigation.name}
{mesure.name}
</h4>
<Badge
variant="outline"
className="text-xs"
>
{mitigation.importance}
{mesure.importance}
</Badge>
</div>
{mitigation.description && (
{mesure.description && (
<div className="text-sm">
<p className="font-semibold mb-1">
Why is this important:
</p>
<p>
{mitigation.description.startsWith(
{mesure.description.startsWith(
"##"
)
? mitigation.description
? mesure.description
.split("\n")
.find((line) =>
line.startsWith(
@@ -626,16 +620,16 @@ function MitigationListContent({
?.replace("## Why?", "")
?.replace("## Why", "")
?.trim() ||
mitigation.description.split(
mesure.description.split(
"\n"
)[1] ||
""
: mitigation.description.substring(
: mesure.description.substring(
0,
180
) +
(mitigation.description
.length > 180
(mesure.description.length >
180
? "..."
: "")}
</p>
@@ -650,7 +644,7 @@ function MitigationListContent({
asChild
>
<Link
to={`/organizations/${organizationId}/mitigations/${mitigation.id}`}
to={`/organizations/${organizationId}/mesures/${mesure.id}`}
>
<span>
Implementation guide
@@ -671,7 +665,7 @@ function MitigationListContent({
</div>
) : (
<div className="flex items-center justify-center p-6 text-center text-tertiary">
No mitigations in this category
No mesures in this category
</div>
)}
</CardContent>
@@ -685,10 +679,9 @@ function MitigationListContent({
);
}
export default function MitigationListView() {
const [queryRef, loadQuery] = useQueryLoader<MitigationListViewQueryType>(
mitigationListViewQuery
);
export default function MesureListView() {
const [queryRef, loadQuery] =
useQueryLoader<MesureListViewQueryType>(mesureListViewQuery);
const { organizationId } = useParams();
@@ -700,12 +693,12 @@ export default function MitigationListView() {
}, [loadQuery, organizationId]);
if (!queryRef) {
return <MitigationListViewSkeleton />;
return <MesureListViewSkeleton />;
}
return (
<Suspense fallback={<MitigationListViewSkeleton />}>
<MitigationListContent queryRef={queryRef} />
<Suspense fallback={<MesureListViewSkeleton />}>
<MesureListContent queryRef={queryRef} />
</Suspense>
);
}

View File

@@ -5,9 +5,9 @@ import { lazy } from "@probo/react-lazy";
import { useLocation } from "react-router";
import { ErrorBoundaryWithLocation } from "../ErrorBoundary";
const MitigationView = lazy(() => import("./MitigationView"));
const MesureView = lazy(() => import("./MesureView"));
export function MitigationViewSkeleton() {
export function MesureViewSkeleton() {
return (
<PageTemplateSkeleton
actions={
@@ -32,13 +32,13 @@ export function MitigationViewSkeleton() {
);
}
export function MitigationPage() {
export function MesurePage() {
const location = useLocation();
return (
<Suspense key={location.pathname} fallback={<MitigationViewSkeleton />}>
<Suspense key={location.pathname} fallback={<MesureViewSkeleton />}>
<ErrorBoundaryWithLocation>
<MitigationView />
<MesureView />
</ErrorBoundaryWithLocation>
</Suspense>
);

View File

@@ -79,26 +79,26 @@ import {
import { Badge } from "@/components/ui/badge";
import { PageTemplate } from "@/components/PageTemplate";
import { MitigationViewSkeleton } from "./MitigationPage";
import { MitigationViewUpdateTaskStateMutation as MitigationViewUpdateTaskStateMutationType } from "./__generated__/MitigationViewUpdateTaskStateMutation.graphql";
import { MitigationViewCreateTaskMutation as MitigationViewCreateTaskMutationType } from "./__generated__/MitigationViewCreateTaskMutation.graphql";
import { MitigationViewDeleteTaskMutation as MitigationViewDeleteTaskMutationType } from "./__generated__/MitigationViewDeleteTaskMutation.graphql";
import { MitigationViewDeleteEvidenceMutation as MitigationViewDeleteEvidenceMutationType } from "./__generated__/MitigationViewDeleteEvidenceMutation.graphql";
import { MitigationViewAssignTaskMutation as MitigationViewAssignTaskMutationType } from "./__generated__/MitigationViewAssignTaskMutation.graphql";
import { MitigationViewUnassignTaskMutation as MitigationViewUnassignTaskMutationType } from "./__generated__/MitigationViewUnassignTaskMutation.graphql";
import { MitigationViewUpdateMitigationStateMutation as MitigationViewUpdateMitigationStateMutationType } from "./__generated__/MitigationViewUpdateMitigationStateMutation.graphql";
import { MitigationViewQuery as MitigationViewQueryType } from "./__generated__/MitigationViewQuery.graphql";
import { MitigationViewOrganizationQuery$data } from "./__generated__/MitigationViewOrganizationQuery.graphql";
import { MesureViewSkeleton } from "./MesurePage";
import { MesureViewUpdateTaskStateMutation as MesureViewUpdateTaskStateMutationType } from "./__generated__/MesureViewUpdateTaskStateMutation.graphql";
import { MesureViewCreateTaskMutation as MesureViewCreateTaskMutationType } from "./__generated__/MesureViewCreateTaskMutation.graphql";
import { MesureViewDeleteTaskMutation as MesureViewDeleteTaskMutationType } from "./__generated__/MesureViewDeleteTaskMutation.graphql";
import { MesureViewDeleteEvidenceMutation as MesureViewDeleteEvidenceMutationType } from "./__generated__/MesureViewDeleteEvidenceMutation.graphql";
import { MesureViewAssignTaskMutation as MesureViewAssignTaskMutationType } from "./__generated__/MesureViewAssignTaskMutation.graphql";
import { MesureViewUnassignTaskMutation as MesureViewUnassignTaskMutationType } from "./__generated__/MesureViewUnassignTaskMutation.graphql";
import { MesureViewUpdateMesureStateMutation as MesureViewUpdateMesureStateMutationType } from "./__generated__/MesureViewUpdateMesureStateMutation.graphql";
import { MesureViewQuery as MesureViewQueryType } from "./__generated__/MesureViewQuery.graphql";
import { MesureViewOrganizationQuery$data } from "./__generated__/MesureViewOrganizationQuery.graphql";
import {
MitigationViewFrameworksQuery,
MitigationViewFrameworksQuery$data,
} from "./__generated__/MitigationViewFrameworksQuery.graphql";
MesureViewFrameworksQuery,
MesureViewFrameworksQuery$data,
} from "./__generated__/MesureViewFrameworksQuery.graphql";
import {
MitigationViewLinkedControlsQuery,
MitigationViewLinkedControlsQuery$data,
} from "./__generated__/MitigationViewLinkedControlsQuery.graphql";
import { MitigationViewCreateEvidenceMutation as MitigationViewCreateEvidenceMutationType } from "./__generated__/MitigationViewCreateEvidenceMutation.graphql";
import { MitigationViewFulfillEvidenceMutation as MitigationViewFulfillEvidenceMutationType } from "./__generated__/MitigationViewFulfillEvidenceMutation.graphql";
MesureViewLinkedControlsQuery,
MesureViewLinkedControlsQuery$data,
} from "./__generated__/MesureViewLinkedControlsQuery.graphql";
import { MesureViewCreateEvidenceMutation as MesureViewCreateEvidenceMutationType } from "./__generated__/MesureViewCreateEvidenceMutation.graphql";
import { MesureViewFulfillEvidenceMutation as MesureViewFulfillEvidenceMutationType } from "./__generated__/MesureViewFulfillEvidenceMutation.graphql";
// Function to format ISO8601 duration to human-readable format
const formatDuration = (isoDuration: string): string => {
@@ -137,17 +137,17 @@ const formatDuration = (isoDuration: string): string => {
}
};
const mitigationViewQuery = graphql`
query MitigationViewQuery($mitigationId: ID!) {
mitigation: node(id: $mitigationId) {
const mesureViewQuery = graphql`
query MesureViewQuery($mesureId: ID!) {
mesure: node(id: $mesureId) {
id
... on Mitigation {
... on Mesure {
name
description
state
importance
category
tasks(first: 100) @connection(key: "MitigationView_tasks") {
tasks(first: 100) @connection(key: "MesureView_tasks") {
__id
edges {
node {
@@ -161,8 +161,7 @@ const mitigationViewQuery = graphql`
fullName
primaryEmailAddress
}
evidences(first: 50)
@connection(key: "MitigationView_evidences") {
evidences(first: 50) @connection(key: "MesureView_evidences") {
__id
edges {
node {
@@ -187,7 +186,7 @@ const mitigationViewQuery = graphql`
`;
const updateTaskStateMutation = graphql`
mutation MitigationViewUpdateTaskStateMutation($input: UpdateTaskInput!) {
mutation MesureViewUpdateTaskStateMutation($input: UpdateTaskInput!) {
updateTask(input: $input) {
task {
id
@@ -199,7 +198,7 @@ const updateTaskStateMutation = graphql`
`;
const createTaskMutation = graphql`
mutation MitigationViewCreateTaskMutation(
mutation MesureViewCreateTaskMutation(
$input: CreateTaskInput!
$connections: [ID!]!
) {
@@ -223,7 +222,7 @@ const createTaskMutation = graphql`
`;
const deleteTaskMutation = graphql`
mutation MitigationViewDeleteTaskMutation(
mutation MesureViewDeleteTaskMutation(
$input: DeleteTaskInput!
$connections: [ID!]!
) {
@@ -234,7 +233,7 @@ const deleteTaskMutation = graphql`
`;
const createEvidenceMutation = graphql`
mutation MitigationViewCreateEvidenceMutation(
mutation MesureViewCreateEvidenceMutation(
$input: CreateEvidenceInput!
$connections: [ID!]!
) {
@@ -258,7 +257,7 @@ const createEvidenceMutation = graphql`
`;
const deleteEvidenceMutation = graphql`
mutation MitigationViewDeleteEvidenceMutation(
mutation MesureViewDeleteEvidenceMutation(
$input: DeleteEvidenceInput!
$connections: [ID!]!
) {
@@ -270,7 +269,7 @@ const deleteEvidenceMutation = graphql`
// Add a GraphQL query to fetch the fileUrl for an evidence item
const getEvidenceFileUrlQuery = graphql`
query MitigationViewGetEvidenceFileUrlQuery($evidenceId: ID!) {
query MesureViewGetEvidenceFileUrlQuery($evidenceId: ID!) {
node(id: $evidenceId) {
... on Evidence {
id
@@ -281,7 +280,7 @@ const getEvidenceFileUrlQuery = graphql`
`;
const assignTaskMutation = graphql`
mutation MitigationViewAssignTaskMutation($input: AssignTaskInput!) {
mutation MesureViewAssignTaskMutation($input: AssignTaskInput!) {
assignTask(input: $input) {
task {
id
@@ -296,7 +295,7 @@ const assignTaskMutation = graphql`
`;
const unassignTaskMutation = graphql`
mutation MitigationViewUnassignTaskMutation($input: UnassignTaskInput!) {
mutation MesureViewUnassignTaskMutation($input: UnassignTaskInput!) {
unassignTask(input: $input) {
task {
id
@@ -310,12 +309,10 @@ const unassignTaskMutation = graphql`
}
`;
const updateMitigationStateMutation = graphql`
mutation MitigationViewUpdateMitigationStateMutation(
$input: UpdateMitigationInput!
) {
updateMitigation(input: $input) {
mitigation {
const updateMesureStateMutation = graphql`
mutation MesureViewUpdateMesureStateMutation($input: UpdateMesureInput!) {
updateMesure(input: $input) {
mesure {
id
state
}
@@ -324,12 +321,12 @@ const updateMitigationStateMutation = graphql`
`;
const organizationQuery = graphql`
query MitigationViewOrganizationQuery($organizationId: ID!) {
query MesureViewOrganizationQuery($organizationId: ID!) {
organization: node(id: $organizationId) {
id
... on Organization {
peoples(first: 100, orderBy: { direction: ASC, field: FULL_NAME })
@connection(key: "MitigationView_peoples") {
@connection(key: "MesureView_peoples") {
edges {
node {
id
@@ -345,7 +342,7 @@ const organizationQuery = graphql`
// New queries and mutations for Control Mapping
const frameworksQuery = graphql`
query MitigationViewFrameworksQuery($organizationId: ID!) {
query MesureViewFrameworksQuery($organizationId: ID!) {
organization: node(id: $organizationId) {
id
... on Organization {
@@ -373,11 +370,11 @@ const frameworksQuery = graphql`
`;
const linkedControlsQuery = graphql`
query MitigationViewLinkedControlsQuery($mitigationId: ID!) {
mitigation: node(id: $mitigationId) {
query MesureViewLinkedControlsQuery($mesureId: ID!) {
mesure: node(id: $mesureId) {
id
... on Mitigation {
controls(first: 100) @connection(key: "Mitigation__controls") {
... on Mesure {
controls(first: 100) @connection(key: "MesureView_controls") {
edges {
node {
id
@@ -393,20 +390,20 @@ const linkedControlsQuery = graphql`
`;
const createControlMappingMutation = graphql`
mutation MitigationViewCreateControlMappingMutation(
$input: CreateControlMitigationMappingInput!
mutation MesureViewCreateControlMappingMutation(
$input: CreateControlMesureMappingInput!
) {
createControlMitigationMapping(input: $input) {
createControlMesureMapping(input: $input) {
success
}
}
`;
const deleteControlMappingMutation = graphql`
mutation MitigationViewDeleteControlMappingMutation(
$input: DeleteControlMitigationMappingInput!
mutation MesureViewDeleteControlMappingMutation(
$input: DeleteControlMesureMappingInput!
) {
deleteControlMitigationMapping(input: $input) {
deleteControlMesureMapping(input: $input) {
success
}
}
@@ -414,7 +411,7 @@ const deleteControlMappingMutation = graphql`
// Add a mutation to fulfill evidence
const fulfillEvidenceMutation = graphql`
mutation MitigationViewFulfillEvidenceMutation(
mutation MesureViewFulfillEvidenceMutation(
$input: FulfillEvidenceInput!
$connections: [ID!]!
) {
@@ -437,13 +434,13 @@ const fulfillEvidenceMutation = graphql`
}
`;
// Add query to fetch risks linked to a mitigation
const mitigationRisksQuery = graphql`
query MitigationViewRisksQuery($mitigationId: ID!) {
mitigation: node(id: $mitigationId) {
// Add query to fetch risks linked to a mesure
const mesureRisksQuery = graphql`
query MesureViewRisksQuery($mesureId: ID!) {
mesure: node(id: $mesureId) {
id
... on Mitigation {
risks(first: 100) @connection(key: "MitigationView_risks") {
... on Mesure {
risks(first: 100) @connection(key: "MesureView_risks") {
edges {
node {
id
@@ -499,8 +496,8 @@ type RiskNode = {
};
// Define the risks data type
type MitigationRisksData = {
mitigation?: {
type MesureRisksData = {
mesure?: {
id: string;
risks?: {
edges: Array<{
@@ -510,17 +507,17 @@ type MitigationRisksData = {
};
};
function MitigationViewContent({
function MesureViewContent({
queryRef,
}: {
queryRef: PreloadedQuery<MitigationViewQueryType>;
queryRef: PreloadedQuery<MesureViewQueryType>;
}) {
const data = usePreloadedQuery<MitigationViewQueryType>(
mitigationViewQuery,
const data = usePreloadedQuery<MesureViewQueryType>(
mesureViewQuery,
queryRef
);
const { toast } = useToast();
const { organizationId, mitigationId } = useParams();
const { organizationId, mesureId } = useParams();
const navigate = useNavigate();
const environment = useRelayEnvironment();
@@ -533,15 +530,15 @@ function MitigationViewContent({
// Load organization data for people selector
const [organizationData, setOrganizationData] =
useState<MitigationViewOrganizationQuery$data | null>(null);
useState<MesureViewOrganizationQuery$data | null>(null);
// Control mapping state
const [isControlMappingDialogOpen, setIsControlMappingDialogOpen] =
useState(false);
const [frameworksData, setFrameworksData] =
useState<MitigationViewFrameworksQuery$data | null>(null);
useState<MesureViewFrameworksQuery$data | null>(null);
const [linkedControlsData, setLinkedControlsData] =
useState<MitigationViewLinkedControlsQuery$data | null>(null);
useState<MesureViewLinkedControlsQuery$data | null>(null);
const [controlSearchQuery, setControlSearchQuery] = useState("");
const [selectedFrameworkId, setSelectedFrameworkId] = useState<string | null>(
null
@@ -562,7 +559,7 @@ function MitigationViewContent({
if (organizationId) {
fetchQuery(environment, organizationQuery, { organizationId }).subscribe({
next: (data: unknown) => {
setOrganizationData(data as MitigationViewOrganizationQuery$data);
setOrganizationData(data as MesureViewOrganizationQuery$data);
},
error: (error: Error) => {
console.error("Error fetching organization:", error);
@@ -573,36 +570,34 @@ function MitigationViewContent({
// Load linked controls when component mounts
useEffect(() => {
if (mitigationId) {
fetchQuery(environment, linkedControlsQuery, { mitigationId }).subscribe({
if (mesureId) {
fetchQuery(environment, linkedControlsQuery, { mesureId }).subscribe({
next: (data: unknown) => {
setLinkedControlsData(data as MitigationViewLinkedControlsQuery$data);
setLinkedControlsData(data as MesureViewLinkedControlsQuery$data);
},
error: (error: Error) => {
console.error("Error fetching linked controls:", error);
},
});
}
}, [environment, mitigationId]);
}, [environment, mesureId]);
// Add state for risks data
const [risksData, setRisksData] = useState<MitigationRisksData | null>(null);
const [risksData, setRisksData] = useState<MesureRisksData | null>(null);
// Load risks data when component mounts
useEffect(() => {
if (mitigationId) {
fetchQuery(environment, mitigationRisksQuery, { mitigationId }).subscribe(
{
next: (data: unknown) => {
setRisksData(data as MitigationRisksData);
},
error: (error: Error) => {
console.error("Error fetching risks:", error);
},
}
);
if (mesureId) {
fetchQuery(environment, mesureRisksQuery, { mesureId }).subscribe({
next: (data: unknown) => {
setRisksData(data as MesureRisksData);
},
error: (error: Error) => {
console.error("Error fetching risks:", error);
},
});
}
}, [environment, mitigationId]);
}, [environment, mesureId]);
const formatImportance = (importance: string | undefined): string => {
if (!importance) return "";
@@ -656,33 +651,30 @@ function MitigationViewContent({
return "bg-secondary-bg text-primary";
};
const [updateTask] = useMutation<MitigationViewUpdateTaskStateMutationType>(
const [updateTask] = useMutation<MesureViewUpdateTaskStateMutationType>(
updateTaskStateMutation
);
const [createTask] =
useMutation<MitigationViewCreateTaskMutationType>(createTaskMutation);
useMutation<MesureViewCreateTaskMutationType>(createTaskMutation);
const [deleteTask] =
useMutation<MitigationViewDeleteTaskMutationType>(deleteTaskMutation);
const [createEvidence] =
useMutation<MitigationViewCreateEvidenceMutationType>(
createEvidenceMutation
);
const [deleteEvidence] =
useMutation<MitigationViewDeleteEvidenceMutationType>(
deleteEvidenceMutation
);
useMutation<MesureViewDeleteTaskMutationType>(deleteTaskMutation);
const [createEvidence] = useMutation<MesureViewCreateEvidenceMutationType>(
createEvidenceMutation
);
const [deleteEvidence] = useMutation<MesureViewDeleteEvidenceMutationType>(
deleteEvidenceMutation
);
const [assignTask] =
useMutation<MitigationViewAssignTaskMutationType>(assignTaskMutation);
useMutation<MesureViewAssignTaskMutationType>(assignTaskMutation);
const [unassignTask] =
useMutation<MitigationViewUnassignTaskMutationType>(unassignTaskMutation);
const [fulfillEvidence] =
useMutation<MitigationViewFulfillEvidenceMutationType>(
fulfillEvidenceMutation
);
useMutation<MesureViewUnassignTaskMutationType>(unassignTaskMutation);
const [fulfillEvidence] = useMutation<MesureViewFulfillEvidenceMutationType>(
fulfillEvidenceMutation
);
const [updateMitigationState] =
useMutation<MitigationViewUpdateMitigationStateMutationType>(
updateMitigationStateMutation
const [updateMesureState] =
useMutation<MesureViewUpdateMesureStateMutationType>(
updateMesureStateMutation
);
const [isCreateTaskOpen, setIsCreateTaskOpen] = useState(false);
@@ -765,7 +757,7 @@ function MitigationViewContent({
// Track if task panel is open
const [isTaskPanelOpen, setIsTaskPanelOpen] = useState(false);
const tasks = data.mitigation.tasks?.edges.map((edge) => edge.node) || [];
const tasks = data.mesure.tasks?.edges.map((edge) => edge.node) || [];
// Add useEffect to handle URL parameters for task selection
useEffect(() => {
@@ -907,10 +899,10 @@ function MitigationViewContent({
return;
}
if (!data.mitigation.id) {
if (!data.mesure.id) {
toast({
title: "Error creating task",
description: "Mitigation ID is missing",
description: "Mesure ID is missing",
variant: "destructive",
});
return;
@@ -920,9 +912,9 @@ function MitigationViewContent({
createTask({
variables: {
connections: [`${data.mitigation.tasks?.__id}`],
connections: [`${data.mesure.tasks?.__id}`],
input: {
mitigationId: data.mitigation.id,
mesureId: data.mesure.id,
name: newTaskName,
description: newTaskDescription,
timeEstimate: isoTimeEstimate === "" ? null : isoTimeEstimate,
@@ -960,7 +952,7 @@ function MitigationViewContent({
deleteTask({
variables: {
connections: [`${data.mitigation.tasks?.__id}`],
connections: [`${data.mesure.tasks?.__id}`],
input: {
taskId: taskToDelete.id,
},
@@ -983,10 +975,8 @@ function MitigationViewContent({
});
};
const handleEditMitigation = () => {
navigate(
`/organizations/${organizationId}/mitigations/${mitigationId}/edit`
);
const handleEditMesure = () => {
navigate(`/organizations/${organizationId}/mesures/${mesureId}/edit`);
};
const handleCreateEvidence = (taskId: string, taskName: string) => {
@@ -1458,12 +1448,12 @@ function MitigationViewContent({
});
};
// Function to handle mitigation state change
const handleMitigationStateChange = (newState: string) => {
updateMitigationState({
// Function to handle mesure state change
const handleMesureStateChange = (newState: string) => {
updateMesureState({
variables: {
input: {
id: data.mitigation.id,
id: data.mesure.id,
state: newState as
| "NOT_STARTED"
| "IN_PROGRESS"
@@ -1473,15 +1463,15 @@ function MitigationViewContent({
},
onCompleted: () => {
toast({
title: "Mitigation state updated",
description: `Mitigation state has been updated to ${formatState(
title: "Mesure state updated",
description: `Mesure state has been updated to ${formatState(
newState
)}.`,
});
},
onError: (error) => {
toast({
title: "Error updating mitigation state",
title: "Error updating mesure state",
description: error.message,
variant: "destructive",
});
@@ -1612,12 +1602,12 @@ function MitigationViewContent({
// Control mapping functions
const loadFrameworksAndControls = useCallback(() => {
if (!organizationId || !mitigationId) return;
if (!organizationId || !mesureId) return;
setIsLoadingControls(true);
// Fetch all frameworks and their controls
fetchQuery<MitigationViewFrameworksQuery>(environment, frameworksQuery, {
fetchQuery<MesureViewFrameworksQuery>(environment, frameworksQuery, {
organizationId,
}).subscribe({
next: (data) => {
@@ -1635,14 +1625,12 @@ function MitigationViewContent({
}
},
complete: () => {
// Fetch already linked controls for this mitigation
// Fetch already linked controls for this mesure
fetchQuery(environment, linkedControlsQuery, {
mitigationId,
mesureId,
}).subscribe({
next: (data: unknown) => {
setLinkedControlsData(
data as MitigationViewLinkedControlsQuery$data
);
setLinkedControlsData(data as MesureViewLinkedControlsQuery$data);
setIsLoadingControls(false);
},
error: (error: Error) => {
@@ -1666,7 +1654,7 @@ function MitigationViewContent({
});
},
});
}, [environment, mitigationId, organizationId, selectedFrameworkId, toast]);
}, [environment, mesureId, organizationId, selectedFrameworkId, toast]);
const getControls = useCallback(() => {
if (!frameworksData?.organization?.frameworks?.edges) return [];
@@ -1691,8 +1679,8 @@ function MitigationViewContent({
}, [frameworksData, selectedFrameworkId]);
const getLinkedControls = useCallback(() => {
if (!linkedControlsData?.mitigation?.controls?.edges) return [];
return (linkedControlsData.mitigation.controls.edges || []).map(
if (!linkedControlsData?.mesure?.controls?.edges) return [];
return (linkedControlsData.mesure.controls.edges || []).map(
(edge) => edge.node
);
}, [linkedControlsData]);
@@ -1709,7 +1697,7 @@ function MitigationViewContent({
const handleLinkControl = useCallback(
(controlId: string) => {
if (!mitigationId) return;
if (!mesureId) return;
setIsLinkingControl(true);
@@ -1717,7 +1705,7 @@ function MitigationViewContent({
variables: {
input: {
controlId,
mitigationId,
mesureId,
},
},
onCompleted: (_, errors) => {
@@ -1734,11 +1722,11 @@ function MitigationViewContent({
}
// Refresh linked controls data
fetchQuery<MitigationViewLinkedControlsQuery>(
fetchQuery<MesureViewLinkedControlsQuery>(
environment,
linkedControlsQuery,
{
mitigationId,
mesureId,
}
).subscribe({
next: (data) => {
@@ -1751,7 +1739,7 @@ function MitigationViewContent({
toast({
title: "Success",
description: "Control successfully linked to mitigation.",
description: "Control successfully linked to mesure.",
});
},
onError: (error) => {
@@ -1765,12 +1753,12 @@ function MitigationViewContent({
},
});
},
[commitCreateControlMapping, environment, mitigationId, toast]
[commitCreateControlMapping, environment, mesureId, toast]
);
const handleUnlinkControl = useCallback(
(controlId: string) => {
if (!mitigationId) return;
if (!mesureId) return;
setIsUnlinkingControl(true);
@@ -1778,7 +1766,7 @@ function MitigationViewContent({
variables: {
input: {
controlId,
mitigationId,
mesureId,
},
},
onCompleted: (_, errors) => {
@@ -1796,12 +1784,10 @@ function MitigationViewContent({
// Refresh linked controls data
fetchQuery(environment, linkedControlsQuery, {
mitigationId,
mesureId,
}).subscribe({
next: (data: unknown) => {
setLinkedControlsData(
data as MitigationViewLinkedControlsQuery$data
);
setLinkedControlsData(data as MesureViewLinkedControlsQuery$data);
},
error: (error: Error) => {
console.error("Error refreshing linked controls:", error);
@@ -1810,7 +1796,7 @@ function MitigationViewContent({
toast({
title: "Success",
description: "Control successfully unlinked from mitigation.",
description: "Control successfully unlinked from mesure.",
});
},
onError: (error) => {
@@ -1824,7 +1810,7 @@ function MitigationViewContent({
},
});
},
[commitDeleteControlMapping, environment, mitigationId, toast]
[commitDeleteControlMapping, environment, mesureId, toast]
);
const handleOpenControlMappingDialog = useCallback(() => {
@@ -1882,21 +1868,21 @@ function MitigationViewContent({
return (
<PageTemplate
title={data.mitigation.name ?? ""}
title={data.mesure.name ?? ""}
actions={
<div className="flex items-center gap-2">
<Button onClick={handleEditMitigation}>Edit Mitigation</Button>
<Button onClick={handleEditMesure}>Edit Mesure</Button>
<Select
defaultValue={data.mitigation.state}
onValueChange={handleMitigationStateChange}
defaultValue={data.mesure.state}
onValueChange={handleMesureStateChange}
>
<SelectTrigger className="w-[160px] h-10 text-sm">
<div
className={`${getStateColor(
data.mitigation.state
data.mesure.state
)} px-2 py-0.5 rounded-sm text-sm w-full text-center`}
>
{formatState(data.mitigation.state)}
{formatState(data.mesure.state)}
</div>
</SelectTrigger>
<SelectContent>
@@ -1908,10 +1894,10 @@ function MitigationViewContent({
</Select>
<div
className={`${getImportanceColor(
data.mitigation.importance
data.mesure.importance
)} px-3 py-1 rounded-full text-sm`}
>
{formatImportance(data.mitigation.importance)}
{formatImportance(data.mesure.importance)}
</div>
</div>
}
@@ -1920,7 +1906,7 @@ function MitigationViewContent({
<Card className="mt-4">
<CardContent className="pt-6">
<div className="prose prose-gray prose-sm md:prose-base text-secondary max-w-3xl">
<ReactMarkdown>{data.mitigation.description}</ReactMarkdown>
<ReactMarkdown>{data.mesure.description}</ReactMarkdown>
</div>
</CardContent>
</Card>
@@ -1946,20 +1932,20 @@ function MitigationViewContent({
<TabsTrigger value="controls" className="flex items-center gap-2">
<ShieldCheck className="w-4 h-4" />
Controls
{linkedControlsData?.mitigation?.controls?.edges &&
linkedControlsData.mitigation.controls.edges.length > 0 && (
{linkedControlsData?.mesure?.controls?.edges &&
linkedControlsData.mesure.controls.edges.length > 0 && (
<span className="ml-1.5 bg-blue-100 text-blue-800 rounded-full text-xs px-2 py-0.5">
{linkedControlsData.mitigation.controls.edges.length}
{linkedControlsData.mesure.controls.edges.length}
</span>
)}
</TabsTrigger>
<TabsTrigger value="risks" className="flex items-center gap-2">
<AlertTriangle className="w-4 h-4" />
Risks
{risksData?.mitigation?.risks?.edges &&
risksData.mitigation.risks.edges.length > 0 && (
{risksData?.mesure?.risks?.edges &&
risksData.mesure.risks.edges.length > 0 && (
<span className="ml-1.5 bg-blue-100 text-blue-800 rounded-full text-xs px-2 py-0.5">
{risksData.mitigation.risks.edges.length}
{risksData.mesure.risks.edges.length}
</span>
)}
</TabsTrigger>
@@ -1988,10 +1974,10 @@ function MitigationViewContent({
>
<DialogContent className="max-w-3xl max-h-[80vh] overflow-hidden flex flex-col">
<DialogHeader>
<DialogTitle>Map Mitigation to Controls</DialogTitle>
<DialogTitle>Map Mesure to Controls</DialogTitle>
<DialogDescription>
Search and select controls to link to this mitigation. This
helps track which controls are addressed by this mitigation.
Search and select controls to link to this mesure. This
helps track which controls are addressed by this mesure.
</DialogDescription>
</DialogHeader>
@@ -2140,8 +2126,8 @@ function MitigationViewContent({
{/* Linked Controls List */}
<Card>
<CardContent className="p-4">
{linkedControlsData?.mitigation?.controls?.edges &&
linkedControlsData.mitigation.controls.edges.length > 0 ? (
{linkedControlsData?.mesure?.controls?.edges &&
linkedControlsData.mesure.controls.edges.length > 0 ? (
<div className="overflow-x-auto">
<table className="w-full">
<thead>
@@ -2189,8 +2175,8 @@ function MitigationViewContent({
</div>
) : (
<div className="text-center py-8 text-secondary">
No controls linked to this mitigation yet. Click &quot;Map
to Controls&quot; to link controls.
No controls linked to this mesure yet. Click &quot;Map to
Controls&quot; to link controls.
</div>
)}
</CardContent>
@@ -2222,7 +2208,7 @@ function MitigationViewContent({
<DialogHeader>
<DialogTitle>Create New Task</DialogTitle>
<DialogDescription>
Add a new task to this mitigation. Click save when
Add a new task to this mesure. Click save when
you&apos;re done.
</DialogDescription>
</DialogHeader>
@@ -2809,8 +2795,8 @@ function MitigationViewContent({
<Card>
<CardContent className="p-4">
{risksData?.mitigation?.risks?.edges &&
risksData.mitigation.risks.edges.length > 0 ? (
{risksData?.mesure?.risks?.edges &&
risksData.mesure.risks.edges.length > 0 ? (
<div className="overflow-x-auto">
<table className="w-full">
<thead>
@@ -2830,7 +2816,7 @@ function MitigationViewContent({
</tr>
</thead>
<tbody>
{risksData.mitigation.risks.edges.map(({ node }) => (
{risksData.mesure.risks.edges.map(({ node }) => (
<tr
key={node.id}
className="border-b hover:bg-invert-bg"
@@ -2870,7 +2856,7 @@ function MitigationViewContent({
</div>
) : (
<div className="text-center py-8 text-secondary">
No risks linked to this mitigation yet.
No risks linked to this mesure yet.
</div>
)}
</CardContent>
@@ -3674,24 +3660,24 @@ function MitigationViewContent({
);
}
export default function MitigationView() {
const { mitigationId } = useParams();
export default function MesureView() {
const { mesureId } = useParams();
const [queryRef, loadQuery] =
useQueryLoader<MitigationViewQueryType>(mitigationViewQuery);
useQueryLoader<MesureViewQueryType>(mesureViewQuery);
useEffect(() => {
if (mitigationId) {
loadQuery({ mitigationId });
if (mesureId) {
loadQuery({ mesureId });
}
}, [mitigationId, loadQuery]);
}, [mesureId, loadQuery]);
if (!queryRef) {
return <MitigationViewSkeleton />;
return <MesureViewSkeleton />;
}
return (
<Suspense fallback={<MitigationViewSkeleton />}>
<MitigationViewContent queryRef={queryRef} />
<Suspense fallback={<MesureViewSkeleton />}>
<MesureViewContent queryRef={queryRef} />
</Suspense>
);
}

View File

@@ -4,26 +4,26 @@ import { lazy } from "@probo/react-lazy";
import { useLocation } from "react-router";
import { ErrorBoundaryWithLocation } from "../ErrorBoundary";
const EditMitigationView = lazy(() => import("./EditMitigationView"));
const NewMesureView = lazy(() => import("./NewMesureView"));
export function EditMitigationViewSkeleton() {
export function NewMesureViewSkeleton() {
return (
<PageTemplateSkeleton
title="Edit Mitigation"
description="Edit a mitigation. You will be able to link it to control and risks"
title="New Mesure"
description="Add a new mesure. You will be able to link it to control and risks"
>
<div className="max-w-2xl aspect-square bg-subtle-bg rounded-xl animate-pulse" />
</PageTemplateSkeleton>
);
}
export function EditMitigationPage() {
export function NewMesurePage() {
const location = useLocation();
return (
<Suspense key={location.pathname} fallback={<EditMitigationViewSkeleton />}>
<Suspense key={location.pathname} fallback={<NewMesureViewSkeleton />}>
<ErrorBoundaryWithLocation>
<EditMitigationView />
<NewMesureView />
</ErrorBoundaryWithLocation>
</Suspense>
);

View File

@@ -3,20 +3,20 @@ import { ConnectionHandler, graphql, useMutation } from "react-relay";
import { useParams, useNavigate } from "react-router";
import { PageTemplate } from "@/components/PageTemplate";
import { useToast } from "@/hooks/use-toast";
import { NewMitigationViewCreateMitigationMutation } from "./__generated__/NewMitigationViewCreateMitigationMutation.graphql";
import { NewMesureViewCreateMesureMutation } from "./__generated__/NewMesureViewCreateMesureMutation.graphql";
import { EditableField } from "@/components/EditableField";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { cn } from "@/lib/utils";
const createMitigationMutation = graphql`
mutation NewMitigationViewCreateMitigationMutation(
$input: CreateMitigationInput!
const createMesureMutation = graphql`
mutation NewMesureViewCreateMesureMutation(
$input: CreateMesureInput!
$connections: [ID!]!
) {
createMitigation(input: $input) {
mitigationEdge @prependEdge(connections: $connections) {
createMesure(input: $input) {
mesureEdge @prependEdge(connections: $connections) {
node {
id
name
@@ -27,7 +27,7 @@ const createMitigationMutation = graphql`
}
`;
export default function NewMitigationView() {
export default function NewMesureView() {
const { organizationId } = useParams<{
organizationId: string;
}>();
@@ -41,9 +41,7 @@ export default function NewMitigationView() {
});
const [commit, isInFlight] =
useMutation<NewMitigationViewCreateMitigationMutation>(
createMitigationMutation
);
useMutation<NewMesureViewCreateMesureMutation>(createMesureMutation);
const handleFieldChange = (field: keyof typeof formData, value: unknown) => {
setFormData((prev) => ({
@@ -66,7 +64,7 @@ export default function NewMitigationView() {
const connectionId = ConnectionHandler.getConnectionID(
organizationId!,
"MitigationListView_mitigations"
"MesureListView_mesures"
);
commit({
@@ -84,7 +82,7 @@ export default function NewMitigationView() {
if (errors) {
toast({
title: "Error",
description: errors[0]?.message || "Failed to create mitigation",
description: errors[0]?.message || "Failed to create mesure",
variant: "destructive",
});
return;
@@ -92,17 +90,17 @@ export default function NewMitigationView() {
toast({
title: "Success",
description: "Mitigation created successfully",
description: "Mesure created successfully",
});
navigate(
`/organizations/${organizationId}/mitigations/${data.createMitigation.mitigationEdge.node.id}`
`/organizations/${organizationId}/mesures/${data.createMesure.mesureEdge.node.id}`
);
},
onError(error) {
toast({
title: "Error",
description: error.message || "Failed to create mitigation",
description: error.message || "Failed to create mesure",
variant: "destructive",
});
},
@@ -111,8 +109,8 @@ export default function NewMitigationView() {
return (
<PageTemplate
title="New Mitigation"
description="Add a new mitigation. You will be able to link it to control and risks"
title="New Mesure"
description="Add a new mesure. You will be able to link it to control and risks"
>
<Card className="max-w-2xl">
<form onSubmit={handleSubmit} className="p-6 space-y-6">
@@ -129,7 +127,7 @@ export default function NewMitigationView() {
onChange={(value) => handleFieldChange("description", value)}
required
multiline
helpText="Provide a detailed description of the mitigation"
helpText="Provide a detailed description of the mesure"
/>
<EditableField
@@ -190,13 +188,13 @@ export default function NewMitigationView() {
type="button"
variant="outline"
onClick={() =>
navigate(`/organizations/${organizationId}/mitigations`)
navigate(`/organizations/${organizationId}/mesures`)
}
>
Cancel
</Button>
<Button type="submit" disabled={isInFlight}>
{isInFlight ? "Creating..." : "Create Mitigation"}
{isInFlight ? "Creating..." : "Create Mesure"}
</Button>
</div>
</form>

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<851436cc3003fed7f1e384d153eff0b7>>
* @generated SignedSource<<7a5c27ece406a4250a38977e9ed9173f>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,22 +9,22 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MitigationImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type EditMitigationViewQuery$variables = {
mitigationId: string;
export type MesureImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type EditMesureViewQuery$variables = {
mesureId: string;
};
export type EditMitigationViewQuery$data = {
export type EditMesureViewQuery$data = {
readonly node: {
readonly category?: string;
readonly description?: string;
readonly id?: string;
readonly importance?: MitigationImportance;
readonly importance?: MesureImportance;
readonly name?: string;
};
};
export type EditMitigationViewQuery = {
response: EditMitigationViewQuery$data;
variables: EditMitigationViewQuery$variables;
export type EditMesureViewQuery = {
response: EditMesureViewQuery$data;
variables: EditMesureViewQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -32,14 +32,14 @@ var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "mitigationId"
"name": "mesureId"
}
],
v1 = [
{
"kind": "Variable",
"name": "id",
"variableName": "mitigationId"
"variableName": "mesureId"
}
],
v2 = {
@@ -82,7 +82,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "EditMitigationViewQuery",
"name": "EditMesureViewQuery",
"selections": [
{
"alias": null,
@@ -101,7 +101,7 @@ return {
(v5/*: any*/),
(v6/*: any*/)
],
"type": "Mitigation",
"type": "Mesure",
"abstractKey": null
}
],
@@ -115,7 +115,7 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "EditMitigationViewQuery",
"name": "EditMesureViewQuery",
"selections": [
{
"alias": null,
@@ -141,7 +141,7 @@ return {
(v5/*: any*/),
(v6/*: any*/)
],
"type": "Mitigation",
"type": "Mesure",
"abstractKey": null
}
],
@@ -150,16 +150,16 @@ return {
]
},
"params": {
"cacheID": "df8ca216b15dda843c6da7f82bc4fb37",
"cacheID": "d38df91a88f32d80da84fc47b7ca17ca",
"id": null,
"metadata": {},
"name": "EditMitigationViewQuery",
"name": "EditMesureViewQuery",
"operationKind": "query",
"text": "query EditMitigationViewQuery(\n $mitigationId: ID!\n) {\n node(id: $mitigationId) {\n __typename\n ... on Mitigation {\n id\n name\n description\n category\n importance\n }\n id\n }\n}\n"
"text": "query EditMesureViewQuery(\n $mesureId: ID!\n) {\n node(id: $mesureId) {\n __typename\n ... on Mesure {\n id\n name\n description\n category\n importance\n }\n id\n }\n}\n"
}
};
})();
(node as any).hash = "bb3db4a2e4bcdcd77f8847d302f74340";
(node as any).hash = "abca56f710248363bacef919222a8420";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<ef4c93d248af00040b679e1bdb225a64>>
* @generated SignedSource<<869dc4adbc0716aa90912098821ce101>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,31 +9,31 @@
// @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 UpdateMitigationInput = {
export type MesureImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type MesureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type UpdateMesureInput = {
category?: string | null | undefined;
description?: string | null | undefined;
id: string;
importance?: MitigationImportance | null | undefined;
importance?: MesureImportance | null | undefined;
name?: string | null | undefined;
state?: MitigationState | null | undefined;
state?: MesureState | null | undefined;
};
export type EditMitigationViewUpdateMitigationMutation$variables = {
input: UpdateMitigationInput;
export type EditMesureViewUpdateMesureMutation$variables = {
input: UpdateMesureInput;
};
export type EditMitigationViewUpdateMitigationMutation$data = {
readonly updateMitigation: {
readonly mitigation: {
export type EditMesureViewUpdateMesureMutation$data = {
readonly updateMesure: {
readonly mesure: {
readonly description: string;
readonly id: string;
readonly name: string;
};
};
};
export type EditMitigationViewUpdateMitigationMutation = {
response: EditMitigationViewUpdateMitigationMutation$data;
variables: EditMitigationViewUpdateMitigationMutation$variables;
export type EditMesureViewUpdateMesureMutation = {
response: EditMesureViewUpdateMesureMutation$data;
variables: EditMesureViewUpdateMesureMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -54,17 +54,17 @@ v1 = [
"variableName": "input"
}
],
"concreteType": "UpdateMitigationPayload",
"concreteType": "UpdateMesurePayload",
"kind": "LinkedField",
"name": "updateMitigation",
"name": "updateMesure",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Mitigation",
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "mitigation",
"name": "mesure",
"plural": false,
"selections": [
{
@@ -100,7 +100,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "EditMitigationViewUpdateMitigationMutation",
"name": "EditMesureViewUpdateMesureMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
@@ -109,20 +109,20 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "EditMitigationViewUpdateMitigationMutation",
"name": "EditMesureViewUpdateMesureMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "b28b509d2111119e074541df44720f4f",
"cacheID": "ab674147338f145102c150b220578304",
"id": null,
"metadata": {},
"name": "EditMitigationViewUpdateMitigationMutation",
"name": "EditMesureViewUpdateMesureMutation",
"operationKind": "mutation",
"text": "mutation EditMitigationViewUpdateMitigationMutation(\n $input: UpdateMitigationInput!\n) {\n updateMitigation(input: $input) {\n mitigation {\n id\n name\n description\n }\n }\n}\n"
"text": "mutation EditMesureViewUpdateMesureMutation(\n $input: UpdateMesureInput!\n) {\n updateMesure(input: $input) {\n mesure {\n id\n name\n description\n }\n }\n}\n"
}
};
})();
(node as any).hash = "30ac146016e936fd8912b480286c93de";
(node as any).hash = "5f00ce5e7a705abecd93b06e727d5587";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<d4590a13a15cf248104340854bc46aa7>>
* @generated SignedSource<<251663bea47f61a5857366afa4cc0d28>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,35 +9,35 @@
// @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 ImportMitigationInput = {
export type MesureImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type MesureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type ImportMesureInput = {
file: any;
organizationId: string;
};
export type MitigationListViewImportMitigationMutation$variables = {
export type MesureListViewImportMesureMutation$variables = {
connections: ReadonlyArray<string>;
input: ImportMitigationInput;
input: ImportMesureInput;
};
export type MitigationListViewImportMitigationMutation$data = {
readonly importMitigation: {
readonly mitigationEdges: ReadonlyArray<{
export type MesureListViewImportMesureMutation$data = {
readonly importMesure: {
readonly mesureEdges: ReadonlyArray<{
readonly node: {
readonly category: string;
readonly createdAt: string;
readonly description: string;
readonly id: string;
readonly importance: MitigationImportance;
readonly importance: MesureImportance;
readonly name: string;
readonly state: MitigationState;
readonly state: MesureState;
readonly updatedAt: string;
};
}>;
};
};
export type MitigationListViewImportMitigationMutation = {
response: MitigationListViewImportMitigationMutation$data;
variables: MitigationListViewImportMitigationMutation$variables;
export type MesureListViewImportMesureMutation = {
response: MesureListViewImportMesureMutation$data;
variables: MesureListViewImportMesureMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -61,15 +61,15 @@ v2 = [
v3 = {
"alias": null,
"args": null,
"concreteType": "MitigationEdge",
"concreteType": "MesureEdge",
"kind": "LinkedField",
"name": "mitigationEdges",
"name": "mesureEdges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Mitigation",
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "node",
"plural": false,
@@ -144,14 +144,14 @@ return {
],
"kind": "Fragment",
"metadata": null,
"name": "MitigationListViewImportMitigationMutation",
"name": "MesureListViewImportMesureMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "ImportMitigationPayload",
"concreteType": "ImportMesurePayload",
"kind": "LinkedField",
"name": "importMitigation",
"name": "importMesure",
"plural": false,
"selections": [
(v3/*: any*/)
@@ -169,14 +169,14 @@ return {
(v0/*: any*/)
],
"kind": "Operation",
"name": "MitigationListViewImportMitigationMutation",
"name": "MesureListViewImportMesureMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "ImportMitigationPayload",
"concreteType": "ImportMesurePayload",
"kind": "LinkedField",
"name": "importMitigation",
"name": "importMesure",
"plural": false,
"selections": [
(v3/*: any*/),
@@ -187,7 +187,7 @@ return {
"handle": "appendEdge",
"key": "",
"kind": "LinkedHandle",
"name": "mitigationEdges",
"name": "mesureEdges",
"handleArgs": [
{
"kind": "Variable",
@@ -202,16 +202,16 @@ return {
]
},
"params": {
"cacheID": "84c038c572378999bfaacb87e8172b1e",
"cacheID": "179ac701005009dc5f30388570061264",
"id": null,
"metadata": {},
"name": "MitigationListViewImportMitigationMutation",
"name": "MesureListViewImportMesureMutation",
"operationKind": "mutation",
"text": "mutation MitigationListViewImportMitigationMutation(\n $input: ImportMitigationInput!\n) {\n importMitigation(input: $input) {\n mitigationEdges {\n node {\n id\n name\n description\n category\n state\n importance\n createdAt\n updatedAt\n }\n }\n }\n}\n"
"text": "mutation MesureListViewImportMesureMutation(\n $input: ImportMesureInput!\n) {\n importMesure(input: $input) {\n mesureEdges {\n node {\n id\n name\n description\n category\n state\n importance\n createdAt\n updatedAt\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "59e3d4a8e71cee0dcee606b93d706dad";
(node as any).hash = "c1c9deeaa806b9553b7eb25d8832818c";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<cfd9a630fcbe359cd0b4db0e940dd564>>
* @generated SignedSource<<90d959a85cf60161201cb5736ac6abcf>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,34 +9,34 @@
// @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 MitigationListViewQuery$variables = {
export type MesureImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type MesureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type MesureListViewQuery$variables = {
first?: number | null | undefined;
organizationId: string;
};
export type MitigationListViewQuery$data = {
export type MesureListViewQuery$data = {
readonly organization: {
readonly id: string;
readonly mitigations?: {
readonly mesures?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly category: string;
readonly createdAt: string;
readonly description: string;
readonly id: string;
readonly importance: MitigationImportance;
readonly importance: MesureImportance;
readonly name: string;
readonly state: MitigationState;
readonly state: MesureState;
readonly updatedAt: string;
};
}>;
};
};
};
export type MitigationListViewQuery = {
response: MitigationListViewQuery$data;
variables: MitigationListViewQuery$variables;
export type MesureListViewQuery = {
response: MesureListViewQuery$data;
variables: MesureListViewQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -75,7 +75,7 @@ v5 = [
{
"alias": null,
"args": null,
"concreteType": "MitigationEdge",
"concreteType": "MesureEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
@@ -83,7 +83,7 @@ v5 = [
{
"alias": null,
"args": null,
"concreteType": "Mitigation",
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "node",
"plural": false,
@@ -193,7 +193,7 @@ return {
],
"kind": "Fragment",
"metadata": null,
"name": "MitigationListViewQuery",
"name": "MesureListViewQuery",
"selections": [
{
"alias": "organization",
@@ -208,11 +208,11 @@ return {
"kind": "InlineFragment",
"selections": [
{
"alias": "mitigations",
"alias": "mesures",
"args": null,
"concreteType": "MitigationConnection",
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "__MitigationListView_mitigations_connection",
"name": "__MesureListView_mesures_connection",
"plural": false,
"selections": (v5/*: any*/),
"storageKey": null
@@ -235,7 +235,7 @@ return {
(v0/*: any*/)
],
"kind": "Operation",
"name": "MitigationListViewQuery",
"name": "MesureListViewQuery",
"selections": [
{
"alias": "organization",
@@ -253,9 +253,9 @@ return {
{
"alias": null,
"args": (v6/*: any*/),
"concreteType": "MitigationConnection",
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "mitigations",
"name": "mesures",
"plural": false,
"selections": (v5/*: any*/),
"storageKey": null
@@ -265,9 +265,9 @@ return {
"args": (v6/*: any*/),
"filters": null,
"handle": "connection",
"key": "MitigationListView_mitigations",
"key": "MesureListView_mesures",
"kind": "LinkedHandle",
"name": "mitigations"
"name": "mesures"
}
],
"type": "Organization",
@@ -279,7 +279,7 @@ return {
]
},
"params": {
"cacheID": "9951f5e4be50df7a883af63426fe5fde",
"cacheID": "9f6e9e1487bd34be972a52077bc91ee8",
"id": null,
"metadata": {
"connection": [
@@ -289,18 +289,18 @@ return {
"direction": "forward",
"path": [
"organization",
"mitigations"
"mesures"
]
}
]
},
"name": "MitigationListViewQuery",
"name": "MesureListViewQuery",
"operationKind": "query",
"text": "query MitigationListViewQuery(\n $organizationId: ID!\n $first: Int\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n mitigations(first: $first) {\n edges {\n node {\n id\n name\n description\n category\n state\n importance\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
"text": "query MesureListViewQuery(\n $organizationId: ID!\n $first: Int\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n mesures(first: $first) {\n edges {\n node {\n id\n name\n description\n category\n state\n importance\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "6b2de4417fd7175dd9ccd34549e097b7";
(node as any).hash = "47928382749f3bac585927423bcdd09e";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<c176425ad01ae9a330d0b8217a54841f>>
* @generated SignedSource<<d85f0048d0939eddb1152b5e0b361749>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -13,10 +13,10 @@ export type AssignTaskInput = {
assignedToId: string;
taskId: string;
};
export type MitigationViewAssignTaskMutation$variables = {
export type MesureViewAssignTaskMutation$variables = {
input: AssignTaskInput;
};
export type MitigationViewAssignTaskMutation$data = {
export type MesureViewAssignTaskMutation$data = {
readonly assignTask: {
readonly task: {
readonly assignedTo: {
@@ -28,9 +28,9 @@ export type MitigationViewAssignTaskMutation$data = {
};
};
};
export type MitigationViewAssignTaskMutation = {
response: MitigationViewAssignTaskMutation$data;
variables: MitigationViewAssignTaskMutation$variables;
export type MesureViewAssignTaskMutation = {
response: MesureViewAssignTaskMutation$data;
variables: MesureViewAssignTaskMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -110,7 +110,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewAssignTaskMutation",
"name": "MesureViewAssignTaskMutation",
"selections": (v2/*: any*/),
"type": "Mutation",
"abstractKey": null
@@ -119,20 +119,20 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewAssignTaskMutation",
"name": "MesureViewAssignTaskMutation",
"selections": (v2/*: any*/)
},
"params": {
"cacheID": "c01a2f758aea8268b73365c426b7c08a",
"cacheID": "6d3f95b9e223f40d7e333b951193abcc",
"id": null,
"metadata": {},
"name": "MitigationViewAssignTaskMutation",
"name": "MesureViewAssignTaskMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewAssignTaskMutation(\n $input: AssignTaskInput!\n) {\n assignTask(input: $input) {\n task {\n id\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n }\n }\n}\n"
"text": "mutation MesureViewAssignTaskMutation(\n $input: AssignTaskInput!\n) {\n assignTask(input: $input) {\n task {\n id\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "2b01502cb830a0d914553e01ceb2445f";
(node as any).hash = "28bc00cb45866a86eb79ebe0c1396a65";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<2eea3e72c7001db14095958b3bcd750a>>
* @generated SignedSource<<f5d09284634ce1975ceff8ce576884c9>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,21 +9,21 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type CreateControlMitigationMappingInput = {
export type CreateControlMesureMappingInput = {
controlId: string;
mitigationId: string;
mesureId: string;
};
export type ControlCreateMitigationMappingMutation$variables = {
input: CreateControlMitigationMappingInput;
export type MesureViewCreateControlMappingMutation$variables = {
input: CreateControlMesureMappingInput;
};
export type ControlCreateMitigationMappingMutation$data = {
readonly createControlMitigationMapping: {
export type MesureViewCreateControlMappingMutation$data = {
readonly createControlMesureMapping: {
readonly success: boolean;
};
};
export type ControlCreateMitigationMappingMutation = {
response: ControlCreateMitigationMappingMutation$data;
variables: ControlCreateMitigationMappingMutation$variables;
export type MesureViewCreateControlMappingMutation = {
response: MesureViewCreateControlMappingMutation$data;
variables: MesureViewCreateControlMappingMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -44,9 +44,9 @@ v1 = [
"variableName": "input"
}
],
"concreteType": "CreateControlMitigationMappingPayload",
"concreteType": "CreateControlMesureMappingPayload",
"kind": "LinkedField",
"name": "createControlMitigationMapping",
"name": "createControlMesureMapping",
"plural": false,
"selections": [
{
@@ -65,7 +65,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ControlCreateMitigationMappingMutation",
"name": "MesureViewCreateControlMappingMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
@@ -74,20 +74,20 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ControlCreateMitigationMappingMutation",
"name": "MesureViewCreateControlMappingMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "955241a049e81cd7faed45d69ce3b145",
"cacheID": "78c1205d1a787ee2cc4e1173e3ef463f",
"id": null,
"metadata": {},
"name": "ControlCreateMitigationMappingMutation",
"name": "MesureViewCreateControlMappingMutation",
"operationKind": "mutation",
"text": "mutation ControlCreateMitigationMappingMutation(\n $input: CreateControlMitigationMappingInput!\n) {\n createControlMitigationMapping(input: $input) {\n success\n }\n}\n"
"text": "mutation MesureViewCreateControlMappingMutation(\n $input: CreateControlMesureMappingInput!\n) {\n createControlMesureMapping(input: $input) {\n success\n }\n}\n"
}
};
})();
(node as any).hash = "ffbcf187d7f2d3c65a2d1fb5c6a180bb";
(node as any).hash = "cdbbc7ebd2c99ef1d19bac274af5a147";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<487ccddf967e20c9111c5074548bebae>>
* @generated SignedSource<<0601ac43da57ebf5dffbd0e3ce9abde7>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -19,11 +19,11 @@ export type CreateEvidenceInput = {
type: EvidenceType;
url?: string | null | undefined;
};
export type MitigationViewCreateEvidenceMutation$variables = {
export type MesureViewCreateEvidenceMutation$variables = {
connections: ReadonlyArray<string>;
input: CreateEvidenceInput;
};
export type MitigationViewCreateEvidenceMutation$data = {
export type MesureViewCreateEvidenceMutation$data = {
readonly createEvidence: {
readonly evidenceEdge: {
readonly node: {
@@ -41,9 +41,9 @@ export type MitigationViewCreateEvidenceMutation$data = {
};
};
};
export type MitigationViewCreateEvidenceMutation = {
response: MitigationViewCreateEvidenceMutation$data;
variables: MitigationViewCreateEvidenceMutation$variables;
export type MesureViewCreateEvidenceMutation = {
response: MesureViewCreateEvidenceMutation$data;
variables: MesureViewCreateEvidenceMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -164,7 +164,7 @@ return {
],
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewCreateEvidenceMutation",
"name": "MesureViewCreateEvidenceMutation",
"selections": [
{
"alias": null,
@@ -189,7 +189,7 @@ return {
(v0/*: any*/)
],
"kind": "Operation",
"name": "MitigationViewCreateEvidenceMutation",
"name": "MesureViewCreateEvidenceMutation",
"selections": [
{
"alias": null,
@@ -222,16 +222,16 @@ return {
]
},
"params": {
"cacheID": "899aada42838cb5db77546be2bd6adb2",
"cacheID": "550cd90cddee628ec42ebd53ac749af0",
"id": null,
"metadata": {},
"name": "MitigationViewCreateEvidenceMutation",
"name": "MesureViewCreateEvidenceMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewCreateEvidenceMutation(\n $input: CreateEvidenceInput!\n) {\n createEvidence(input: $input) {\n evidenceEdge {\n node {\n id\n filename\n fileUrl\n mimeType\n type\n url\n size\n state\n createdAt\n description\n }\n }\n }\n}\n"
"text": "mutation MesureViewCreateEvidenceMutation(\n $input: CreateEvidenceInput!\n) {\n createEvidence(input: $input) {\n evidenceEdge {\n node {\n id\n filename\n fileUrl\n mimeType\n type\n url\n size\n state\n createdAt\n description\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "ca8611e07bcf9233313c3a1580bfc7eb";
(node as any).hash = "2a00046ec29c9dc07b563b5442a85d2d";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<e544ac1f4a0b6d728cba2b66a2f97520>>
* @generated SignedSource<<fa3e50475f102e38ffd517849b9aedf2>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -13,15 +13,15 @@ export type TaskState = "DONE" | "TODO";
export type CreateTaskInput = {
assignedToId?: string | null | undefined;
description: string;
mitigationId: string;
mesureId: string;
name: string;
timeEstimate?: any | null | undefined;
};
export type MitigationViewCreateTaskMutation$variables = {
export type MesureViewCreateTaskMutation$variables = {
connections: ReadonlyArray<string>;
input: CreateTaskInput;
};
export type MitigationViewCreateTaskMutation$data = {
export type MesureViewCreateTaskMutation$data = {
readonly createTask: {
readonly taskEdge: {
readonly node: {
@@ -39,9 +39,9 @@ export type MitigationViewCreateTaskMutation$data = {
};
};
};
export type MitigationViewCreateTaskMutation = {
response: MitigationViewCreateTaskMutation$data;
variables: MitigationViewCreateTaskMutation$variables;
export type MesureViewCreateTaskMutation = {
response: MesureViewCreateTaskMutation$data;
variables: MesureViewCreateTaskMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -154,7 +154,7 @@ return {
],
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewCreateTaskMutation",
"name": "MesureViewCreateTaskMutation",
"selections": [
{
"alias": null,
@@ -179,7 +179,7 @@ return {
(v0/*: any*/)
],
"kind": "Operation",
"name": "MitigationViewCreateTaskMutation",
"name": "MesureViewCreateTaskMutation",
"selections": [
{
"alias": null,
@@ -212,16 +212,16 @@ return {
]
},
"params": {
"cacheID": "273c3d2ae0de44280e85e47db23db892",
"cacheID": "453cd7da016798ce86c012c9d1cf29f1",
"id": null,
"metadata": {},
"name": "MitigationViewCreateTaskMutation",
"name": "MesureViewCreateTaskMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewCreateTaskMutation(\n $input: CreateTaskInput!\n) {\n createTask(input: $input) {\n taskEdge {\n node {\n id\n name\n description\n timeEstimate\n state\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n }\n }\n }\n}\n"
"text": "mutation MesureViewCreateTaskMutation(\n $input: CreateTaskInput!\n) {\n createTask(input: $input) {\n taskEdge {\n node {\n id\n name\n description\n timeEstimate\n state\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "ad8a56e4976e9dc15f4ee8e1b32d9fa9";
(node as any).hash = "19abdc1f9accd5deb6bc36a88a91b04d";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<7c4ad77e70fa42cf8257113897a607ec>>
* @generated SignedSource<<aa1cb94133ffcc770185dddcf490492e>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,21 +9,21 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type DeleteControlMitigationMappingInput = {
export type DeleteControlMesureMappingInput = {
controlId: string;
mitigationId: string;
mesureId: string;
};
export type ControlDeleteMitigationMappingMutation$variables = {
input: DeleteControlMitigationMappingInput;
export type MesureViewDeleteControlMappingMutation$variables = {
input: DeleteControlMesureMappingInput;
};
export type ControlDeleteMitigationMappingMutation$data = {
readonly deleteControlMitigationMapping: {
export type MesureViewDeleteControlMappingMutation$data = {
readonly deleteControlMesureMapping: {
readonly success: boolean;
};
};
export type ControlDeleteMitigationMappingMutation = {
response: ControlDeleteMitigationMappingMutation$data;
variables: ControlDeleteMitigationMappingMutation$variables;
export type MesureViewDeleteControlMappingMutation = {
response: MesureViewDeleteControlMappingMutation$data;
variables: MesureViewDeleteControlMappingMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -44,9 +44,9 @@ v1 = [
"variableName": "input"
}
],
"concreteType": "DeleteControlMitigationMappingPayload",
"concreteType": "DeleteControlMesureMappingPayload",
"kind": "LinkedField",
"name": "deleteControlMitigationMapping",
"name": "deleteControlMesureMapping",
"plural": false,
"selections": [
{
@@ -65,7 +65,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ControlDeleteMitigationMappingMutation",
"name": "MesureViewDeleteControlMappingMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
@@ -74,20 +74,20 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ControlDeleteMitigationMappingMutation",
"name": "MesureViewDeleteControlMappingMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "3d09a29c8ae06a97d098e565a7f2d172",
"cacheID": "5293df3ec3b7a9c5dab1ae7c41177186",
"id": null,
"metadata": {},
"name": "ControlDeleteMitigationMappingMutation",
"name": "MesureViewDeleteControlMappingMutation",
"operationKind": "mutation",
"text": "mutation ControlDeleteMitigationMappingMutation(\n $input: DeleteControlMitigationMappingInput!\n) {\n deleteControlMitigationMapping(input: $input) {\n success\n }\n}\n"
"text": "mutation MesureViewDeleteControlMappingMutation(\n $input: DeleteControlMesureMappingInput!\n) {\n deleteControlMesureMapping(input: $input) {\n success\n }\n}\n"
}
};
})();
(node as any).hash = "6905236aeeb313e5deed3e569a0c7c54";
(node as any).hash = "14d324c311f9f5aa0a27c0d705fe7bb6";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<c7cba05f3dbc917afc82d3a3dae6045c>>
* @generated SignedSource<<5819ea12b0c6baff2a21d28b6d22bf29>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -12,18 +12,18 @@ import { ConcreteRequest } from 'relay-runtime';
export type DeleteEvidenceInput = {
evidenceId: string;
};
export type MitigationViewDeleteEvidenceMutation$variables = {
export type MesureViewDeleteEvidenceMutation$variables = {
connections: ReadonlyArray<string>;
input: DeleteEvidenceInput;
};
export type MitigationViewDeleteEvidenceMutation$data = {
export type MesureViewDeleteEvidenceMutation$data = {
readonly deleteEvidence: {
readonly deletedEvidenceId: string;
};
};
export type MitigationViewDeleteEvidenceMutation = {
response: MitigationViewDeleteEvidenceMutation$data;
variables: MitigationViewDeleteEvidenceMutation$variables;
export type MesureViewDeleteEvidenceMutation = {
response: MesureViewDeleteEvidenceMutation$data;
variables: MesureViewDeleteEvidenceMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -59,7 +59,7 @@ return {
],
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewDeleteEvidenceMutation",
"name": "MesureViewDeleteEvidenceMutation",
"selections": [
{
"alias": null,
@@ -84,7 +84,7 @@ return {
(v0/*: any*/)
],
"kind": "Operation",
"name": "MitigationViewDeleteEvidenceMutation",
"name": "MesureViewDeleteEvidenceMutation",
"selections": [
{
"alias": null,
@@ -117,16 +117,16 @@ return {
]
},
"params": {
"cacheID": "4770e84f6f87fb95b9f102cf8e572f44",
"cacheID": "26fbd71aca06943318c6154a0079d6d7",
"id": null,
"metadata": {},
"name": "MitigationViewDeleteEvidenceMutation",
"name": "MesureViewDeleteEvidenceMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewDeleteEvidenceMutation(\n $input: DeleteEvidenceInput!\n) {\n deleteEvidence(input: $input) {\n deletedEvidenceId\n }\n}\n"
"text": "mutation MesureViewDeleteEvidenceMutation(\n $input: DeleteEvidenceInput!\n) {\n deleteEvidence(input: $input) {\n deletedEvidenceId\n }\n}\n"
}
};
})();
(node as any).hash = "993f84f2e310e888a78200abb9b79ae0";
(node as any).hash = "1121dd991a7505864bcd00f06065f2eb";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<c91c57e5263b695d85ca6d95f14acc1d>>
* @generated SignedSource<<c70fd910b41f49426916f3f3aa1433bd>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -12,18 +12,18 @@ import { ConcreteRequest } from 'relay-runtime';
export type DeleteTaskInput = {
taskId: string;
};
export type MitigationViewDeleteTaskMutation$variables = {
export type MesureViewDeleteTaskMutation$variables = {
connections: ReadonlyArray<string>;
input: DeleteTaskInput;
};
export type MitigationViewDeleteTaskMutation$data = {
export type MesureViewDeleteTaskMutation$data = {
readonly deleteTask: {
readonly deletedTaskId: string;
};
};
export type MitigationViewDeleteTaskMutation = {
response: MitigationViewDeleteTaskMutation$data;
variables: MitigationViewDeleteTaskMutation$variables;
export type MesureViewDeleteTaskMutation = {
response: MesureViewDeleteTaskMutation$data;
variables: MesureViewDeleteTaskMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -59,7 +59,7 @@ return {
],
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewDeleteTaskMutation",
"name": "MesureViewDeleteTaskMutation",
"selections": [
{
"alias": null,
@@ -84,7 +84,7 @@ return {
(v0/*: any*/)
],
"kind": "Operation",
"name": "MitigationViewDeleteTaskMutation",
"name": "MesureViewDeleteTaskMutation",
"selections": [
{
"alias": null,
@@ -117,16 +117,16 @@ return {
]
},
"params": {
"cacheID": "f586e9c07d233eb31a72c2564c448fe4",
"cacheID": "a5096acddc7796fbc89521cc80b5538e",
"id": null,
"metadata": {},
"name": "MitigationViewDeleteTaskMutation",
"name": "MesureViewDeleteTaskMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewDeleteTaskMutation(\n $input: DeleteTaskInput!\n) {\n deleteTask(input: $input) {\n deletedTaskId\n }\n}\n"
"text": "mutation MesureViewDeleteTaskMutation(\n $input: DeleteTaskInput!\n) {\n deleteTask(input: $input) {\n deletedTaskId\n }\n}\n"
}
};
})();
(node as any).hash = "2d6cfcb4704b95bc89f9f4715488d133";
(node as any).hash = "42867b2a8776a0facd18b0b24499ccc9";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<641911581864265e2933d2d5f2705bfe>>
* @generated SignedSource<<296196d78af980e2c7456af3192b29ef>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,10 +9,10 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MitigationViewFrameworksQuery$variables = {
export type MesureViewFrameworksQuery$variables = {
organizationId: string;
};
export type MitigationViewFrameworksQuery$data = {
export type MesureViewFrameworksQuery$data = {
readonly organization: {
readonly frameworks?: {
readonly edges: ReadonlyArray<{
@@ -35,9 +35,9 @@ export type MitigationViewFrameworksQuery$data = {
readonly id: string;
};
};
export type MitigationViewFrameworksQuery = {
response: MitigationViewFrameworksQuery$data;
variables: MitigationViewFrameworksQuery$variables;
export type MesureViewFrameworksQuery = {
response: MesureViewFrameworksQuery$data;
variables: MesureViewFrameworksQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -163,7 +163,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewFrameworksQuery",
"name": "MesureViewFrameworksQuery",
"selections": [
{
"alias": "organization",
@@ -240,7 +240,7 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewFrameworksQuery",
"name": "MesureViewFrameworksQuery",
"selections": [
{
"alias": "organization",
@@ -331,7 +331,7 @@ return {
]
},
"params": {
"cacheID": "34e6669a992e649351d4284a2d66c66a",
"cacheID": "68ea9b6b474fc4c715eda4e5814b3343",
"id": null,
"metadata": {
"connection": [
@@ -352,13 +352,13 @@ return {
}
]
},
"name": "MitigationViewFrameworksQuery",
"name": "MesureViewFrameworksQuery",
"operationKind": "query",
"text": "query MitigationViewFrameworksQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n frameworks(first: 100) {\n edges {\n node {\n id\n name\n controls(first: 100) {\n edges {\n node {\n id\n referenceId\n name\n description\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
"text": "query MesureViewFrameworksQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n frameworks(first: 100) {\n edges {\n node {\n id\n name\n controls(first: 100) {\n edges {\n node {\n id\n referenceId\n name\n description\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "f4f9ed0abc3a0d36365801dcc60c4333";
(node as any).hash = "c66b330acf51a54f75ac9b4238c30ec1";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<780fd466293ec923661adc90f801380a>>
* @generated SignedSource<<a690863c83d2e67fa057c3fe63b63979>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -17,11 +17,11 @@ export type FulfillEvidenceInput = {
name?: string | null | undefined;
url?: string | null | undefined;
};
export type MitigationViewFulfillEvidenceMutation$variables = {
export type MesureViewFulfillEvidenceMutation$variables = {
connections: ReadonlyArray<string>;
input: FulfillEvidenceInput;
};
export type MitigationViewFulfillEvidenceMutation$data = {
export type MesureViewFulfillEvidenceMutation$data = {
readonly fulfillEvidence: {
readonly evidenceEdge: {
readonly node: {
@@ -39,9 +39,9 @@ export type MitigationViewFulfillEvidenceMutation$data = {
};
};
};
export type MitigationViewFulfillEvidenceMutation = {
response: MitigationViewFulfillEvidenceMutation$data;
variables: MitigationViewFulfillEvidenceMutation$variables;
export type MesureViewFulfillEvidenceMutation = {
response: MesureViewFulfillEvidenceMutation$data;
variables: MesureViewFulfillEvidenceMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -162,7 +162,7 @@ return {
],
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewFulfillEvidenceMutation",
"name": "MesureViewFulfillEvidenceMutation",
"selections": [
{
"alias": null,
@@ -187,7 +187,7 @@ return {
(v0/*: any*/)
],
"kind": "Operation",
"name": "MitigationViewFulfillEvidenceMutation",
"name": "MesureViewFulfillEvidenceMutation",
"selections": [
{
"alias": null,
@@ -220,16 +220,16 @@ return {
]
},
"params": {
"cacheID": "efdf549604c425e8bb58ccf51df580c9",
"cacheID": "605c054b1e501d03ded168635513d859",
"id": null,
"metadata": {},
"name": "MitigationViewFulfillEvidenceMutation",
"name": "MesureViewFulfillEvidenceMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewFulfillEvidenceMutation(\n $input: FulfillEvidenceInput!\n) {\n fulfillEvidence(input: $input) {\n evidenceEdge {\n node {\n id\n filename\n fileUrl\n mimeType\n type\n url\n size\n state\n createdAt\n description\n }\n }\n }\n}\n"
"text": "mutation MesureViewFulfillEvidenceMutation(\n $input: FulfillEvidenceInput!\n) {\n fulfillEvidence(input: $input) {\n evidenceEdge {\n node {\n id\n filename\n fileUrl\n mimeType\n type\n url\n size\n state\n createdAt\n description\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "2a7f04e50e4e6fc39457a861a22baf08";
(node as any).hash = "049b31ff4cf60918ec33c2c10fcb9b46";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<c39e6569df1609b4a9cf0a6c1673df3a>>
* @generated SignedSource<<d3565063e8e1b68e794fe4347c923138>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,18 +9,18 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MitigationViewGetEvidenceFileUrlQuery$variables = {
export type MesureViewGetEvidenceFileUrlQuery$variables = {
evidenceId: string;
};
export type MitigationViewGetEvidenceFileUrlQuery$data = {
export type MesureViewGetEvidenceFileUrlQuery$data = {
readonly node: {
readonly fileUrl?: string | null | undefined;
readonly id?: string;
};
};
export type MitigationViewGetEvidenceFileUrlQuery = {
response: MitigationViewGetEvidenceFileUrlQuery$data;
variables: MitigationViewGetEvidenceFileUrlQuery$variables;
export type MesureViewGetEvidenceFileUrlQuery = {
response: MesureViewGetEvidenceFileUrlQuery$data;
variables: MesureViewGetEvidenceFileUrlQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -57,7 +57,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewGetEvidenceFileUrlQuery",
"name": "MesureViewGetEvidenceFileUrlQuery",
"selections": [
{
"alias": null,
@@ -87,7 +87,7 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewGetEvidenceFileUrlQuery",
"name": "MesureViewGetEvidenceFileUrlQuery",
"selections": [
{
"alias": null,
@@ -119,16 +119,16 @@ return {
]
},
"params": {
"cacheID": "1dc81a5d665b9141b5cd62ef893ff0e1",
"cacheID": "05edf89cc90a90e1a96bd02f8448b629",
"id": null,
"metadata": {},
"name": "MitigationViewGetEvidenceFileUrlQuery",
"name": "MesureViewGetEvidenceFileUrlQuery",
"operationKind": "query",
"text": "query MitigationViewGetEvidenceFileUrlQuery(\n $evidenceId: ID!\n) {\n node(id: $evidenceId) {\n __typename\n ... on Evidence {\n id\n fileUrl\n }\n id\n }\n}\n"
"text": "query MesureViewGetEvidenceFileUrlQuery(\n $evidenceId: ID!\n) {\n node(id: $evidenceId) {\n __typename\n ... on Evidence {\n id\n fileUrl\n }\n id\n }\n}\n"
}
};
})();
(node as any).hash = "9d7bbfc81ce73246b671989102da3192";
(node as any).hash = "2bef4c934e725a40e5140a812bd31bc8";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<c9c1170d3b2dcef033fe6f69b6a9b11e>>
* @generated SignedSource<<7f9c4ed295020bbeadd37ac046817d51>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,11 +9,11 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MitigationViewLinkedControlsQuery$variables = {
mitigationId: string;
export type MesureViewLinkedControlsQuery$variables = {
mesureId: string;
};
export type MitigationViewLinkedControlsQuery$data = {
readonly mitigation: {
export type MesureViewLinkedControlsQuery$data = {
readonly mesure: {
readonly controls?: {
readonly edges: ReadonlyArray<{
readonly node: {
@@ -27,9 +27,9 @@ export type MitigationViewLinkedControlsQuery$data = {
readonly id: string;
};
};
export type MitigationViewLinkedControlsQuery = {
response: MitigationViewLinkedControlsQuery$data;
variables: MitigationViewLinkedControlsQuery$variables;
export type MesureViewLinkedControlsQuery = {
response: MesureViewLinkedControlsQuery$data;
variables: MesureViewLinkedControlsQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -37,14 +37,14 @@ var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "mitigationId"
"name": "mesureId"
}
],
v1 = [
{
"kind": "Variable",
"name": "id",
"variableName": "mitigationId"
"variableName": "mesureId"
}
],
v2 = {
@@ -152,10 +152,10 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewLinkedControlsQuery",
"name": "MesureViewLinkedControlsQuery",
"selections": [
{
"alias": "mitigation",
"alias": "mesure",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
@@ -171,13 +171,13 @@ return {
"args": null,
"concreteType": "ControlConnection",
"kind": "LinkedField",
"name": "__Mitigation__controls_connection",
"name": "__MesureView_controls_connection",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": null
}
],
"type": "Mitigation",
"type": "Mesure",
"abstractKey": null
}
],
@@ -191,10 +191,10 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewLinkedControlsQuery",
"name": "MesureViewLinkedControlsQuery",
"selections": [
{
"alias": "mitigation",
"alias": "mesure",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
@@ -221,12 +221,12 @@ return {
"args": (v5/*: any*/),
"filters": null,
"handle": "connection",
"key": "Mitigation__controls",
"key": "MesureView_controls",
"kind": "LinkedHandle",
"name": "controls"
}
],
"type": "Mitigation",
"type": "Mesure",
"abstractKey": null
}
],
@@ -235,7 +235,7 @@ return {
]
},
"params": {
"cacheID": "7429166728b5a233e15cb0f4cb33d15c",
"cacheID": "84229c9d2f99008d1b85401ad2c0e185",
"id": null,
"metadata": {
"connection": [
@@ -244,19 +244,19 @@ return {
"cursor": null,
"direction": "forward",
"path": [
"mitigation",
"mesure",
"controls"
]
}
]
},
"name": "MitigationViewLinkedControlsQuery",
"name": "MesureViewLinkedControlsQuery",
"operationKind": "query",
"text": "query MitigationViewLinkedControlsQuery(\n $mitigationId: ID!\n) {\n mitigation: node(id: $mitigationId) {\n __typename\n id\n ... on Mitigation {\n controls(first: 100) {\n edges {\n node {\n id\n referenceId\n name\n description\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
"text": "query MesureViewLinkedControlsQuery(\n $mesureId: ID!\n) {\n mesure: node(id: $mesureId) {\n __typename\n id\n ... on Mesure {\n controls(first: 100) {\n edges {\n node {\n id\n referenceId\n name\n description\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "0748d068025e5f577ab56a8014ee38cc";
(node as any).hash = "c9a7971b4e7f8e4a708d69211333bb8a";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<780c10208a633b2ce7cd34ccc580cf25>>
* @generated SignedSource<<c50d4f287a6322e4dada5685bc5d830f>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,10 +9,10 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MitigationViewOrganizationQuery$variables = {
export type MesureViewOrganizationQuery$variables = {
organizationId: string;
};
export type MitigationViewOrganizationQuery$data = {
export type MesureViewOrganizationQuery$data = {
readonly organization: {
readonly id: string;
readonly peoples?: {
@@ -26,9 +26,9 @@ export type MitigationViewOrganizationQuery$data = {
};
};
};
export type MitigationViewOrganizationQuery = {
response: MitigationViewOrganizationQuery$data;
variables: MitigationViewOrganizationQuery$variables;
export type MesureViewOrganizationQuery = {
response: MesureViewOrganizationQuery$data;
variables: MesureViewOrganizationQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -153,7 +153,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewOrganizationQuery",
"name": "MesureViewOrganizationQuery",
"selections": [
{
"alias": "organization",
@@ -174,10 +174,10 @@ return {
],
"concreteType": "PeopleConnection",
"kind": "LinkedField",
"name": "__MitigationView_peoples_connection",
"name": "__MesureView_peoples_connection",
"plural": false,
"selections": (v5/*: any*/),
"storageKey": "__MitigationView_peoples_connection(orderBy:{\"direction\":\"ASC\",\"field\":\"FULL_NAME\"})"
"storageKey": "__MesureView_peoples_connection(orderBy:{\"direction\":\"ASC\",\"field\":\"FULL_NAME\"})"
}
],
"type": "Organization",
@@ -194,7 +194,7 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewOrganizationQuery",
"name": "MesureViewOrganizationQuery",
"selections": [
{
"alias": "organization",
@@ -226,7 +226,7 @@ return {
"orderBy"
],
"handle": "connection",
"key": "MitigationView_peoples",
"key": "MesureView_peoples",
"kind": "LinkedHandle",
"name": "peoples"
}
@@ -240,7 +240,7 @@ return {
]
},
"params": {
"cacheID": "3d1fc2d02bc6eea68edcabc6fc6f0b56",
"cacheID": "cc07a873a9d2756876763a8491fd305a",
"id": null,
"metadata": {
"connection": [
@@ -255,13 +255,13 @@ return {
}
]
},
"name": "MitigationViewOrganizationQuery",
"name": "MesureViewOrganizationQuery",
"operationKind": "query",
"text": "query MitigationViewOrganizationQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n peoples(first: 100, orderBy: {direction: ASC, field: FULL_NAME}) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
"text": "query MesureViewOrganizationQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n peoples(first: 100, orderBy: {direction: ASC, field: FULL_NAME}) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "73abf70f60b6f5a07b25f3c83676e02f";
(node as any).hash = "4d0f80a682d98e8b90102b47ec2a7cb3";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<8b25e364318ac90f1c1eaf313a6286cb>>
* @generated SignedSource<<911e86f76b51015804e409479ee4068c>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -11,20 +11,20 @@
import { ConcreteRequest } from 'relay-runtime';
export type EvidenceState = "FULFILLED" | "REQUESTED";
export type EvidenceType = "FILE" | "LINK";
export type MitigationImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type MitigationState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type MesureImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type MesureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type TaskState = "DONE" | "TODO";
export type MitigationViewQuery$variables = {
mitigationId: string;
export type MesureViewQuery$variables = {
mesureId: string;
};
export type MitigationViewQuery$data = {
readonly mitigation: {
export type MesureViewQuery$data = {
readonly mesure: {
readonly category?: string;
readonly description?: string;
readonly id: string;
readonly importance?: MitigationImportance;
readonly importance?: MesureImportance;
readonly name?: string;
readonly state?: MitigationState;
readonly state?: MesureState;
readonly tasks?: {
readonly __id: string;
readonly edges: ReadonlyArray<{
@@ -60,9 +60,9 @@ export type MitigationViewQuery$data = {
};
};
};
export type MitigationViewQuery = {
response: MitigationViewQuery$data;
variables: MitigationViewQuery$variables;
export type MesureViewQuery = {
response: MesureViewQuery$data;
variables: MesureViewQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -70,14 +70,14 @@ var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "mitigationId"
"name": "mesureId"
}
],
v1 = [
{
"kind": "Variable",
"name": "id",
"variableName": "mitigationId"
"variableName": "mesureId"
}
],
v2 = {
@@ -298,10 +298,10 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewQuery",
"name": "MesureViewQuery",
"selections": [
{
"alias": "mitigation",
"alias": "mesure",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
@@ -322,7 +322,7 @@ return {
"args": null,
"concreteType": "TaskConnection",
"kind": "LinkedField",
"name": "__MitigationView_tasks_connection",
"name": "__MesureView_tasks_connection",
"plural": false,
"selections": [
{
@@ -352,7 +352,7 @@ return {
"args": null,
"concreteType": "EvidenceConnection",
"kind": "LinkedField",
"name": "__MitigationView_evidences_connection",
"name": "__MesureView_evidences_connection",
"plural": false,
"selections": (v14/*: any*/),
"storageKey": null
@@ -371,7 +371,7 @@ return {
"storageKey": null
}
],
"type": "Mitigation",
"type": "Mesure",
"abstractKey": null
}
],
@@ -385,10 +385,10 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewQuery",
"name": "MesureViewQuery",
"selections": [
{
"alias": "mitigation",
"alias": "mesure",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
@@ -450,7 +450,7 @@ return {
"args": (v16/*: any*/),
"filters": null,
"handle": "connection",
"key": "MitigationView_evidences",
"key": "MesureView_evidences",
"kind": "LinkedHandle",
"name": "evidences"
},
@@ -472,12 +472,12 @@ return {
"args": (v15/*: any*/),
"filters": null,
"handle": "connection",
"key": "MitigationView_tasks",
"key": "MesureView_tasks",
"kind": "LinkedHandle",
"name": "tasks"
}
],
"type": "Mitigation",
"type": "Mesure",
"abstractKey": null
}
],
@@ -486,7 +486,7 @@ return {
]
},
"params": {
"cacheID": "711b5dac4db6ca883144ece5d4bc48c3",
"cacheID": "e4c3abf8e8559e732088a9123863a375",
"id": null,
"metadata": {
"connection": [
@@ -501,19 +501,19 @@ return {
"cursor": null,
"direction": "forward",
"path": [
"mitigation",
"mesure",
"tasks"
]
}
]
},
"name": "MitigationViewQuery",
"name": "MesureViewQuery",
"operationKind": "query",
"text": "query MitigationViewQuery(\n $mitigationId: ID!\n) {\n mitigation: node(id: $mitigationId) {\n __typename\n id\n ... on Mitigation {\n name\n description\n state\n importance\n category\n tasks(first: 100) {\n edges {\n node {\n id\n name\n description\n state\n timeEstimate\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n evidences(first: 50) {\n edges {\n node {\n id\n mimeType\n filename\n size\n state\n type\n url\n createdAt\n description\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
"text": "query MesureViewQuery(\n $mesureId: ID!\n) {\n mesure: node(id: $mesureId) {\n __typename\n id\n ... on Mesure {\n name\n description\n state\n importance\n category\n tasks(first: 100) {\n edges {\n node {\n id\n name\n description\n state\n timeEstimate\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n evidences(first: 50) {\n edges {\n node {\n id\n mimeType\n filename\n size\n state\n type\n url\n createdAt\n description\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "cb5d73e09aa6168901bf5db0f931e24c";
(node as any).hash = "38c0abd51a589411fc60391269af0227";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<b7154e691d26fef3b8f64ec3a39304fd>>
* @generated SignedSource<<a6bd25e3b378dcc7ac26ba611a054fbe>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,11 +9,11 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MitigationViewRisksQuery$variables = {
mitigationId: string;
export type MesureViewRisksQuery$variables = {
mesureId: string;
};
export type MitigationViewRisksQuery$data = {
readonly mitigation: {
export type MesureViewRisksQuery$data = {
readonly mesure: {
readonly id: string;
readonly risks?: {
readonly edges: ReadonlyArray<{
@@ -30,9 +30,9 @@ export type MitigationViewRisksQuery$data = {
};
};
};
export type MitigationViewRisksQuery = {
response: MitigationViewRisksQuery$data;
variables: MitigationViewRisksQuery$variables;
export type MesureViewRisksQuery = {
response: MesureViewRisksQuery$data;
variables: MesureViewRisksQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -40,14 +40,14 @@ var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "mitigationId"
"name": "mesureId"
}
],
v1 = [
{
"kind": "Variable",
"name": "id",
"variableName": "mitigationId"
"variableName": "mesureId"
}
],
v2 = {
@@ -176,10 +176,10 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewRisksQuery",
"name": "MesureViewRisksQuery",
"selections": [
{
"alias": "mitigation",
"alias": "mesure",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
@@ -195,13 +195,13 @@ return {
"args": null,
"concreteType": "RiskConnection",
"kind": "LinkedField",
"name": "__MitigationView_risks_connection",
"name": "__MesureView_risks_connection",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": null
}
],
"type": "Mitigation",
"type": "Mesure",
"abstractKey": null
}
],
@@ -215,10 +215,10 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewRisksQuery",
"name": "MesureViewRisksQuery",
"selections": [
{
"alias": "mitigation",
"alias": "mesure",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
@@ -245,12 +245,12 @@ return {
"args": (v5/*: any*/),
"filters": null,
"handle": "connection",
"key": "MitigationView_risks",
"key": "MesureView_risks",
"kind": "LinkedHandle",
"name": "risks"
}
],
"type": "Mitigation",
"type": "Mesure",
"abstractKey": null
}
],
@@ -259,7 +259,7 @@ return {
]
},
"params": {
"cacheID": "6e8982bef70e90ee745d6985c82c597e",
"cacheID": "b8095743d31791d2084177fde0203ed4",
"id": null,
"metadata": {
"connection": [
@@ -268,19 +268,19 @@ return {
"cursor": null,
"direction": "forward",
"path": [
"mitigation",
"mesure",
"risks"
]
}
]
},
"name": "MitigationViewRisksQuery",
"name": "MesureViewRisksQuery",
"operationKind": "query",
"text": "query MitigationViewRisksQuery(\n $mitigationId: ID!\n) {\n mitigation: node(id: $mitigationId) {\n __typename\n id\n ... on Mitigation {\n risks(first: 100) {\n edges {\n node {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
"text": "query MesureViewRisksQuery(\n $mesureId: ID!\n) {\n mesure: node(id: $mesureId) {\n __typename\n id\n ... on Mesure {\n risks(first: 100) {\n edges {\n node {\n id\n name\n description\n inherentLikelihood\n inherentImpact\n createdAt\n updatedAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "0fe825c558627da60c1025efa825f91e";
(node as any).hash = "0609b3e58837ae65fb4df484b967060a";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<a0f8386de345c2c768657efd4358518c>>
* @generated SignedSource<<1a725a74db916d1672685d90c48def81>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -12,10 +12,10 @@ import { ConcreteRequest } from 'relay-runtime';
export type UnassignTaskInput = {
taskId: string;
};
export type MitigationViewUnassignTaskMutation$variables = {
export type MesureViewUnassignTaskMutation$variables = {
input: UnassignTaskInput;
};
export type MitigationViewUnassignTaskMutation$data = {
export type MesureViewUnassignTaskMutation$data = {
readonly unassignTask: {
readonly task: {
readonly assignedTo: {
@@ -27,9 +27,9 @@ export type MitigationViewUnassignTaskMutation$data = {
};
};
};
export type MitigationViewUnassignTaskMutation = {
response: MitigationViewUnassignTaskMutation$data;
variables: MitigationViewUnassignTaskMutation$variables;
export type MesureViewUnassignTaskMutation = {
response: MesureViewUnassignTaskMutation$data;
variables: MesureViewUnassignTaskMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -109,7 +109,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewUnassignTaskMutation",
"name": "MesureViewUnassignTaskMutation",
"selections": (v2/*: any*/),
"type": "Mutation",
"abstractKey": null
@@ -118,20 +118,20 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewUnassignTaskMutation",
"name": "MesureViewUnassignTaskMutation",
"selections": (v2/*: any*/)
},
"params": {
"cacheID": "6cf554a835936763f3b4f55f04c9771f",
"cacheID": "3f91f027e7a8a935f306386469bbac21",
"id": null,
"metadata": {},
"name": "MitigationViewUnassignTaskMutation",
"name": "MesureViewUnassignTaskMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewUnassignTaskMutation(\n $input: UnassignTaskInput!\n) {\n unassignTask(input: $input) {\n task {\n id\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n }\n }\n}\n"
"text": "mutation MesureViewUnassignTaskMutation(\n $input: UnassignTaskInput!\n) {\n unassignTask(input: $input) {\n task {\n id\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "07d79596fef3416fdc001077d2d51c75";
(node as any).hash = "c5c62c4c4d16dfd6147a1d44aa35b8fe";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<1d924bb487fd93636fa7207c5aa08cdc>>
* @generated SignedSource<<9dac57f235ab6d16f6b3f78002c83dcc>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,30 +9,30 @@
// @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 UpdateMitigationInput = {
export type MesureImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type MesureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type UpdateMesureInput = {
category?: string | null | undefined;
description?: string | null | undefined;
id: string;
importance?: MitigationImportance | null | undefined;
importance?: MesureImportance | null | undefined;
name?: string | null | undefined;
state?: MitigationState | null | undefined;
state?: MesureState | null | undefined;
};
export type MitigationViewUpdateMitigationStateMutation$variables = {
input: UpdateMitigationInput;
export type MesureViewUpdateMesureStateMutation$variables = {
input: UpdateMesureInput;
};
export type MitigationViewUpdateMitigationStateMutation$data = {
readonly updateMitigation: {
readonly mitigation: {
export type MesureViewUpdateMesureStateMutation$data = {
readonly updateMesure: {
readonly mesure: {
readonly id: string;
readonly state: MitigationState;
readonly state: MesureState;
};
};
};
export type MitigationViewUpdateMitigationStateMutation = {
response: MitigationViewUpdateMitigationStateMutation$data;
variables: MitigationViewUpdateMitigationStateMutation$variables;
export type MesureViewUpdateMesureStateMutation = {
response: MesureViewUpdateMesureStateMutation$data;
variables: MesureViewUpdateMesureStateMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -53,17 +53,17 @@ v1 = [
"variableName": "input"
}
],
"concreteType": "UpdateMitigationPayload",
"concreteType": "UpdateMesurePayload",
"kind": "LinkedField",
"name": "updateMitigation",
"name": "updateMesure",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Mitigation",
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "mitigation",
"name": "mesure",
"plural": false,
"selections": [
{
@@ -92,7 +92,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewUpdateMitigationStateMutation",
"name": "MesureViewUpdateMesureStateMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
@@ -101,20 +101,20 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewUpdateMitigationStateMutation",
"name": "MesureViewUpdateMesureStateMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "7e4a92a089fa5927b0239004c3fb5f47",
"cacheID": "59db8143f555230677a401f5bed6a6c3",
"id": null,
"metadata": {},
"name": "MitigationViewUpdateMitigationStateMutation",
"name": "MesureViewUpdateMesureStateMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewUpdateMitigationStateMutation(\n $input: UpdateMitigationInput!\n) {\n updateMitigation(input: $input) {\n mitigation {\n id\n state\n }\n }\n}\n"
"text": "mutation MesureViewUpdateMesureStateMutation(\n $input: UpdateMesureInput!\n) {\n updateMesure(input: $input) {\n mesure {\n id\n state\n }\n }\n}\n"
}
};
})();
(node as any).hash = "e985902d55a537a08b8a2d4482abe0b3";
(node as any).hash = "ae0f63f654568f052621f28e73382172";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<a68054962a4ec7ae205dc2976fe8d2bf>>
* @generated SignedSource<<efb9132cf25dca5dff1df4fa6f139cd1>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -17,10 +17,10 @@ export type UpdateTaskInput = {
taskId: string;
timeEstimate?: any | null | undefined;
};
export type MitigationViewUpdateTaskStateMutation$variables = {
export type MesureViewUpdateTaskStateMutation$variables = {
input: UpdateTaskInput;
};
export type MitigationViewUpdateTaskStateMutation$data = {
export type MesureViewUpdateTaskStateMutation$data = {
readonly updateTask: {
readonly task: {
readonly id: string;
@@ -29,9 +29,9 @@ export type MitigationViewUpdateTaskStateMutation$data = {
};
};
};
export type MitigationViewUpdateTaskStateMutation = {
response: MitigationViewUpdateTaskStateMutation$data;
variables: MitigationViewUpdateTaskStateMutation$variables;
export type MesureViewUpdateTaskStateMutation = {
response: MesureViewUpdateTaskStateMutation$data;
variables: MesureViewUpdateTaskStateMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -98,7 +98,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewUpdateTaskStateMutation",
"name": "MesureViewUpdateTaskStateMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
@@ -107,20 +107,20 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MitigationViewUpdateTaskStateMutation",
"name": "MesureViewUpdateTaskStateMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "f8d2ca86f8e7856b3d24bcd810490a6a",
"cacheID": "3af3e26a5c5be4c129b6d1706d3d1b59",
"id": null,
"metadata": {},
"name": "MitigationViewUpdateTaskStateMutation",
"name": "MesureViewUpdateTaskStateMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewUpdateTaskStateMutation(\n $input: UpdateTaskInput!\n) {\n updateTask(input: $input) {\n task {\n id\n state\n timeEstimate\n }\n }\n}\n"
"text": "mutation MesureViewUpdateTaskStateMutation(\n $input: UpdateTaskInput!\n) {\n updateTask(input: $input) {\n task {\n id\n state\n timeEstimate\n }\n }\n}\n"
}
};
})();
(node as any).hash = "7ab07c94be8f56a93d39178828d85823";
(node as any).hash = "fd909d70346802420c83942efa30ef20";
export default node;

View File

@@ -0,0 +1,221 @@
/**
* @generated SignedSource<<6e5efc598a8e6657fd0a1375e6104ff6>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from "relay-runtime";
export type EvidenceState = "FULLFILLED" | "REQUESTED";
export type EvidenceType = "FILE" | "LINK";
export type UploadEvidenceInput = {
description: string;
file?: any | null | undefined;
name: string;
taskId: string;
type: EvidenceType;
url?: string | null | undefined;
};
export type MesureViewUploadEvidenceMutation$variables = {
connections: ReadonlyArray<string>;
input: UploadEvidenceInput;
};
export type MesureViewUploadEvidenceMutation$data = {
readonly uploadEvidence: {
readonly evidenceEdge: {
readonly node: {
readonly createdAt: string;
readonly fileUrl: string | null | undefined;
readonly filename: string;
readonly id: string;
readonly mimeType: string;
readonly size: number;
readonly state: EvidenceState;
readonly type: EvidenceType;
readonly url: string | null | undefined;
};
};
};
};
export type MesureViewUploadEvidenceMutation = {
response: MesureViewUploadEvidenceMutation$data;
variables: MesureViewUploadEvidenceMutation$variables;
};
const node: ConcreteRequest = (function () {
var v0 = {
defaultValue: null,
kind: "LocalArgument",
name: "connections",
},
v1 = {
defaultValue: null,
kind: "LocalArgument",
name: "input",
},
v2 = [
{
kind: "Variable",
name: "input",
variableName: "input",
},
],
v3 = {
alias: null,
args: null,
concreteType: "EvidenceEdge",
kind: "LinkedField",
name: "evidenceEdge",
plural: false,
selections: [
{
alias: null,
args: null,
concreteType: "Evidence",
kind: "LinkedField",
name: "node",
plural: false,
selections: [
{
alias: null,
args: null,
kind: "ScalarField",
name: "id",
storageKey: null,
},
{
alias: null,
args: null,
kind: "ScalarField",
name: "filename",
storageKey: null,
},
{
alias: null,
args: null,
kind: "ScalarField",
name: "fileUrl",
storageKey: null,
},
{
alias: null,
args: null,
kind: "ScalarField",
name: "mimeType",
storageKey: null,
},
{
alias: null,
args: null,
kind: "ScalarField",
name: "type",
storageKey: null,
},
{
alias: null,
args: null,
kind: "ScalarField",
name: "url",
storageKey: null,
},
{
alias: null,
args: null,
kind: "ScalarField",
name: "size",
storageKey: null,
},
{
alias: null,
args: null,
kind: "ScalarField",
name: "state",
storageKey: null,
},
{
alias: null,
args: null,
kind: "ScalarField",
name: "createdAt",
storageKey: null,
},
],
storageKey: null,
},
],
storageKey: null,
};
return {
fragment: {
argumentDefinitions: [v0 /*: any*/, v1 /*: any*/],
kind: "Fragment",
metadata: null,
name: "MesureViewUploadEvidenceMutation",
selections: [
{
alias: null,
args: v2 /*: any*/,
concreteType: "UploadEvidencePayload",
kind: "LinkedField",
name: "uploadEvidence",
plural: false,
selections: [v3 /*: any*/],
storageKey: null,
},
],
type: "Mutation",
abstractKey: null,
},
kind: "Request",
operation: {
argumentDefinitions: [v1 /*: any*/, v0 /*: any*/],
kind: "Operation",
name: "MesureViewUploadEvidenceMutation",
selections: [
{
alias: null,
args: v2 /*: any*/,
concreteType: "UploadEvidencePayload",
kind: "LinkedField",
name: "uploadEvidence",
plural: false,
selections: [
v3 /*: any*/,
{
alias: null,
args: null,
filters: null,
handle: "appendEdge",
key: "",
kind: "LinkedHandle",
name: "evidenceEdge",
handleArgs: [
{
kind: "Variable",
name: "connections",
variableName: "connections",
},
],
},
],
storageKey: null,
},
],
},
params: {
cacheID: "30a6915055d3f6b63d96836b26f05a45",
id: null,
metadata: {},
name: "MesureViewUploadEvidenceMutation",
operationKind: "mutation",
text: "mutation MesureViewUploadEvidenceMutation(\n $input: UploadEvidenceInput!\n) {\n uploadEvidence(input: $input) {\n evidenceEdge {\n node {\n id\n filename\n fileUrl\n mimeType\n type\n url\n size\n state\n createdAt\n }\n }\n }\n}\n",
},
};
})();
(node as any).hash = "4cf5430a0971ba1ddf476765df614e30";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<50b15dea665515ca83a54c39e03453c2>>
* @generated SignedSource<<3b585f9a06a084982155a0f356838402>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,21 +9,21 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MitigationImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type CreateMitigationInput = {
export type MesureImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
export type CreateMesureInput = {
category: string;
description: string;
importance: MitigationImportance;
importance: MesureImportance;
name: string;
organizationId: string;
};
export type NewMitigationViewCreateMitigationMutation$variables = {
export type NewMesureViewCreateMesureMutation$variables = {
connections: ReadonlyArray<string>;
input: CreateMitigationInput;
input: CreateMesureInput;
};
export type NewMitigationViewCreateMitigationMutation$data = {
readonly createMitigation: {
readonly mitigationEdge: {
export type NewMesureViewCreateMesureMutation$data = {
readonly createMesure: {
readonly mesureEdge: {
readonly node: {
readonly description: string;
readonly id: string;
@@ -32,9 +32,9 @@ export type NewMitigationViewCreateMitigationMutation$data = {
};
};
};
export type NewMitigationViewCreateMitigationMutation = {
response: NewMitigationViewCreateMitigationMutation$data;
variables: NewMitigationViewCreateMitigationMutation$variables;
export type NewMesureViewCreateMesureMutation = {
response: NewMesureViewCreateMesureMutation$data;
variables: NewMesureViewCreateMesureMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -58,15 +58,15 @@ v2 = [
v3 = {
"alias": null,
"args": null,
"concreteType": "MitigationEdge",
"concreteType": "MesureEdge",
"kind": "LinkedField",
"name": "mitigationEdge",
"name": "mesureEdge",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Mitigation",
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "node",
"plural": false,
@@ -106,14 +106,14 @@ return {
],
"kind": "Fragment",
"metadata": null,
"name": "NewMitigationViewCreateMitigationMutation",
"name": "NewMesureViewCreateMesureMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "CreateMitigationPayload",
"concreteType": "CreateMesurePayload",
"kind": "LinkedField",
"name": "createMitigation",
"name": "createMesure",
"plural": false,
"selections": [
(v3/*: any*/)
@@ -131,14 +131,14 @@ return {
(v0/*: any*/)
],
"kind": "Operation",
"name": "NewMitigationViewCreateMitigationMutation",
"name": "NewMesureViewCreateMesureMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "CreateMitigationPayload",
"concreteType": "CreateMesurePayload",
"kind": "LinkedField",
"name": "createMitigation",
"name": "createMesure",
"plural": false,
"selections": [
(v3/*: any*/),
@@ -149,7 +149,7 @@ return {
"handle": "prependEdge",
"key": "",
"kind": "LinkedHandle",
"name": "mitigationEdge",
"name": "mesureEdge",
"handleArgs": [
{
"kind": "Variable",
@@ -164,16 +164,16 @@ return {
]
},
"params": {
"cacheID": "9615313ab1f2555f58a79b85741684f4",
"cacheID": "de8b930c9628c62ae4272bd427076ebd",
"id": null,
"metadata": {},
"name": "NewMitigationViewCreateMitigationMutation",
"name": "NewMesureViewCreateMesureMutation",
"operationKind": "mutation",
"text": "mutation NewMitigationViewCreateMitigationMutation(\n $input: CreateMitigationInput!\n) {\n createMitigation(input: $input) {\n mitigationEdge {\n node {\n id\n name\n description\n }\n }\n }\n}\n"
"text": "mutation NewMesureViewCreateMesureMutation(\n $input: CreateMesureInput!\n) {\n createMesure(input: $input) {\n mesureEdge {\n node {\n id\n name\n description\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "6b6ead3a24d113ec969c98680956ebb9";
(node as any).hash = "94532353875a658b6e0b87a8181eab5e";
export default node;

View File

@@ -1,229 +0,0 @@
/**
* @generated SignedSource<<6e5efc598a8e6657fd0a1375e6104ff6>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type EvidenceState = "FULLFILLED" | "REQUESTED";
export type EvidenceType = "FILE" | "LINK";
export type UploadEvidenceInput = {
description: string;
file?: any | null | undefined;
name: string;
taskId: string;
type: EvidenceType;
url?: string | null | undefined;
};
export type MitigationViewUploadEvidenceMutation$variables = {
connections: ReadonlyArray<string>;
input: UploadEvidenceInput;
};
export type MitigationViewUploadEvidenceMutation$data = {
readonly uploadEvidence: {
readonly evidenceEdge: {
readonly node: {
readonly createdAt: string;
readonly fileUrl: string | null | undefined;
readonly filename: string;
readonly id: string;
readonly mimeType: string;
readonly size: number;
readonly state: EvidenceState;
readonly type: EvidenceType;
readonly url: string | null | undefined;
};
};
};
};
export type MitigationViewUploadEvidenceMutation = {
response: MitigationViewUploadEvidenceMutation$data;
variables: MitigationViewUploadEvidenceMutation$variables;
};
const node: ConcreteRequest = (function(){
var v0 = {
"defaultValue": null,
"kind": "LocalArgument",
"name": "connections"
},
v1 = {
"defaultValue": null,
"kind": "LocalArgument",
"name": "input"
},
v2 = [
{
"kind": "Variable",
"name": "input",
"variableName": "input"
}
],
v3 = {
"alias": null,
"args": null,
"concreteType": "EvidenceEdge",
"kind": "LinkedField",
"name": "evidenceEdge",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Evidence",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "filename",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fileUrl",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "mimeType",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "type",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "url",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "size",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "state",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
};
return {
"fragment": {
"argumentDefinitions": [
(v0/*: any*/),
(v1/*: any*/)
],
"kind": "Fragment",
"metadata": null,
"name": "MitigationViewUploadEvidenceMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "UploadEvidencePayload",
"kind": "LinkedField",
"name": "uploadEvidence",
"plural": false,
"selections": [
(v3/*: any*/)
],
"storageKey": null
}
],
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": [
(v1/*: any*/),
(v0/*: any*/)
],
"kind": "Operation",
"name": "MitigationViewUploadEvidenceMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "UploadEvidencePayload",
"kind": "LinkedField",
"name": "uploadEvidence",
"plural": false,
"selections": [
(v3/*: any*/),
{
"alias": null,
"args": null,
"filters": null,
"handle": "appendEdge",
"key": "",
"kind": "LinkedHandle",
"name": "evidenceEdge",
"handleArgs": [
{
"kind": "Variable",
"name": "connections",
"variableName": "connections"
}
]
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "30a6915055d3f6b63d96836b26f05a45",
"id": null,
"metadata": {},
"name": "MitigationViewUploadEvidenceMutation",
"operationKind": "mutation",
"text": "mutation MitigationViewUploadEvidenceMutation(\n $input: UploadEvidenceInput!\n) {\n uploadEvidence(input: $input) {\n evidenceEdge {\n node {\n id\n filename\n fileUrl\n mimeType\n type\n url\n size\n state\n createdAt\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "4cf5430a0971ba1ddf476765df614e30";
export default node;

View File

@@ -16,7 +16,7 @@ export function PolicyListViewSkeleton() {
<div className="bg-subtle-bg animate-pulse h-9 w-1/6 rounded-lg" />
}
>
{/* Search and filter mitigations skeleton */}
{/* Search and filter mesures skeleton */}
<div className="flex flex-col md:flex-row gap-4 mb-6">
<div className="flex-1 h-10 bg-subtle-bg animate-pulse rounded" />
<div className="flex gap-2">

View File

@@ -232,7 +232,7 @@ function PolicyListViewContent({
</Button>
}
>
{/* Search and filter mitigations */}
{/* Search and filter mesures */}
<div className="flex flex-col md:flex-row gap-4 mb-6">
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-tertiary" />

View File

@@ -54,11 +54,11 @@ import {
TableRow,
} from "@/components/ui/table";
import {
ShowRiskViewOrganizationMitigationsQuery,
ShowRiskViewOrganizationMitigationsQuery$data,
} from "./__generated__/ShowRiskViewOrganizationMitigationsQuery.graphql";
import { ShowRiskViewCreateRiskMitigationMappingMutation } from "./__generated__/ShowRiskViewCreateRiskMitigationMappingMutation.graphql";
import { ShowRiskViewDeleteRiskMitigationMappingMutation } from "./__generated__/ShowRiskViewDeleteRiskMitigationMappingMutation.graphql";
ShowRiskViewOrganizationMesuresQuery,
ShowRiskViewOrganizationMesuresQuery$data,
} from "./__generated__/ShowRiskViewOrganizationMesuresQuery.graphql";
import { ShowRiskViewCreateRiskMesureMappingMutation } from "./__generated__/ShowRiskViewCreateRiskMesureMappingMutation.graphql";
import { ShowRiskViewDeleteRiskMesureMappingMutation } from "./__generated__/ShowRiskViewDeleteRiskMesureMappingMutation.graphql";
import {
ShowRiskViewOrganizationPoliciesQuery,
ShowRiskViewOrganizationPoliciesQuery$data,
@@ -84,7 +84,7 @@ const showRiskViewQuery = graphql`
residualImpact
createdAt
updatedAt
mitigations(first: 100) @connection(key: "Risk__mitigations") {
mesures(first: 100) @connection(key: "Risk__mesures") {
edges {
node {
id
@@ -122,13 +122,13 @@ const showRiskViewQuery = graphql`
}
`;
// Add query to fetch all mitigations for the organization
const organizationMitigationsQuery = graphql`
query ShowRiskViewOrganizationMitigationsQuery($organizationId: ID!) {
// Add query to fetch all mesures for the organization
const organizationMesuresQuery = graphql`
query ShowRiskViewOrganizationMesuresQuery($organizationId: ID!) {
organization: node(id: $organizationId) {
id
... on Organization {
mitigations(first: 100) @connection(key: "Organization__mitigations") {
mesures(first: 100) @connection(key: "Organization__mesures") {
edges {
node {
id
@@ -164,23 +164,23 @@ const organizationPoliciesQuery = graphql`
}
`;
// Add mutation to create risk-mitigation mapping
const createRiskMitigationMappingMutation = graphql`
mutation ShowRiskViewCreateRiskMitigationMappingMutation(
$input: CreateRiskMitigationMappingInput!
// Add mutation to create risk-mesure mapping
const createRiskMesureMappingMutation = graphql`
mutation ShowRiskViewCreateRiskMesureMappingMutation(
$input: CreateRiskMesureMappingInput!
) {
createRiskMitigationMapping(input: $input) {
createRiskMesureMapping(input: $input) {
success
}
}
`;
// Add mutation to delete risk-mitigation mapping
const deleteRiskMitigationMappingMutation = graphql`
mutation ShowRiskViewDeleteRiskMitigationMappingMutation(
$input: DeleteRiskMitigationMappingInput!
// Add mutation to delete risk-mesure mapping
const deleteRiskMesureMappingMutation = graphql`
mutation ShowRiskViewDeleteRiskMesureMappingMutation(
$input: DeleteRiskMesureMappingInput!
) {
deleteRiskMitigationMapping(input: $input) {
deleteRiskMesureMapping(input: $input) {
success
}
}
@@ -238,8 +238,8 @@ function ShowRiskViewContent({
risk.inherentImpact!
);
// Fix typing for mitigations
const mitigations = risk.mitigations?.edges?.map((edge) => edge.node) || [];
// Fix typing for mesures
const mesures = risk.mesures?.edges?.map((edge) => edge.node) || [];
const residualSeverity = getRiskSeverity(
risk.residualLikelihood!,
risk.residualImpact!
@@ -251,17 +251,17 @@ function ShowRiskViewContent({
// Fix typing for controls
const controls = risk.controls?.edges?.map((edge) => edge.node) || [];
// Add state for mitigation mapping dialog
const [isMitigationDialogOpen, setIsMitigationDialogOpen] = useState(false);
const [organizationMitigationsData, setOrganizationMitigationsData] =
useState<ShowRiskViewOrganizationMitigationsQuery$data | null>(null);
const [mitigationSearchQuery, setMitigationSearchQuery] = useState("");
// Add state for mesure mapping dialog
const [isMesureDialogOpen, setIsMesureDialogOpen] = useState(false);
const [organizationMesuresData, setOrganizationMesuresData] =
useState<ShowRiskViewOrganizationMesuresQuery$data | null>(null);
const [mesureSearchQuery, setMesureSearchQuery] = useState("");
const [categoryFilter, setCategoryFilter] = useState<string | null>(null);
const [isLoadingMitigations, setIsLoadingMitigations] = useState(false);
const [linkingMitigations, setLinkingMitigations] = useState<
Record<string, boolean>
>({});
const [unlinkingMitigations, setUnlinkingMitigations] = useState<
const [isLoadingMesures, setIsLoadingMesures] = useState(false);
const [linkingMesures, setLinkingMesures] = useState<Record<string, boolean>>(
{}
);
const [unlinkingMesures, setUnlinkingMesures] = useState<
Record<string, boolean>
>({});
@@ -279,13 +279,13 @@ function ShowRiskViewContent({
>({});
// Setup mutation hooks
const [createRiskMitigationMapping] =
useMutation<ShowRiskViewCreateRiskMitigationMappingMutation>(
createRiskMitigationMappingMutation
const [createRiskMesureMapping] =
useMutation<ShowRiskViewCreateRiskMesureMappingMutation>(
createRiskMesureMappingMutation
);
const [deleteRiskMitigationMapping] =
useMutation<ShowRiskViewDeleteRiskMitigationMappingMutation>(
deleteRiskMitigationMappingMutation
const [deleteRiskMesureMapping] =
useMutation<ShowRiskViewDeleteRiskMesureMappingMutation>(
deleteRiskMesureMappingMutation
);
// Setup policy mutation hooks
@@ -300,13 +300,13 @@ function ShowRiskViewContent({
// Clear filters when dialog closes
useEffect(() => {
if (!isMitigationDialogOpen) {
setMitigationSearchQuery("");
if (!isMesureDialogOpen) {
setMesureSearchQuery("");
setCategoryFilter(null);
setLinkingMitigations({});
setUnlinkingMitigations({});
setLinkingMesures({});
setUnlinkingMesures({});
}
}, [isMitigationDialogOpen]);
}, [isMesureDialogOpen]);
// Clear filters when policy dialog closes
useEffect(() => {
@@ -317,30 +317,30 @@ function ShowRiskViewContent({
}
}, [isPolicyDialogOpen]);
// Load mitigations data when needed
const loadMitigationsData = useCallback(() => {
// Load mesures data when needed
const loadMesuresData = useCallback(() => {
if (!organizationId || !risk.id) return;
setIsLoadingMitigations(true);
setIsLoadingMesures(true);
// Fetch all mitigations for the organization
fetchQuery<ShowRiskViewOrganizationMitigationsQuery>(
// Fetch all mesures for the organization
fetchQuery<ShowRiskViewOrganizationMesuresQuery>(
environment,
organizationMitigationsQuery,
organizationMesuresQuery,
{
organizationId,
}
).subscribe({
next: (data) => {
setOrganizationMitigationsData(data);
setIsLoadingMitigations(false);
setOrganizationMesuresData(data);
setIsLoadingMesures(false);
},
error: (error: Error) => {
console.error("Error fetching organization mitigations:", error);
setIsLoadingMitigations(false);
console.error("Error fetching organization mesures:", error);
setIsLoadingMesures(false);
toast({
title: "Error",
description: "Failed to load mitigations.",
description: "Failed to load mesures.",
variant: "destructive",
});
},
@@ -378,52 +378,49 @@ function ShowRiskViewContent({
}, [risk.id, environment, organizationId, toast]);
// Helper functions
const getMitigations = useCallback(() => {
if (!organizationMitigationsData?.organization?.mitigations?.edges)
return [];
return organizationMitigationsData.organization.mitigations.edges.map(
const getMesures = useCallback(() => {
if (!organizationMesuresData?.organization?.mesures?.edges) return [];
return organizationMesuresData.organization.mesures.edges.map(
(edge) => edge.node
);
}, [organizationMitigationsData]);
}, [organizationMesuresData]);
const getMitigationCategories = useCallback(() => {
const mitigations = getMitigations();
const getMesureCategories = useCallback(() => {
const mesures = getMesures();
const categories = new Set<string>();
mitigations.forEach((mitigation) => {
if (mitigation.category) {
categories.add(mitigation.category);
mesures.forEach((mesure) => {
if (mesure.category) {
categories.add(mesure.category);
}
});
return Array.from(categories).sort();
}, [getMitigations]);
}, [getMesures]);
const filteredMitigations = useCallback(() => {
const mitigations = getMitigations();
if (!mitigationSearchQuery && !categoryFilter) return mitigations;
const filteredMesures = useCallback(() => {
const mesures = getMesures();
if (!mesureSearchQuery && !categoryFilter) return mesures;
return mitigations.filter((mitigation) => {
return mesures.filter((mesure) => {
// Filter by search query
const matchesSearch =
!mitigationSearchQuery ||
mitigation.name
.toLowerCase()
.includes(mitigationSearchQuery.toLowerCase()) ||
(mitigation.description &&
mitigation.description
!mesureSearchQuery ||
mesure.name.toLowerCase().includes(mesureSearchQuery.toLowerCase()) ||
(mesure.description &&
mesure.description
.toLowerCase()
.includes(mitigationSearchQuery.toLowerCase()));
.includes(mesureSearchQuery.toLowerCase()));
// Filter by category
const matchesCategory =
!categoryFilter ||
categoryFilter === "all" ||
mitigation.category === categoryFilter;
mesure.category === categoryFilter;
return matchesSearch && matchesCategory;
});
}, [getMitigations, mitigationSearchQuery, categoryFilter]);
}, [getMesures, mesureSearchQuery, categoryFilter]);
// Helper functions for policies
const getPolicies = useCallback(() => {
@@ -445,38 +442,38 @@ function ShowRiskViewContent({
});
}, [getPolicies, policySearchQuery]);
// Handle linking a mitigation to this risk
const handleLinkMitigation = useCallback(
// Handle linking a mesure to this risk
const handleLinkMesure = useCallback(
(
mitigation: NonNullable<
mesure: NonNullable<
NonNullable<
ShowRiskViewOrganizationMitigationsQuery$data["organization"]
>["mitigations"]
ShowRiskViewOrganizationMesuresQuery$data["organization"]
>["mesures"]
>["edges"][0]["node"]
) => {
if (!risk.id) return;
// Track this specific mitigation as linking
setLinkingMitigations((prev) => ({ ...prev, [mitigation.id]: true }));
// Track this specific mesure as linking
setLinkingMesures((prev) => ({ ...prev, [mesure.id]: true }));
createRiskMitigationMapping({
createRiskMesureMapping({
variables: {
input: {
riskId: risk.id,
mitigationId: mitigation.id,
mesureId: mesure.id,
},
},
onCompleted: (_, errors) => {
setLinkingMitigations((prev) => ({
setLinkingMesures((prev) => ({
...prev,
[mitigation.id]: false,
[mesure.id]: false,
}));
if (errors && errors.length > 0) {
console.error("Error linking mitigation:", errors);
console.error("Error linking mesure:", errors);
toast({
title: "Error",
description: "Failed to link mitigation. Please try again.",
description: "Failed to link mesure. Please try again.",
variant: "destructive",
});
return;
@@ -497,58 +494,58 @@ function ShowRiskViewContent({
toast({
title: "Success",
description: `Linked mitigation "${mitigation.name}" to this risk.`,
description: `Linked mesure "${mesure.name}" to this risk.`,
});
},
onError: (error) => {
setLinkingMitigations((prev) => ({
setLinkingMesures((prev) => ({
...prev,
[mitigation.id]: false,
[mesure.id]: false,
}));
console.error("Error linking mitigation:", error);
console.error("Error linking mesure:", error);
toast({
title: "Error",
description: "Failed to link mitigation. Please try again.",
description: "Failed to link mesure. Please try again.",
variant: "destructive",
});
},
});
},
[risk.id, createRiskMitigationMapping, toast, environment, loadQuery]
[risk.id, createRiskMesureMapping, toast, environment, loadQuery]
);
// Handle unlinking a mitigation from this risk
const handleUnlinkMitigation = useCallback(
// Handle unlinking a mesure from this risk
const handleUnlinkMesure = useCallback(
(
mitigation: NonNullable<
mesure: NonNullable<
NonNullable<
ShowRiskViewOrganizationMitigationsQuery$data["organization"]
>["mitigations"]
ShowRiskViewOrganizationMesuresQuery$data["organization"]
>["mesures"]
>["edges"][0]["node"]
) => {
if (!risk.id) return;
// Track this specific mitigation as unlinking
setUnlinkingMitigations((prev) => ({ ...prev, [mitigation.id]: true }));
// Track this specific mesure as unlinking
setUnlinkingMesures((prev) => ({ ...prev, [mesure.id]: true }));
deleteRiskMitigationMapping({
deleteRiskMesureMapping({
variables: {
input: {
riskId: risk.id,
mitigationId: mitigation.id,
mesureId: mesure.id,
},
},
onCompleted: (_, errors) => {
setUnlinkingMitigations((prev) => ({
setUnlinkingMesures((prev) => ({
...prev,
[mitigation.id]: false,
[mesure.id]: false,
}));
if (errors && errors.length > 0) {
console.error("Error unlinking mitigation:", errors);
console.error("Error unlinking mesure:", errors);
toast({
title: "Error",
description: "Failed to unlink mitigation. Please try again.",
description: "Failed to unlink mesure. Please try again.",
variant: "destructive",
});
return;
@@ -569,24 +566,24 @@ function ShowRiskViewContent({
toast({
title: "Success",
description: `Unlinked mitigation "${mitigation.name}" from this risk.`,
description: `Unlinked mesure "${mesure.name}" from this risk.`,
});
},
onError: (error) => {
setUnlinkingMitigations((prev) => ({
setUnlinkingMesures((prev) => ({
...prev,
[mitigation.id]: false,
[mesure.id]: false,
}));
console.error("Error unlinking mitigation:", error);
console.error("Error unlinking mesure:", error);
toast({
title: "Error",
description: "Failed to unlink mitigation. Please try again.",
description: "Failed to unlink mesure. Please try again.",
variant: "destructive",
});
},
});
},
[risk.id, deleteRiskMitigationMapping, toast, environment, loadQuery]
[risk.id, deleteRiskMesureMapping, toast, environment, loadQuery]
);
// Handle linking a policy to this risk
@@ -871,8 +868,8 @@ function ShowRiskViewContent({
</Badge>
</p>
<p className="text-xs text-secondary mt-1">
{mitigations.length} mitigation
{mitigations.length !== 1 ? "s" : ""} applied
{mesures.length} mesure
{mesures.length !== 1 ? "s" : ""} applied
</p>
</div>
</div>
@@ -880,56 +877,53 @@ function ShowRiskViewContent({
</CardContent>
</Card>
<Tabs defaultValue="mitigations" className="w-full">
<Tabs defaultValue="mesures" className="w-full">
<TabsList>
<TabsTrigger value="mitigations">Mitigations</TabsTrigger>
<TabsTrigger value="mesures">Mesures</TabsTrigger>
<TabsTrigger value="policies">Policies</TabsTrigger>
<TabsTrigger value="controls">Controls</TabsTrigger>
</TabsList>
<TabsContent value="mitigations" className="space-y-4">
<TabsContent value="mesures" className="space-y-4">
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-semibold">Risk Mitigations</h2>
<h2 className="text-xl font-semibold">Risk Mesures</h2>
<Button
onClick={() => {
setIsMitigationDialogOpen(true);
loadMitigationsData();
setIsMesureDialogOpen(true);
loadMesuresData();
}}
>
<Plus className="mr-2 h-4 w-4" />
Link Mitigation
Link Mesure
</Button>
</div>
{risk.mitigations?.edges?.length &&
risk.mitigations?.edges?.length > 0 ? (
{risk.mesures?.edges?.length && risk.mesures?.edges?.length > 0 ? (
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-full">Mitigation</TableHead>
<TableHead className="w-full">Mesure</TableHead>
<TableHead className="w-20">Actions</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{risk.mitigations?.edges.map(({ node: mitigation }) => (
<TableRow key={mitigation.id}>
{risk.mesures?.edges.map(({ node: mesure }) => (
<TableRow key={mesure.id}>
<TableCell>
<Link
to={`/organizations/${organizationId}/mitigations/${mitigation.id}`}
to={`/organizations/${organizationId}/mesures/${mesure.id}`}
className="font-medium text-blue-600 hover:underline"
>
{mitigation.name}
{mesure.name}
</Link>
</TableCell>
<TableCell>
<Button
variant="ghost"
size="icon"
onClick={() => handleUnlinkMitigation(mitigation)}
disabled={
unlinkingMitigations[mitigation.id] || false
}
title="Unlink mitigation"
onClick={() => handleUnlinkMesure(mesure)}
disabled={unlinkingMesures[mesure.id] || false}
title="Unlink mesure"
>
<Trash2 className="h-4 w-4 text-danger" />
</Button>
@@ -941,7 +935,7 @@ function ShowRiskViewContent({
</div>
) : (
<div className="text-center py-10 text-secondary">
<p>No mitigations associated with this risk.</p>
<p>No mesures associated with this risk.</p>
</div>
)}
</TabsContent>
@@ -1039,18 +1033,15 @@ function ShowRiskViewContent({
</TabsContent>
</Tabs>
{/* Dialog for linking mitigations */}
<Dialog
open={isMitigationDialogOpen}
onOpenChange={setIsMitigationDialogOpen}
>
{/* Dialog for linking mesures */}
<Dialog open={isMesureDialogOpen} onOpenChange={setIsMesureDialogOpen}>
<DialogContent className="max-w-3xl">
<DialogHeader>
<div className="flex justify-between items-center">
<div>
<DialogTitle>Manage Risk Mitigations</DialogTitle>
<DialogTitle>Manage Risk Mesures</DialogTitle>
<DialogDescription>
Link or unlink mitigations to manage this risk.
Link or unlink mesures to manage this risk.
</DialogDescription>
</div>
</div>
@@ -1062,10 +1053,10 @@ function ShowRiskViewContent({
<div className="relative">
<Search className="absolute left-2 top-2.5 h-4 w-4 text-tertiary" />
<Input
placeholder="Search mitigations..."
placeholder="Search mesures..."
className="pl-8"
value={mitigationSearchQuery}
onChange={(e) => setMitigationSearchQuery(e.target.value)}
value={mesureSearchQuery}
onChange={(e) => setMesureSearchQuery(e.target.value)}
/>
</div>
</div>
@@ -1080,7 +1071,7 @@ function ShowRiskViewContent({
</SelectTrigger>
<SelectContent>
<SelectItem value="all">All Categories</SelectItem>
{getMitigationCategories().map((category) => (
{getMesureCategories().map((category) => (
<SelectItem key={category} value={category}>
{category}
</SelectItem>
@@ -1090,37 +1081,35 @@ function ShowRiskViewContent({
</div>
<div className="border rounded-md max-h-96 overflow-y-auto">
{isLoadingMitigations ? (
<div className="p-4 text-center">Loading mitigations...</div>
) : filteredMitigations().length === 0 ? (
<div className="p-4 text-center">No mitigations found.</div>
{isLoadingMesures ? (
<div className="p-4 text-center">Loading mesures...</div>
) : filteredMesures().length === 0 ? (
<div className="p-4 text-center">No mesures found.</div>
) : (
<div className="divide-y">
{filteredMitigations().map((mitigation) => {
{filteredMesures().map((mesure) => {
// 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 isLinked = risk.mesures?.edges?.some(
(edge) => edge.node.id === mesure.id
);
const isLinking =
linkingMitigations[mitigation.id] || false;
const isUnlinking =
unlinkingMitigations[mitigation.id] || false;
const isLinking = linkingMesures[mesure.id] || false;
const isUnlinking = unlinkingMesures[mesure.id] || false;
return (
<div
key={mitigation.id}
key={mesure.id}
className="relative p-4 hover:bg-blue-50 transition-colors duration-150"
>
<div className="flex justify-between items-center">
<div className="flex items-center gap-2">
<h3 className="font-medium">{mitigation.name}</h3>
{mitigation.category && (
<h3 className="font-medium">{mesure.name}</h3>
{mesure.category && (
<Badge
variant="outline"
className="text-xs font-normal"
>
<Tag className="h-3 w-3 mr-1" />
{mitigation.category}
{mesure.category}
</Badge>
)}
</div>
@@ -1129,9 +1118,7 @@ function ShowRiskViewContent({
size="sm"
variant="outline"
disabled={isUnlinking}
onClick={() =>
handleUnlinkMitigation(mitigation)
}
onClick={() => handleUnlinkMesure(mesure)}
className="text-red-600 border-red-200 hover:bg-red-50"
>
{isUnlinking ? "Unlinking..." : "Unlink"}
@@ -1140,7 +1127,7 @@ function ShowRiskViewContent({
<Button
size="sm"
disabled={isLinking}
onClick={() => handleLinkMitigation(mitigation)}
onClick={() => handleLinkMesure(mesure)}
>
{isLinking ? "Linking..." : "Link"}
</Button>
@@ -1157,7 +1144,7 @@ function ShowRiskViewContent({
<DialogFooter>
<Button
variant="outline"
onClick={() => setIsMitigationDialogOpen(false)}
onClick={() => setIsMesureDialogOpen(false)}
>
Close
</Button>

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<73623cc6511c56dd418345cd64d500d5>>
* @generated SignedSource<<b2d5c0102cdcaff05ca490a75b797625>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,21 +9,21 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type CreateRiskMitigationMappingInput = {
mitigationId: string;
export type CreateRiskMesureMappingInput = {
mesureId: string;
riskId: string;
};
export type ShowRiskViewCreateRiskMitigationMappingMutation$variables = {
input: CreateRiskMitigationMappingInput;
export type ShowRiskViewCreateRiskMesureMappingMutation$variables = {
input: CreateRiskMesureMappingInput;
};
export type ShowRiskViewCreateRiskMitigationMappingMutation$data = {
readonly createRiskMitigationMapping: {
export type ShowRiskViewCreateRiskMesureMappingMutation$data = {
readonly createRiskMesureMapping: {
readonly success: boolean;
};
};
export type ShowRiskViewCreateRiskMitigationMappingMutation = {
response: ShowRiskViewCreateRiskMitigationMappingMutation$data;
variables: ShowRiskViewCreateRiskMitigationMappingMutation$variables;
export type ShowRiskViewCreateRiskMesureMappingMutation = {
response: ShowRiskViewCreateRiskMesureMappingMutation$data;
variables: ShowRiskViewCreateRiskMesureMappingMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -44,9 +44,9 @@ v1 = [
"variableName": "input"
}
],
"concreteType": "CreateRiskMitigationMappingPayload",
"concreteType": "CreateRiskMesureMappingPayload",
"kind": "LinkedField",
"name": "createRiskMitigationMapping",
"name": "createRiskMesureMapping",
"plural": false,
"selections": [
{
@@ -65,7 +65,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ShowRiskViewCreateRiskMitigationMappingMutation",
"name": "ShowRiskViewCreateRiskMesureMappingMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
@@ -74,20 +74,20 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ShowRiskViewCreateRiskMitigationMappingMutation",
"name": "ShowRiskViewCreateRiskMesureMappingMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "5a8744dfb9cf5f977c2702d848aab7ae",
"cacheID": "f7d34307825549877c07678c77ca17c6",
"id": null,
"metadata": {},
"name": "ShowRiskViewCreateRiskMitigationMappingMutation",
"name": "ShowRiskViewCreateRiskMesureMappingMutation",
"operationKind": "mutation",
"text": "mutation ShowRiskViewCreateRiskMitigationMappingMutation(\n $input: CreateRiskMitigationMappingInput!\n) {\n createRiskMitigationMapping(input: $input) {\n success\n }\n}\n"
"text": "mutation ShowRiskViewCreateRiskMesureMappingMutation(\n $input: CreateRiskMesureMappingInput!\n) {\n createRiskMesureMapping(input: $input) {\n success\n }\n}\n"
}
};
})();
(node as any).hash = "bdb664dab4a9e655c0923cfdd4ab0fe9";
(node as any).hash = "e1d7cdd482d6658c2befddd478a3397d";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<406a706e512ed01c1924632306a4f81c>>
* @generated SignedSource<<0fc791ecc00bfd6b1aa3a8da262df36c>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,21 +9,21 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type DeleteRiskMitigationMappingInput = {
mitigationId: string;
export type DeleteRiskMesureMappingInput = {
mesureId: string;
riskId: string;
};
export type ShowRiskViewDeleteRiskMitigationMappingMutation$variables = {
input: DeleteRiskMitigationMappingInput;
export type ShowRiskViewDeleteRiskMesureMappingMutation$variables = {
input: DeleteRiskMesureMappingInput;
};
export type ShowRiskViewDeleteRiskMitigationMappingMutation$data = {
readonly deleteRiskMitigationMapping: {
export type ShowRiskViewDeleteRiskMesureMappingMutation$data = {
readonly deleteRiskMesureMapping: {
readonly success: boolean;
};
};
export type ShowRiskViewDeleteRiskMitigationMappingMutation = {
response: ShowRiskViewDeleteRiskMitigationMappingMutation$data;
variables: ShowRiskViewDeleteRiskMitigationMappingMutation$variables;
export type ShowRiskViewDeleteRiskMesureMappingMutation = {
response: ShowRiskViewDeleteRiskMesureMappingMutation$data;
variables: ShowRiskViewDeleteRiskMesureMappingMutation$variables;
};
const node: ConcreteRequest = (function(){
@@ -44,9 +44,9 @@ v1 = [
"variableName": "input"
}
],
"concreteType": "DeleteRiskMitigationMappingPayload",
"concreteType": "DeleteRiskMesureMappingPayload",
"kind": "LinkedField",
"name": "deleteRiskMitigationMapping",
"name": "deleteRiskMesureMapping",
"plural": false,
"selections": [
{
@@ -65,7 +65,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ShowRiskViewDeleteRiskMitigationMappingMutation",
"name": "ShowRiskViewDeleteRiskMesureMappingMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
@@ -74,20 +74,20 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ShowRiskViewDeleteRiskMitigationMappingMutation",
"name": "ShowRiskViewDeleteRiskMesureMappingMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "9a4b56b457c7fb53dc2583da93a3aaa4",
"cacheID": "d46920306e833fb33b4f10dca6aa1c5a",
"id": null,
"metadata": {},
"name": "ShowRiskViewDeleteRiskMitigationMappingMutation",
"name": "ShowRiskViewDeleteRiskMesureMappingMutation",
"operationKind": "mutation",
"text": "mutation ShowRiskViewDeleteRiskMitigationMappingMutation(\n $input: DeleteRiskMitigationMappingInput!\n) {\n deleteRiskMitigationMapping(input: $input) {\n success\n }\n}\n"
"text": "mutation ShowRiskViewDeleteRiskMesureMappingMutation(\n $input: DeleteRiskMesureMappingInput!\n) {\n deleteRiskMesureMapping(input: $input) {\n success\n }\n}\n"
}
};
})();
(node as any).hash = "d9fece39ecffbd551662d6491088ce4c";
(node as any).hash = "e55c8d6490fbcfe0d287053200b6347d";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<da6cda7380aec978f37e3adc35942e03>>
* @generated SignedSource<<1fdd1781c11f4c88aeb14ba52fc3e884>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,29 +9,29 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MitigationState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type ShowRiskViewOrganizationMitigationsQuery$variables = {
export type MesureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type ShowRiskViewOrganizationMesuresQuery$variables = {
organizationId: string;
};
export type ShowRiskViewOrganizationMitigationsQuery$data = {
export type ShowRiskViewOrganizationMesuresQuery$data = {
readonly organization: {
readonly id: string;
readonly mitigations?: {
readonly mesures?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly category: string;
readonly description: string;
readonly id: string;
readonly name: string;
readonly state: MitigationState;
readonly state: MesureState;
};
}>;
};
};
};
export type ShowRiskViewOrganizationMitigationsQuery = {
response: ShowRiskViewOrganizationMitigationsQuery$data;
variables: ShowRiskViewOrganizationMitigationsQuery$variables;
export type ShowRiskViewOrganizationMesuresQuery = {
response: ShowRiskViewOrganizationMesuresQuery$data;
variables: ShowRiskViewOrganizationMesuresQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -67,7 +67,7 @@ v4 = [
{
"alias": null,
"args": null,
"concreteType": "MitigationEdge",
"concreteType": "MesureEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
@@ -75,7 +75,7 @@ v4 = [
{
"alias": null,
"args": null,
"concreteType": "Mitigation",
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "node",
"plural": false,
@@ -161,7 +161,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ShowRiskViewOrganizationMitigationsQuery",
"name": "ShowRiskViewOrganizationMesuresQuery",
"selections": [
{
"alias": "organization",
@@ -176,11 +176,11 @@ return {
"kind": "InlineFragment",
"selections": [
{
"alias": "mitigations",
"alias": "mesures",
"args": null,
"concreteType": "MitigationConnection",
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "__Organization__mitigations_connection",
"name": "__Organization__mesures_connection",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": null
@@ -200,7 +200,7 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ShowRiskViewOrganizationMitigationsQuery",
"name": "ShowRiskViewOrganizationMesuresQuery",
"selections": [
{
"alias": "organization",
@@ -218,21 +218,21 @@ return {
{
"alias": null,
"args": (v5/*: any*/),
"concreteType": "MitigationConnection",
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "mitigations",
"name": "mesures",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": "mitigations(first:100)"
"storageKey": "mesures(first:100)"
},
{
"alias": null,
"args": (v5/*: any*/),
"filters": null,
"handle": "connection",
"key": "Organization__mitigations",
"key": "Organization__mesures",
"kind": "LinkedHandle",
"name": "mitigations"
"name": "mesures"
}
],
"type": "Organization",
@@ -244,7 +244,7 @@ return {
]
},
"params": {
"cacheID": "a73345064022bd2f11ef2f971cd898b5",
"cacheID": "af9a0c71ad20ea7e65e3c625e30b00d8",
"id": null,
"metadata": {
"connection": [
@@ -254,18 +254,18 @@ return {
"direction": "forward",
"path": [
"organization",
"mitigations"
"mesures"
]
}
]
},
"name": "ShowRiskViewOrganizationMitigationsQuery",
"name": "ShowRiskViewOrganizationMesuresQuery",
"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 state\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
"text": "query ShowRiskViewOrganizationMesuresQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n mesures(first: 100) {\n edges {\n node {\n id\n name\n description\n category\n state\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "76ce05cd9f5a367595eb31b5df24a679";
(node as any).hash = "addb9873294354cedf28bc3262cb736a";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<486518520656d7e1392a34ee1877fe22>>
* @generated SignedSource<<166b32236b296d1d0a4956cabacb1715>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,7 +9,7 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MitigationState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type MesureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type PolicyStatus = "ACTIVE" | "DRAFT";
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED";
export type ShowRiskViewQuery$variables = {
@@ -33,7 +33,7 @@ export type ShowRiskViewQuery$data = {
readonly id: string;
readonly inherentImpact?: number;
readonly inherentLikelihood?: number;
readonly mitigations?: {
readonly mesures?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly category: string;
@@ -41,7 +41,7 @@ export type ShowRiskViewQuery$data = {
readonly description: string;
readonly id: string;
readonly name: string;
readonly state: MitigationState;
readonly state: MesureState;
};
}>;
};
@@ -218,7 +218,7 @@ v16 = [
{
"alias": null,
"args": null,
"concreteType": "MitigationEdge",
"concreteType": "MesureEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
@@ -226,7 +226,7 @@ v16 = [
{
"alias": null,
"args": null,
"concreteType": "Mitigation",
"concreteType": "Mesure",
"kind": "LinkedField",
"name": "node",
"plural": false,
@@ -371,11 +371,11 @@ return {
(v11/*: any*/),
(v12/*: any*/),
{
"alias": "mitigations",
"alias": "mesures",
"args": null,
"concreteType": "MitigationConnection",
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "__Risk__mitigations_connection",
"name": "__Risk__mesures_connection",
"plural": false,
"selections": (v16/*: any*/),
"storageKey": null
@@ -443,21 +443,21 @@ return {
{
"alias": null,
"args": (v19/*: any*/),
"concreteType": "MitigationConnection",
"concreteType": "MesureConnection",
"kind": "LinkedField",
"name": "mitigations",
"name": "mesures",
"plural": false,
"selections": (v16/*: any*/),
"storageKey": "mitigations(first:100)"
"storageKey": "mesures(first:100)"
},
{
"alias": null,
"args": (v19/*: any*/),
"filters": null,
"handle": "connection",
"key": "Risk__mitigations",
"key": "Risk__mesures",
"kind": "LinkedHandle",
"name": "mitigations"
"name": "mesures"
},
{
"alias": null,
@@ -507,7 +507,7 @@ return {
]
},
"params": {
"cacheID": "8867786ee5bfa23bfd16d52d0023beeb",
"cacheID": "b315b57d1b366f87758e300825909da0",
"id": null,
"metadata": {
"connection": [
@@ -517,7 +517,7 @@ return {
"direction": "forward",
"path": [
"node",
"mitigations"
"mesures"
]
},
{
@@ -542,11 +542,11 @@ return {
},
"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 treatment\n owner {\n id\n fullName\n }\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n createdAt\n updatedAt\n mitigations(first: 100) {\n edges {\n node {\n id\n name\n description\n category\n createdAt\n state\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n policies(first: 100) {\n edges {\n node {\n id\n name\n status\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n controls(first: 100) {\n edges {\n node {\n id\n referenceId\n name\n description\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
"text": "query ShowRiskViewQuery(\n $riskId: ID!\n) {\n node(id: $riskId) {\n __typename\n id\n ... on Risk {\n name\n description\n treatment\n owner {\n id\n fullName\n }\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n createdAt\n updatedAt\n mesures(first: 100) {\n edges {\n node {\n id\n name\n description\n category\n createdAt\n state\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n policies(first: 100) {\n edges {\n node {\n id\n name\n status\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n controls(first: 100) {\n edges {\n node {\n id\n referenceId\n name\n description\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "264f7dd097e487eda41cdc4d04a14274";
(node as any).hash = "bbb709790492c573d25ee19412956501";
export default node;

View File

@@ -116,11 +116,11 @@ WHERE %s
return nil
}
func (c *Controls) LoadByMitigationID(
func (c *Controls) LoadByMesureID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
mitigationID gid.GID,
mesureID gid.GID,
cursor *page.Cursor[ControlOrderField],
) error {
q := `
@@ -137,9 +137,9 @@ WITH ctrl AS (
FROM
controls c
INNER JOIN
controls_mitigations cm ON c.id = cm.control_id
controls_mesures cm ON c.id = cm.control_id
WHERE
cm.mitigation_id = @mitigation_id
cm.mesure_id = @mesure_id
)
SELECT
id,
@@ -157,7 +157,7 @@ WHERE %s
`
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.NamedArgs{"mitigation_id": mitigationID}
args := pgx.NamedArgs{"mesure_id": mesureID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
@@ -200,9 +200,9 @@ WITH ctrl AS (
LEFT JOIN
risks_policies rp ON cp.policy_id = rp.policy_id
LEFT JOIN
controls_mitigations cm ON c.id = cm.control_id
controls_mesures cm ON c.id = cm.control_id
LEFT JOIN
risks_mitigations rm ON (rm.mitigation_id = cm.mitigation_id)
risks_mesures rm ON (rm.mesure_id = cm.mesure_id)
WHERE
rp.risk_id = @risk_id OR rm.risk_id = @risk_id
)

View File

@@ -26,80 +26,80 @@ import (
)
type (
ControlMitigation struct {
ControlID gid.GID `db:"control_id"`
MitigationID gid.GID `db:"mitigation_id"`
TenantID gid.TenantID `db:"tenant_id"`
CreatedAt time.Time `db:"created_at"`
ControlMesure struct {
ControlID gid.GID `db:"control_id"`
MesureID gid.GID `db:"mesure_id"`
TenantID gid.TenantID `db:"tenant_id"`
CreatedAt time.Time `db:"created_at"`
}
ControlMitigations []*ControlMitigation
ControlMesures []*ControlMesure
)
func (cm ControlMitigation) Upsert(
func (cm ControlMesure) Upsert(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
INSERT INTO
controls_mitigations (
controls_mesures (
control_id,
mitigation_id,
mesure_id,
tenant_id,
created_at
)
VALUES (
@control_id,
@mitigation_id,
@mesure_id,
@tenant_id,
@created_at
)
ON CONFLICT (control_id, mitigation_id) DO NOTHING;
ON CONFLICT (control_id, mesure_id) DO NOTHING;
`
args := pgx.StrictNamedArgs{
"control_id": cm.ControlID,
"mitigation_id": cm.MitigationID,
"tenant_id": scope.GetTenantID(),
"created_at": cm.CreatedAt,
"control_id": cm.ControlID,
"mesure_id": cm.MesureID,
"tenant_id": scope.GetTenantID(),
"created_at": cm.CreatedAt,
}
_, err := conn.Exec(ctx, q, args)
return err
}
func (cm ControlMitigation) Insert(
func (cm ControlMesure) Insert(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
INSERT INTO
controls_mitigations (
controls_mesures (
control_id,
mitigation_id,
mesure_id,
tenant_id,
created_at
)
VALUES (
@control_id,
@mitigation_id,
@mesure_id,
@tenant_id,
@created_at
);
`
args := pgx.StrictNamedArgs{
"control_id": cm.ControlID,
"mitigation_id": cm.MitigationID,
"tenant_id": scope.GetTenantID(),
"created_at": cm.CreatedAt,
"control_id": cm.ControlID,
"mesure_id": cm.MesureID,
"tenant_id": scope.GetTenantID(),
"created_at": cm.CreatedAt,
}
_, err := conn.Exec(ctx, q, args)
return err
}
func (cm ControlMitigation) Delete(
func (cm ControlMesure) Delete(
ctx context.Context,
conn pg.Conn,
scope Scoper,
@@ -107,16 +107,16 @@ func (cm ControlMitigation) Delete(
q := `
DELETE
FROM
controls_mitigations
controls_mesures
WHERE
%s
AND control_id = @control_id
AND mitigation_id = @mitigation_id;
AND mesure_id = @mesure_id;
`
args := pgx.StrictNamedArgs{
"control_id": cm.ControlID,
"mitigation_id": cm.MitigationID,
"control_id": cm.ControlID,
"mesure_id": cm.MesureID,
}
maps.Copy(args, scope.SQLArguments())
q = fmt.Sprintf(q, scope.SQLFragment())
@@ -125,39 +125,39 @@ WHERE
return err
}
func (cms *ControlMitigations) LoadByMitigationID(
func (cms *ControlMesures) LoadByMesureID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
mitigationID gid.GID,
mesureID gid.GID,
) error {
q := `
SELECT
control_id,
mitigation_id,
mesure_id,
tenant_id,
created_at
FROM
control_mitigations
controls_mesures
WHERE
%s
AND mitigation_id = @mitigation_id
AND mesure_id = @mesure_id
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"mitigation_id": mitigationID}
args := pgx.StrictNamedArgs{"mesure_id": mesureID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query control_mitigations: %w", err)
return fmt.Errorf("cannot query control_mesures: %w", err)
}
controlMitigations, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ControlMitigation])
controlMesures, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ControlMesure])
if err != nil {
return fmt.Errorf("cannot collect control_mitigations: %w", err)
return fmt.Errorf("cannot collect control_mesures: %w", err)
}
*cms = controlMitigations
*cms = controlMesures
return nil
}

View File

@@ -17,7 +17,7 @@ package coredata
const (
OrganizationEntityType uint16 = iota
FrameworkEntityType
MitigationEntityType
MesureEntityType
TaskEntityType
EvidenceEntityType
_ControlStateTransitionEntityType // UNUSED

View File

@@ -28,41 +28,41 @@ import (
)
type (
Mitigation struct {
ID gid.GID `db:"id"`
TenantID gid.TenantID `db:"tenant_id"`
OrganizationID gid.GID `db:"organization_id"`
Category string `db:"category"`
Name string `db:"name"`
Description string `db:"description"`
Importance MitigationImportance `db:"importance"`
State MitigationState `db:"state"`
ReferenceID string `db:"reference_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
Mesure struct {
ID gid.GID `db:"id"`
TenantID gid.TenantID `db:"tenant_id"`
OrganizationID gid.GID `db:"organization_id"`
Category string `db:"category"`
Name string `db:"name"`
Description string `db:"description"`
Importance MesureImportance `db:"importance"`
State MesureState `db:"state"`
ReferenceID string `db:"reference_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
}
Mitigations []*Mitigation
Mesures []*Mesure
)
func (c Mitigation) CursorKey(orderBy MitigationOrderField) page.CursorKey {
func (m Mesure) CursorKey(orderBy MesureOrderField) page.CursorKey {
switch orderBy {
case MitigationOrderFieldCreatedAt:
return page.NewCursorKey(c.ID, c.CreatedAt)
case MesureOrderFieldCreatedAt:
return page.NewCursorKey(m.ID, m.CreatedAt)
}
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (c *Mitigations) LoadByRiskID(
func (m *Mesures) LoadByRiskID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
riskID gid.GID,
cursor *page.Cursor[MitigationOrderField],
cursor *page.Cursor[MesureOrderField],
) error {
q := `
WITH mtgtns AS (
WITH msrs AS (
SELECT
m.id,
m.tenant_id,
@@ -76,9 +76,9 @@ WITH mtgtns AS (
m.created_at,
m.updated_at
FROM
mitigations m
mesures m
INNER JOIN
risks_mitigations rm ON m.id = rm.mitigation_id
risks_mesures rm ON m.id = rm.mesure_id
WHERE
rm.risk_id = @risk_id
)
@@ -95,7 +95,7 @@ SELECT
created_at,
updated_at
FROM
mtgtns
msrs
WHERE %s
AND %s
`
@@ -107,25 +107,25 @@ WHERE %s
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query mitigations: %w", err)
return fmt.Errorf("cannot query mesures: %w", err)
}
mitigations, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Mitigation])
mesures, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Mesure])
if err != nil {
return fmt.Errorf("cannot collect mitigations: %w", err)
return fmt.Errorf("cannot collect mesures: %w", err)
}
*c = mitigations
*m = mesures
return nil
}
func (c *Mitigations) LoadByControlID(
func (m *Mesures) LoadByControlID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
controlID gid.GID,
cursor *page.Cursor[MitigationOrderField],
cursor *page.Cursor[MesureOrderField],
) error {
q := `
WITH mtgtns AS (
@@ -142,9 +142,9 @@ WITH mtgtns AS (
m.created_at,
m.updated_at
FROM
mitigations m
mesures m
INNER JOIN
controls_mitigations cm ON m.id = cm.mitigation_id
controls_mesures cm ON m.id = cm.mesure_id
WHERE
cm.control_id = @control_id
)
@@ -173,25 +173,25 @@ WHERE %s
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query mitigations: %w", err)
return fmt.Errorf("cannot query mesures: %w", err)
}
mitigations, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Mitigation])
mesures, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Mesure])
if err != nil {
return fmt.Errorf("cannot collect mitigations: %w", err)
return fmt.Errorf("cannot collect mesures: %w", err)
}
*c = mitigations
*m = mesures
return nil
}
func (c *Mitigations) LoadByOrganizationID(
func (m *Mesures) LoadByOrganizationID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
organizationID gid.GID,
cursor *page.Cursor[MitigationOrderField],
cursor *page.Cursor[MesureOrderField],
) error {
q := `
SELECT
@@ -207,7 +207,7 @@ SELECT
created_at,
updated_at
FROM
mitigations
mesures
WHERE
%s
AND organization_id = @organization_id
@@ -221,24 +221,24 @@ WHERE
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query mitigations: %w", err)
return fmt.Errorf("cannot query mesures: %w", err)
}
mitigations, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Mitigation])
mesures, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Mesure])
if err != nil {
return fmt.Errorf("cannot collect mitigations: %w", err)
return fmt.Errorf("cannot collect mesures: %w", err)
}
*c = mitigations
*m = mesures
return nil
}
func (c *Mitigation) LoadByID(
func (m *Mesure) LoadByID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
mitigationID gid.GID,
mesureID gid.GID,
) error {
q := `
SELECT
@@ -254,41 +254,41 @@ SELECT
created_at,
updated_at
FROM
mitigations
mesures
WHERE
%s
AND id = @mitigation_id
AND id = @mesure_id
LIMIT 1;
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"mitigation_id": mitigationID}
args := pgx.StrictNamedArgs{"mesure_id": mesureID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query mitigations: %w", err)
return fmt.Errorf("cannot query mesures: %w", err)
}
mitigation, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Mitigation])
mesure, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Mesure])
if err != nil {
return fmt.Errorf("cannot collect mitigations: %w", err)
return fmt.Errorf("cannot collect mesures: %w", err)
}
*c = mitigation
*m = mesure
return nil
}
func (c *Mitigation) Upsert(
func (m *Mesure) Upsert(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
INSERT INTO
mitigations (
mesures (
tenant_id,
id,
organization_id,
@@ -303,7 +303,7 @@ INSERT INTO
)
VALUES (
@tenant_id,
@mitigation_id,
@mesure_id,
@organization_id,
@category,
@name,
@@ -335,41 +335,41 @@ RETURNING
args := pgx.StrictNamedArgs{
"tenant_id": scope.GetTenantID(),
"mitigation_id": c.ID,
"organization_id": c.OrganizationID,
"category": c.Category,
"name": c.Name,
"importance": c.Importance,
"state": c.State,
"description": c.Description,
"reference_id": c.ReferenceID,
"created_at": c.CreatedAt,
"updated_at": c.UpdatedAt,
"mesure_id": m.ID,
"organization_id": m.OrganizationID,
"category": m.Category,
"name": m.Name,
"importance": m.Importance,
"state": m.State,
"description": m.Description,
"reference_id": m.ReferenceID,
"created_at": m.CreatedAt,
"updated_at": m.UpdatedAt,
}
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query mitigations: %w", err)
return fmt.Errorf("cannot query mesures: %w", err)
}
mitigation, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Mitigation])
mesure, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Mesure])
if err != nil {
return fmt.Errorf("cannot collect mitigations: %w", err)
return fmt.Errorf("cannot collect mesures: %w", err)
}
*c = mitigation
*m = mesure
return nil
}
func (c Mitigation) Insert(
func (m Mesure) Insert(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
INSERT INTO
mitigations (
mesures (
tenant_id,
id,
organization_id,
@@ -384,7 +384,7 @@ INSERT INTO
)
VALUES (
@tenant_id,
@mitigation_id,
@mesure_id,
@organization_id,
@category,
@name,
@@ -399,28 +399,28 @@ VALUES (
args := pgx.StrictNamedArgs{
"tenant_id": scope.GetTenantID(),
"mitigation_id": c.ID,
"organization_id": c.OrganizationID,
"category": c.Category,
"name": c.Name,
"description": c.Description,
"reference_id": c.ReferenceID,
"created_at": c.CreatedAt,
"updated_at": c.UpdatedAt,
"state": c.State,
"importance": c.Importance,
"mesure_id": m.ID,
"organization_id": m.OrganizationID,
"category": m.Category,
"name": m.Name,
"description": m.Description,
"reference_id": m.ReferenceID,
"created_at": m.CreatedAt,
"updated_at": m.UpdatedAt,
"state": m.State,
"importance": m.Importance,
}
_, err := conn.Exec(ctx, q, args)
return err
}
func (c *Mitigation) Update(
func (m *Mesure) Update(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
UPDATE mitigations
UPDATE mesures
SET
name = @name,
description = @description,
@@ -429,18 +429,18 @@ SET
importance = @importance,
updated_at = @updated_at
WHERE %s
AND id = @mitigation_id
AND id = @mesure_id
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.NamedArgs{
"mitigation_id": c.ID,
"name": c.Name,
"description": c.Description,
"category": c.Category,
"state": c.State,
"importance": c.Importance,
"updated_at": c.UpdatedAt,
"mesure_id": m.ID,
"name": m.Name,
"description": m.Description,
"category": m.Category,
"state": m.State,
"importance": m.Importance,
"updated_at": m.UpdatedAt,
}
maps.Copy(args, scope.SQLArguments())

View File

@@ -20,48 +20,48 @@ import (
"fmt"
)
type MitigationImportance uint8
type MesureImportance uint8
const (
MitigationImportanceMandatory MitigationImportance = iota
MitigationImportancePreferred
MitigationImportanceAdvanced
MesureImportanceMandatory MesureImportance = iota
MesureImportancePreferred
MesureImportanceAdvanced
)
func (i MitigationImportance) String() string {
func (i MesureImportance) String() string {
return []string{"MANDATORY", "PREFERRED", "ADVANCED"}[i]
}
func (i *MitigationImportance) Scan(value interface{}) error {
func (i *MesureImportance) Scan(value interface{}) error {
switch v := value.(type) {
case uint8:
*i = MitigationImportance(v)
*i = MesureImportance(v)
case string:
switch v {
case "MANDATORY":
*i = MitigationImportanceMandatory
*i = MesureImportanceMandatory
case "PREFERRED":
*i = MitigationImportancePreferred
*i = MesureImportancePreferred
case "ADVANCED":
*i = MitigationImportanceAdvanced
*i = MesureImportanceAdvanced
default:
return fmt.Errorf("invalid MitigationImportance value: %q", v)
return fmt.Errorf("invalid MesureImportance value: %q", v)
}
default:
return fmt.Errorf("unsupported type for MitigationImportance: %T", value)
return fmt.Errorf("unsupported type for MesureImportance: %T", value)
}
return nil
}
func (i MitigationImportance) Value() (driver.Value, error) {
func (i MesureImportance) Value() (driver.Value, error) {
return i.String(), nil
}
func (i MitigationImportance) MarshalJSON() ([]byte, error) {
func (i MesureImportance) MarshalJSON() ([]byte, error) {
return json.Marshal(i.String())
}
func (i *MitigationImportance) UnmarshalJSON(data []byte) error {
func (i *MesureImportance) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
@@ -69,18 +69,18 @@ func (i *MitigationImportance) UnmarshalJSON(data []byte) error {
switch s {
case "MANDATORY":
*i = MitigationImportanceMandatory
*i = MesureImportanceMandatory
case "PREFERRED":
*i = MitigationImportancePreferred
*i = MesureImportancePreferred
case "ADVANCED":
*i = MitigationImportanceAdvanced
*i = MesureImportanceAdvanced
default:
return fmt.Errorf("invalid MitigationImportance value: %q", s)
return fmt.Errorf("invalid MesureImportance value: %q", s)
}
return nil
}
func (i *MitigationImportance) UnmarshalText(text []byte) error {
func (i *MesureImportance) UnmarshalText(text []byte) error {
var s string
if err := json.Unmarshal(text, &s); err != nil {
return err
@@ -88,13 +88,13 @@ func (i *MitigationImportance) UnmarshalText(text []byte) error {
switch s {
case "MANDATORY":
*i = MitigationImportanceMandatory
*i = MesureImportanceMandatory
case "PREFERRED":
*i = MitigationImportancePreferred
*i = MesureImportancePreferred
case "ADVANCED":
*i = MitigationImportanceAdvanced
*i = MesureImportanceAdvanced
default:
return fmt.Errorf("invalid MitigationImportance value: %q", s)
return fmt.Errorf("invalid MesureImportance value: %q", s)
}
return nil
}

View File

@@ -15,26 +15,26 @@
package coredata
type (
MitigationOrderField string
MesureOrderField string
)
const (
MitigationOrderFieldCreatedAt MitigationOrderField = "CREATED_AT"
MesureOrderFieldCreatedAt MesureOrderField = "CREATED_AT"
)
func (p MitigationOrderField) Column() string {
func (p MesureOrderField) Column() string {
return string(p)
}
func (p MitigationOrderField) String() string {
func (p MesureOrderField) String() string {
return string(p)
}
func (p MitigationOrderField) MarshalText() ([]byte, error) {
func (p MesureOrderField) MarshalText() ([]byte, error) {
return []byte(p.String()), nil
}
func (p *MitigationOrderField) UnmarshalText(text []byte) error {
*p = MitigationOrderField(text)
func (p *MesureOrderField) UnmarshalText(text []byte) error {
*p = MesureOrderField(text)
return nil
}

View File

@@ -0,0 +1,84 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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 (
MesureState uint8
)
const (
MesureStateNotStarted MesureState = iota
MesureStateInProgress
MesureStateNotApplicable
MesureStateImplemented
)
func (ms MesureState) MarshalText() ([]byte, error) {
return []byte(ms.String()), nil
}
func (ms *MesureState) UnmarshalText(data []byte) error {
val := string(data)
switch val {
case MesureStateNotStarted.String():
*ms = MesureStateNotStarted
case MesureStateInProgress.String():
*ms = MesureStateInProgress
case MesureStateNotApplicable.String():
*ms = MesureStateNotApplicable
case MesureStateImplemented.String():
*ms = MesureStateImplemented
default:
return fmt.Errorf("invalid MesureState value: %q", val)
}
return nil
}
func (ms MesureState) String() string {
var val string
switch ms {
case MesureStateNotStarted:
val = "NOT_STARTED"
case MesureStateInProgress:
val = "IN_PROGRESS"
case MesureStateNotApplicable:
val = "NOT_APPLICABLE"
case MesureStateImplemented:
val = "IMPLEMENTED"
}
return val
}
func (ms *MesureState) Scan(value any) error {
val, ok := value.(string)
if !ok {
return fmt.Errorf("invalid scan source for MesureState, expected string got %T", value)
}
return ms.UnmarshalText([]byte(val))
}
func (ms MesureState) Value() (driver.Value, error) {
return ms.String(), nil
}

View File

@@ -0,0 +1,2 @@
ALTER TABLE mitigations RENAME TO mesures;

View File

@@ -0,0 +1,2 @@
ALTER TABLE risks_mitigations RENAME TO risks_mesures;
ALTER TABLE risks_mesures RENAME COLUMN mitigation_id TO mesure_id;

View File

@@ -0,0 +1,2 @@
ALTER TABLE controls_mitigations RENAME TO controls_mesures;
ALTER TABLE controls_mesures RENAME COLUMN mitigation_id TO mesure_id;

View File

@@ -0,0 +1 @@
ALTER TABLE tasks RENAME COLUMN mitigation_id TO mesure_id;

View File

@@ -1,84 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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 (
MitigationState uint8
)
const (
MitigationStateNotStarted MitigationState = iota
MitigationStateInProgress
MitigationStateNotApplicable
MitigationStateImplemented
)
func (cs MitigationState) MarshalText() ([]byte, error) {
return []byte(cs.String()), nil
}
func (cs *MitigationState) UnmarshalText(data []byte) error {
val := string(data)
switch val {
case MitigationStateNotStarted.String():
*cs = MitigationStateNotStarted
case MitigationStateInProgress.String():
*cs = MitigationStateInProgress
case MitigationStateNotApplicable.String():
*cs = MitigationStateNotApplicable
case MitigationStateImplemented.String():
*cs = MitigationStateImplemented
default:
return fmt.Errorf("invalid MitigationState value: %q", val)
}
return nil
}
func (cs MitigationState) String() string {
var val string
switch cs {
case MitigationStateNotStarted:
val = "NOT_STARTED"
case MitigationStateInProgress:
val = "IN_PROGRESS"
case MitigationStateNotApplicable:
val = "NOT_APPLICABLE"
case MitigationStateImplemented:
val = "IMPLEMENTED"
}
return val
}
func (cs *MitigationState) Scan(value any) error {
val, ok := value.(string)
if !ok {
return fmt.Errorf("invalid scan source for MitigationState, expected string got %T", value)
}
return cs.UnmarshalText([]byte(val))
}
func (cs MitigationState) Value() (driver.Value, error) {
return cs.String(), nil
}

View File

@@ -62,11 +62,11 @@ func (r *Risk) ResidualSeverity() float64 {
return r.ResidualLikelihood * r.ResidualImpact
}
func (r *Risks) LoadByMitigationID(
func (r *Risks) LoadByMesureID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
mitigationID gid.GID,
mesureID gid.GID,
cursor *page.Cursor[RiskOrderField],
) error {
q := `
@@ -87,9 +87,9 @@ WITH rsks AS (
FROM
risks r
INNER JOIN
risks_mitigations rm ON r.id = rm.risk_id
risks_mesures rm ON r.id = rm.risk_id
WHERE
rm.mitigation_id = @mitigation_id
rm.mesure_id = @mesure_id
)
SELECT
id,
@@ -111,7 +111,7 @@ WHERE %s
`
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.NamedArgs{"mitigation_id": mitigationID}
args := pgx.NamedArgs{"mesure_id": mesureID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)

View File

@@ -26,48 +26,48 @@ import (
)
type (
RiskMitigation struct {
RiskID gid.GID `db:"risk_id"`
MitigationID gid.GID `db:"mitigation_id"`
TenantID gid.TenantID `db:"tenant_id"`
CreatedAt time.Time `db:"created_at"`
RiskMesure struct {
RiskID gid.GID `db:"risk_id"`
MesureID gid.GID `db:"mesure_id"`
TenantID gid.TenantID `db:"tenant_id"`
CreatedAt time.Time `db:"created_at"`
}
RiskMitigations []*RiskMitigation
RiskMesures []*RiskMesure
)
func (rm RiskMitigation) Insert(
func (rm RiskMesure) Insert(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
INSERT INTO
risks_mitigations (
risks_mesures (
risk_id,
mitigation_id,
mesure_id,
tenant_id,
created_at
)
VALUES (
@risk_id,
@mitigation_id,
@mesure_id,
@tenant_id,
@created_at
);
`
args := pgx.StrictNamedArgs{
"risk_id": rm.RiskID,
"mitigation_id": rm.MitigationID,
"tenant_id": scope.GetTenantID(),
"created_at": rm.CreatedAt,
"risk_id": rm.RiskID,
"mesure_id": rm.MesureID,
"tenant_id": scope.GetTenantID(),
"created_at": rm.CreatedAt,
}
_, err := conn.Exec(ctx, q, args)
return err
}
func (rm RiskMitigation) Delete(
func (rm RiskMesure) Delete(
ctx context.Context,
conn pg.Conn,
scope Scoper,
@@ -75,18 +75,18 @@ func (rm RiskMitigation) Delete(
q := `
DELETE
FROM
risks_mitigations
risks_mesures
WHERE
%s
AND risk_id = @risk_id
AND mitigation_id = @mitigation_id;
AND mesure_id = @mesure_id;
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{
"risk_id": rm.RiskID,
"mitigation_id": rm.MitigationID,
"risk_id": rm.RiskID,
"mesure_id": rm.MesureID,
}
maps.Copy(args, scope.SQLArguments())

View File

@@ -30,7 +30,7 @@ import (
type (
Task struct {
ID gid.GID `db:"id"`
MitigationID gid.GID `db:"mitigation_id"`
MesureID gid.GID `db:"mesure_id"`
Name string `db:"name"`
Description string `db:"description"`
State TaskState `db:"state"`
@@ -62,7 +62,7 @@ func (c *Task) LoadByID(
q := `
SELECT
id,
mitigation_id,
mesure_id,
name,
description,
state,
@@ -109,7 +109,7 @@ INSERT INTO
tasks (
tenant_id,
id,
mitigation_id,
mesure_id,
name,
description,
reference_id,
@@ -122,7 +122,7 @@ INSERT INTO
VALUES (
@tenant_id,
@task_id,
@mitigation_id,
@mesure_id,
@name,
@description,
@reference_id,
@@ -137,7 +137,7 @@ VALUES (
args := pgx.StrictNamedArgs{
"tenant_id": scope.GetTenantID(),
"task_id": c.ID,
"mitigation_id": c.MitigationID,
"mesure_id": c.MesureID,
"name": c.Name,
"description": c.Description,
"reference_id": c.ReferenceID,
@@ -161,7 +161,7 @@ INSERT INTO
tasks (
tenant_id,
id,
mitigation_id,
mesure_id,
name,
description,
reference_id,
@@ -174,7 +174,7 @@ INSERT INTO
VALUES (
@tenant_id,
@task_id,
@mitigation_id,
@mesure_id,
@name,
@description,
@reference_id,
@@ -184,13 +184,13 @@ VALUES (
@created_at,
@updated_at
)
ON CONFLICT (mitigation_id, reference_id) DO UPDATE SET
ON CONFLICT (mesure_id, reference_id) DO UPDATE SET
name = @name,
description = @description,
updated_at = @updated_at
RETURNING
id,
mitigation_id,
mesure_id,
name,
description,
reference_id,
@@ -204,7 +204,7 @@ RETURNING
args := pgx.StrictNamedArgs{
"tenant_id": scope.GetTenantID(),
"task_id": c.ID,
"mitigation_id": c.MitigationID,
"mesure_id": c.MesureID,
"name": c.Name,
"description": c.Description,
"reference_id": c.ReferenceID,
@@ -229,17 +229,17 @@ RETURNING
return nil
}
func (c *Tasks) LoadByMitigationID(
func (c *Tasks) LoadByMesureID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
mitigationID gid.GID,
mesureID gid.GID,
cursor *page.Cursor[TaskOrderField],
) error {
q := `
SELECT
id,
mitigation_id,
mesure_id,
name,
description,
state,
@@ -252,12 +252,12 @@ FROM
tasks
WHERE
%s
AND mitigation_id = @mitigation_id
AND mesure_id = @mesure_id
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.StrictNamedArgs{"mitigation_id": mitigationID}
args := pgx.StrictNamedArgs{"mesure_id": mesureID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, cursor.SQLArguments())
@@ -323,7 +323,7 @@ WHERE %s
AND id = @task_id
RETURNING
id,
mitigation_id,
mesure_id,
name,
description,
reference_id,
@@ -371,7 +371,7 @@ WHERE %s
AND id = @task_id
RETURNING
id,
mitigation_id,
mesure_id,
name,
description,
reference_id,

View File

@@ -76,9 +76,9 @@ func (s ControlService) ListForPolicyID(
return page.NewPage(controls, cursor), nil
}
func (s ControlService) ListForMitigationID(
func (s ControlService) ListForMesureID(
ctx context.Context,
mitigationID gid.GID,
mesureID gid.GID,
cursor *page.Cursor[coredata.ControlOrderField],
) (*page.Page[*coredata.Control, coredata.ControlOrderField], error) {
var controls coredata.Controls
@@ -86,7 +86,7 @@ func (s ControlService) ListForMitigationID(
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return controls.LoadByMitigationID(ctx, conn, s.svc.scope, mitigationID, cursor)
return controls.LoadByMesureID(ctx, conn, s.svc.scope, mesureID, cursor)
},
)
@@ -97,42 +97,42 @@ func (s ControlService) ListForMitigationID(
return page.NewPage(controls, cursor), nil
}
func (s ControlService) CreateMitigationMapping(
func (s ControlService) CreateMesureMapping(
ctx context.Context,
controlID gid.GID,
mitigationID gid.GID,
mesureID gid.GID,
) error {
controlMitigation := &coredata.ControlMitigation{
ControlID: controlID,
MitigationID: mitigationID,
TenantID: s.svc.scope.GetTenantID(),
CreatedAt: time.Now(),
controlMesure := &coredata.ControlMesure{
ControlID: controlID,
MesureID: mesureID,
TenantID: s.svc.scope.GetTenantID(),
CreatedAt: time.Now(),
}
return s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return controlMitigation.Insert(ctx, conn, s.svc.scope)
return controlMesure.Insert(ctx, conn, s.svc.scope)
},
)
}
func (s ControlService) DeleteMitigationMapping(
func (s ControlService) DeleteMesureMapping(
ctx context.Context,
controlID gid.GID,
mitigationID gid.GID,
mesureID gid.GID,
) error {
controlMitigation := &coredata.ControlMitigation{
ControlID: controlID,
MitigationID: mitigationID,
TenantID: s.svc.scope.GetTenantID(),
CreatedAt: time.Now(),
controlMesure := &coredata.ControlMesure{
ControlID: controlID,
MesureID: mesureID,
TenantID: s.svc.scope.GetTenantID(),
CreatedAt: time.Now(),
}
return s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return controlMitigation.Delete(ctx, conn, s.svc.scope)
return controlMesure.Delete(ctx, conn, s.svc.scope)
},
)
}

383
pkg/probo/mesure_service.go Normal file
View File

@@ -0,0 +1,383 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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 probo
import (
"context"
"fmt"
"time"
"github.com/getprobo/probo/pkg/coredata"
"github.com/getprobo/probo/pkg/gid"
"github.com/getprobo/probo/pkg/page"
"go.gearno.de/crypto/uuid"
"go.gearno.de/kit/pg"
)
type (
MesureService struct {
svc *TenantService
}
CreateMesureRequest struct {
OrganizationID gid.GID
Name string
Description string
Category string
Importance coredata.MesureImportance
}
UpdateMesureRequest struct {
ID gid.GID
Name *string
Description *string
Category *string
State *coredata.MesureState
Importance *coredata.MesureImportance
}
ImportMesureRequest struct {
Mesures []struct {
Name string `json:"name"`
Description string `json:"description"`
Category string `json:"category"`
Importance coredata.MesureImportance `json:"importance"`
ReferenceID string `json:"reference-id"`
Standards []struct {
Framework string `json:"framework"`
Control string `json:"control"`
} `json:"standards"`
Tasks []struct {
Name string `json:"name"`
Description string `json:"description"`
ReferenceID string `json:"reference-id"`
RequestedEvidences []struct {
ReferenceID string `json:"reference-id"`
Type coredata.EvidenceType `json:"type"`
Name string `json:"name"`
} `json:"requested-evidences"`
} `json:"tasks"`
} `json:"mesures"`
}
)
func (s MesureService) ListForRiskID(
ctx context.Context,
riskID gid.GID,
cursor *page.Cursor[coredata.MesureOrderField],
) (*page.Page[*coredata.Mesure, coredata.MesureOrderField], error) {
var mesures coredata.Mesures
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return mesures.LoadByRiskID(ctx, conn, s.svc.scope, riskID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(mesures, cursor), nil
}
func (s MesureService) ListForControlID(
ctx context.Context,
controlID gid.GID,
cursor *page.Cursor[coredata.MesureOrderField],
) (*page.Page[*coredata.Mesure, coredata.MesureOrderField], error) {
var mesures coredata.Mesures
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return mesures.LoadByControlID(ctx, conn, s.svc.scope, controlID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(mesures, cursor), nil
}
func (s MesureService) Get(
ctx context.Context,
mesureID gid.GID,
) (*coredata.Mesure, error) {
mesure := &coredata.Mesure{}
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return mesure.LoadByID(ctx, conn, s.svc.scope, mesureID)
},
)
if err != nil {
return nil, err
}
return mesure, nil
}
func (s MesureService) Import(
ctx context.Context,
organizationID gid.GID,
req ImportMesureRequest,
) (*page.Page[*coredata.Mesure, coredata.MesureOrderField], error) {
importedMesures := coredata.Mesures{}
err := s.svc.pg.WithTx(
ctx,
func(tx pg.Conn) error {
for i := range req.Mesures {
now := time.Now()
mesureID, err := gid.NewGID(organizationID.TenantID(), coredata.MesureEntityType)
if err != nil {
return fmt.Errorf("cannot create global id: %w", err)
}
mesure := &coredata.Mesure{
ID: mesureID,
OrganizationID: organizationID,
Name: req.Mesures[i].Name,
Description: req.Mesures[i].Description,
Category: req.Mesures[i].Category,
State: coredata.MesureStateNotStarted,
ReferenceID: req.Mesures[i].ReferenceID,
Importance: req.Mesures[i].Importance,
CreatedAt: now,
UpdatedAt: now,
}
importedMesures = append(importedMesures, mesure)
if err := mesure.Upsert(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot upsert mesure: %w", err)
}
for j := range req.Mesures[i].Tasks {
taskID, err := gid.NewGID(organizationID.TenantID(), coredata.TaskEntityType)
if err != nil {
return fmt.Errorf("cannot create global id: %w", err)
}
task := &coredata.Task{
ID: taskID,
MesureID: mesure.ID,
Name: req.Mesures[i].Tasks[j].Name,
Description: req.Mesures[i].Tasks[j].Description,
ReferenceID: req.Mesures[i].Tasks[j].ReferenceID,
State: coredata.TaskStateTodo,
CreatedAt: now,
UpdatedAt: now,
}
if err := task.Upsert(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot upsert task: %w", err)
}
for k := range req.Mesures[i].Tasks[j].RequestedEvidences {
evidenceID, err := gid.NewGID(organizationID.TenantID(), coredata.EvidenceEntityType)
if err != nil {
return fmt.Errorf("cannot create global id: %w", err)
}
evidence := &coredata.Evidence{
State: coredata.EvidenceStateRequested,
ID: evidenceID,
TaskID: task.ID,
ReferenceID: req.Mesures[i].Tasks[j].RequestedEvidences[k].ReferenceID,
Type: req.Mesures[i].Tasks[j].RequestedEvidences[k].Type,
Description: req.Mesures[i].Tasks[j].RequestedEvidences[k].Name,
CreatedAt: now,
UpdatedAt: now,
}
if err := evidence.Upsert(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot upsert evidence: %w", err)
}
}
}
for _, standard := range req.Mesures[i].Standards {
framework := &coredata.Framework{}
if err := framework.LoadByReferenceID(ctx, tx, s.svc.scope, standard.Framework); err != nil {
continue
}
control := &coredata.Control{}
if err := control.LoadByFrameworkIDAndReferenceID(ctx, tx, s.svc.scope, framework.ID, standard.Control); err != nil {
continue
}
controlMesure := &coredata.ControlMesure{
ControlID: control.ID,
MesureID: mesure.ID,
CreatedAt: now,
}
if err := controlMesure.Upsert(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot insert control mesure: %w", err)
}
}
}
return nil
},
)
if err != nil {
return nil, fmt.Errorf("cannot import mesures: %w", err)
}
cursor := page.NewCursor(
len(importedMesures),
nil,
page.Head,
page.OrderBy[coredata.MesureOrderField]{
Field: coredata.MesureOrderFieldCreatedAt,
Direction: page.OrderDirectionAsc,
},
)
return page.NewPage(importedMesures, cursor), nil
}
func (s MesureService) Update(
ctx context.Context,
req UpdateMesureRequest,
) (*coredata.Mesure, error) {
mesure := &coredata.Mesure{ID: req.ID}
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := mesure.LoadByID(ctx, conn, s.svc.scope, req.ID); err != nil {
return fmt.Errorf("cannot load mesure: %w", err)
}
if req.Name != nil {
mesure.Name = *req.Name
}
if req.Description != nil {
mesure.Description = *req.Description
}
if req.Category != nil {
mesure.Category = *req.Category
}
if req.State != nil {
mesure.State = *req.State
}
if req.Importance != nil {
mesure.Importance = *req.Importance
}
mesure.UpdatedAt = time.Now()
if err := mesure.Update(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot update mesure: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return mesure, nil
}
func (s MesureService) ListForOrganizationID(
ctx context.Context,
organizationID gid.GID,
cursor *page.Cursor[coredata.MesureOrderField],
) (*page.Page[*coredata.Mesure, coredata.MesureOrderField], error) {
var mesures coredata.Mesures
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return mesures.LoadByOrganizationID(
ctx,
conn,
s.svc.scope,
organizationID,
cursor,
)
},
)
if err != nil {
return nil, err
}
return page.NewPage(mesures, cursor), nil
}
func (s MesureService) Create(
ctx context.Context,
req CreateMesureRequest,
) (*coredata.Mesure, error) {
now := time.Now()
mesureID, err := gid.NewGID(s.svc.scope.GetTenantID(), coredata.MesureEntityType)
if err != nil {
return nil, fmt.Errorf("cannot create mesure global id: %w", err)
}
referenceID, err := uuid.NewV4()
if err != nil {
return nil, fmt.Errorf("cannot generate reference id: %w", err)
}
mesure := &coredata.Mesure{
ID: mesureID,
OrganizationID: req.OrganizationID,
Name: req.Name,
Description: req.Description,
Category: req.Category,
ReferenceID: "custom-mesure-" + referenceID.String(),
State: coredata.MesureStateNotStarted,
Importance: req.Importance,
CreatedAt: now,
UpdatedAt: now,
}
err = s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := mesure.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot insert mesure: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return mesure, nil
}

View File

@@ -1,383 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// 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 probo
import (
"context"
"fmt"
"time"
"github.com/getprobo/probo/pkg/coredata"
"github.com/getprobo/probo/pkg/gid"
"github.com/getprobo/probo/pkg/page"
"go.gearno.de/crypto/uuid"
"go.gearno.de/kit/pg"
)
type (
MitigationService struct {
svc *TenantService
}
CreateMitigationRequest struct {
OrganizationID gid.GID
Name string
Description string
Category string
Importance coredata.MitigationImportance
}
UpdateMitigationRequest struct {
ID gid.GID
Name *string
Description *string
Category *string
State *coredata.MitigationState
Importance *coredata.MitigationImportance
}
ImportMitigationRequest struct {
Mitigations []struct {
Name string `json:"name"`
Description string `json:"description"`
Category string `json:"category"`
Importance coredata.MitigationImportance `json:"importance"`
ReferenceID string `json:"reference-id"`
Standards []struct {
Framework string `json:"framework"`
Control string `json:"control"`
} `json:"standards"`
Tasks []struct {
Name string `json:"name"`
Description string `json:"description"`
ReferenceID string `json:"reference-id"`
RequestedEvidences []struct {
ReferenceID string `json:"reference-id"`
Type coredata.EvidenceType `json:"type"`
Name string `json:"name"`
} `json:"requested-evidences"`
} `json:"tasks"`
} `json:"mitigations"`
}
)
func (s MitigationService) ListForRiskID(
ctx context.Context,
riskID gid.GID,
cursor *page.Cursor[coredata.MitigationOrderField],
) (*page.Page[*coredata.Mitigation, coredata.MitigationOrderField], error) {
var mitigations coredata.Mitigations
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return mitigations.LoadByRiskID(ctx, conn, s.svc.scope, riskID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(mitigations, cursor), nil
}
func (s MitigationService) ListForControlID(
ctx context.Context,
controlID gid.GID,
cursor *page.Cursor[coredata.MitigationOrderField],
) (*page.Page[*coredata.Mitigation, coredata.MitigationOrderField], error) {
var mitigations coredata.Mitigations
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return mitigations.LoadByControlID(ctx, conn, s.svc.scope, controlID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(mitigations, cursor), nil
}
func (s MitigationService) Get(
ctx context.Context,
mitigationID gid.GID,
) (*coredata.Mitigation, error) {
mitigation := &coredata.Mitigation{}
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return mitigation.LoadByID(ctx, conn, s.svc.scope, mitigationID)
},
)
if err != nil {
return nil, err
}
return mitigation, nil
}
func (s MitigationService) Import(
ctx context.Context,
organizationID gid.GID,
req ImportMitigationRequest,
) (*page.Page[*coredata.Mitigation, coredata.MitigationOrderField], error) {
importedMitigations := coredata.Mitigations{}
err := s.svc.pg.WithTx(
ctx,
func(tx pg.Conn) error {
for i := range req.Mitigations {
now := time.Now()
mitigationID, err := gid.NewGID(organizationID.TenantID(), coredata.MitigationEntityType)
if err != nil {
return fmt.Errorf("cannot create global id: %w", err)
}
mitigation := &coredata.Mitigation{
ID: mitigationID,
OrganizationID: organizationID,
Name: req.Mitigations[i].Name,
Description: req.Mitigations[i].Description,
Category: req.Mitigations[i].Category,
State: coredata.MitigationStateNotStarted,
ReferenceID: req.Mitigations[i].ReferenceID,
Importance: req.Mitigations[i].Importance,
CreatedAt: now,
UpdatedAt: now,
}
importedMitigations = append(importedMitigations, mitigation)
if err := mitigation.Upsert(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot upsert mitigation: %w", err)
}
for j := range req.Mitigations[i].Tasks {
taskID, err := gid.NewGID(organizationID.TenantID(), coredata.TaskEntityType)
if err != nil {
return fmt.Errorf("cannot create global id: %w", err)
}
task := &coredata.Task{
ID: taskID,
MitigationID: mitigation.ID,
Name: req.Mitigations[i].Tasks[j].Name,
Description: req.Mitigations[i].Tasks[j].Description,
ReferenceID: req.Mitigations[i].Tasks[j].ReferenceID,
State: coredata.TaskStateTodo,
CreatedAt: now,
UpdatedAt: now,
}
if err := task.Upsert(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot upsert task: %w", err)
}
for k := range req.Mitigations[i].Tasks[j].RequestedEvidences {
evidenceID, err := gid.NewGID(organizationID.TenantID(), coredata.EvidenceEntityType)
if err != nil {
return fmt.Errorf("cannot create global id: %w", err)
}
evidence := &coredata.Evidence{
State: coredata.EvidenceStateRequested,
ID: evidenceID,
TaskID: task.ID,
ReferenceID: req.Mitigations[i].Tasks[j].RequestedEvidences[k].ReferenceID,
Type: req.Mitigations[i].Tasks[j].RequestedEvidences[k].Type,
Description: req.Mitigations[i].Tasks[j].RequestedEvidences[k].Name,
CreatedAt: now,
UpdatedAt: now,
}
if err := evidence.Upsert(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot upsert evidence: %w", err)
}
}
}
for _, standard := range req.Mitigations[i].Standards {
framework := &coredata.Framework{}
if err := framework.LoadByReferenceID(ctx, tx, s.svc.scope, standard.Framework); err != nil {
continue
}
control := &coredata.Control{}
if err := control.LoadByFrameworkIDAndReferenceID(ctx, tx, s.svc.scope, framework.ID, standard.Control); err != nil {
continue
}
controlMitigation := &coredata.ControlMitigation{
ControlID: control.ID,
MitigationID: mitigation.ID,
CreatedAt: now,
}
if err := controlMitigation.Upsert(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot insert control mitigation: %w", err)
}
}
}
return nil
},
)
if err != nil {
return nil, fmt.Errorf("cannot import mitigations: %w", err)
}
cursor := page.NewCursor(
len(importedMitigations),
nil,
page.Head,
page.OrderBy[coredata.MitigationOrderField]{
Field: coredata.MitigationOrderFieldCreatedAt,
Direction: page.OrderDirectionAsc,
},
)
return page.NewPage(importedMitigations, cursor), nil
}
func (s MitigationService) Update(
ctx context.Context,
req UpdateMitigationRequest,
) (*coredata.Mitigation, error) {
mitigation := &coredata.Mitigation{ID: req.ID}
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := mitigation.LoadByID(ctx, conn, s.svc.scope, req.ID); err != nil {
return fmt.Errorf("cannot load mitigation: %w", err)
}
if req.Name != nil {
mitigation.Name = *req.Name
}
if req.Description != nil {
mitigation.Description = *req.Description
}
if req.Category != nil {
mitigation.Category = *req.Category
}
if req.State != nil {
mitigation.State = *req.State
}
if req.Importance != nil {
mitigation.Importance = *req.Importance
}
mitigation.UpdatedAt = time.Now()
if err := mitigation.Update(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot update mitigation: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return mitigation, nil
}
func (s MitigationService) ListForOrganizationID(
ctx context.Context,
organizationID gid.GID,
cursor *page.Cursor[coredata.MitigationOrderField],
) (*page.Page[*coredata.Mitigation, coredata.MitigationOrderField], error) {
var mitigations coredata.Mitigations
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return mitigations.LoadByOrganizationID(
ctx,
conn,
s.svc.scope,
organizationID,
cursor,
)
},
)
if err != nil {
return nil, err
}
return page.NewPage(mitigations, cursor), nil
}
func (s MitigationService) Create(
ctx context.Context,
req CreateMitigationRequest,
) (*coredata.Mitigation, error) {
now := time.Now()
mitigationID, err := gid.NewGID(s.svc.scope.GetTenantID(), coredata.MitigationEntityType)
if err != nil {
return nil, fmt.Errorf("cannot create mitigation global id: %w", err)
}
referenceID, err := uuid.NewV4()
if err != nil {
return nil, fmt.Errorf("cannot generate reference id: %w", err)
}
mitigation := &coredata.Mitigation{
ID: mitigationID,
OrganizationID: req.OrganizationID,
Name: req.Name,
Description: req.Description,
Category: req.Category,
ReferenceID: "custom-mitigation-" + referenceID.String(),
State: coredata.MitigationStateNotStarted,
Importance: req.Importance,
CreatedAt: now,
UpdatedAt: now,
}
err = s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := mitigation.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot insert mitigation: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return mitigation, nil
}

View File

@@ -66,7 +66,7 @@ func (s OrganizationService) Create(
ctx,
func(conn pg.Conn) error {
if err := organization.Insert(ctx, conn); err != nil {
return fmt.Errorf("cannot insert mitigation: %w", err)
return fmt.Errorf("cannot insert organization: %w", err)
}
return nil

View File

@@ -55,9 +55,9 @@ type (
}
)
func (s RiskService) ListForMitigationID(
func (s RiskService) ListForMesureID(
ctx context.Context,
mitigationID gid.GID,
mesureID gid.GID,
cursor *page.Cursor[coredata.RiskOrderField],
) (*page.Page[*coredata.Risk, coredata.RiskOrderField], error) {
var risks coredata.Risks
@@ -65,7 +65,7 @@ func (s RiskService) ListForMitigationID(
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return risks.LoadByMitigationID(ctx, conn, s.svc.scope, mitigationID, cursor)
return risks.LoadByMesureID(ctx, conn, s.svc.scope, mesureID, cursor)
},
)
@@ -116,42 +116,42 @@ func (s RiskService) DeletePolicyMapping(
)
}
func (s RiskService) CreateMitigationMapping(
func (s RiskService) CreateMesureMapping(
ctx context.Context,
riskID gid.GID,
mitigationID gid.GID,
mesureID gid.GID,
) error {
riskMitigation := &coredata.RiskMitigation{
RiskID: riskID,
MitigationID: mitigationID,
TenantID: s.svc.scope.GetTenantID(),
CreatedAt: time.Now(),
riskMesure := &coredata.RiskMesure{
RiskID: riskID,
MesureID: mesureID,
TenantID: s.svc.scope.GetTenantID(),
CreatedAt: time.Now(),
}
return s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return riskMitigation.Insert(ctx, conn, s.svc.scope)
return riskMesure.Insert(ctx, conn, s.svc.scope)
},
)
}
func (s RiskService) DeleteMitigationMapping(
func (s RiskService) DeleteMesureMapping(
ctx context.Context,
riskID gid.GID,
mitigationID gid.GID,
mesureID gid.GID,
) error {
riskMitigation := &coredata.RiskMitigation{
RiskID: riskID,
MitigationID: mitigationID,
TenantID: s.svc.scope.GetTenantID(),
CreatedAt: time.Now(),
riskMesure := &coredata.RiskMesure{
RiskID: riskID,
MesureID: mesureID,
TenantID: s.svc.scope.GetTenantID(),
CreatedAt: time.Now(),
}
return s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return riskMitigation.Delete(ctx, conn, s.svc.scope)
return riskMesure.Delete(ctx, conn, s.svc.scope)
},
)
}

View File

@@ -39,7 +39,7 @@ type (
scope coredata.Scoper
Frameworks *FrameworkService
Mitigations *MitigationService
Mesures *MesureService
Tasks *TaskService
Evidences *EvidenceService
Organizations *OrganizationService
@@ -80,7 +80,7 @@ func (s *Service) WithTenant(tenantID gid.TenantID) *TenantService {
}
tenantService.Frameworks = &FrameworkService{svc: tenantService}
tenantService.Mitigations = &MitigationService{svc: tenantService}
tenantService.Mesures = &MesureService{svc: tenantService}
tenantService.Tasks = &TaskService{svc: tenantService}
tenantService.Evidences = &EvidenceService{svc: tenantService}
tenantService.Peoples = &PeopleService{svc: tenantService}

View File

@@ -32,7 +32,7 @@ type (
}
CreateTaskRequest struct {
MitigationID gid.GID
MesureID gid.GID
Name string
Description string
TimeEstimate *time.Duration
@@ -65,7 +65,7 @@ func (s TaskService) Create(
task := &coredata.Task{
ID: taskID,
MitigationID: req.MitigationID,
MesureID: req.MesureID,
Name: req.Name,
Description: req.Description,
TimeEstimate: req.TimeEstimate,
@@ -215,9 +215,9 @@ func (s TaskService) Delete(
return nil
}
func (s TaskService) ListForMitigationID(
func (s TaskService) ListForMesureID(
ctx context.Context,
mitigationID gid.GID,
mesureID gid.GID,
cursor *page.Cursor[coredata.TaskOrderField],
) (*page.Page[*coredata.Task, coredata.TaskOrderField], error) {
var tasks coredata.Tasks
@@ -225,11 +225,11 @@ func (s TaskService) ListForMitigationID(
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return tasks.LoadByMitigationID(
return tasks.LoadByMesureID(
ctx,
conn,
s.svc.scope,
mitigationID,
mesureID,
cursor,
)
},

View File

@@ -39,23 +39,23 @@ enum OrderDirection
DESC @goEnum(value: "github.com/getprobo/probo/pkg/page.OrderDirectionDesc")
}
enum MitigationState
@goModel(model: "github.com/getprobo/probo/pkg/coredata.MitigationState") {
enum MesureState
@goModel(model: "github.com/getprobo/probo/pkg/coredata.MesureState") {
NOT_STARTED
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.MitigationStateNotStarted"
value: "github.com/getprobo/probo/pkg/coredata.MesureStateNotStarted"
)
IN_PROGRESS
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.MitigationStateInProgress"
value: "github.com/getprobo/probo/pkg/coredata.MesureStateInProgress"
)
NOT_APPLICABLE
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.MitigationStateNotApplicable"
value: "github.com/getprobo/probo/pkg/coredata.MesureStateNotApplicable"
)
IMPLEMENTED
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.MitigationStateImplemented"
value: "github.com/getprobo/probo/pkg/coredata.MesureStateImplemented"
)
}
@@ -91,21 +91,19 @@ enum PeopleKind
)
}
enum MitigationImportance
@goModel(
model: "github.com/getprobo/probo/pkg/coredata.MitigationImportance"
) {
enum MesureImportance
@goModel(model: "github.com/getprobo/probo/pkg/coredata.MesureImportance") {
MANDATORY
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.MitigationImportanceMandatory"
value: "github.com/getprobo/probo/pkg/coredata.MesureImportanceMandatory"
)
PREFERRED
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.MitigationImportancePreferred"
value: "github.com/getprobo/probo/pkg/coredata.MesureImportancePreferred"
)
ADVANCED
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.MitigationImportanceAdvanced"
value: "github.com/getprobo/probo/pkg/coredata.MesureImportanceAdvanced"
)
}
@@ -213,13 +211,11 @@ enum ControlOrderField
)
}
enum MitigationOrderField
@goModel(
model: "github.com/getprobo/probo/pkg/coredata.MitigationOrderField"
) {
enum MesureOrderField
@goModel(model: "github.com/getprobo/probo/pkg/coredata.MesureOrderField") {
CREATED_AT
@goEnum(
value: "github.com/getprobo/probo/pkg/coredata.MitigationOrderFieldCreatedAt"
value: "github.com/getprobo/probo/pkg/coredata.MesureOrderFieldCreatedAt"
)
}
@@ -307,12 +303,12 @@ input ControlOrder
field: ControlOrderField!
}
input MitigationOrder
input MesureOrder
@goModel(
model: "github.com/getprobo/probo/pkg/server/api/console/v1/types.MitigationOrderBy"
model: "github.com/getprobo/probo/pkg/server/api/console/v1/types.MesureOrderBy"
) {
direction: OrderDirection!
field: MitigationOrderField!
field: MesureOrderField!
}
input TaskOrder
@@ -406,13 +402,13 @@ type Organization implements Node {
orderBy: PolicyOrder
): PolicyConnection! @goField(forceResolver: true)
mitigations(
mesures(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: MitigationOrder
): MitigationConnection! @goField(forceResolver: true)
orderBy: MesureOrder
): MesureConnection! @goField(forceResolver: true)
risks(
first: Int
@@ -516,13 +512,13 @@ type Control implements Node {
name: String!
description: String!
mitigations(
mesures(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: MitigationOrder
): MitigationConnection! @goField(forceResolver: true)
orderBy: MesureOrder
): MesureConnection! @goField(forceResolver: true)
policies(
first: Int
@@ -536,13 +532,13 @@ type Control implements Node {
updatedAt: Datetime!
}
type Mitigation implements Node {
type Mesure implements Node {
id: ID!
category: String!
name: String!
description: String!
state: MitigationState!
importance: MitigationImportance!
state: MesureState!
importance: MesureImportance!
tasks(
first: Int
@@ -641,13 +637,13 @@ type Risk implements Node {
owner: People @goField(forceResolver: true)
mitigations(
mesures(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: MitigationOrder
): MitigationConnection! @goField(forceResolver: true)
orderBy: MesureOrder
): MesureConnection! @goField(forceResolver: true)
policies(
first: Int
@@ -748,14 +744,14 @@ type ControlEdge {
node: Control!
}
type MitigationConnection {
edges: [MitigationEdge!]!
type MesureConnection {
edges: [MesureEdge!]!
pageInfo: PageInfo!
}
type MitigationEdge {
type MesureEdge {
cursor: CursorKey!
node: Mitigation!
node: Mesure!
}
type TaskConnection {
@@ -847,21 +843,21 @@ type Mutation {
importFramework(input: ImportFrameworkInput!): ImportFrameworkPayload!
deleteFramework(input: DeleteFrameworkInput!): DeleteFrameworkPayload!
# Mitigation mutations
createMitigation(input: CreateMitigationInput!): CreateMitigationPayload!
updateMitigation(input: UpdateMitigationInput!): UpdateMitigationPayload!
importMitigation(input: ImportMitigationInput!): ImportMitigationPayload!
# Mesure mutations
createMesure(input: CreateMesureInput!): CreateMesurePayload!
updateMesure(input: UpdateMesureInput!): UpdateMesurePayload!
importMesure(input: ImportMesureInput!): ImportMesurePayload!
# Control mutations
createControlMitigationMapping(
input: CreateControlMitigationMappingInput!
): CreateControlMitigationMappingPayload!
createControlMesureMapping(
input: CreateControlMesureMappingInput!
): CreateControlMesureMappingPayload!
createControlPolicyMapping(
input: CreateControlPolicyMappingInput!
): CreateControlPolicyMappingPayload!
deleteControlMitigationMapping(
input: DeleteControlMitigationMappingInput!
): DeleteControlMitigationMappingPayload!
deleteControlMesureMapping(
input: DeleteControlMesureMappingInput!
): DeleteControlMesureMappingPayload!
deleteControlPolicyMapping(
input: DeleteControlPolicyMappingInput!
): DeleteControlPolicyMappingPayload!
@@ -877,12 +873,12 @@ type Mutation {
createRisk(input: CreateRiskInput!): CreateRiskPayload!
updateRisk(input: UpdateRiskInput!): UpdateRiskPayload!
deleteRisk(input: DeleteRiskInput!): DeleteRiskPayload!
createRiskMitigationMapping(
input: CreateRiskMitigationMappingInput!
): CreateRiskMitigationMappingPayload!
deleteRiskMitigationMapping(
input: DeleteRiskMitigationMappingInput!
): DeleteRiskMitigationMappingPayload!
createRiskMesureMapping(
input: CreateRiskMesureMappingInput!
): CreateRiskMesureMappingPayload!
deleteRiskMesureMapping(
input: DeleteRiskMesureMappingInput!
): DeleteRiskMesureMappingPayload!
createRiskPolicyMapping(
input: CreateRiskPolicyMappingInput!
@@ -1019,30 +1015,30 @@ input DeleteFrameworkInput {
frameworkId: ID!
}
input CreateMitigationInput {
input CreateMesureInput {
organizationId: ID!
name: String!
description: String!
category: String!
importance: MitigationImportance!
importance: MesureImportance!
}
input UpdateMitigationInput {
input UpdateMesureInput {
id: ID!
name: String
description: String
category: String
state: MitigationState
importance: MitigationImportance
state: MesureState
importance: MesureImportance
}
input ImportMitigationInput {
input ImportMesureInput {
organizationId: ID!
file: Upload!
}
input CreateTaskInput {
mitigationId: ID!
mesureId: ID!
name: String!
description: String!
timeEstimate: Duration
@@ -1070,9 +1066,9 @@ input UnassignTaskInput {
taskId: ID!
}
input CreateControlMitigationMappingInput {
input CreateControlMesureMappingInput {
controlId: ID!
mitigationId: ID!
mesureId: ID!
}
input CreateControlPolicyMappingInput {
@@ -1080,9 +1076,9 @@ input CreateControlPolicyMappingInput {
policyId: ID!
}
input DeleteControlMitigationMappingInput {
input DeleteControlMesureMappingInput {
controlId: ID!
mitigationId: ID!
mesureId: ID!
}
input DeleteControlPolicyMappingInput {
@@ -1118,14 +1114,14 @@ input DeleteRiskInput {
riskId: ID!
}
input CreateRiskMitigationMappingInput {
input CreateRiskMesureMappingInput {
riskId: ID!
mitigationId: ID!
mesureId: ID!
}
input DeleteRiskMitigationMappingInput {
input DeleteRiskMesureMappingInput {
riskId: ID!
mitigationId: ID!
mesureId: ID!
}
input CreateRiskPolicyMappingInput {
@@ -1267,16 +1263,16 @@ type DeleteFrameworkPayload {
deletedFrameworkId: ID!
}
type CreateMitigationPayload {
mitigationEdge: MitigationEdge!
type CreateMesurePayload {
mesureEdge: MesureEdge!
}
type UpdateMitigationPayload {
mitigation: Mitigation!
type UpdateMesurePayload {
mesure: Mesure!
}
type ImportMitigationPayload {
mitigationEdges: [MitigationEdge!]!
type ImportMesurePayload {
mesureEdges: [MesureEdge!]!
}
type CreateTaskPayload {
@@ -1299,7 +1295,7 @@ type UnassignTaskPayload {
task: Task!
}
type CreateControlMitigationMappingPayload {
type CreateControlMesureMappingPayload {
success: Boolean!
}
@@ -1307,7 +1303,7 @@ type CreateControlPolicyMappingPayload {
success: Boolean!
}
type DeleteControlMitigationMappingPayload {
type DeleteControlMesureMappingPayload {
success: Boolean!
}
@@ -1327,11 +1323,11 @@ type DeleteRiskPayload {
deletedRiskId: ID!
}
type CreateRiskMitigationMappingPayload {
type CreateRiskMesureMappingPayload {
success: Boolean!
}
type DeleteRiskMitigationMappingPayload {
type DeleteRiskMesureMappingPayload {
success: Boolean!
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,31 +20,31 @@ import (
)
type (
MitigationOrderBy OrderBy[coredata.MitigationOrderField]
MesureOrderBy OrderBy[coredata.MesureOrderField]
)
func NewMitigationConnection(p *page.Page[*coredata.Mitigation, coredata.MitigationOrderField]) *MitigationConnection {
var edges = make([]*MitigationEdge, len(p.Data))
func NewMesureConnection(p *page.Page[*coredata.Mesure, coredata.MesureOrderField]) *MesureConnection {
var edges = make([]*MesureEdge, len(p.Data))
for i := range edges {
edges[i] = NewMitigationEdge(p.Data[i], p.Cursor.OrderBy.Field)
edges[i] = NewMesureEdge(p.Data[i], p.Cursor.OrderBy.Field)
}
return &MitigationConnection{
return &MesureConnection{
Edges: edges,
PageInfo: NewPageInfo(p),
}
}
func NewMitigationEdge(c *coredata.Mitigation, orderBy coredata.MitigationOrderField) *MitigationEdge {
return &MitigationEdge{
func NewMesureEdge(c *coredata.Mesure, orderBy coredata.MesureOrderField) *MesureEdge {
return &MesureEdge{
Cursor: c.CursorKey(orderBy),
Node: NewMitigation(c),
Node: NewMesure(c),
}
}
func NewMitigation(c *coredata.Mitigation) *Mitigation {
return &Mitigation{
func NewMesure(c *coredata.Mesure) *Mesure {
return &Mesure{
ID: c.ID,
Category: c.Category,
Name: c.Name,

View File

@@ -37,14 +37,14 @@ type ConfirmEmailPayload struct {
}
type Control struct {
ID gid.GID `json:"id"`
ReferenceID string `json:"referenceId"`
Name string `json:"name"`
Description string `json:"description"`
Mitigations *MitigationConnection `json:"mitigations"`
Policies *PolicyConnection `json:"policies"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
ID gid.GID `json:"id"`
ReferenceID string `json:"referenceId"`
Name string `json:"name"`
Description string `json:"description"`
Mesures *MesureConnection `json:"mesures"`
Policies *PolicyConnection `json:"policies"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
func (Control) IsNode() {}
@@ -60,12 +60,12 @@ type ControlEdge struct {
Node *Control `json:"node"`
}
type CreateControlMitigationMappingInput struct {
ControlID gid.GID `json:"controlId"`
MitigationID gid.GID `json:"mitigationId"`
type CreateControlMesureMappingInput struct {
ControlID gid.GID `json:"controlId"`
MesureID gid.GID `json:"mesureId"`
}
type CreateControlMitigationMappingPayload struct {
type CreateControlMesureMappingPayload struct {
Success bool `json:"success"`
}
@@ -101,16 +101,16 @@ type CreateFrameworkPayload struct {
FrameworkEdge *FrameworkEdge `json:"frameworkEdge"`
}
type CreateMitigationInput struct {
OrganizationID gid.GID `json:"organizationId"`
Name string `json:"name"`
Description string `json:"description"`
Category string `json:"category"`
Importance coredata.MitigationImportance `json:"importance"`
type CreateMesureInput struct {
OrganizationID gid.GID `json:"organizationId"`
Name string `json:"name"`
Description string `json:"description"`
Category string `json:"category"`
Importance coredata.MesureImportance `json:"importance"`
}
type CreateMitigationPayload struct {
MitigationEdge *MitigationEdge `json:"mitigationEdge"`
type CreateMesurePayload struct {
MesureEdge *MesureEdge `json:"mesureEdge"`
}
type CreateOrganizationInput struct {
@@ -158,12 +158,12 @@ type CreateRiskInput struct {
ResidualImpact *float64 `json:"residualImpact,omitempty"`
}
type CreateRiskMitigationMappingInput struct {
RiskID gid.GID `json:"riskId"`
MitigationID gid.GID `json:"mitigationId"`
type CreateRiskMesureMappingInput struct {
RiskID gid.GID `json:"riskId"`
MesureID gid.GID `json:"mesureId"`
}
type CreateRiskMitigationMappingPayload struct {
type CreateRiskMesureMappingPayload struct {
Success bool `json:"success"`
}
@@ -181,7 +181,7 @@ type CreateRiskPolicyMappingPayload struct {
}
type CreateTaskInput struct {
MitigationID gid.GID `json:"mitigationId"`
MesureID gid.GID `json:"mesureId"`
Name string `json:"name"`
Description string `json:"description"`
TimeEstimate *time.Duration `json:"timeEstimate,omitempty"`
@@ -220,12 +220,12 @@ type CreateVendorPayload struct {
VendorEdge *VendorEdge `json:"vendorEdge"`
}
type DeleteControlMitigationMappingInput struct {
ControlID gid.GID `json:"controlId"`
MitigationID gid.GID `json:"mitigationId"`
type DeleteControlMesureMappingInput struct {
ControlID gid.GID `json:"controlId"`
MesureID gid.GID `json:"mesureId"`
}
type DeleteControlMitigationMappingPayload struct {
type DeleteControlMesureMappingPayload struct {
Success bool `json:"success"`
}
@@ -282,12 +282,12 @@ type DeleteRiskInput struct {
RiskID gid.GID `json:"riskId"`
}
type DeleteRiskMitigationMappingInput struct {
RiskID gid.GID `json:"riskId"`
MitigationID gid.GID `json:"mitigationId"`
type DeleteRiskMesureMappingInput struct {
RiskID gid.GID `json:"riskId"`
MesureID gid.GID `json:"mesureId"`
}
type DeleteRiskMitigationMappingPayload struct {
type DeleteRiskMesureMappingPayload struct {
Success bool `json:"success"`
}
@@ -397,13 +397,13 @@ type ImportFrameworkPayload struct {
FrameworkEdge *FrameworkEdge `json:"frameworkEdge"`
}
type ImportMitigationInput struct {
type ImportMesureInput struct {
OrganizationID gid.GID `json:"organizationId"`
File graphql.Upload `json:"file"`
}
type ImportMitigationPayload struct {
MitigationEdges []*MitigationEdge `json:"mitigationEdges"`
type ImportMesurePayload struct {
MesureEdges []*MesureEdge `json:"mesureEdges"`
}
type InviteUserInput struct {
@@ -416,49 +416,49 @@ type InviteUserPayload struct {
Success bool `json:"success"`
}
type Mitigation struct {
ID gid.GID `json:"id"`
Category string `json:"category"`
Name string `json:"name"`
Description string `json:"description"`
State coredata.MitigationState `json:"state"`
Importance coredata.MitigationImportance `json:"importance"`
Tasks *TaskConnection `json:"tasks"`
Risks *RiskConnection `json:"risks"`
Controls *ControlConnection `json:"controls"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
type Mesure struct {
ID gid.GID `json:"id"`
Category string `json:"category"`
Name string `json:"name"`
Description string `json:"description"`
State coredata.MesureState `json:"state"`
Importance coredata.MesureImportance `json:"importance"`
Tasks *TaskConnection `json:"tasks"`
Risks *RiskConnection `json:"risks"`
Controls *ControlConnection `json:"controls"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
func (Mitigation) IsNode() {}
func (this Mitigation) GetID() gid.GID { return this.ID }
func (Mesure) IsNode() {}
func (this Mesure) GetID() gid.GID { return this.ID }
type MitigationConnection struct {
Edges []*MitigationEdge `json:"edges"`
PageInfo *PageInfo `json:"pageInfo"`
type MesureConnection struct {
Edges []*MesureEdge `json:"edges"`
PageInfo *PageInfo `json:"pageInfo"`
}
type MitigationEdge struct {
type MesureEdge struct {
Cursor page.CursorKey `json:"cursor"`
Node *Mitigation `json:"node"`
Node *Mesure `json:"node"`
}
type Mutation struct {
}
type Organization struct {
ID gid.GID `json:"id"`
Name string `json:"name"`
LogoURL *string `json:"logoUrl,omitempty"`
Users *UserConnection `json:"users"`
Frameworks *FrameworkConnection `json:"frameworks"`
Vendors *VendorConnection `json:"vendors"`
Peoples *PeopleConnection `json:"peoples"`
Policies *PolicyConnection `json:"policies"`
Mitigations *MitigationConnection `json:"mitigations"`
Risks *RiskConnection `json:"risks"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
ID gid.GID `json:"id"`
Name string `json:"name"`
LogoURL *string `json:"logoUrl,omitempty"`
Users *UserConnection `json:"users"`
Frameworks *FrameworkConnection `json:"frameworks"`
Vendors *VendorConnection `json:"vendors"`
Peoples *PeopleConnection `json:"peoples"`
Policies *PolicyConnection `json:"policies"`
Mesures *MesureConnection `json:"mesures"`
Risks *RiskConnection `json:"risks"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
func (Organization) IsNode() {}
@@ -569,7 +569,7 @@ type Risk struct {
ResidualImpact float64 `json:"residualImpact"`
ResidualSeverity float64 `json:"residualSeverity"`
Owner *People `json:"owner,omitempty"`
Mitigations *MitigationConnection `json:"mitigations"`
Mesures *MesureConnection `json:"mesures"`
Policies *PolicyConnection `json:"policies"`
Controls *ControlConnection `json:"controls"`
CreatedAt time.Time `json:"createdAt"`
@@ -637,17 +637,17 @@ type UpdateFrameworkPayload struct {
Framework *Framework `json:"framework"`
}
type UpdateMitigationInput struct {
ID gid.GID `json:"id"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
Category *string `json:"category,omitempty"`
State *coredata.MitigationState `json:"state,omitempty"`
Importance *coredata.MitigationImportance `json:"importance,omitempty"`
type UpdateMesureInput struct {
ID gid.GID `json:"id"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
Category *string `json:"category,omitempty"`
State *coredata.MesureState `json:"state,omitempty"`
Importance *coredata.MesureImportance `json:"importance,omitempty"`
}
type UpdateMitigationPayload struct {
Mitigation *Mitigation `json:"mitigation"`
type UpdateMesurePayload struct {
Mesure *Mesure `json:"mesure"`
}
type UpdateOrganizationInput struct {

View File

@@ -20,16 +20,16 @@ import (
"github.com/vektah/gqlparser/v2/gqlerror"
)
// Mitigations is the resolver for the mitigations field.
func (r *controlResolver) Mitigations(ctx context.Context, obj *types.Control, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MitigationOrderBy) (*types.MitigationConnection, error) {
// Mesures is the resolver for the mesures field.
func (r *controlResolver) Mesures(ctx context.Context, obj *types.Control, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MesureOrderBy) (*types.MesureConnection, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.MitigationOrderField]{
Field: coredata.MitigationOrderFieldCreatedAt,
pageOrderBy := page.OrderBy[coredata.MesureOrderField]{
Field: coredata.MesureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MitigationOrderField]{
pageOrderBy = page.OrderBy[coredata.MesureOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
@@ -37,12 +37,12 @@ func (r *controlResolver) Mitigations(ctx context.Context, obj *types.Control, f
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Mitigations.ListForControlID(ctx, obj.ID, cursor)
page, err := svc.Mesures.ListForControlID(ctx, obj.ID, cursor)
if err != nil {
return nil, fmt.Errorf("cannot list mitigations: %w", err)
return nil, fmt.Errorf("cannot list mesures: %w", err)
}
return types.NewMitigationConnection(page), nil
return types.NewMesureConnection(page), nil
}
// Policies is the resolver for the policies field.
@@ -113,7 +113,7 @@ func (r *frameworkResolver) Controls(ctx context.Context, obj *types.Framework,
}
// Tasks is the resolver for the tasks field.
func (r *mitigationResolver) Tasks(ctx context.Context, obj *types.Mitigation, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TaskOrderBy) (*types.TaskConnection, error) {
func (r *mesureResolver) Tasks(ctx context.Context, obj *types.Mesure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TaskOrderBy) (*types.TaskConnection, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TaskOrderField]{
@@ -129,16 +129,16 @@ func (r *mitigationResolver) Tasks(ctx context.Context, obj *types.Mitigation, f
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Tasks.ListForMitigationID(ctx, obj.ID, cursor)
page, err := svc.Tasks.ListForMesureID(ctx, obj.ID, cursor)
if err != nil {
return nil, fmt.Errorf("cannot list mitigation tasks: %w", err)
return nil, fmt.Errorf("cannot list mesure tasks: %w", err)
}
return types.NewTaskConnection(page), nil
}
// Risks is the resolver for the risks field.
func (r *mitigationResolver) Risks(ctx context.Context, obj *types.Mitigation, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.RiskOrderBy) (*types.RiskConnection, error) {
func (r *mesureResolver) Risks(ctx context.Context, obj *types.Mesure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.RiskOrderBy) (*types.RiskConnection, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.RiskOrderField]{
@@ -154,16 +154,16 @@ func (r *mitigationResolver) Risks(ctx context.Context, obj *types.Mitigation, f
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Risks.ListForMitigationID(ctx, obj.ID, cursor)
page, err := svc.Risks.ListForMesureID(ctx, obj.ID, cursor)
if err != nil {
return nil, fmt.Errorf("cannot list mitigation risks: %w", err)
return nil, fmt.Errorf("cannot list mesure risks: %w", err)
}
return types.NewRiskConnection(page), nil
}
// Controls is the resolver for the controls field.
func (r *mitigationResolver) Controls(ctx context.Context, obj *types.Mitigation, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy) (*types.ControlConnection, error) {
func (r *mesureResolver) Controls(ctx context.Context, obj *types.Mesure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy) (*types.ControlConnection, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
@@ -179,9 +179,9 @@ func (r *mitigationResolver) Controls(ctx context.Context, obj *types.Mitigation
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Controls.ListForMitigationID(ctx, obj.ID, cursor)
page, err := svc.Controls.ListForMesureID(ctx, obj.ID, cursor)
if err != nil {
return nil, fmt.Errorf("cannot list mitigation controls: %w", err)
return nil, fmt.Errorf("cannot list mesure controls: %w", err)
}
return types.NewControlConnection(page), nil
@@ -518,11 +518,11 @@ func (r *mutationResolver) DeleteFramework(ctx context.Context, input types.Dele
}, nil
}
// // CreateMitigation is the resolver for the createMitigation field.
func (r *mutationResolver) CreateMitigation(ctx context.Context, input types.CreateMitigationInput) (*types.CreateMitigationPayload, error) {
// // CreateMesure is the resolver for the createMesure field.
func (r *mutationResolver) CreateMesure(ctx context.Context, input types.CreateMesureInput) (*types.CreateMesurePayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.OrganizationID.TenantID())
mitigation, err := svc.Mitigations.Create(ctx, probo.CreateMitigationRequest{
mesure, err := svc.Mesures.Create(ctx, probo.CreateMesureRequest{
OrganizationID: input.OrganizationID,
Name: input.Name,
Description: input.Description,
@@ -530,19 +530,19 @@ func (r *mutationResolver) CreateMitigation(ctx context.Context, input types.Cre
Importance: input.Importance,
})
if err != nil {
panic(fmt.Errorf("cannot create mitigation: %w", err))
panic(fmt.Errorf("cannot create mesure: %w", err))
}
return &types.CreateMitigationPayload{
MitigationEdge: types.NewMitigationEdge(mitigation, coredata.MitigationOrderFieldCreatedAt),
return &types.CreateMesurePayload{
MesureEdge: types.NewMesureEdge(mesure, coredata.MesureOrderFieldCreatedAt),
}, nil
}
// UpdateMitigation is the resolver for the updateMitigation field.
func (r *mutationResolver) UpdateMitigation(ctx context.Context, input types.UpdateMitigationInput) (*types.UpdateMitigationPayload, error) {
// UpdateMesure is the resolver for the updateMesure field.
func (r *mutationResolver) UpdateMesure(ctx context.Context, input types.UpdateMesureInput) (*types.UpdateMesurePayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.ID.TenantID())
mitigation, err := svc.Mitigations.Update(ctx, probo.UpdateMitigationRequest{
mesure, err := svc.Mesures.Update(ctx, probo.UpdateMesureRequest{
ID: input.ID,
Name: input.Name,
Description: input.Description,
@@ -551,48 +551,48 @@ func (r *mutationResolver) UpdateMitigation(ctx context.Context, input types.Upd
State: input.State,
})
if err != nil {
panic(fmt.Errorf("cannot update mitigation: %w", err))
panic(fmt.Errorf("cannot update mesure: %w", err))
}
return &types.UpdateMitigationPayload{
Mitigation: types.NewMitigation(mitigation),
return &types.UpdateMesurePayload{
Mesure: types.NewMesure(mesure),
}, nil
}
// ImportMitigation is the resolver for the importMitigation field.
func (r *mutationResolver) ImportMitigation(ctx context.Context, input types.ImportMitigationInput) (*types.ImportMitigationPayload, error) {
// ImportMesure is the resolver for the importMesure field.
func (r *mutationResolver) ImportMesure(ctx context.Context, input types.ImportMesureInput) (*types.ImportMesurePayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.OrganizationID.TenantID())
var req probo.ImportMitigationRequest
if err := json.NewDecoder(input.File.File).Decode(&req.Mitigations); err != nil {
return nil, fmt.Errorf("cannot unmarshal mitigation: %w", err)
var req probo.ImportMesureRequest
if err := json.NewDecoder(input.File.File).Decode(&req.Mesures); err != nil {
return nil, fmt.Errorf("cannot unmarshal mesure: %w", err)
}
mitigations, err := svc.Mitigations.Import(ctx, input.OrganizationID, req)
mesures, err := svc.Mesures.Import(ctx, input.OrganizationID, req)
if err != nil {
return nil, fmt.Errorf("cannot import mitigation: %w", err)
return nil, fmt.Errorf("cannot import mesure: %w", err)
}
mitigationEdges := make([]*types.MitigationEdge, len(mitigations.Data))
for i, mitigation := range mitigations.Data {
mitigationEdges[i] = types.NewMitigationEdge(mitigation, coredata.MitigationOrderFieldCreatedAt)
mesureEdges := make([]*types.MesureEdge, len(mesures.Data))
for i, mesure := range mesures.Data {
mesureEdges[i] = types.NewMesureEdge(mesure, coredata.MesureOrderFieldCreatedAt)
}
return &types.ImportMitigationPayload{
MitigationEdges: mitigationEdges,
return &types.ImportMesurePayload{
MesureEdges: mesureEdges,
}, nil
}
// CreateControlMitigationMapping is the resolver for the createControlMitigationMapping field.
func (r *mutationResolver) CreateControlMitigationMapping(ctx context.Context, input types.CreateControlMitigationMappingInput) (*types.CreateControlMitigationMappingPayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.MitigationID.TenantID())
// CreateControlMesureMapping is the resolver for the createControlMesureMapping field.
func (r *mutationResolver) CreateControlMesureMapping(ctx context.Context, input types.CreateControlMesureMappingInput) (*types.CreateControlMesureMappingPayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.MesureID.TenantID())
err := svc.Controls.CreateMitigationMapping(ctx, input.ControlID, input.MitigationID)
err := svc.Controls.CreateMesureMapping(ctx, input.ControlID, input.MesureID)
if err != nil {
panic(fmt.Errorf("cannot create control mitigation mapping: %w", err))
panic(fmt.Errorf("cannot create control mesure mapping: %w", err))
}
return &types.CreateControlMitigationMappingPayload{
return &types.CreateControlMesureMappingPayload{
Success: true,
}, nil
}
@@ -611,16 +611,16 @@ func (r *mutationResolver) CreateControlPolicyMapping(ctx context.Context, input
}, nil
}
// DeleteControlMitigationMapping is the resolver for the deleteControlMitigationMapping field.
func (r *mutationResolver) DeleteControlMitigationMapping(ctx context.Context, input types.DeleteControlMitigationMappingInput) (*types.DeleteControlMitigationMappingPayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.MitigationID.TenantID())
// DeleteControlMesureMapping is the resolver for the deleteControlMesureMapping field.
func (r *mutationResolver) DeleteControlMesureMapping(ctx context.Context, input types.DeleteControlMesureMappingInput) (*types.DeleteControlMesureMappingPayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.MesureID.TenantID())
err := svc.Controls.DeleteMitigationMapping(ctx, input.ControlID, input.MitigationID)
err := svc.Controls.DeleteMesureMapping(ctx, input.ControlID, input.MesureID)
if err != nil {
panic(fmt.Errorf("cannot delete control mitigation mapping: %w", err))
panic(fmt.Errorf("cannot delete control mesure mapping: %w", err))
}
return &types.DeleteControlMitigationMappingPayload{
return &types.DeleteControlMesureMappingPayload{
Success: true,
}, nil
}
@@ -641,10 +641,10 @@ func (r *mutationResolver) DeleteControlPolicyMapping(ctx context.Context, input
// CreateTask is the resolver for the createTask field.
func (r *mutationResolver) CreateTask(ctx context.Context, input types.CreateTaskInput) (*types.CreateTaskPayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.MitigationID.TenantID())
svc := r.GetTenantServiceIfAuthorized(ctx, input.MesureID.TenantID())
task, err := svc.Tasks.Create(ctx, probo.CreateTaskRequest{
MitigationID: input.MitigationID,
MesureID: input.MesureID,
Name: input.Name,
Description: input.Description,
TimeEstimate: input.TimeEstimate,
@@ -788,30 +788,30 @@ func (r *mutationResolver) DeleteRisk(ctx context.Context, input types.DeleteRis
}, nil
}
// CreateRiskMitigationMapping is the resolver for the createRiskMitigationMapping field.
func (r *mutationResolver) CreateRiskMitigationMapping(ctx context.Context, input types.CreateRiskMitigationMappingInput) (*types.CreateRiskMitigationMappingPayload, error) {
// CreateRiskMesureMapping is the resolver for the createRiskMesureMapping field.
func (r *mutationResolver) CreateRiskMesureMapping(ctx context.Context, input types.CreateRiskMesureMappingInput) (*types.CreateRiskMesureMappingPayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.RiskID.TenantID())
err := svc.Risks.CreateMitigationMapping(ctx, input.RiskID, input.MitigationID)
err := svc.Risks.CreateMesureMapping(ctx, input.RiskID, input.MesureID)
if err != nil {
panic(fmt.Errorf("cannot create risk mitigation mapping: %w", err))
panic(fmt.Errorf("cannot create risk mesure mapping: %w", err))
}
return &types.CreateRiskMitigationMappingPayload{
return &types.CreateRiskMesureMappingPayload{
Success: true,
}, nil
}
// DeleteRiskMitigationMapping is the resolver for the deleteRiskMitigationMapping field.
func (r *mutationResolver) DeleteRiskMitigationMapping(ctx context.Context, input types.DeleteRiskMitigationMappingInput) (*types.DeleteRiskMitigationMappingPayload, error) {
// DeleteRiskMesureMapping is the resolver for the deleteRiskMesureMapping field.
func (r *mutationResolver) DeleteRiskMesureMapping(ctx context.Context, input types.DeleteRiskMesureMappingInput) (*types.DeleteRiskMesureMappingPayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.RiskID.TenantID())
err := svc.Risks.DeleteMitigationMapping(ctx, input.RiskID, input.MitigationID)
err := svc.Risks.DeleteMesureMapping(ctx, input.RiskID, input.MesureID)
if err != nil {
panic(fmt.Errorf("cannot delete risk mitigation mapping: %w", err))
panic(fmt.Errorf("cannot delete risk mesure mapping: %w", err))
}
return &types.DeleteRiskMitigationMappingPayload{
return &types.DeleteRiskMesureMappingPayload{
Success: true,
}, nil
}
@@ -1162,16 +1162,16 @@ func (r *organizationResolver) Policies(ctx context.Context, obj *types.Organiza
return types.NewPolicyConnection(page), nil
}
// Mitigations is the resolver for the mitigations field.
func (r *organizationResolver) Mitigations(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MitigationOrderBy) (*types.MitigationConnection, error) {
// Mesures is the resolver for the mesures field.
func (r *organizationResolver) Mesures(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MesureOrderBy) (*types.MesureConnection, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.MitigationOrderField]{
Field: coredata.MitigationOrderFieldCreatedAt,
pageOrderBy := page.OrderBy[coredata.MesureOrderField]{
Field: coredata.MesureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MitigationOrderField]{
pageOrderBy = page.OrderBy[coredata.MesureOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
@@ -1179,12 +1179,12 @@ func (r *organizationResolver) Mitigations(ctx context.Context, obj *types.Organ
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Mitigations.ListForOrganizationID(ctx, obj.ID, cursor)
page, err := svc.Mesures.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list organization mitigations: %w", err))
panic(fmt.Errorf("cannot list organization mesures: %w", err))
}
return types.NewMitigationConnection(page), nil
return types.NewMesureConnection(page), nil
}
// Risks is the resolver for the risks field.
@@ -1288,13 +1288,13 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
}
return types.NewFramework(framework), nil
case coredata.MitigationEntityType:
mitigation, err := svc.Mitigations.Get(ctx, id)
case coredata.MesureEntityType:
mesure, err := svc.Mesures.Get(ctx, id)
if err != nil {
panic(fmt.Errorf("cannot get mitigation: %w", err))
panic(fmt.Errorf("cannot get mesure: %w", err))
}
return types.NewMitigation(mitigation), nil
return types.NewMesure(mesure), nil
case coredata.TaskEntityType:
task, err := svc.Tasks.Get(ctx, id)
if err != nil {
@@ -1372,16 +1372,16 @@ func (r *riskResolver) Owner(ctx context.Context, obj *types.Risk) (*types.Peopl
return types.NewPeople(owner), nil
}
// Mitigations is the resolver for the mitigations field.
func (r *riskResolver) Mitigations(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MitigationOrderBy) (*types.MitigationConnection, error) {
// Mesures is the resolver for the mesures field.
func (r *riskResolver) Mesures(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MesureOrderBy) (*types.MesureConnection, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.MitigationOrderField]{
Field: coredata.MitigationOrderFieldCreatedAt,
pageOrderBy := page.OrderBy[coredata.MesureOrderField]{
Field: coredata.MesureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MitigationOrderField]{
pageOrderBy = page.OrderBy[coredata.MesureOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
@@ -1389,12 +1389,12 @@ func (r *riskResolver) Mitigations(ctx context.Context, obj *types.Risk, first *
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Mitigations.ListForRiskID(ctx, obj.ID, cursor)
page, err := svc.Mesures.ListForRiskID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list risk mitigations: %w", err))
panic(fmt.Errorf("cannot list risk mesures: %w", err))
}
return types.NewMitigationConnection(page), nil
return types.NewMesureConnection(page), nil
}
// Policies is the resolver for the policies field.
@@ -1617,8 +1617,8 @@ func (r *Resolver) Evidence() schema.EvidenceResolver { return &evidenceResolver
// Framework returns schema.FrameworkResolver implementation.
func (r *Resolver) Framework() schema.FrameworkResolver { return &frameworkResolver{r} }
// Mitigation returns schema.MitigationResolver implementation.
func (r *Resolver) Mitigation() schema.MitigationResolver { return &mitigationResolver{r} }
// Mesure returns schema.MesureResolver implementation.
func (r *Resolver) Mesure() schema.MesureResolver { return &mesureResolver{r} }
// Mutation returns schema.MutationResolver implementation.
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
@@ -1652,7 +1652,7 @@ func (r *Resolver) Viewer() schema.ViewerResolver { return &viewerResolver{r} }
type controlResolver struct{ *Resolver }
type evidenceResolver struct{ *Resolver }
type frameworkResolver struct{ *Resolver }
type mitigationResolver struct{ *Resolver }
type mesureResolver struct{ *Resolver }
type mutationResolver struct{ *Resolver }
type organizationResolver struct{ *Resolver }
type policyResolver struct{ *Resolver }