diff options
author | therealbobo | 2020-09-17 08:42:00 +0000 |
---|---|---|
committer | therealbobo | 2020-09-17 08:42:00 +0000 |
commit | 9063c5d4d5b04e4c7f4e689c9246c4b37b72ec68 (patch) | |
tree | e59da614e29386daf53f3930851566b00b49e95a | |
parent | 4cfdf6e2dfe9184e988a145495e072571d512cdc (diff) | |
parent | 98355cdf838d8c18e9a28176ae7a847770545395 (diff) |
conflicts fixed and merge
-rw-r--r-- | frontend/package.json | 1 | ||||
-rw-r--r-- | frontend/public/favicon.ico | bin | 3150 -> 34239 bytes | |||
-rw-r--r-- | frontend/public/logo192.png | bin | 5347 -> 34239 bytes | |||
-rw-r--r-- | frontend/public/logo512.png | bin | 9664 -> 34239 bytes | |||
-rw-r--r-- | frontend/src/views/App.js | 31 | ||||
-rw-r--r-- | frontend/src/views/Config.js | 248 | ||||
-rw-r--r-- | frontend/src/views/Config.scss | 55 | ||||
-rw-r--r-- | frontend/src/views/Header.js | 8 | ||||
-rw-r--r-- | frontend/src/views/Services.js | 23 | ||||
-rw-r--r-- | frontend/src/views/Upload.js | 106 | ||||
-rw-r--r-- | frontend/src/views/Upload.scss | 21 | ||||
-rw-r--r-- | frontend/yarn.lock | 6 |
12 files changed, 487 insertions, 12 deletions
diff --git a/frontend/package.json b/frontend/package.json index 661c2c4..bf995c5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,6 +11,7 @@ "@testing-library/user-event": "^7.1.2", "axios": "^0.19.2", "bootstrap": "^4.4.1", + "bs-custom-file-input": "^1.3.4", "classnames": "^2.2.6", "eslint-config-react-app": "^5.2.1", "node-sass": "^4.14.0", diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico Binary files differindex bcd5dfd..1dc499d 100644 --- a/frontend/public/favicon.ico +++ b/frontend/public/favicon.ico diff --git a/frontend/public/logo192.png b/frontend/public/logo192.png Binary files differindex fc44b0a..1dc499d 100644 --- a/frontend/public/logo192.png +++ b/frontend/public/logo192.png diff --git a/frontend/public/logo512.png b/frontend/public/logo512.png Binary files differindex a4e47a6..1dc499d 100644 --- a/frontend/public/logo512.png +++ b/frontend/public/logo512.png diff --git a/frontend/src/views/App.js b/frontend/src/views/App.js index 6c101fa..ebead2f 100644 --- a/frontend/src/views/App.js +++ b/frontend/src/views/App.js @@ -6,6 +6,8 @@ import {BrowserRouter as Router, Route, Switch} from "react-router-dom"; import Services from "./Services"; import Filters from "./Filters"; import Rules from "./Rules"; +import Config from "./Config"; +import Upload from "./Upload"; class App extends Component { @@ -14,8 +16,22 @@ class App extends Component { this.state = { servicesWindowOpen: false, filterWindowOpen: false, - rulesWindowOpen: false + rulesWindowOpen: false, + configWindowOpen: false, + uploadWindowOpen: false, + configDone: false }; + + fetch('/api/services') + .then(response => { + if( response.status === 503){ + this.setState({configWindowOpen: true}); + } else if (response.status === 200){ + this.setState({configDone: true}); + } + }); + + } render() { @@ -29,13 +45,24 @@ class App extends Component { if (this.state.rulesWindowOpen) { modal = <Rules onHide={() => this.setState({rulesWindowOpen: false})}/>; } + if (this.state.configWindowOpen) { + modal = <Config onHide={() => this.setState({configWindowOpen: false})} + onDone={() => this.setState({configDone: true})}/>; + } + if (this.state.uploadWindowOpen) { + modal = <Upload onHide={() => this.setState({uploadWindowOpen: false}) }/>; + } return ( <div className="app"> <Router> <Header onOpenServices={() => this.setState({servicesWindowOpen: true})} onOpenFilters={() => this.setState({filterWindowOpen: true})} - onOpenRules={() => this.setState({rulesWindowOpen: true})} /> + onOpenRules={() => this.setState({rulesWindowOpen: true})} + onOpenConfig={() => this.setState({configWindowOpen: true})} + onOpenUpload={() => this.setState({uploadWindowOpen: true})} + onConfigDone={this.state.configDone} + /> <Switch> <Route path="/connections/:id" children={<MainPane/>}/> <Route path="/" children={<MainPane/>}/> diff --git a/frontend/src/views/Config.js b/frontend/src/views/Config.js new file mode 100644 index 0000000..f5766eb --- /dev/null +++ b/frontend/src/views/Config.js @@ -0,0 +1,248 @@ +import { + validateIpAddress, +} from "../utils"; +import React, {Component, useState} from 'react'; +import './Config.scss'; +import {Button, ButtonGroup, ToggleButton, Col, Container, Form, FormControl, InputGroup, Modal, Row, Table} from "react-bootstrap"; +import {createCurlCommand} from '../utils'; + +class Config extends Component { + + constructor(props) { + super(props); + + this.state = { + server_address: "", + flag_regex: "", + auth_required: false, + accounts: {}, + showSignup: false, + showConfig: true, + tmpUser:"", + tmpPass:"", + tmpConf:"", + errors:"" + }; + + this.serverIpChanged = this.serverIpChanged.bind(this); + this.flagRegexChanged = this.flagRegexChanged.bind(this); + this.authRequiredChanged = this.authRequiredChanged.bind(this); + this.userChanged = this.userChanged.bind(this); + this.passwdChanged = this.passwdChanged.bind(this); + this.confirmChanged = this.confirmChanged.bind(this); + } + + serverIpChanged(event) { + this.setState({server_address: event.target.value}); + } + + flagRegexChanged(event) { + this.setState({flag_regex: event.target.value}); + } + + authRequiredChanged() { + this.setState({auth_required: !this.value}); + this.checked = !this.checked; + this.value = !this.value; + } + + userChanged(event) { + this.setState({tmpUser: event.target.value}); + } + + passwdChanged(event) { + this.setState({tmpPass: event.target.value}); + } + + confirmChanged(event) { + this.setState({tmpConf: event.target.value}); + } + + setup() { + const requestOptions = { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + config: { + server_address: this.state.server_address, + flag_regex: this.state.flag_regex, + auth_required: this.state.auth_required, + }, + accounts: this.state.accounts + }) + }; + + let msg = ""; + + fetch('/setup', requestOptions) + .then(response => { + if (response.status === 202 ){ + //this.setState({showConfig:false}); + this.props.onHide(); + this.props.onDone(); + } else { + response.json().then(data => { + this.setState( + {errors : data.error.toString()} + ); + }); + } + } + ); + + } + + signup(){ + if (this.state.tmpPass === this.state.tmpConf){ + const accounts = {...this.state.accounts}; + accounts[this.state.tmpUser] = this.state.tmpPass; + this.setState({accounts}); + console.log(this.state); + this.setState({showSignup:false,showConfig:true}) + } + this.setState({tmpUser : ""}); + this.setState({tmpPass : ""}); + this.setState({tmpConf : ""}); + } + + render() { + let rows = Object.keys(this.state.accounts).map(u => + <tr> + <td>{u}</td> + </tr> + ); + + + + return ( + <> + <Modal show={this.state.showSignup} size="lg" aria-labelledby="services-dialog" centered > + <Modal.Header> + <Modal.Title id="services-dialog"> + # passwd + </Modal.Title> + </Modal.Header> + <Modal.Body> + <Container> + <Row> + <Form id="passwd-form"> + <Form.Group controlId="username"> + <Form.Label>username:</Form.Label> + <Form.Control type="text" onChange={this.userChanged} value={this.state.tmpUser}/> + </Form.Group> + + <Form.Group controlId="password"> + <Form.Label>password:</Form.Label> + <Form.Control type="password" onChange={this.passwdChanged} value={this.state.tmpPass}/> + </Form.Group> + + <Form.Group controlId="confirmPassword"> + <Form.Label>confirm password:</Form.Label> + <Form.Control type="password" onChange={this.confirmChanged} value={this.state.tmpConf}/> + </Form.Group> + + + </Form> + + </Row> + + </Container> + </Modal.Body> + <Modal.Footer className="dialog-footer"> + <Button variant="green" onClick={() => this.signup()}>signup</Button> + <Button variant="red" onClick={() => this.setState({showSignup:false,showConfig:true})}>close</Button> + </Modal.Footer> + + </Modal> + <Modal + {...this.props} + show="true" + size="lg" + aria-labelledby="services-dialog" + centered + > + <Modal.Header> + <Modal.Title id="services-dialog"> + ~/.config + </Modal.Title> + </Modal.Header> + <Modal.Body> + <div class="blink"><span><b>Warning:</b></span> once the configuration is completed, it cannot be changed unless you reset caronte :(</div> + <hr/> + <Container> + <Row> + <Col md={5}> + + <ButtonGroup toggle className="mb-2"> + <ToggleButton + type="checkbox" + variant="secondary" + checked={this.state.auth_required} + value={this.state.auth_required} + onChange={() => this.authRequiredChanged()} + > + Authentication + </ToggleButton> + </ButtonGroup> + + <Table borderless size="sm" className="users-list"> + + <thead> + <tr> + <th>users</th> + </tr> + </thead> + <tbody> + {rows} + <tr> <td> + <Button size="sm" onClick={() => this.setState({showSignup:true,showConfig:false})}>new</Button> + </td> </tr> + </tbody> + </Table> + + + + </Col> + + <Col md={7}> + + <Form> + <Form.Group controlId="server_address"> + <Form.Label>server_address:</Form.Label> + <Form.Control type="text" onChange={this.serverIpChanged} value={this.state.server_address}/> + </Form.Group> + + <Form.Group controlId="flag_regex"> + <Form.Label>flag_regex:</Form.Label> + <Form.Control type="text" onChange={this.flagRegexChanged} value={this.state.flag_regex}/> + </Form.Group> + + </Form> + + </Col> + + </Row> + <Row> + <div class="error"> + <b> + {this.state.errors + .split('\n').map((item, key) => { + return <span key={key}>{item}<br/></span>}) + } + </b> + </div> + </Row> + + </Container> + </Modal.Body> + <Modal.Footer className="dialog-footer"> + <Button variant="green" onClick={() => this.setup()}>set</Button> + <Button variant="red" onClick={this.props.onHide}>close</Button> + </Modal.Footer> + </Modal> + </> + ); + } +} + +export default Config; diff --git a/frontend/src/views/Config.scss b/frontend/src/views/Config.scss new file mode 100644 index 0000000..331d7a7 --- /dev/null +++ b/frontend/src/views/Config.scss @@ -0,0 +1,55 @@ +@import '../colors.scss'; + +.curl-output { + width: 100%; + font-size: 13px; +} + +#passwd-form { + margin:auto; +} + +.users-list { + .btn { + width: 70px; + } + + td { + background-color: $color-primary-2; + border-top: 2px solid $color-primary-0; + vertical-align: middle; + text-align: center; + } + + th { + background-color: $color-primary-1; + text-align: center; + } +} + +.btn-color { + border: 3px solid #fff; +} + +.dialog-footer { + .btn { + width: 80px; + } +} + +.blink{ + + span{ + animation: blink 1s linear infinite; + } + @keyframes blink{ + 0%{opacity: 0;} + 50%{opacity: .5;} + 100%{opacity: 1;} + } + +} + +.error{ + color: red; +} diff --git a/frontend/src/views/Header.js b/frontend/src/views/Header.js index 5d0f690..0af7abf 100644 --- a/frontend/src/views/Header.js +++ b/frontend/src/views/Header.js @@ -70,11 +70,11 @@ class Header extends Component { <div className="col"> <div className="header-buttons"> <Button onClick={this.props.onOpenFilters}>filters</Button> - <Button variant="yellow" size="sm">pcaps</Button> + <Button variant="warning" onClick={this.props.onOpenUpload}>pcaps</Button> <Button variant="blue" onClick={this.props.onOpenRules}>rules</Button> - <Button variant="red" onClick={this.props.onOpenServices}> - services - </Button> + <Button variant="red" onClick={this.props.onOpenServices}>services</Button> + <Button variant="green" onClick={this.props.onOpenConfig} + disabled={this.props.onConfigDone}>config</Button> </div> </div> </div> diff --git a/frontend/src/views/Services.js b/frontend/src/views/Services.js index b95b01c..0de021f 100644 --- a/frontend/src/views/Services.js +++ b/frontend/src/views/Services.js @@ -64,12 +64,23 @@ class Services extends Component { saveService() { if (this.state.portValid && this.state.nameValid) { - axios.put("/api/services", { - name: this.state.name, - port: this.state.port, - color: this.state.color, - notes: this.state.notes - }); + const requestOptions = { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + color: this.state.color, + name: this.state.name, + notes: this.state.notes, + port: this.state.port, + }) + }; + + + fetch('/api/services', requestOptions) + .then(function(response){ + console.log(response); + } + ); this.newService(); this.loadServices(); diff --git a/frontend/src/views/Upload.js b/frontend/src/views/Upload.js new file mode 100644 index 0000000..522afe8 --- /dev/null +++ b/frontend/src/views/Upload.js @@ -0,0 +1,106 @@ +import React, {Component} from 'react'; +import './Upload.scss'; +import {Button, ButtonGroup, Col, Container, Form, FormControl, InputGroup, Modal, Row, Table} from "react-bootstrap"; +import bsCustomFileInput from 'bs-custom-file-input' +import {createCurlCommand} from '../utils'; + +class Upload extends Component { + + constructor(props) { + super(props); + + this.state = { + selectedFile: null, + errors: "" + }; + + } + + onFileChange = event => { + this.setState({ selectedFile: event.target.files[0] }); + + }; + + componentDidMount() { + bsCustomFileInput.init() + } + + onFileUpload = () => { + const formData = new FormData(); + formData.append( + "file", + this.state.selectedFile, + this.state.selectedFile.name + ); + fetch('/api/pcap/upload', { + method: 'POST', + body: formData + }) + .then(response => { + if (response.status === 202 ){ + //this.setState({showConfig:false}); + this.props.onHide(); + //this.props.onDone(); + } else { + response.json().then(data => { + this.setState( + {errors : data.error.toString()} + ); + }); + } + } + ); + } + + + render() { + + return ( + <Modal + {...this.props} + show="true" + size="lg" + aria-labelledby="services-dialog" + centered + > + <Modal.Header> + <Modal.Title id="services-dialog"> + /usr/bin/upload + </Modal.Title> + </Modal.Header> + <Modal.Body> + <Container> + <Row> + <Form.File + type="file" + className="custom-file" + onChange={this.onFileChange} + label=".pcap/.pcapng" + id="custom-file" + custom + /> + </Row> + <Row> + <div class="error"> + <b> + <br/> + {this.state.errors + .split('\n').map((item, key) => { + return <span key={key}>{item}<br/></span>}) + } + </b> + </div> + </Row> + </Container> + </Modal.Body> + <Modal.Footer className="dialog-footer"> + + <Button variant="green" onClick={this.onFileUpload}>upload</Button> + <Button variant="red" onClick={this.props.onHide}>close</Button> + </Modal.Footer> + </Modal> + ); + } +} + +export default Upload; diff --git a/frontend/src/views/Upload.scss b/frontend/src/views/Upload.scss new file mode 100644 index 0000000..e327b8c --- /dev/null +++ b/frontend/src/views/Upload.scss @@ -0,0 +1,21 @@ +@import '../colors.scss'; + +.curl-output { + width: 100%; + font-size: 13px; +} + +#pcap-upload{ + align: center; + width: 100%; +} + +.btn-color { + border: 3px solid #fff; +} + +.dialog-footer { + .btn { + width: 80px; + } +} diff --git a/frontend/yarn.lock b/frontend/yarn.lock index b7fc583..39d346b 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -2801,6 +2801,12 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.6.2, browserslist@^4. escalade "^3.0.2" node-releases "^1.1.61" +bs-custom-file-input@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/bs-custom-file-input/-/bs-custom-file-input-1.3.4.tgz#c275cb8d4f1c02ba026324292509fa9a747dbda8" + integrity sha512-NBsQzTnef3OW1MvdKBbMHAYHssCd613MSeJV7z2McXznWtVMnJCy7Ckyc+PwxV6Pk16cu6YBcYWh/ZE0XWNKCA== +>>>>>>> 98355cdf838d8c18e9a28176ae7a847770545395 + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" |