You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spot.apache.org by le...@apache.org on 2017/06/20 16:56:59 UTC
[5/5] incubator-spot git commit: FLOW Score suspicious is now
available on ReactJs,
Ipython notebook is removed from scoring on FLOW Suspicious
FLOW Score suspicious is now available on ReactJs, Ipython notebook is removed from scoring on FLOW Suspicious
Project: http://git-wip-us.apache.org/repos/asf/incubator-spot/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-spot/commit/df352161
Tree: http://git-wip-us.apache.org/repos/asf/incubator-spot/tree/df352161
Diff: http://git-wip-us.apache.org/repos/asf/incubator-spot/diff/df352161
Branch: refs/heads/SPOT-35_graphql_api
Commit: df352161ea6bff9949be54fc3f5c826b31f9733b
Parents: 0e9437f
Author: Montes Velazquez <jo...@intel.com>
Authored: Wed Apr 26 13:49:17 2017 -0500
Committer: LedaLima <ga...@intel.com>
Committed: Tue Jun 20 11:56:30 2017 -0500
----------------------------------------------------------------------
.../flow/js/components/ScoreNotebook.react.js | 200 +++++++++++++++++++
spot-oa/ui/flow/js/stores/NotebookStore.js | 92 +++++++++
spot-oa/ui/flow/js/suspicious.js | 8 +-
spot-oa/ui/flow/suspicious.html | 5 +
4 files changed, 300 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-spot/blob/df352161/spot-oa/ui/flow/js/components/ScoreNotebook.react.js
----------------------------------------------------------------------
diff --git a/spot-oa/ui/flow/js/components/ScoreNotebook.react.js b/spot-oa/ui/flow/js/components/ScoreNotebook.react.js
new file mode 100644
index 0000000..48e06c3
--- /dev/null
+++ b/spot-oa/ui/flow/js/components/ScoreNotebook.react.js
@@ -0,0 +1,200 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements; and to You under the Apache License, Version 2.0.
+
+var React = require('react');
+
+var SuspiciousStore = require('../stores/SuspiciousStore');
+var NotebookStore = require('../stores/NotebookStore');
+var EdInActions = require('../../../js/actions/EdInActions');
+var SelectInput = require('../../../js/components/scoring/SelectInput.react');
+var FilterSelectInput = require('../../../js/components/scoring/FilterSelectInput.react');
+var ButtonsScoring = require('../../../js/components/scoring/ButtonsScoring.react');
+var RatingInput = require('../../../js/components/scoring/RatingInput.react');
+var SearchGlobalInput = require('../../../js/components/scoring/SearchGlobalInput.react');
+
+var SpotUtils = require('../../../js/utils/SpotUtils');
+
+var ScoreNotebook = React.createClass({
+ // mixins: [GridPanelMixin],
+ emptySetMessage: 'There is no data available for selected date.',
+ propTypes: {
+ date: React.PropTypes.string.isRequired,
+ },
+ getInitialState: function () {
+ return {
+ scoredEmelents: []
+ };
+ },
+ componentDidMount: function() {
+ SuspiciousStore.addChangeDataListener(this._onChange);
+ NotebookStore.addChangeDataListener(this._onChange);
+ this.setState({size: NotebookStore.completeClass})
+ },
+ componentWillUnmount: function () {
+ SuspiciousStore.removeChangeDataListener(this._onChange);
+ NotebookStore.addChangeDataListener(this._onChange);
+ },
+ render: function () {
+ var content, state, data, cssCls, srcIpArr = [], dstIpArr = [], srcPortArr = [], dstPortArr = [];
+ state = this.state || {};
+
+ if (state.error)
+ {
+ content = (
+ <div className="text-center text-danger">
+ {state.error}
+ </div>
+ );
+ }
+ else if (state.loading)
+ {
+ content = (
+ <div className="spot-loader">
+ Loading <span className="spinner"></span>
+ </div>
+ );
+ }
+ else if (!state.data || state.data.length === 0)
+ {
+ content = (
+ <div className="text-center">
+ {this.emptySetMessage || ''}
+ </div>
+ );
+ }
+ else
+ {
+ state.data.map((obj) => {
+ if(srcIpArr.indexOf(obj.srcIP) === -1) {
+ srcIpArr.push(obj.srcIP);
+ }
+ if(dstIpArr.indexOf(obj.dstIP) === -1) {
+ dstIpArr.push(obj.dstIP);
+ }
+ if(srcPortArr.indexOf(obj.sport) === -1) {
+ srcPortArr.push(obj.sport);
+ }
+ if(dstPortArr.indexOf(obj.dport) === -1) {
+ dstPortArr.push(obj.dport);
+ }
+ });
+
+ data = [
+ {value: 1, name: 'High', radioName: 'optradio', selected: true},
+ {value: 2, name: 'Medium', radioName: 'optradio', selected: false},
+ {value: 3, name: 'Low', radioName: 'optradio', selected: false}
+ ];
+
+ content = (
+ <div>
+ <div className="margin-up-down">
+ <SearchGlobalInput col="6"/>
+ <RatingInput data={data} col="6"/>
+ </div>
+ <div className="margin-up-down">
+ <ButtonsScoring name="Score" action="score" onChange={this.score.bind(this)} col="3"/>
+ <ButtonsScoring name="Save" action="save" onChange={this.save.bind(this)} col="3"/>
+ <ButtonsScoring name="Reset Scoring" action="reset" onChange={this.reset.bind(this)} col="3"/>
+ </div>
+ <div className="margin-up-down">
+ <FilterSelectInput nameBox="Source Ip" idSelect="#srcIp" idInput="srcIpIn" col="3"/>
+ <FilterSelectInput nameBox="Dest IP" idSelect="#dstIp" idInput="dstIpIn" col="3"/>
+ <FilterSelectInput nameBox="Src Port" idSelect="#srcPort" idInput="srcPortIn" col="3"/>
+ <FilterSelectInput nameBox="Dst Port" idSelect="#dstPort" idInput="dstPortIn" col="3"/>
+ </div>
+ <div className="margin-up-down">
+ <SelectInput title="Source IP" who="srcIp" options={srcIpArr} col="3"/>
+ <SelectInput title="Dest IP" who="dstIp" options={dstIpArr} col="3"/>
+ <SelectInput title="Src Port" who="srcPort" options={srcPortArr} col="3"/>
+ <SelectInput title="Dst Port" who="dstPort" options={dstPortArr} col="3"/>
+ </div>
+ </div>
+ );
+ }
+ cssCls = this.state.size ? 'col-md-6 col-lg-6 col-xs-12' : 'col-md-12 col-lg-12 col-xs-12';
+
+ return(
+ <div className={cssCls + ' spot-frame'}>
+ {content}
+ </div>
+ )
+ },
+ _onChange: function() {
+ const data = SuspiciousStore.getData();
+ this.setState(data);
+ },
+ reset: function() {
+ swal({
+ title: 'Are you sure?',
+ text: "You won't be able to revert this!",
+ type: 'warning',
+ showCancelButton: true,
+ confirmButtonColor: '#3085d6',
+ cancelButtonColor: '#d33',
+ confirmButtonText: 'Yes, reset all!'
+ }).then(() => {
+ EdInActions.resetScoring(SpotUtils.getCurrentDate());
+ swal({
+ title: 'Done!',
+ text: "All scores have been reset.",
+ type: 'success',
+ showCancelButton: false,
+ confirmButtonColor: '#3085d6',
+ cancelButtonColor: '#d33',
+ confirmButtonText: 'Ok!'
+ }).then(() => {
+ this.setState({loading: true});
+ });
+ });
+ },
+ save: function() {
+ let variables = [];
+
+ if (this.state.scoredEmelents.length === 0) {
+ swal('Warning.','You need to score at least 1 threat.','warning');
+ } else {
+ this.state.scoredEmelents.map((row) => {
+ variables.push({
+ 'date': SpotUtils.getCurrentDate(),
+ 'score': row[4],
+ 'srcIp': row[0] || null,
+ 'dstIp': row[1] || null,
+ 'srcPort': row[2] || null,
+ 'dstPort': row[3] || null
+ });
+ });
+
+ EdInActions.saveScoring(variables);
+ this.setState({scoredEmelents: [], loading: true});
+ }
+ },
+ score: function() {
+ //this should be changed to take all data at the time, time needed.
+ let dataScored = this.state.scoredEmelents || [];
+ let quickIpScoring = document.getElementById('globalTxt').value;
+ let srcIp = document.getElementById('srcIp').value;
+ let dstIp = document.getElementById('dstIp').value;
+ let srcPort = document.getElementById('srcPort').value;
+ let dstPort = document.getElementById('dstPort').value;
+ let rating = $('input[name="optradio"]:checked').val();
+
+ //callback from the father
+ if(quickIpScoring !== '') {
+ dataScored.push([quickIpScoring, dstIp, srcPort, dstPort, rating]);
+ dataScored.push([srcIp, quickIpScoring, srcPort, dstPort, rating]);
+ } else {
+ dataScored.push([srcIp, dstIp, srcPort, dstPort, rating]);
+ }
+
+ this.removeSelected([quickIpScoring, srcIp, dstIp, srcPort, dstPort]);
+ this.setState({scoredEmelents: dataScored});
+ },
+ removeSelected: function(data) {
+ //when an user score, all elements selected need to be removed.
+ data.map((element) => data.map((e) => e !== '' ? $(`option[value="${e}"]`).remove() : ''));
+ $(".select-picker, #globalTxt").val('');
+ }
+
+});
+
+
+module.exports = ScoreNotebook;
http://git-wip-us.apache.org/repos/asf/incubator-spot/blob/df352161/spot-oa/ui/flow/js/stores/NotebookStore.js
----------------------------------------------------------------------
diff --git a/spot-oa/ui/flow/js/stores/NotebookStore.js b/spot-oa/ui/flow/js/stores/NotebookStore.js
new file mode 100644
index 0000000..487bce1
--- /dev/null
+++ b/spot-oa/ui/flow/js/stores/NotebookStore.js
@@ -0,0 +1,92 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements; and to You under the Apache License, Version 2.0.
+
+const SpotDispatcher = require('../../../js/dispatchers/SpotDispatcher');
+const SpotConstants = require('../../../js/constants/SpotConstants');
+const SuspiciousStore = require('./SuspiciousStore');
+
+const ObservableWithHeadersGraphQLStore = require('../../../js/stores/ObservableWithHeadersGraphQLStore');
+
+const SCORED_ELEMENTS = 'input';
+const RESET_SCORED_ELEMENTS = 'date';
+
+class NotebookStore extends ObservableWithHeadersGraphQLStore {
+ constructor() {
+ super();
+ this.selectedQuery = 'scoreQuery';
+ this.query = {
+ scoreQuery: `
+ mutation($input:[NetflowScoreInputType!]!) {
+ flow{
+ score(input:$input)
+ {success}
+ }
+ }`,
+ resetQuery: `
+ mutation($date:SpotDateType!) {
+ flow{
+ resetScoredConnections(date:$date){
+ success
+ }
+ }
+ }`
+ };
+ this.completeClass = false;
+ }
+
+ getQuery() {
+ return this.query[this.selectedQuery];
+ }
+
+ unboxData(data) {
+ return data.flow.suspicious;
+ }
+
+ setScoredElements(scoredElements) {
+ this.selectedQuery = 'scoreQuery';
+ this.setVariable(SCORED_ELEMENTS, scoredElements);
+ this.unsetVariables(RESET_SCORED_ELEMENTS);
+ }
+
+ resetScoredElements(date) {
+ this.selectedQuery = 'resetQuery';
+ this.setVariable(RESET_SCORED_ELEMENTS, date);
+ this.unsetVariables(SCORED_ELEMENTS);
+ }
+
+ unsetVariables(variable) {
+ this.unsetVariable(variable);
+ }
+
+ reloadElements() {
+ SuspiciousStore.sendQuery();
+ }
+
+ changeCssCls() {
+ this.completeClass = !this.completeClass;
+ }
+
+
+}
+
+const ns = new NotebookStore();
+
+SpotDispatcher.register(function (action) {
+ switch (action.actionType) {
+ case SpotConstants.SAVE_SCORED_ELEMENTS:
+ ns.setScoredElements(action.scoredElems);
+ ns.sendQuery();
+ break;
+ case SpotConstants.RESET_SCORED_ELEMENTS:
+ ns.resetScoredElements(action.date);
+ ns.sendQuery();
+ break;
+ case SpotConstants.RELOAD_SUSPICIOUS:
+ ns.resetData();
+ break;
+ case SpotConstants.CHANGE_CSS_CLS:
+ ns.changeCssCls();
+ break;
+ }
+});
+
+module.exports = ns;
http://git-wip-us.apache.org/repos/asf/incubator-spot/blob/df352161/spot-oa/ui/flow/js/suspicious.js
----------------------------------------------------------------------
diff --git a/spot-oa/ui/flow/js/suspicious.js b/spot-oa/ui/flow/js/suspicious.js
index cb6b0fa..206d52a 100755
--- a/spot-oa/ui/flow/js/suspicious.js
+++ b/spot-oa/ui/flow/js/suspicious.js
@@ -54,11 +54,9 @@ const Panel = require('../../js/components/Panel.react');
const SuspiciousPanel = require('./components/SuspiciousPanel.react');
const NetworkViewPanel = require('./components/NetworkViewPanel.react');
-const IPythonNotebookPanel = require('../../js/components/IPythonNotebookPanel.react');
+const ScoreNotebook = require('./components/ScoreNotebook.react');
const DetailsPanel = require('./components/DetailsPanel.react');
-const ipynbClosure = IPythonNotebookPanel.createIPythonNotebookClosure(SpotConstants.NOTEBOOK_PANEL);
-
ReactDOM.render(
<div id="spot-content">
<PanelRow>
@@ -70,8 +68,8 @@ ReactDOM.render(
</Panel>
</PanelRow>
<PanelRow>
- <Panel title={ipynbClosure.getTitle()} container extraButtons={ipynbClosure.getButtons}>
- <IPythonNotebookPanel title={ipynbClosure.getTitle()} date={SpotUtils.getCurrentDate()} ipynb="flow/${date}/Edge_Investigation.ipynb" />
+ <Panel title={SpotConstants.SCORING_PANEL} reloadable onReload={EdInActions.reloadSuspicious}>
+ <ScoreNotebook />
</Panel>
<Panel title={SpotConstants.DETAILS_PANEL} container expandable>
<DetailsPanel title={SpotConstants.DETAILS_PANEL} />
http://git-wip-us.apache.org/repos/asf/incubator-spot/blob/df352161/spot-oa/ui/flow/suspicious.html
----------------------------------------------------------------------
diff --git a/spot-oa/ui/flow/suspicious.html b/spot-oa/ui/flow/suspicious.html
index b591445..01d5f50 100755
--- a/spot-oa/ui/flow/suspicious.html
+++ b/spot-oa/ui/flow/suspicious.html
@@ -21,6 +21,7 @@
<title>Netflow :: Suspicious</title>
<meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<!--Bootstrap styles-->
<link rel="stylesheet" type="text/css" href="../css/bootstrap-spot.min.css" />
@@ -30,6 +31,9 @@
<link rel="stylesheet" type="text/css" href="../node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker3.min.css" />
<!-- Spot styles -->
<link rel="stylesheet" type="text/css" href="../css/main.css" />
+ <!-- Sweetalert2 -->
+ <link rel="stylesheet" type="text/css" href="../node_modules/sweetalert2/dist/sweetalert2.min.css">
+
<!-- Favicon -->
<link rel="apple-touch-icon" sizes="57x57" href="../images/favicon/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="../images/favicon/apple-icon-60x60.png"
@@ -153,6 +157,7 @@
<script type="application/javascript" src="../node_modules/react/dist/react.min.js"></script>
<script type="application/javascript" src="../node_modules/react-dom/dist/react-dom.min.js"></script>
<script type="application/javascript" src="../node_modules/react-dom/dist/react-dom-server.min.js"></script>
+ <script type="application/javascript" src="../node_modules/sweetalert2/dist/sweetalert2.min.js"></script>
<script type="application/javascript" src="js/lib/ChordMapper.js"></script>
<script type="application/javascript" src="js/suspicious.bundle.min.js"></script>
</body>