From 25c62736308073c07eff970306d514e8dc7fb42f Mon Sep 17 00:00:00 2001 From: BocognanoSarah Date: Wed, 8 Jan 2025 11:01:19 +0100 Subject: [PATCH 1/3] [frontend] Tools entity version are not fillable (#9330) --- opencti-platform/opencti-front/lang/front/de.json | 3 ++- opencti-platform/opencti-front/lang/front/en.json | 3 ++- opencti-platform/opencti-front/lang/front/es.json | 3 ++- opencti-platform/opencti-front/lang/front/fr.json | 5 +++-- opencti-platform/opencti-front/lang/front/ja.json | 3 ++- opencti-platform/opencti-front/lang/front/ko.json | 3 ++- opencti-platform/opencti-front/lang/front/zh.json | 3 ++- .../components/arsenal/tools/ToolCreation.tsx | 12 ++++++++++++ .../arsenal/tools/ToolEditionOverview.jsx | 15 +++++++++++++++ 9 files changed, 42 insertions(+), 8 deletions(-) diff --git a/opencti-platform/opencti-front/lang/front/de.json b/opencti-platform/opencti-front/lang/front/de.json index 0980573f9996..bf3ffdea05e0 100644 --- a/opencti-platform/opencti-front/lang/front/de.json +++ b/opencti-platform/opencti-front/lang/front/de.json @@ -1054,6 +1054,7 @@ "entity_Payment-Card": "Zahlungskarte", "entity_Persona": "Persona", "entity_Phone-Number": "Telefonnummer", + "entity_Playbook": "Spielbuch", "entity_Position": "Position", "entity_Process": "Prozess", "entity_Public-Dashboard": "Öffentliches Dashboard", @@ -2091,7 +2092,6 @@ "Platform under construction, subscribe to update!": "Plattform im Aufbau, Update abonnieren!", "Platforms": "Plattformen", "Playbook": "Spielbuch", - "entity_Playbook": "Spielbuch", "Playbook is running": "Playbook wird ausgeführt", "Playbook is stopped": "Playbook ist gestoppt", "Playbook successfully completed.": "Playbook erfolgreich abgeschlossen.", @@ -2798,6 +2798,7 @@ "Tool types": "Werkzeug-Typen", "Tool usage": "Verwendung des Tools", "Tool version": "Werkzeugversion", + "Tool Version": "Werkzeug-Version", "Tools": "Werkzeuge", "Tools versions": "Versionen der Werkzeuge", "Top 10": "Top 10", diff --git a/opencti-platform/opencti-front/lang/front/en.json b/opencti-platform/opencti-front/lang/front/en.json index d17e7521be39..0c60437716ea 100644 --- a/opencti-platform/opencti-front/lang/front/en.json +++ b/opencti-platform/opencti-front/lang/front/en.json @@ -1054,6 +1054,7 @@ "entity_Payment-Card": "Payment card", "entity_Persona": "Persona", "entity_Phone-Number": "Phone number", + "entity_Playbook": "Playbook", "entity_Position": "Position", "entity_Process": "Process", "entity_Public-Dashboard": "Public Dashboard", @@ -2091,7 +2092,6 @@ "Platform under construction, subscribe to update!": "Platform under construction, subscribe to update!", "Platforms": "Platforms", "Playbook": "Playbook", - "entity_Playbook": "Playbook", "Playbook is running": "Playbook is running", "Playbook is stopped": "Playbook is stopped", "Playbook successfully completed.": "Playbook successfully completed.", @@ -2798,6 +2798,7 @@ "Tool types": "Tool types", "Tool usage": "Tool usage", "Tool version": "Tool version", + "Tool Version": "Tool Version", "Tools": "Tools", "Tools versions": "Tools versions", "Top 10": "Top 10", diff --git a/opencti-platform/opencti-front/lang/front/es.json b/opencti-platform/opencti-front/lang/front/es.json index e4178307d96b..da7e6730322b 100644 --- a/opencti-platform/opencti-front/lang/front/es.json +++ b/opencti-platform/opencti-front/lang/front/es.json @@ -1054,6 +1054,7 @@ "entity_Payment-Card": "Tarjeta bancaria", "entity_Persona": "Persona", "entity_Phone-Number": "Número de teléfono", + "entity_Playbook": "Playbook", "entity_Position": "Posición", "entity_Process": "Proceso", "entity_Public-Dashboard": "Cuadro de mandos público", @@ -2091,7 +2092,6 @@ "Platform under construction, subscribe to update!": "Plataforma en construcción, ¡suscríbete para estar al día!", "Platforms": "Plataformas", "Playbook": "Playbook", - "entity_Playbook": "Playbook", "Playbook is running": "Playbook se está ejecutando", "Playbook is stopped": "Playbook está parado", "Playbook successfully completed.": "Playbook completado con éxito.", @@ -2798,6 +2798,7 @@ "Tool types": "Tipos de herramienta", "Tool usage": "Uso de la herramienta", "Tool version": "Versión de la herramienta", + "Tool Version": "Versión de la herramienta", "Tools": "Herramientas", "Tools versions": "Versiones de las herramientas", "Top 10": "Top 10", diff --git a/opencti-platform/opencti-front/lang/front/fr.json b/opencti-platform/opencti-front/lang/front/fr.json index 7255c5b681d1..39be5f98b83d 100644 --- a/opencti-platform/opencti-front/lang/front/fr.json +++ b/opencti-platform/opencti-front/lang/front/fr.json @@ -1054,6 +1054,7 @@ "entity_Payment-Card": "Carte de paiement", "entity_Persona": "Persona", "entity_Phone-Number": "Numéro de téléphone", + "entity_Playbook": "Playbook", "entity_Position": "Position", "entity_Process": "Processus", "entity_Public-Dashboard": "Tableau de bord public", @@ -2091,7 +2092,6 @@ "Platform under construction, subscribe to update!": "Plateforme en cours de construction, abonnez-vous pour être mis à jour !", "Platforms": "Systèmes d'exploitation", "Playbook": "Playbook", - "entity_Playbook": "Playbook", "Playbook is running": "Le Playbook est en cours d'exécution", "Playbook is stopped": "Playbook est arrêté", "Playbook successfully completed.": "Playbook terminé avec succès.", @@ -2798,6 +2798,7 @@ "Tool types": "Types d'outil", "Tool usage": "Utilisation de cet outil", "Tool version": "Version de l'outil", + "Tool Version": "Version de l'outil", "Tools": "Outils", "Tools versions": "Versions des outils", "Top 10": "Top 10", @@ -3130,7 +3131,7 @@ "You must provide at least one external reference for this type of entity": "Vous devez fournir au moins une référence externe pour ce type d'entité", "You need a confidence level to edit objects in the platform.": "Vous avez besoin d'un niveau de confiance pour éditer des objets sur la plateforme.", "You need to activate a two-factor authentication. Please type the code generated in your application.": "Vous devez activer une authentification à deux facteurs. Veuillez saisir le code généré dans votre application.", - "You need to activate OpenCTI Enterprise Edition to use this feature.": "Vous devez activer activer l'édition Enterprise d'OpenCTI pour utiliser cette fonctionnalité.", + "You need to activate OpenCTI enterprise edition to use this feature.": "Vous devez activer OpenCTI enterprise edition pour utiliser cette fonctionnalité.", "You need to validate your two-factor authentication. Please type the code generated in your application": "Vous devez valider votre authentification à deux facteurs. Veuillez saisir le code généré dans votre application.", "You see only marking definitions that can be shared (defined by the admin)": "Vous ne voyez que les définitions de marquage qui peuvent être partagées (définies par l'administrateur)", "You will be automatically logged out at end of the timer.": "Vous serez automatiquement déconnecté à la fin du décompte.", diff --git a/opencti-platform/opencti-front/lang/front/ja.json b/opencti-platform/opencti-front/lang/front/ja.json index f9183794fcd1..0dc580aae3c6 100644 --- a/opencti-platform/opencti-front/lang/front/ja.json +++ b/opencti-platform/opencti-front/lang/front/ja.json @@ -1054,6 +1054,7 @@ "entity_Payment-Card": "クレジットカード番号", "entity_Persona": "ペルソナ", "entity_Phone-Number": "電話番号", + "entity_Playbook": "プレイブック", "entity_Position": "位置", "entity_Process": "プロセス", "entity_Public-Dashboard": "パブリック・ダッシュボード", @@ -2091,7 +2092,6 @@ "Platform under construction, subscribe to update!": "プラットフォームは構築中です!", "Platforms": "プラットフォーム", "Playbook": "プレイブック", - "entity_Playbook": "プレイブック", "Playbook is running": "プレイブック実行中", "Playbook is stopped": "プレイブック停止中", "Playbook successfully completed.": "プレイブックは正常に終了しました。", @@ -2798,6 +2798,7 @@ "Tool types": "ツール種別", "Tool usage": "ツールの使い方", "Tool version": "ツールバージョン", + "Tool Version": "ツールバージョン", "Tools": "ツール", "Tools versions": "ツールバージョン", "Top 10": "トップ10", diff --git a/opencti-platform/opencti-front/lang/front/ko.json b/opencti-platform/opencti-front/lang/front/ko.json index 92feea53ca94..3a13f8f5c3c9 100644 --- a/opencti-platform/opencti-front/lang/front/ko.json +++ b/opencti-platform/opencti-front/lang/front/ko.json @@ -1054,6 +1054,7 @@ "entity_Payment-Card": "결제 카드", "entity_Persona": "entity_Persona", "entity_Phone-Number": "전화번호", + "entity_Playbook": "플레이북", "entity_Position": "위치", "entity_Process": "프로세스", "entity_Public-Dashboard": "공개 대시보드", @@ -2091,7 +2092,6 @@ "Platform under construction, subscribe to update!": "플랫폼이 구축 중입니다. 업데이트를 구독하세요!", "Platforms": "플랫폼", "Playbook": "플레이북", - "entity_Playbook": "플레이북", "Playbook is running": "플레이북이 실행 중입니다", "Playbook is stopped": "플레이북이 중지되었습니다", "Playbook successfully completed.": "플레이북이 성공적으로 완료되었습니다.", @@ -2798,6 +2798,7 @@ "Tool types": "도구 유형", "Tool usage": "도구 사용", "Tool version": "도구 버전", + "Tool Version": "도구 버전", "Tools": "도구", "Tools versions": "도구 버전", "Top 10": "상위 10", diff --git a/opencti-platform/opencti-front/lang/front/zh.json b/opencti-platform/opencti-front/lang/front/zh.json index cb8dd67d7900..eff71a48424c 100644 --- a/opencti-platform/opencti-front/lang/front/zh.json +++ b/opencti-platform/opencti-front/lang/front/zh.json @@ -1054,6 +1054,7 @@ "entity_Payment-Card": "支付卡", "entity_Persona": "人格面具", "entity_Phone-Number": "电话号码", + "entity_Playbook": "剧本", "entity_Position": "位置", "entity_Process": "进程", "entity_Public-Dashboard": "公共仪表板", @@ -2091,7 +2092,6 @@ "Platform under construction, subscribe to update!": "平台正在建设中,请订阅更新!", "Platforms": "平台", "Playbook": "剧本", - "entity_Playbook": "剧本", "Playbook is running": "剧本正在运行", "Playbook is stopped": "剧本已停止", "Playbook successfully completed.": "播放簿已成功完成。", @@ -2798,6 +2798,7 @@ "Tool types": "工具类型", "Tool usage": "工具用法", "Tool version": "工具版本", + "Tool Version": "工具版本", "Tools": "攻击工具", "Tools versions": "工具版本", "Top 10": "前十名", diff --git a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolCreation.tsx b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolCreation.tsx index 45b76f59fb25..51d50ea6c4a0 100644 --- a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolCreation.tsx +++ b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolCreation.tsx @@ -33,6 +33,7 @@ import BulkTextModal from '../../../../components/fields/BulkTextField/BulkTextM import ProgressBar from '../../../../components/ProgressBar'; import BulkTextField from '../../../../components/fields/BulkTextField/BulkTextField'; import BulkTextModalButton from '../../../../components/fields/BulkTextField/BulkTextModalButton'; +import TextField from '../../../../components/TextField'; const toolMutation = graphql` mutation ToolCreationMutation($input: ToolAddInput!) { @@ -59,6 +60,7 @@ interface ToolAddInput { objectLabel: Option[] externalReferences: { value: string }[] tool_types: string[] + tool_version: string confidence: number | null file: File | null } @@ -94,6 +96,7 @@ export const ToolCreationForm: FunctionComponent = ({ description: Yup.string().nullable(), confidence: Yup.number().nullable(), tool_types: Yup.array().nullable(), + tool_version: Yup.string().nullable(), }; const toolValidator = useSchemaCreationValidation(TOOL_TYPE, basicShape); @@ -137,6 +140,7 @@ export const ToolCreationForm: FunctionComponent = ({ killChainPhases: (values.killChainPhases ?? []).map(({ value }) => value), objectLabel: values.objectLabel.map((v) => v.value), tool_types: values.tool_types, + tool_version: values.tool_version, confidence: parseInt(String(values.confidence), 10), externalReferences: values.externalReferences.map(({ value }) => value), file: values.file, @@ -169,6 +173,7 @@ export const ToolCreationForm: FunctionComponent = ({ objectLabel: [], externalReferences: [], tool_types: [], + tool_version: '', confidence: defaultConfidence ?? null, file: null, }, @@ -260,6 +265,13 @@ export const ToolCreationForm: FunctionComponent = ({ containerStyle={fieldSpacingContainerStyle} onChange={setFieldValue} /> + { description: Yup.string().nullable(), confidence: Yup.number().nullable(), tool_types: Yup.array().nullable(), + tool_version: Yup.string().nullable(), references: Yup.array(), x_opencti_workflow_id: Yup.object(), }; @@ -112,6 +113,7 @@ const ToolEditionOverviewComponent = (props) => { R.assoc('objectMarking', R.pluck('value', values.objectMarking)), R.assoc('killChainPhases', R.pluck('value', values.killChainPhases)), R.assoc('tool_types', values.tool_types), + R.assoc('tool_version', values.tool_version), R.assoc('x_opencti_workflow_id', values.x_opencti_workflow_id?.value), R.toPairs, R.map((n) => ({ @@ -160,6 +162,7 @@ const ToolEditionOverviewComponent = (props) => { R.assoc('objectMarking', convertMarkings(tool)), R.assoc('x_opencti_workflow_id', convertStatus(t_i18n, tool)), R.assoc('tool_types', tool.tool_types ?? []), + R.assoc('tool_version', tool.tool_version), R.assoc('references', []), R.pick([ 'name', @@ -278,6 +281,18 @@ const ToolEditionOverviewComponent = (props) => { multiple={true} editContext={context} /> + + } + /> {enableReferences && ( Date: Mon, 13 Jan 2025 18:07:50 +0100 Subject: [PATCH 2/3] [frontend] pr comments and refacto --- .../private/components/arsenal/tools/Tool.tsx | 2 +- .../components/arsenal/tools/ToolDetails.jsx | 112 ------ .../components/arsenal/tools/ToolDetails.tsx | 108 ++++++ .../arsenal/tools/ToolEditionOverview.jsx | 353 ------------------ .../arsenal/tools/ToolEditionOverview.tsx | 344 +++++++++++++++++ 5 files changed, 453 insertions(+), 466 deletions(-) delete mode 100644 opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolDetails.jsx create mode 100644 opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolDetails.tsx delete mode 100644 opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.jsx create mode 100644 opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.tsx diff --git a/opencti-platform/opencti-front/src/private/components/arsenal/tools/Tool.tsx b/opencti-platform/opencti-front/src/private/components/arsenal/tools/Tool.tsx index 6520fbd9682a..3d315695b940 100644 --- a/opencti-platform/opencti-front/src/private/components/arsenal/tools/Tool.tsx +++ b/opencti-platform/opencti-front/src/private/components/arsenal/tools/Tool.tsx @@ -90,7 +90,7 @@ const Tool: React.FC = ({ toolData }) => { case 'details': return ( - + ); case 'basicInformation': diff --git a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolDetails.jsx b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolDetails.jsx deleted file mode 100644 index 9eac0c4167f8..000000000000 --- a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolDetails.jsx +++ /dev/null @@ -1,112 +0,0 @@ -import React, { Component } from 'react'; -import * as PropTypes from 'prop-types'; -import * as R from 'ramda'; -import { createFragmentContainer, graphql } from 'react-relay'; -import withStyles from '@mui/styles/withStyles'; -import Paper from '@mui/material/Paper'; -import List from '@mui/material/List'; -import ListItem from '@mui/material/ListItem'; -import ListItemText from '@mui/material/ListItemText'; -import Typography from '@mui/material/Typography'; -import Grid from '@mui/material/Grid'; -import inject18n from '../../../../components/i18n'; -import ExpandableMarkdown from '../../../../components/ExpandableMarkdown'; -import ItemOpenVocab from '../../../../components/ItemOpenVocab'; -import StixCoreObjectKillChainPhasesView from '../../common/stix_core_objects/StixCoreObjectKillChainPhasesView'; - -const styles = (theme) => ({ - paper: { - marginTop: theme.spacing(1), - padding: '15px', - borderRadius: 4, - }, - chip: { - fontSize: 12, - lineHeight: '12px', - backgroundColor: theme.palette.background.accent, - color: theme.palette.text.primary, - textTransform: 'uppercase', - borderRadius: 4, - margin: '0 5px 5px 0', - }, -}); - -class ToolDetailsComponent extends Component { - render() { - const { t, classes, tool } = this.props; - return ( -
- - {t('Details')} - - - - - - {t('Description')} - - - - {t('Tool version')} - - {tool.tool_version ?? '-'} - - - - {t('Tool types')} - - {(tool.tool_types && tool.tool_types.length > 0) ? ( - - {tool.tool_types.map((tool_type) => ( - - - } - /> - - ))} - - ) : ('-')} - - - - -
- ); - } -} - -ToolDetailsComponent.propTypes = { - tool: PropTypes.object, - classes: PropTypes.object, - t: PropTypes.func, - fld: PropTypes.func, -}; - -const ToolDetails = createFragmentContainer(ToolDetailsComponent, { - tool: graphql` - fragment ToolDetails_tool on Tool { - id - description - tool_version - tool_types - killChainPhases { - id - entity_type - kill_chain_name - phase_name - x_opencti_order - } - } - `, -}); - -export default R.compose(inject18n, withStyles(styles))(ToolDetails); diff --git a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolDetails.tsx b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolDetails.tsx new file mode 100644 index 000000000000..056c8273682d --- /dev/null +++ b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolDetails.tsx @@ -0,0 +1,108 @@ +import React, { FunctionComponent } from 'react'; +import { graphql, useFragment } from 'react-relay'; +import Paper from '@mui/material/Paper'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemText from '@mui/material/ListItemText'; +import Typography from '@mui/material/Typography'; +import Grid from '@mui/material/Grid'; +import Tooltip from '@mui/material/Tooltip'; +import makeStyles from '@mui/styles/makeStyles'; +import { ToolDetails_tool$key } from '@components/arsenal/tools/__generated__/ToolDetails_tool.graphql'; +import ExpandableMarkdown from '../../../../components/ExpandableMarkdown'; +import ItemOpenVocab from '../../../../components/ItemOpenVocab'; +import StixCoreObjectKillChainPhasesView from '../../common/stix_core_objects/StixCoreObjectKillChainPhasesView'; +import { truncate } from '../../../../utils/String'; +import FieldOrEmpty from '../../../../components/FieldOrEmpty'; +import { useFormatter } from '../../../../components/i18n'; +import type { Theme } from '../../../../components/Theme'; + +const useStyles = makeStyles((theme) => ({ + paper: { + marginTop: theme.spacing(1), + padding: '15px', + borderRadius: 4, + }, +})); + +const ToolDetailsFragment = graphql` + fragment ToolDetails_tool on Tool { + id + description + tool_version + tool_types + killChainPhases { + id + entity_type + kill_chain_name + phase_name + x_opencti_order + } + } +`; + +interface ToolDetailsProps { + tools: ToolDetails_tool$key; +} + +const ToolDetails: FunctionComponent = ({ tools }) => { + const { t_i18n } = useFormatter(); + const classes = useStyles(); + const tool = useFragment( + ToolDetailsFragment, + tools, + ); + return ( +
+ + {t_i18n('Details')} + + + + + + {t_i18n('Description')} + + + + {t_i18n('Tool version')} + + + + {truncate(tool.tool_version, 20)} + + + + + + {t_i18n('Tool types')} + + {(tool.tool_types && tool.tool_types.length > 0) ? ( + + {tool.tool_types.map((tool_type) => ( + + + } + /> + + ))} + + ) : ('-')} + + + + +
+ ); +}; + +export default ToolDetails; diff --git a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.jsx b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.jsx deleted file mode 100644 index e511e07f2280..000000000000 --- a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.jsx +++ /dev/null @@ -1,353 +0,0 @@ -import React from 'react'; -import { createFragmentContainer, graphql } from 'react-relay'; -import { Field, Form, Formik } from 'formik'; -import * as R from 'ramda'; -import * as Yup from 'yup'; -import { useFormatter } from '../../../../components/i18n'; -import TextField from '../../../../components/TextField'; -import { SubscriptionFocus } from '../../../../components/Subscription'; -import KillChainPhasesField from '../../common/form/KillChainPhasesField'; -import CreatedByField from '../../common/form/CreatedByField'; -import ObjectMarkingField from '../../common/form/ObjectMarkingField'; -import MarkdownField from '../../../../components/fields/MarkdownField'; -import CommitMessage from '../../common/form/CommitMessage'; -import { adaptFieldValue } from '../../../../utils/String'; -import StatusField from '../../common/form/StatusField'; -import { convertCreatedBy, convertKillChainPhases, convertMarkings, convertStatus } from '../../../../utils/edition'; -import { fieldSpacingContainerStyle } from '../../../../utils/field'; -import OpenVocabField from '../../common/form/OpenVocabField'; -import ConfidenceField from '../../common/form/ConfidenceField'; -import { useSchemaEditionValidation } from '../../../../utils/hooks/useEntitySettings'; -import useFormEditor from '../../../../utils/hooks/useFormEditor'; -import AlertConfidenceForEntity from '../../../../components/AlertConfidenceForEntity'; - -const toolMutationFieldPatch = graphql` - mutation ToolEditionOverviewFieldPatchMutation( - $id: ID! - $input: [EditInput]! - $commitMessage: String - $references: [String] - ) { - toolEdit(id: $id) { - fieldPatch( - input: $input - commitMessage: $commitMessage - references: $references - ) { - ...ToolEditionOverview_tool - ...Tool_tool - } - } - } -`; - -export const toolEditionOverviewFocus = graphql` - mutation ToolEditionOverviewFocusMutation($id: ID!, $input: EditContext!) { - toolEdit(id: $id) { - contextPatch(input: $input) { - id - } - } - } -`; - -const toolMutationRelationAdd = graphql` - mutation ToolEditionOverviewRelationAddMutation( - $id: ID! - $input: StixRefRelationshipAddInput! - ) { - toolEdit(id: $id) { - relationAdd(input: $input) { - from { - ...ToolEditionOverview_tool - } - } - } - } -`; - -const toolMutationRelationDelete = graphql` - mutation ToolEditionOverviewRelationDeleteMutation( - $id: ID! - $toId: StixRef! - $relationship_type: String! - ) { - toolEdit(id: $id) { - relationDelete(toId: $toId, relationship_type: $relationship_type) { - ...ToolEditionOverview_tool - } - } - } -`; - -const ToolEditionOverviewComponent = (props) => { - const { tool, enableReferences, context, handleClose } = props; - const { t_i18n } = useFormatter(); - - const basicShape = { - name: Yup.string().trim().min(2).required(t_i18n('This field is required')), - description: Yup.string().nullable(), - confidence: Yup.number().nullable(), - tool_types: Yup.array().nullable(), - tool_version: Yup.string().nullable(), - references: Yup.array(), - x_opencti_workflow_id: Yup.object(), - }; - const toolValidator = useSchemaEditionValidation('Tool', basicShape); - - const queries = { - fieldPatch: toolMutationFieldPatch, - relationAdd: toolMutationRelationAdd, - relationDelete: toolMutationRelationDelete, - editionFocus: toolEditionOverviewFocus, - }; - const editor = useFormEditor(tool, enableReferences, queries, toolValidator); - - const onSubmit = (values, { setSubmitting }) => { - const commitMessage = values.message; - const references = R.pluck('value', values.references || []); - const inputValues = R.pipe( - R.dissoc('message'), - R.dissoc('references'), - R.assoc('createdBy', values.createdBy?.value), - R.assoc('objectMarking', R.pluck('value', values.objectMarking)), - R.assoc('killChainPhases', R.pluck('value', values.killChainPhases)), - R.assoc('tool_types', values.tool_types), - R.assoc('tool_version', values.tool_version), - R.assoc('x_opencti_workflow_id', values.x_opencti_workflow_id?.value), - R.toPairs, - R.map((n) => ({ - key: n[0], - value: adaptFieldValue(n[1]), - })), - )(values); - editor.fieldPatch({ - variables: { - id: tool.id, - input: inputValues, - commitMessage: - commitMessage && commitMessage.length > 0 ? commitMessage : null, - references, - }, - onCompleted: () => { - setSubmitting(false); - handleClose(); - }, - }); - }; - - const handleSubmitField = (name, value) => { - if (!enableReferences) { - let finalValue = value; - if (name === 'x_opencti_workflow_id') { - finalValue = value.value; - } - toolValidator - .validateAt(name, { [name]: value }) - .then(() => { - editor.fieldPatch({ - variables: { - id: tool.id, - input: { key: name, value: finalValue }, - }, - }); - }) - .catch(() => false); - } - }; - - const initialValues = R.pipe( - R.assoc('createdBy', convertCreatedBy(tool)), - R.assoc('killChainPhases', convertKillChainPhases(tool)), - R.assoc('objectMarking', convertMarkings(tool)), - R.assoc('x_opencti_workflow_id', convertStatus(t_i18n, tool)), - R.assoc('tool_types', tool.tool_types ?? []), - R.assoc('tool_version', tool.tool_version), - R.assoc('references', []), - R.pick([ - 'name', - 'references', - 'description', - 'createdBy', - 'killChainPhases', - 'objectMarking', - 'x_opencti_workflow_id', - 'tool_types', - 'confidence', - ]), - )(tool); - return ( - - {({ - submitForm, - isSubmitting, - setFieldValue, - values, - isValid, - dirty, - }) => ( -
- - - } - /> - - } - /> - - - } - onChange={editor.changeKillChainPhases} - /> - {tool.workflowEnabled && ( - - } - /> - )} - - } - onChange={editor.changeCreated} - /> - - } - setFieldValue={setFieldValue} - onChange={editor.changeMarking} - /> - setFieldValue(name, value)} - containerStyle={fieldSpacingContainerStyle} - variant="edit" - multiple={true} - editContext={context} - /> - - } - /> - {enableReferences && ( - - )} - - )} -
- ); -}; - -export default createFragmentContainer(ToolEditionOverviewComponent, { - tool: graphql` - fragment ToolEditionOverview_tool on Tool { - id - name - description - tool_types - confidence - entity_type - createdBy { - ... on Identity { - id - name - entity_type - } - } - killChainPhases { - id - entity_type - kill_chain_name - phase_name - x_opencti_order - } - objectMarking { - id - definition_type - definition - x_opencti_order - x_opencti_color - } - status { - id - order - template { - name - color - } - } - workflowEnabled - } - `, -}); diff --git a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.tsx b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.tsx new file mode 100644 index 000000000000..9a887bbbdff3 --- /dev/null +++ b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.tsx @@ -0,0 +1,344 @@ +import React, { FunctionComponent } from 'react'; +import { graphql, useFragment } from 'react-relay'; +import { Field, Form, Formik } from 'formik'; +import * as Yup from 'yup'; +import { FormikConfig } from 'formik/dist/types'; +import { GenericContext } from '@components/common/model/GenericContextModel'; +import { useTheme } from '@mui/styles'; +import TextField from '../../../../components/TextField'; +import { SubscriptionFocus } from '../../../../components/Subscription'; +import CreatedByField from '../../common/form/CreatedByField'; +import ObjectMarkingField from '../../common/form/ObjectMarkingField'; +import CommitMessage from '../../common/form/CommitMessage'; +import { adaptFieldValue } from '../../../../utils/String'; +import StatusField from '../../common/form/StatusField'; +import { convertCreatedBy, convertKillChainPhases, convertMarkings, convertStatus } from '../../../../utils/edition'; +import { useFormatter } from '../../../../components/i18n'; +import { Option } from '../../common/form/ReferenceField'; +import { ToolEditionOverview_tool$key as Tool$key } from './__generated__/ToolEditionOverview_tool.graphql'; +import KillChainPhasesField from '../../common/form/KillChainPhasesField'; +import OpenVocabField from '../../common/form/OpenVocabField'; +import ConfidenceField from '../../common/form/ConfidenceField'; +import useFormEditor, { GenericData } from '../../../../utils/hooks/useFormEditor'; +import AlertConfidenceForEntity from '../../../../components/AlertConfidenceForEntity'; +import { useSchemaEditionValidation } from '../../../../utils/hooks/useEntitySettings'; +import type { Theme } from '../../../../components/Theme'; +import { fieldSpacingContainerStyle } from '../../../../utils/field'; + +const toolMutationFieldPatch = graphql` + mutation ToolEditionOverviewFieldPatchMutation( + $id: ID! + $input: [EditInput]! + $commitMessage: String + $references: [String] + ) { + toolEdit(id: $id) { + fieldPatch( + input: $input + commitMessage: $commitMessage + references: $references + ) { + ...ToolEditionOverview_tool + } + } + } +`; + +const toolEditionOverviewFocus = graphql` + mutation ToolEditionOverviewFocusMutation($id: ID!, $input: EditContext!) { + toolEdit(id: $id) { + contextPatch(input: $input) { + id + } + } + } +`; + +const toolMutationRelationAdd = graphql` + mutation ToolEditionOverviewRelationAddMutation( + $id: ID! + $input: StixRefRelationshipAddInput! + ) { + stixDomainObjectEdit(id: $id) { + relationAdd(input: $input) { + from { + ...ToolEditionOverview_tool + } + } + } + } +`; + +const toolMutationRelationDelete = graphql` + mutation ToolEditionOverviewRelationDeleteMutation( + $id: ID! + $toId: StixRef! + $relationship_type: String! + ) { + stixDomainObjectEdit(id: $id) { + relationDelete(toId: $toId, relationship_type: $relationship_type) { + ...ToolEditionOverview_tool + } + } + } +`; + +const ToolEditionOverviewFragment = graphql` + fragment ToolEditionOverview_tool on Tool { + id + name + description + tool_types + tool_version + confidence + createdBy { + ... on Identity { + id + name + entity_type + } + } + killChainPhases { + id + phase_name + } + objectMarking { + id + definition + } + status { + id + template { + name + } + } + workflowEnabled + } +`; + +interface ToolEditionOverviewProps { + toolRef: Tool$key; + context?: readonly (GenericContext | null)[] | null; + enableReferences?: boolean; + handleClose: () => void; +} + +interface ToolEditionFormValues { + name?: string; + description?: string; + tool_version?: string; + createdBy?: Option + killChainPhases?: Option[]; + objectMarking?: Option[]; + x_opencti_workflow_id?: Option + references: Option[]; + message?: string; +} + +const ToolEditionOverview: FunctionComponent = ({ + toolRef, + context, + enableReferences = false, + handleClose, +}) => { + const { t_i18n } = useFormatter(); + const theme = useTheme(); + + const tool = useFragment(ToolEditionOverviewFragment, toolRef); + + const toolValidator = useSchemaEditionValidation('Tool', { + name: Yup.string().min(2).required(t_i18n('This field is required')), + description: Yup.string().nullable(), + confidence: Yup.number().nullable(), + tool_types: Yup.array().nullable(), + tool_version: Yup.string().nullable(), + x_opencti_workflow_id: Yup.object().nullable(), + references: Yup.array().nullable(), + }); + + const queries = { + fieldPatch: toolMutationFieldPatch, + relationAdd: toolMutationRelationAdd, + relationDelete: toolMutationRelationDelete, + editionFocus: toolEditionOverviewFocus, + }; + + const editor = useFormEditor( + tool as GenericData, + enableReferences, + queries, + toolValidator, + ); + + const handleSubmitField = (name: string, value: Option[] | string) => { + if (!enableReferences) { + toolValidator + .validateAt(name, { [name]: value }) + .then(() => { + editor.fieldPatch({ + variables: { + id: tool.id, + input: [ + { + key: name, + value: Array.isArray(value) + ? value.map((o) => (o as Option).value) + : value, + }, + ], + }, + }); + }) + .catch(() => false); + } + }; + + const onSubmit: FormikConfig['onSubmit'] = (values, { setSubmitting }) => { + const { message, references, ...otherValues } = values; + const commitMessage = message ?? ''; + const commitReferences = (references ?? []).map(({ value }) => value); + + const inputValues = Object.entries({ + ...otherValues, + createdBy: values.createdBy?.value, + killChainPhases: values.killChainPhases?.map(({ value }) => value), + objectMarking: values.objectMarking?.map(({ value }) => value), + x_opencti_workflow_id: values.x_opencti_workflow_id?.value, + }).map(([key, value]) => ({ key, value: adaptFieldValue(value) })); + + editor.fieldPatch({ + variables: { + id: tool.id, + input: inputValues, + commitMessage: commitMessage.length > 0 ? commitMessage : null, + references: commitReferences, + }, + onCompleted: () => { + setSubmitting(false); + handleClose(); + }, + }); + }; + + const createdBy = convertCreatedBy(tool); + const status = convertStatus(tool); + + const initialValues = { + name: tool.name, + description: tool.description ?? '', + confidence: tool.confidence, + tool_types: tool.tool_types ?? [], + tool_version: tool.tool_version ?? '', + createdBy: createdBy as Option, + killChainPhases: convertKillChainPhases(tool), + objectMarking: convertMarkings(tool), + x_opencti_workflow_id: status as Option, + references: [], + }; + + return ( + + enableReinitialize={true} + initialValues={initialValues} + validationSchema={toolValidator} + onSubmit={onSubmit} + > + {({ submitForm, isSubmitting, setFieldValue, values }) => ( +
+ + } + /> + } + /> + + } + onChange={editor.changeField} + /> + {tool.workflowEnabled && ( + } + /> + )} + } + onChange={editor.changeField} + /> + } + onChange={editor.changeField} + /> + handleSubmitField(name, value as string)} + onChange={(name, value) => setFieldValue(name, value)} + containerStyle={fieldSpacingContainerStyle} + multiple + /> + } + /> + {enableReferences && ( + + )} + + )} + + ); +}; + +export default ToolEditionOverview; From ff3391219b341af9127ff0230d867eeba0dc6884 Mon Sep 17 00:00:00 2001 From: BocognanoSarah Date: Tue, 14 Jan 2025 10:33:57 +0100 Subject: [PATCH 3/3] [frontend] deepscan --- .../components/arsenal/tools/ToolEditionContainer.jsx | 2 +- .../components/arsenal/tools/ToolEditionOverview.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionContainer.jsx b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionContainer.jsx index bf549b5c7705..dbea20bb344b 100644 --- a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionContainer.jsx +++ b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionContainer.jsx @@ -24,7 +24,7 @@ const ToolEditionContainer = (props) => { controlledDial={isFABReplaced ? controlledDial : undefined} >