aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/components/panels
diff options
context:
space:
mode:
authorEmiliano Ciavatta2020-09-27 15:48:38 +0000
committerEmiliano Ciavatta2020-09-27 15:48:38 +0000
commit1412a34f64e234dbc7d4e6815b841699f4dd104a (patch)
tree3575bfa3d8e4d926066d3a84991809ca14083d97 /frontend/src/components/panels
parent44af615b32faf53c04cd38cb63782cf1b1332c94 (diff)
Add other custom fields
Diffstat (limited to 'frontend/src/components/panels')
-rw-r--r--frontend/src/components/panels/PcapPane.js110
-rw-r--r--frontend/src/components/panels/RulePane.js166
-rw-r--r--frontend/src/components/panels/RulePane.scss16
3 files changed, 255 insertions, 37 deletions
diff --git a/frontend/src/components/panels/PcapPane.js b/frontend/src/components/panels/PcapPane.js
index 701edf2..7e0fa6c 100644
--- a/frontend/src/components/panels/PcapPane.js
+++ b/frontend/src/components/panels/PcapPane.js
@@ -3,7 +3,7 @@ import './PcapPane.scss';
import Table from "react-bootstrap/Table";
import backend from "../../backend";
import {createCurlCommand, formatSize, timestampToTime2} from "../../utils";
-import {Button, Col, Container, Form, Row} from "react-bootstrap";
+import {Button, Col, Container, Row} from "react-bootstrap";
import InputField from "../fields/InputField";
import CheckField from "../fields/CheckField";
import TextField from "../fields/TextField";
@@ -15,45 +15,48 @@ class PcapPane extends Component {
this.state = {
sessions: [],
- isFileValid: true,
- isFileFocused: false,
- selectedFile: null,
+ isUploadFileValid: true,
+ isUploadFileFocused: false,
+ uploadSelectedFile: null,
uploadFlushAll: false,
uploadStatusCode: null,
- uploadOutput: null
+ uploadOutput: null,
+ isFileValid: true,
+ isFileFocused: false,
+ fileValue: "",
+ fileFlushAll: false,
+ fileStatusCode: null,
+ fileOutput: null,
+ deleteOriginalFile: false
};
-
- this.loadSessions = this.loadSessions.bind(this);
- this.handleFileChange = this.handleFileChange.bind(this);
- this.handleUploadPcap = this.handleUploadPcap.bind(this);
}
componentDidMount() {
this.loadSessions();
}
- loadSessions() {
- backend.get("/api/pcap/sessions").then(res => this.setState({sessions: res}));
- }
+ loadSessions = () => {
+ backend.getJson("/api/pcap/sessions").then(res => this.setState({sessions: res}));
+ };
- handleFileChange(file) {
+ handleUploadFileChange = (file) => {
this.setState({
- isFileValid: file != null && file.type.endsWith("pcap"),
- isFileFocused: false,
- selectedFile: file
+ isUploadFileValid: file != null && file.type.endsWith("pcap"),
+ isUploadFileFocused: false,
+ uploadSelectedFile: file
});
- }
+ };
- handleUploadPcap() {
- if (this.state.selectedFile == null || !this.state.isFileValid) {
- this.setState({isFileFocused: true});
+ handleUploadPcap = () => {
+ if (this.state.uploadSelectedFile == null || !this.state.isUploadFileValid) {
+ this.setState({isUploadFileFocused: true});
return;
}
const formData = new FormData();
formData.append(
"file",
- this.state.selectedFile
+ this.state.uploadSelectedFile
);
backend.postFile("/api/pcap/upload", formData).then(response =>
@@ -62,7 +65,33 @@ class PcapPane extends Component {
uploadOutput: JSON.stringify(result)
}))
);
- }
+ };
+
+ handleFileChange = (file) => {
+ this.setState({
+ isFileValid: file !== "" && file.endsWith("pcap"),
+ isFileFocused: false,
+ fileValue: file
+ });
+ };
+
+ handleProcessPcap = () => {
+ if (this.state.fileValue === "" || !this.state.isFileValid) {
+ this.setState({isFileFocused: true});
+ return;
+ }
+
+ backend.post("/api/pcap/file", {
+ file: this.state.fileValue,
+ flush_all: this.state.fileFlushAll,
+ delete_original_file: this.state.deleteOriginalFile
+ }).then(response =>
+ response.json().then(result => this.setState({
+ fileStatusCode: response.status + " " + response.statusText,
+ fileOutput: JSON.stringify(result)
+ }))
+ );
+ };
render() {
let sessions = this.state.sessions.map(s =>
@@ -82,7 +111,7 @@ class PcapPane extends Component {
const uploadOutput = this.state.uploadOutput != null ? this.state.uploadOutput :
createCurlCommand("pcap/upload", "POST", null, {
- file: "@" + ((this.state.selectedFile != null && this.state.isFileValid) ? this.state.selectedFile.name :
+ file: "@" + ((this.state.uploadSelectedFile != null && this.state.isUploadFileValid) ? this.state.uploadSelectedFile.name :
"invalid.pcap"),
flush_all: this.state.uploadFlushAll
})
@@ -120,17 +149,17 @@ class PcapPane extends Component {
<div className="pane-section">
<Container className="p-0">
<Row>
- <Col>
+ <Col style={{"paddingRight": "0"}}>
<div className="section-header">
<span className="api-request">POST /api/pcap/upload</span>
<span className="api-response">{this.state.uploadStatusCode}</span>
</div>
<div className="section-content">
- <InputField type={"file"} name={"file"} invalid={!this.state.isFileValid}
- active={this.state.isFileFocused}
- onChange={this.handleFileChange} value={this.state.selectedFile}
- defaultValue={"No .pcap[ng] selected"}/>
+ <InputField type={"file"} name={"file"} invalid={!this.state.isUploadFileValid}
+ active={this.state.isUploadFileFocused}
+ onChange={this.handleUploadFileChange} value={this.state.uploadSelectedFile}
+ defaultValue={"no .pcap[ng] selected"}/>
<div className="upload-actions">
<div className="upload-options">
@@ -148,24 +177,31 @@ class PcapPane extends Component {
<Col>
<div className="section-header">
<span className="api-request">POST /api/pcap/file</span>
- <span className="api-response"></span>
+ <span className="api-response">{this.state.fileStatusCode}</span>
</div>
<div className="section-content">
- <Form.Control type="text" id="pcap-upload" className="custom-file"
- onChange={this.onLocalFileChange} placeholder="local .pcap/.pcapng"
- custom
- />
+ <InputField name="file" active={this.state.isUploadFileFocused}
+ onChange={this.handleFileChange} value={this.state.uploadSelectedFile}
+ defaultValue={"local .pcap[ng] path"} inline/>
+
+ <div className="upload-actions" style={{"marginTop": "11px"}}>
+ <div className="upload-options">
+ <CheckField name="flush_all" checked={this.state.uploadFlushAll}
+ onChange={v => this.setState({uploadFlushAll: v})}/>
+ <CheckField name="delete_original_file" checked={this.state.uploadFlushAll}
+ onChange={v => this.setState({uploadFlushAll: v})}/>
+ </div>
+ <Button variant="blue" onClick={this.handleUploadPcap}>process</Button>
+ </div>
+
+ <TextField value={uploadOutput} rows={4} readonly small={true}/>
</div>
</Col>
</Row>
</Container>
-
-
</div>
-
</div>
-
);
}
}
diff --git a/frontend/src/components/panels/RulePane.js b/frontend/src/components/panels/RulePane.js
new file mode 100644
index 0000000..fbc8785
--- /dev/null
+++ b/frontend/src/components/panels/RulePane.js
@@ -0,0 +1,166 @@
+import React, {Component} from 'react';
+import './RulePane.scss';
+import Table from "react-bootstrap/Table";
+import {Button, Col, Container, Row} from "react-bootstrap";
+import InputField from "../fields/InputField";
+import CheckField from "../fields/CheckField";
+import TextField from "../fields/TextField";
+import backend from "../../backend";
+import NumericField from "../fields/extensions/NumericField";
+import ColorField from "../fields/extensions/ColorField";
+import ChoiceField from "../fields/ChoiceField";
+import ButtonField from "../fields/ButtonField";
+
+class RulePane extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ rules: [],
+ };
+ }
+
+ componentDidMount() {
+ this.loadRules();
+ }
+
+ loadRules = () => {
+ backend.getJson("/api/rules").then(res => this.setState({rules: res}));
+ };
+
+
+ render() {
+ let rules = this.state.rules.map(r =>
+ <tr className="table-row">
+ <td>{r["id"].substring(0, 8)}</td>
+ <td>{r["name"]}</td>
+ <td>{r["notes"]}</td>
+ {/*<td>{((new Date(s["completed_at"]) - new Date(s["started_at"])) / 1000).toFixed(3)}s</td>*/}
+ {/*<td>{formatSize(s["size"])}</td>*/}
+ {/*<td>{s["processed_packets"]}</td>*/}
+ {/*<td>{s["invalid_packets"]}</td>*/}
+ {/*<td>undefined</td>*/}
+ {/*<td className="table-cell-action"><a target="_blank"*/}
+ {/* href={"/api/pcap/sessions/" + s["id"] + "/download"}>download</a>*/}
+ {/*</td>*/}
+ </tr>
+ );
+
+ return (
+ <div className="pane-container rule-pane">
+ <div className="pane-section">
+ <div className="section-header">
+ <span className="api-request">GET /api/rules</span>
+ <span className="api-response">200 OK</span>
+ </div>
+
+ <div className="section-table">
+ <Table borderless size="sm">
+ <thead>
+ <tr>
+ <th>id</th>
+ <th>name</th>
+ <th>notes</th>
+ </tr>
+ </thead>
+ <tbody>
+ {rules}
+ </tbody>
+ </Table>
+ </div>
+ </div>
+
+ <div className="pane-section">
+ <div className="section-header">
+ <span className="api-request">POST /api/rules</span>
+ <span className="api-response"></span>
+ </div>
+
+ <div className="section-content">
+ <Container className="p-0">
+ <Row>
+ <Col>
+ <InputField name="name" inline />
+ <ColorField value={this.state.test1} onChange={(e) => this.setState({test1: e})} inline />
+ <TextField name="notes" rows={2} />
+ </Col>
+
+ <Col>
+ <div >filters:</div>
+ <NumericField name="service_port" inline value={this.state.test} onChange={(e) => this.setState({test: e})} validate={(e) => e%2 === 0} />
+
+ <NumericField name="client_port" inline />
+ <InputField name="client_address" />
+ </Col>
+
+ <Col>
+ <NumericField name="min_duration" inline />
+ <NumericField name="max_duration" inline />
+ <NumericField name="min_bytes" inline />
+ <NumericField name="max_bytes" inline />
+
+ </Col>
+ </Row>
+ </Container>
+
+ <div className="post-rules-actions">
+ <label>options:</label>
+ <div className="rules-options">
+ <CheckField name={"enabled"} />
+ </div>
+
+ <ButtonField variant="blue" name="clear" bordered />
+ <ButtonField variant="green" name="add_rule" bordered />
+ </div>
+
+ patterns:
+ <div className="section-table">
+ <Table borderless size="sm">
+ <thead>
+ <tr>
+ <th>regex</th>
+ <th>Aa</th>
+ <th>.*</th>
+ <th>\n+</th>
+ <th>UTF8</th>
+ <th>Uni_</th>
+ <th>min</th>
+ <th>max</th>
+ <th>direction</th>
+ <th>actions</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td style={{"width": "500px"}}><InputField small /></td>
+ <td><CheckField small /></td>
+ <td><CheckField small /></td>
+ <td><CheckField small /></td>
+ <td><CheckField small /></td>
+ <td><CheckField small /></td>
+ <td style={{"width": "70px"}}><NumericField small /></td>
+ <td style={{"width": "70px"}}><NumericField small /></td>
+ <td><ChoiceField small keys={[0, 1, 2]} values={["both", "c->s", "s->c"]} value="both" /></td>
+ <td><Button variant="green" size="sm">add</Button></td>
+ </tr>
+ </tbody>
+ </Table>
+ </div>
+
+ <ButtonField name="add_rule" variant="green" bordered />
+ <br />
+ <ButtonField name="add_rule" small color="red"/>
+ <br />
+ <ButtonField name="add_rule" bordered border={"green"} />
+ </div>
+ </div>
+
+
+ </div>
+ );
+ }
+
+}
+
+export default RulePane;
diff --git a/frontend/src/components/panels/RulePane.scss b/frontend/src/components/panels/RulePane.scss
new file mode 100644
index 0000000..b030c6a
--- /dev/null
+++ b/frontend/src/components/panels/RulePane.scss
@@ -0,0 +1,16 @@
+
+.rule-pane {
+ .post-rules-actions {
+ display: flex;
+
+ .rules-options {
+ flex: 1;
+ }
+
+ button {
+ margin-left: 10px;
+ }
+ }
+
+
+} \ No newline at end of file