Added show/hide techniques button in attack report, refactored technique dropdowns

This commit is contained in:
VakarisZ 2019-11-26 10:18:13 +02:00
parent 1e9c9c196b
commit 4932ddd3d3
6 changed files with 111 additions and 55 deletions

View File

@ -67,7 +67,7 @@
"dependencies": { "dependencies": {
"@emotion/core": "^10.0.22", "@emotion/core": "^10.0.22",
"@kunukn/react-collapse": "^1.2.7", "@kunukn/react-collapse": "^1.2.7",
"bootstrap": "3.4.1", "bootstrap": "^3.4.1",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"core-js": "^2.6.10", "core-js": "^2.6.10",
"d3": "^5.14.1", "d3": "^5.14.1",

View File

@ -1,14 +1,13 @@
import React from 'react'; import React from 'react';
import {Col} from 'react-bootstrap'; import {Col} from 'react-bootstrap';
import {ReactiveGraph} from 'components/reactive-graph/ReactiveGraph';
import {edgeGroupToColor, options} from 'components/map/MapOptions';
import '../../styles/Collapse.scss'; import '../../styles/Collapse.scss';
import '../../styles/report/AttackReport.scss' import '../../styles/report/AttackReport.scss'
import AuthComponent from '../AuthComponent';
import {ScanStatus} from '../attack/techniques/Helpers'; import {ScanStatus} from '../attack/techniques/Helpers';
import Collapse from '@kunukn/react-collapse';
import Matrix from './attack/ReportMatrix'; import Matrix from './attack/ReportMatrix';
import SelectedTechnique from './attack/SelectedTechnique'; import SelectedTechnique from './attack/SelectedTechnique';
import TechniqueDropdowns from './attack/TechniqueDropdowns';
import T1210 from '../attack/techniques/T1210'; import T1210 from '../attack/techniques/T1210';
import T1197 from '../attack/techniques/T1197'; import T1197 from '../attack/techniques/T1197';
@ -62,9 +61,8 @@ const techComponents = {
'T1064': T1064 'T1064': T1064
}; };
const classNames = require('classnames');
class AttackReport extends AuthComponent { class AttackReport extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -82,9 +80,6 @@ class AttackReport extends AuthComponent {
} }
} }
onToggle = technique =>
this.setState(state => ({collapseOpen: state.collapseOpen === technique ? null : technique}));
onTechniqueSelect = (technique, value, mapped = false) => { onTechniqueSelect = (technique, value, mapped = false) => {
//this.setState({selectedTechnique: technique}); //this.setState({selectedTechnique: technique});
let selectedTechnique = this.getTechniqueByTitle(technique); let selectedTechnique = this.getTechniqueByTitle(technique);
@ -105,39 +100,6 @@ class AttackReport extends AuthComponent {
} }
} }
getTechniqueCollapse(tech_id) {
return (
<div key={tech_id} className={classNames('collapse-item', {'item--active': this.state.collapseOpen === tech_id})}>
<button className={classNames('btn-collapse', AttackReport.getComponentClass(tech_id, this.state.techniques))}
onClick={() => this.onToggle(tech_id)}>
<span>{this.state.techniques[tech_id].title}</span>
<span>
<i className={classNames('fa', this.state.collapseOpen === tech_id ? 'fa-chevron-down' : 'fa-chevron-up')}></i>
</span>
</button>
<Collapse
className="collapse-comp"
isOpen={this.state.collapseOpen === tech_id}
onChange={({collapseState}) => {
this.setState({tech_id: collapseState});
}}
onInit={({collapseState}) => {
this.setState({tech_id: collapseState});
}}
render={collapseState => this.createTechniqueContent(collapseState, tech_id)}/>
</div>
);
}
createTechniqueContent(collapseState, technique) {
const TechniqueComponent = techComponents[technique];
return (
<div className={`content ${collapseState}`}>
<TechniqueComponent data={this.state.techniques[technique]}/>
</div>
);
}
renderLegend() { renderLegend() {
return (<div id="header" className="row justify-content-between attack-legend"> return (<div id="header" className="row justify-content-between attack-legend">
<Col xs={3}> <Col xs={3}>
@ -160,10 +122,6 @@ class AttackReport extends AuthComponent {
} }
generateReportContent() { generateReportContent() {
let content = [];
Object.keys(this.state.techniques).forEach((tech_id) => {
content.push(this.getTechniqueCollapse(tech_id))
});
return ( return (
<div id="attack" className="attack-report"> <div id="attack" className="attack-report">
<h3> <h3>
@ -177,9 +135,8 @@ class AttackReport extends AuthComponent {
<SelectedTechnique techComponents={techComponents} <SelectedTechnique techComponents={techComponents}
techniques={this.state.techniques} techniques={this.state.techniques}
selected={this.state.selectedTechnique}/> selected={this.state.selectedTechnique}/>
<div> <TechniqueDropdowns techniques={this.state.techniques}
<section className="attack-report">{content}</section> techComponents={techComponents}/>
</div>
<br/> <br/>
</div> </div>
) )

View File

@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import Checkbox from '../../ui-components/Checkbox'; import Checkbox from '../../ui-components/Checkbox';
import ReactTable from 'react-table'; import ReactTable from 'react-table';
import 'filepond/dist/filepond.min.css'; import 'filepond/dist/filepond.min.css';

View File

@ -17,8 +17,9 @@ class SelectedTechnique extends React.Component {
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
if (this.props.selected !== prevProps.selected) { if (this.props.selected !== prevProps.selected || this.props.techniques !== prevProps.techniques) {
this.setState({ selectedTechnique: this.props.selected }) this.setState({ selectedTechnique: this.props.selected,
techniques: this.props.techniques})
} }
} }
@ -41,13 +42,11 @@ class SelectedTechnique extends React.Component {
); );
} }
render(){ render(){
let content = {}; let content = {};
let selectedTechId = this.state.selectedTechnique; let selectedTechId = this.state.selectedTechnique;
if(selectedTechId === false){ if(selectedTechId === false){
content = "Select a technique from attack matrix"; content = "None. Select a technique from ATT&CK matrix above.";
} else { } else {
content = this.getSelectedTechniqueComponent(selectedTechId) content = this.getSelectedTechniqueComponent(selectedTechId)
} }

View File

@ -0,0 +1,89 @@
import React from "react";
import Collapse from '@kunukn/react-collapse';
import {Button} from 'react-bootstrap';
import AttackReport from '../AttackReport';
const classNames = require('classnames');
class TechniqueDropdowns extends React.Component{
constructor(props) {
super(props);
this.state = {
techniques: this.props.techniques,
techComponents: this.props.techComponents,
collapseOpen: '',
techniquesHidden: true
};
}
componentDidUpdate(prevProps) {
if (this.props.techniques !== prevProps.techniques) {
this.setState({ techniques: this.props.techniques })
}
}
onToggle = technique =>
this.setState(state => ({collapseOpen: state.collapseOpen === technique ? null : technique}));
getTechniqueCollapse(tech_id) {
return (
<div key={tech_id} className={classNames('collapse-item', {'item--active': this.state.collapseOpen === tech_id})}>
<button className={classNames('btn-collapse', AttackReport.getComponentClass(tech_id, this.state.techniques))}
onClick={() => this.onToggle(tech_id)}>
<span>{this.state.techniques[tech_id].title}</span>
<span>
<i className={classNames('fa', this.state.collapseOpen === tech_id ? 'fa-chevron-down' : 'fa-chevron-up')}></i>
</span>
</button>
<Collapse
className="collapse-comp"
isOpen={this.state.collapseOpen === tech_id}
onChange={({collapseState}) => {
this.setState({tech_id: collapseState});
}}
onInit={({collapseState}) => {
this.setState({tech_id: collapseState});
}}
render={collapseState => this.createTechniqueContent(collapseState, tech_id)}/>
</div>
);
}
createTechniqueContent(collapseState, technique) {
const TechniqueComponent = this.state.techComponents[technique];
return (
<div className={`content ${collapseState}`}>
<TechniqueComponent data={this.state.techniques[technique]}/>
</div>
);
}
toggleTechList(){
this.setState({techniquesHidden: (! this.state.techniquesHidden)})
}
render(){
let listClass = '';
let content = [];
if (this.state.techniquesHidden){
listClass = "hidden-list"
} else {
Object.keys(this.state.techniques).forEach((tech_id) => {
content.push(this.getTechniqueCollapse(tech_id))
});
}
return (
<div className="dropdown-list">
<Button bsStyle="link"
bsSize="large"
onClick={() => this.toggleTechList()}>
{this.state.techniquesHidden ? "Show all" : "Hide all"}
</Button>
<section className={`attack-report ${listClass}`}>{content}</section>
</div>);
}
}
export default TechniqueDropdowns;

View File

@ -11,3 +11,13 @@
.attack-report div.attack-legend { .attack-report div.attack-legend {
margin-top: 30px; margin-top: 30px;
} }
.attack-report .hidden-list{
display: none;
}
.attack-report .dropdown-list .btn-lg {
margin-top: 30px;
margin-bottom: 20px;
padding: 0;
}