diff options
author | Emiliano Ciavatta | 2020-09-27 15:48:38 +0000 |
---|---|---|
committer | Emiliano Ciavatta | 2020-09-27 15:48:38 +0000 |
commit | 1412a34f64e234dbc7d4e6815b841699f4dd104a (patch) | |
tree | 3575bfa3d8e4d926066d3a84991809ca14083d97 /frontend/src/components/panels | |
parent | 44af615b32faf53c04cd38cb63782cf1b1332c94 (diff) |
Add other custom fields
Diffstat (limited to 'frontend/src/components/panels')
-rw-r--r-- | frontend/src/components/panels/PcapPane.js | 110 | ||||
-rw-r--r-- | frontend/src/components/panels/RulePane.js | 166 | ||||
-rw-r--r-- | frontend/src/components/panels/RulePane.scss | 16 |
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 |