From 46de8000c1acf9eec0bbd871c153cb67e6598975 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Wed, 21 Oct 2020 12:15:16 +0300 Subject: [PATCH] Fixed and moved AWS run components into a separate folder --- .../pages/RunMonkeyPage/AwsRunTable.js | 109 ---------------- .../RunOnAWS/AWSInstanceTable.js | 119 ++++++++++++++++++ .../{ => RunOnAWS}/AWSRunButton.js | 12 +- .../AWSRunOptions.js} | 43 ++++--- .../cc/ui/src/styles/pages/MonkeyRunPage.scss | 5 + 5 files changed, 156 insertions(+), 132 deletions(-) delete mode 100644 monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/AwsRunTable.js create mode 100644 monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSInstanceTable.js rename monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/{ => RunOnAWS}/AWSRunButton.js (86%) rename monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/{AWSRunInstances.js => RunOnAWS/AWSRunOptions.js} (75%) diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/AwsRunTable.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/AwsRunTable.js deleted file mode 100644 index 8c7ccf490..000000000 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/AwsRunTable.js +++ /dev/null @@ -1,109 +0,0 @@ -import React from 'react'; -import ReactTable from 'react-table' -import checkboxHOC from 'react-table/lib/hoc/selectTable'; - -const CheckboxTable = checkboxHOC(ReactTable); - -const columns = [ - { - Header: 'Machines', - columns: [ - {Header: 'Machine', accessor: 'name'}, - {Header: 'Instance ID', accessor: 'instance_id'}, - {Header: 'IP Address', accessor: 'ip_address'}, - {Header: 'OS', accessor: 'os'} - ] - } -]; - -const pageSize = 10; - -class AwsRunTableComponent extends React.Component { - constructor(props) { - super(props); - this.state = { - selection: [], - selectAll: false, - result: {} - } - } - - toggleSelection = (key) => { - // start off with the existing state - let selection = [...this.state.selection]; - const keyIndex = selection.indexOf(key); - // check to see if the key exists - if (keyIndex >= 0) { - // it does exist so we will remove it using destructing - selection = [ - ...selection.slice(0, keyIndex), - ...selection.slice(keyIndex + 1) - ]; - } else { - // it does not exist so add it - selection.push(key); - } - // update the state - this.setState({selection}); - }; - - isSelected = key => { - return this.state.selection.includes(key); - }; - - toggleAll = () => { - const selectAll = !this.state.selectAll; - const selection = []; - if (selectAll) { - // we need to get at the internals of ReactTable - const wrappedInstance = this.checkboxTable.getWrappedInstance(); - // the 'sortedData' property contains the currently accessible records based on the filter and sort - const currentRecords = wrappedInstance.getResolvedState().sortedData; - // we just push all the IDs onto the selection array - currentRecords.forEach(item => { - selection.push(item._original.instance_id); - }); - } - this.setState({selectAll, selection}); - }; - - getTrProps = (_, r) => { - let color = 'inherit'; - if (r) { - let instId = r.original.instance_id; - if (this.isSelected(instId)) { - color = '#ffed9f'; - } else if (Object.prototype.hasOwnProperty.call(this.state.result, instId)) { - color = this.state.result[instId] ? '#00f01b' : '#f00000' - } - } - - return { - style: {backgroundColor: color} - }; - }; - - render() { - return ( -
- (this.checkboxTable = r)} - keyField="instance_id" - columns={columns} - data={this.props.data} - showPagination={true} - defaultPageSize={pageSize} - className="-highlight" - selectType="checkbox" - toggleSelection={this.toggleSelection} - isSelected={this.isSelected} - toggleAll={this.toggleAll} - selectAll={this.state.selectAll} - getTrProps={this.getTrProps} - /> -
- ); - } -} - -export default AwsRunTableComponent; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSInstanceTable.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSInstanceTable.js new file mode 100644 index 000000000..cf792f7b8 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSInstanceTable.js @@ -0,0 +1,119 @@ +import React, {useState} from 'react'; +import ReactTable from 'react-table' +import checkboxHOC from 'react-table/lib/hoc/selectTable'; +import PropTypes from 'prop-types'; + + +const CheckboxTable = checkboxHOC(ReactTable); + +const columns = [ + { + Header: 'Machines', + columns: [ + {Header: 'Machine', accessor: 'name'}, + {Header: 'Instance ID', accessor: 'instance_id'}, + {Header: 'IP Address', accessor: 'ip_address'}, + {Header: 'OS', accessor: 'os'} + ] + } +]; + +const pageSize = 10; + +function AWSInstanceTable(props) { + + const [allToggled, setAllToggled] = useState(false); + let checkboxTable = null; + + function toggleSelection(key) { + key = key.replace('select-', ''); + // start off with the existing state + let modifiedSelection = [...props.selection]; + const keyIndex = modifiedSelection.indexOf(key); + // check to see if the key exists + if (keyIndex >= 0) { + // it does exist so we will remove it using destructing + modifiedSelection = [ + ...modifiedSelection.slice(0, keyIndex), + ...modifiedSelection.slice(keyIndex + 1) + ]; + } else { + // it does not exist so add it + modifiedSelection.push(key); + } + // update the state + props.setSelection(modifiedSelection); + } + + function isSelected(key) { + return props.selection.includes(key); + } + + function toggleAll() { + const selectAll = !allToggled; + const selection = []; + if (selectAll) { + // we need to get at the internals of ReactTable + const wrappedInstance = checkboxTable.getWrappedInstance(); + // the 'sortedData' property contains the currently accessible records based on the filter and sort + const currentRecords = wrappedInstance.getResolvedState().sortedData; + // we just push all the IDs onto the selection array + currentRecords.forEach(item => { + selection.push(item._original.instance_id); + }); + } + setAllToggled(selectAll); + props.setSelection(selection); + } + + function getTrProps(_, r) { + let color = 'inherit'; + if (r) { + let instId = r.original.instance_id; + if (isSelected(instId)) { + color = '#ffed9f'; + } else if (Object.prototype.hasOwnProperty.call(props.results, instId)) { + color = props.results[instId] ? '#00f01b' : '#f00000' + } + } + + return { + style: {backgroundColor: color} + }; + } + + return ( +
+ (checkboxTable = r)} + keyField="instance_id" + columns={columns} + data={props.data} + showPagination={true} + defaultPageSize={pageSize} + className="-highlight" + selectType="checkbox" + toggleSelection={toggleSelection} + isSelected={isSelected} + toggleAll={toggleAll} + selectAll={allToggled} + getTrProps={getTrProps} + /> +
+ ); + +} + +AWSInstanceTable.propTypes = { + data: PropTypes.arrayOf(PropTypes.exact({ + instance_id: PropTypes.string, + name: PropTypes.string, + os: PropTypes.string, + ip_address: PropTypes.string + })), + results: PropTypes.arrayOf(PropTypes.string), + selection: PropTypes.arrayOf(PropTypes.string), + setSelection: PropTypes.func +} + +export default AWSInstanceTable; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/AWSRunButton.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSRunButton.js similarity index 86% rename from monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/AWSRunButton.js rename to monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSRunButton.js index 42f16c614..3903d2a8e 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/AWSRunButton.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSRunButton.js @@ -1,11 +1,11 @@ import React, {useEffect, useState} from 'react'; -import AuthComponent from '../../AuthComponent'; -import '../../../styles/components/RunOnIslandButton.scss'; +import AuthComponent from '../../../AuthComponent'; +import '../../../../styles/components/RunOnIslandButton.scss'; import {faCloud} from '@fortawesome/free-solid-svg-icons'; -import AWSRunInstances from './AWSRunInstances'; -import NextSelectionButton from '../../ui-components/inline-selection/NextSelectionButton'; +import AWSRunOptions from './AWSRunOptions'; +import NextSelectionButton from '../../../ui-components/inline-selection/NextSelectionButton'; import {Alert, Button} from 'react-bootstrap'; -import LoadingIcon from '../../ui-components/LoadingIcon'; +import LoadingIcon from '../../../ui-components/LoadingIcon'; function AWSRunButton(props) { @@ -49,7 +49,7 @@ function AWSRunButton(props) { description={'Run on a chosen AWS instance in the cloud.'} icon={faCloud} onButtonClick={() => { - props.setComponent(AWSRunInstances, + props.setComponent(AWSRunOptions, {AWSInstances: AWSInstances, setComponent: props.setComponent}) }}/> } diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/AWSRunInstances.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSRunOptions.js similarity index 75% rename from monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/AWSRunInstances.js rename to monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSRunOptions.js index 4cc4f4e88..4c75e0ae3 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/AWSRunInstances.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSRunOptions.js @@ -3,27 +3,36 @@ import {Button, Nav} from 'react-bootstrap'; import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; import {faSync} from '@fortawesome/free-solid-svg-icons/faSync'; -import '../../../styles/components/RunOnIslandButton.scss'; import {faInfoCircle} from '@fortawesome/free-solid-svg-icons/faInfoCircle'; -import AwsRunTable from './AwsRunTable'; -import AuthComponent from '../../AuthComponent'; +import AwsRunTable from './AWSInstanceTable'; +import AuthComponent from '../../../AuthComponent'; +import InlineSelection from '../../../ui-components/inline-selection/InlineSelection'; -function AWSRunInstances(props) { +const AWSRunOptions = (props) => { + return InlineSelection(getContents, { + ...props, + onBackButtonClick: () => {props.setComponent()} + }) +} + + +const getContents = (props) => { const authComponent = new AuthComponent({}); - let awsTable = null let [allIPs, setAllIPs] = useState([]); let [selectedIp, setSelectedIp] = useState(null); let [AWSClicked, setAWSClicked] = useState(false); + let [runResults, setRunResults] = useState([]); + let [selectedInstances, setSelectedInstances] = useState([]); useEffect(() => { getIps(); - }, [allIPs]); + }, []); function getIps() { - this.authFetch('/api') + authComponent.authFetch('/api') .then(res => res.json()) .then(res => { setAllIPs(res['ip_addresses']); @@ -33,7 +42,7 @@ function AWSRunInstances(props) { function runOnAws() { setAWSClicked(true); - let instances = awsTable.state.selection.map(x => instanceIdToInstance(x)); + let instances = selectedInstances.map(x => instanceIdToInstance(x)); authComponent.authFetch('/api/remote-monkey', { @@ -45,17 +54,14 @@ function AWSRunInstances(props) { let result = res['result']; // update existing state, not run-over - let prevRes = awsTable.state.result; + let prevRes = result; for (let key in result) { if (result.hasOwnProperty(key)) { prevRes[key] = result[key]; } } - awsTable.setState({ - result: prevRes, - selection: [], - selectAll: false - }); + setRunResults(prevRes); + setSelectedInstances([]); setAWSClicked(false); }); } @@ -89,10 +95,13 @@ function AWSRunInstances(props) { } (awsTable = r)} + results={runResults} + selection={selectedInstances} + setSelection={setSelectedInstances} /> -
+