From a82850cb647ba5f12c6608ac9c48df7b9f372451 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 30 Jun 2021 14:13:01 +0300 Subject: [PATCH 1/3] Add ransomware directories property to UISchema object This addition is required to manipulate the UI components in ransomware configuration UI without the need to create object's properties. Otherwise we'd have to create ransomware.encryption.directories in UI schema using code. --- .../ui/src/components/configuration-components/UiSchema.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js b/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js index ac9104817..79dced094 100644 --- a/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js +++ b/monkey/monkey_island/cc/ui/src/components/configuration-components/UiSchema.js @@ -71,6 +71,13 @@ export default function UiSchema(props) { } } }, + ransomware: { + encryption: { + directories: { + // Directory inputs are dynamically hidden + } + } + }, internal: { general: { started_on_island: {'ui:widget': 'hidden'} From 889df554ae875f6b309db9f3565b57c56c3ca16d Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 30 Jun 2021 14:24:27 +0300 Subject: [PATCH 2/3] Refactor form data in ConfigurePage.js to be held in state This change will allow dynamically modifying other state parameters and re-rendering on form data change --- .../ui/src/components/pages/ConfigurePage.js | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js b/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js index ed827401b..19dae5fbc 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js @@ -27,7 +27,6 @@ class ConfigurePageComponent extends AuthComponent { constructor(props) { super(props); this.currentSection = 'attack'; - this.currentFormData = {}; this.initialConfig = {}; this.initialAttackConfig = {}; this.sectionsOrder = ['attack', 'basic', 'basic_network', 'ransomware', 'monkey', 'internal']; @@ -35,6 +34,7 @@ class ConfigurePageComponent extends AuthComponent { this.state = { attackConfig: {}, configuration: {}, + currentFormData: {}, importCandidateConfig: null, lastAction: 'none', schema: {}, @@ -213,14 +213,15 @@ class ConfigurePageComponent extends AuthComponent { }; onChange = ({formData}) => { - this.currentFormData = formData; + let configuration = this.state.configuration; + configuration[this.state.selectedSection] = formData; + this.setState({currentFormData: formData, configuration: configuration}); }; updateConfigSection = () => { let newConfig = this.state.configuration; - if (Object.keys(this.currentFormData).length > 0) { - newConfig[this.currentSection] = this.currentFormData; - this.currentFormData = {}; + if (Object.keys(this.state.currentFormData).length > 0) { + newConfig[this.currentSection] = this.state.currentFormData; } this.setState({configuration: newConfig, lastAction: 'none'}); }; @@ -295,8 +296,8 @@ class ConfigurePageComponent extends AuthComponent { userChangedConfig() { if (JSON.stringify(this.state.configuration) === JSON.stringify(this.initialConfig)) { - if (Object.keys(this.currentFormData).length === 0 || - JSON.stringify(this.initialConfig[this.currentSection]) === JSON.stringify(this.currentFormData)) { + if (Object.keys(this.state.currentFormData).length === 0 || + JSON.stringify(this.initialConfig[this.currentSection]) === JSON.stringify(this.state.currentFormData)) { return false; } } @@ -316,7 +317,8 @@ class ConfigurePageComponent extends AuthComponent { this.updateConfigSection(); this.currentSection = key; this.setState({ - selectedSection: key + selectedSection: key, + currentFormData: this.state.configuration[key] }); }; @@ -332,7 +334,8 @@ class ConfigurePageComponent extends AuthComponent { this.setState({ lastAction: 'reset', schema: res.schema, - configuration: res.configuration + configuration: res.configuration, + currentFormData: res.configuration[this.state.selectedSection] }); this.setInitialConfig(res.configuration); this.props.onStatusChange(); @@ -407,7 +410,7 @@ class ConfigurePageComponent extends AuthComponent { setPbaFilenameLinux: this.setPbaFilenameLinux, selectedSection: this.state.selectedSection }) - formProperties['formData'] = this.state.configuration[this.state.selectedSection]; + formProperties['formData'] = this.state.currentFormData; formProperties['onChange'] = this.onChange; formProperties['customFormats'] = formValidationFormats; formProperties['transformErrors'] = transformErrors; From 16f97f2811472d7a0ca9e6c83276dad13cd73c9a Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 30 Jun 2021 15:53:40 +0300 Subject: [PATCH 3/3] Hide the input fields for directories to be encrypted if "Should encrypt" option is disabled This change will enhance the UX by hiding the irrelevant inputs. This also allows us to add further logic to dynamically hide/show or otherwise modify uiSchema --- .../UISchemaManipulators.tsx | 21 +++++++++++++++++++ .../ui/src/components/pages/ConfigurePage.js | 5 +++++ 2 files changed, 26 insertions(+) create mode 100644 monkey/monkey_island/cc/ui/src/components/configuration-components/UISchemaManipulators.tsx diff --git a/monkey/monkey_island/cc/ui/src/components/configuration-components/UISchemaManipulators.tsx b/monkey/monkey_island/cc/ui/src/components/configuration-components/UISchemaManipulators.tsx new file mode 100644 index 000000000..637a128f3 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/configuration-components/UISchemaManipulators.tsx @@ -0,0 +1,21 @@ + +const manipulatorList = [ransomwareDirManipulator] + +function applyUiSchemaManipulators(selectedSection, + formData, + uiSchema) { + for(let i = 0; i < manipulatorList.length; i++){ + manipulatorList[i](selectedSection, formData, uiSchema); + } +} + +function ransomwareDirManipulator(selectedSection, + formData, + uiSchema) { + if (selectedSection === 'ransomware'){ + uiSchema.encryption.directories = + {'ui:disabled': !formData['encryption']['enabled']}; + } +} + +export default applyUiSchemaManipulators; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js b/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js index 19dae5fbc..310555408 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js @@ -16,6 +16,7 @@ import UnsafeOptionsWarningModal from '../configuration-components/UnsafeOptions import isUnsafeOptionSelected from '../utils/SafeOptionValidator.js'; import ConfigExportModal from '../configuration-components/ExportConfigModal'; import ConfigImportModal from '../configuration-components/ImportConfigModal'; +import applyUiSchemaManipulators from '../configuration-components/UISchemaManipulators.tsx'; const ATTACK_URL = '/api/attack'; const CONFIG_URL = '/api/configuration/island'; @@ -417,6 +418,10 @@ class ConfigurePageComponent extends AuthComponent { formProperties['className'] = 'config-form'; formProperties['liveValidate'] = true; + applyUiSchemaManipulators(this.state.selectedSection, + formProperties['formData'], + formProperties['uiSchema']); + if (this.state.selectedSection === 'internal') { return () } else {