aboutsummaryrefslogtreecommitdiff
path: root/frontend/src
diff options
context:
space:
mode:
authorEmiliano Ciavatta2020-04-29 13:13:20 +0000
committerEmiliano Ciavatta2020-04-29 13:13:20 +0000
commit3f3ae121ef082a430f4bdc84ab7970a5633d552a (patch)
treedc08aea5263e33d9b456bf03a99a33bc261a723d /frontend/src
parentd1eeb1a6b3eed3c666cc6f94ba2a932abbce8515 (diff)
Frontend checkpoint
Diffstat (limited to 'frontend/src')
-rw-r--r--frontend/src/App.css38
-rw-r--r--frontend/src/App.js26
-rw-r--r--frontend/src/App.test.js9
-rw-r--r--frontend/src/colors.scss11
-rw-r--r--frontend/src/components/Connection.js73
-rw-r--r--frontend/src/components/Connection.scss54
-rw-r--r--frontend/src/components/ConnectionContent.js61
-rw-r--r--frontend/src/components/ConnectionContent.scss28
-rw-r--r--frontend/src/index.css13
-rw-r--r--frontend/src/index.js5
-rw-r--r--frontend/src/index.scss88
-rw-r--r--frontend/src/views/App.js26
-rw-r--r--frontend/src/views/App.scss2
-rw-r--r--frontend/src/views/Connections.js96
-rw-r--r--frontend/src/views/Connections.scss13
-rw-r--r--frontend/src/views/Footer.js19
-rw-r--r--frontend/src/views/Footer.scss14
-rw-r--r--frontend/src/views/Header.js48
-rw-r--r--frontend/src/views/Header.scss18
-rw-r--r--frontend/src/views/MainPane.js49
-rw-r--r--frontend/src/views/MainPane.scss9
21 files changed, 612 insertions, 88 deletions
diff --git a/frontend/src/App.css b/frontend/src/App.css
deleted file mode 100644
index 74b5e05..0000000
--- a/frontend/src/App.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.App {
- text-align: center;
-}
-
-.App-logo {
- height: 40vmin;
- pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
- .App-logo {
- animation: App-logo-spin infinite 20s linear;
- }
-}
-
-.App-header {
- background-color: #282c34;
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: calc(10px + 2vmin);
- color: white;
-}
-
-.App-link {
- color: #61dafb;
-}
-
-@keyframes App-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
diff --git a/frontend/src/App.js b/frontend/src/App.js
deleted file mode 100644
index ce9cbd2..0000000
--- a/frontend/src/App.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react';
-import logo from './logo.svg';
-import './App.css';
-
-function App() {
- return (
- <div className="App">
- <header className="App-header">
- <img src={logo} className="App-logo" alt="logo" />
- <p>
- Edit <code>src/App.js</code> and save to reload.
- </p>
- <a
- className="App-link"
- href="https://reactjs.org"
- target="_blank"
- rel="noopener noreferrer"
- >
- Learn React
- </a>
- </header>
- </div>
- );
-}
-
-export default App;
diff --git a/frontend/src/App.test.js b/frontend/src/App.test.js
deleted file mode 100644
index 4db7ebc..0000000
--- a/frontend/src/App.test.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import React from 'react';
-import { render } from '@testing-library/react';
-import App from './App';
-
-test('renders learn react link', () => {
- const { getByText } = render(<App />);
- const linkElement = getByText(/learn react/i);
- expect(linkElement).toBeInTheDocument();
-});
diff --git a/frontend/src/colors.scss b/frontend/src/colors.scss
new file mode 100644
index 0000000..290a0cd
--- /dev/null
+++ b/frontend/src/colors.scss
@@ -0,0 +1,11 @@
+$color-primary-0: #17223B; // Main Primary color */
+$color-primary-1: #040B1B;
+$color-primary-2: #0F192E;
+$color-primary-3: #1D2841;
+$color-primary-4: #EAEAEA;
+
+$color-secondary-0: #FF6767;
+$color-secondary-1: #A20A0A;
+$color-secondary-2: #DF3030;
+$color-secondary-3: #FF9D9D;
+$color-secondary-4: #FFDFDF;
diff --git a/frontend/src/components/Connection.js b/frontend/src/components/Connection.js
new file mode 100644
index 0000000..4bdc8cd
--- /dev/null
+++ b/frontend/src/components/Connection.js
@@ -0,0 +1,73 @@
+import React, {Component} from 'react';
+import './Connection.scss';
+import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
+import {
+ faCloudDownloadAlt,
+ faCloudUploadAlt,
+ faComment,
+ faEyeSlash,
+ faHourglassHalf,
+ faLaptop,
+ faLink,
+ faServer,
+ faThumbtack,
+} from '@fortawesome/free-solid-svg-icons'
+
+class Connection extends Component {
+ render() {
+ let conn = this.props.data
+ let serviceName = "assign"
+ let serviceColor = "#fff"
+ if (conn.service != null) {
+ serviceName = conn.service.name
+ serviceColor = conn.service.color
+ }
+ let startedAt = new Date(conn.started_at)
+ let closedAt = new Date(conn.closed_at)
+ let duration = ((closedAt - startedAt) / 1000).toFixed(3)
+ let timeInfo = `Started at ${startedAt}\nClosed at ${closedAt}\nProcessed at ${new Date(conn.processed_at)}`
+
+
+ return (
+ <tr className={conn.marked ? "connection connection-marked" : "connection"}>
+ <div className="connection-header">
+ <span className="connection-service">
+ <button className="btn" style={{
+ "backgroundColor": serviceColor
+ }}>{serviceName}</button>
+ </span>
+ <span className="connection-src">
+ <FontAwesomeIcon icon={faLaptop}/>
+ <span className="connection-ip-port">{conn.ip_src}:{conn.port_src}</span>
+ </span>
+ <span className="connection-separator">{"->"}</span>
+ <span className="connection-dst">
+ <FontAwesomeIcon icon={faServer}/>
+ <span className="connection-ip-port">{conn.ip_dst}:{conn.port_dst}</span>
+ </span>
+
+ <span className="connection-duration" data-toggle="tooltip" data-placement="top" title={timeInfo}>
+ <FontAwesomeIcon icon={faHourglassHalf}/>
+ <span className="connection-seconds">{duration}s</span>
+ </span>
+ <span className="connection-bytes">
+ <FontAwesomeIcon icon={faCloudDownloadAlt}/>
+ <span className="connection-bytes-count">{conn.client_bytes}</span>
+ <FontAwesomeIcon icon={faCloudUploadAlt}/>
+ <span className="connection-bytes-count">{conn.server_bytes}</span>
+ </span>
+ <span className="connection-hide"><FontAwesomeIcon icon={faEyeSlash}/></span>
+ <span className="connection-mark"><FontAwesomeIcon icon={faThumbtack}/></span>
+ <span className="connection-comment"><FontAwesomeIcon icon={faComment}/></span>
+ <span className="connection-link"><FontAwesomeIcon icon={faLink}/></span>
+ </div>
+
+
+ </tr>
+ );
+ }
+
+}
+
+
+export default Connection;
diff --git a/frontend/src/components/Connection.scss b/frontend/src/components/Connection.scss
new file mode 100644
index 0000000..8910cb4
--- /dev/null
+++ b/frontend/src/components/Connection.scss
@@ -0,0 +1,54 @@
+@import '../colors.scss';
+
+.connection {
+ background-color: $color-primary-0;
+ margin-bottom: 5px;
+
+
+ &.connection-marked {
+ border-right: 5px solid $color-secondary-2;
+ }
+
+ .connection-service {
+ padding: 0 12px 0 0;
+
+ .btn {
+ font-size: 12px;
+ width: 120px;
+ }
+ }
+
+ .connection-separator {
+ margin: 0 10px;
+ }
+
+ .connection-duration {
+ margin-left: 15px;
+
+ //.connection-seconds {
+ // width: 75px;
+ // display: inline-block;
+ // text-align: right;
+ //}
+ }
+
+ .connection-bytes {
+ margin-left: 10px;
+ margin-right: 10px;
+
+ .connection-bytes-count {
+ margin-right: 5px;
+ }
+ }
+
+ .connection-hide, .connection-mark, .connection-comment, .connection-link {
+ margin-left: 5px;
+ }
+
+
+ svg {
+ margin-right: 6px;
+ }
+
+}
+
diff --git a/frontend/src/components/ConnectionContent.js b/frontend/src/components/ConnectionContent.js
new file mode 100644
index 0000000..061282c
--- /dev/null
+++ b/frontend/src/components/ConnectionContent.js
@@ -0,0 +1,61 @@
+import React, {Component} from 'react';
+import './ConnectionContent.scss';
+import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
+import {
+
+} from '@fortawesome/free-solid-svg-icons'
+import {useParams} from "react-router-dom";
+import { Dropdown } from 'react-bootstrap';
+
+class ConnectionContent extends Component {
+ render() {
+ let content = this.props.connectionPayload
+
+ console.log(content)
+
+ if (content === undefined) {
+ return <div>nope</div>
+ }
+
+ let payload = content.map(c =>
+ <span key={c.id} className={c.from_client ? "from-client" : "from-server"} title="cccccc">
+ {c.content}
+
+ </span>
+ )
+
+
+
+
+ return (
+ <div className="connection-content">
+ <div className="connection-content-options">
+ <Dropdown>
+ <Dropdown.Toggle variant="success" id="dropdown-basic">
+ format
+ </Dropdown.Toggle>
+
+ <Dropdown.Menu>
+ <Dropdown.Item href="#/action-1">plain</Dropdown.Item>
+ <Dropdown.Item href="#/action-2">hex</Dropdown.Item>
+ <Dropdown.Item href="#/action-3">hexdump</Dropdown.Item>
+ <Dropdown.Item href="#/action-3">base32</Dropdown.Item>
+ <Dropdown.Item href="#/action-3">base64</Dropdown.Item>
+ <Dropdown.Item href="#/action-3">ascii</Dropdown.Item>
+ </Dropdown.Menu>
+ </Dropdown>
+
+
+ </div>
+
+ <pre>{payload}</pre>
+
+
+ </div>
+ );
+ }
+
+}
+
+
+export default ConnectionContent;
diff --git a/frontend/src/components/ConnectionContent.scss b/frontend/src/components/ConnectionContent.scss
new file mode 100644
index 0000000..074d975
--- /dev/null
+++ b/frontend/src/components/ConnectionContent.scss
@@ -0,0 +1,28 @@
+@import '../colors.scss';
+
+.connection-content {
+ background-color: $color-primary-3;
+ height: 100%;
+ overflow: auto;
+
+
+ pre {
+ background-color: $color-primary-0;
+ padding: 10px 20px;
+ word-break: break-all;
+ }
+
+ .from-client {
+ color: #d4e0fc;
+ }
+
+ .from-server {
+ color: $color-secondary-4;
+
+ &:hover {
+ background-color: $color-primary-3;
+ border-top: 1px solid $color-primary-1;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/frontend/src/index.css b/frontend/src/index.css
deleted file mode 100644
index ec2585e..0000000
--- a/frontend/src/index.css
+++ /dev/null
@@ -1,13 +0,0 @@
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
- monospace;
-}
diff --git a/frontend/src/index.js b/frontend/src/index.js
index f5185c1..2e90371 100644
--- a/frontend/src/index.js
+++ b/frontend/src/index.js
@@ -1,7 +1,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
-import './index.css';
-import App from './App';
+import 'bootstrap/dist/css/bootstrap.css';
+import './index.scss';
+import App from './views/App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
diff --git a/frontend/src/index.scss b/frontend/src/index.scss
new file mode 100644
index 0000000..5c18095
--- /dev/null
+++ b/frontend/src/index.scss
@@ -0,0 +1,88 @@
+@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500&display=swap');
+@import-normalize;
+
+@import 'colors.scss';
+
+
+body {
+ margin: 0;
+ font-family: 'Fira Code', monospace;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ background-color: $color-primary-2;
+ color: $color-primary-4;
+
+ height: 100%;
+ max-height: 100%;
+}
+
+pre {
+ font-family: 'Fira Code', monospace;
+ font-size: 14px;
+}
+
+button {
+ :focus {
+ outline: none;
+ box-shadow: none;
+ }
+}
+
+.btn {
+ border-radius: 0;
+ color: $color-primary-4;
+}
+
+.btn-primary {
+ margin-left: 20px;
+ padding: 5px 12px;
+ background-color: $color-secondary-2;
+ font-weight: 500;
+ border: 0;
+ border-bottom: 5px solid $color-secondary-1;
+
+ color: $color-secondary-4;
+ outline:none;
+
+
+ :focus, :active {
+ outline: none;
+ box-shadow: none;
+ }
+
+}
+
+.btn-primary:hover {
+ background-color: $color-secondary-1;
+ border-color: $color-secondary-1;
+ outline: none;
+}
+
+a {
+ color: $color-primary-4;
+
+ &:hover {
+ color: $color-primary-4;
+ text-decoration: none;
+ }
+}
+
+/* width */
+::-webkit-scrollbar {
+ width: 12px;
+}
+
+/* Track */
+::-webkit-scrollbar-track {
+ background: $color-primary-0;
+}
+
+/* Handle */
+::-webkit-scrollbar-thumb {
+ background: $color-primary-1;
+}
+
+/* Handle on hover */
+::-webkit-scrollbar-thumb:hover {
+ background: $color-secondary-2;
+} \ No newline at end of file
diff --git a/frontend/src/views/App.js b/frontend/src/views/App.js
new file mode 100644
index 0000000..4d80da5
--- /dev/null
+++ b/frontend/src/views/App.js
@@ -0,0 +1,26 @@
+import React, {Component} from 'react';
+import Header from "./Header";
+import './App.scss';
+import MainPane from "./MainPane";
+import Footer from "./Footer";
+import {Route, BrowserRouter as Router, Switch} from "react-router-dom";
+
+class App extends Component {
+
+ render() {
+ return (
+ <div className="app">
+ <Router>
+ <Header/>
+ <Switch>
+ <Route path="/" children={<MainPane/>} />
+ <Route path="/connection/:id" children={<MainPane/>} />
+ </Switch>
+ <Footer/>
+ </Router>
+ </div>
+ );
+ }
+}
+
+export default App;
diff --git a/frontend/src/views/App.scss b/frontend/src/views/App.scss
new file mode 100644
index 0000000..2ee17ac
--- /dev/null
+++ b/frontend/src/views/App.scss
@@ -0,0 +1,2 @@
+.app {
+} \ No newline at end of file
diff --git a/frontend/src/views/Connections.js b/frontend/src/views/Connections.js
new file mode 100644
index 0000000..5876a40
--- /dev/null
+++ b/frontend/src/views/Connections.js
@@ -0,0 +1,96 @@
+import React, {Component} from 'react';
+import './Connections.scss';
+import axios from 'axios'
+import Connection from "../components/Connection";
+import {Link} from "react-router-dom";
+import Table from 'react-bootstrap/Table';
+
+class Connections extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ connections: [],
+ };
+ }
+
+
+ componentDidMount() {
+ axios.get("/api/connections").then(res => this.setState({connections: res.data}))
+ }
+
+ render() {
+ let connection = {
+ "id": "5dd95ff0fe7ae01ae7f419c2",
+ "ip_src": "10.62.82.1",
+ "ip_dst": "10.62.82.2",
+ "port_src": 59113,
+ "port_dst": 23179,
+ "started_at": "2019-11-23T16:36:00.1Z",
+ "closed_at": "2019-11-23T16:36:00.971Z",
+ "client_bytes": 331,
+ "server_bytes": 85,
+ "client_documents": 1,
+ "server_documents": 1,
+ "processed_at": "2020-04-21T17:10:29.532Z",
+ "matched_rules": [],
+ "hidden": false,
+ "marked": true,
+ "comment": "",
+ "service": {
+ "port": 23179,
+ "name": "kaboom",
+ "color": "#3C6D3C",
+ "notes": "wdddoddddddw"
+ }
+ }
+
+ return (
+ <div className="connections">
+ <Table striped hover>
+ <thead>
+ <tr>
+ <th>service</th>
+ <th>srcip</th>
+ <th>dstip</th>
+ <th>srcport</th>
+ <th>dstport</th>
+ <th>duration</th>
+ <th>up</th>
+ <th>down</th>
+ <th>actions</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>1</td>
+ <td>Mark</td>
+ <td>Otto</td>
+ <td>@mdo</td>
+ </tr>
+ <tr>
+ <td>2</td>
+ <td>Jacob</td>
+ <td>Thornton</td>
+ <td>@fat</td>
+ </tr>
+ <tr>
+ <td>3</td>
+ <td colSpan="2">Larry the Bird</td>
+ <td>@twitter</td>
+ </tr>
+ </tbody>
+ </Table>
+
+ {
+ this.state.connections.map(c =>
+ <Link to={"/connection/" + c.id}><Connection data={c} /></Link>
+ )
+ }
+ </div>
+ );
+ }
+
+}
+
+
+export default Connections;
diff --git a/frontend/src/views/Connections.scss b/frontend/src/views/Connections.scss
new file mode 100644
index 0000000..da74e11
--- /dev/null
+++ b/frontend/src/views/Connections.scss
@@ -0,0 +1,13 @@
+@import '../colors.scss';
+
+.connections {
+ background-color: $color-primary-3;
+ padding: 10px 10px 10px 10px;
+
+ height: 100%;
+ overflow: auto;
+
+ .table {
+ color: $color-primary-4;
+ }
+} \ No newline at end of file
diff --git a/frontend/src/views/Footer.js b/frontend/src/views/Footer.js
new file mode 100644
index 0000000..b6ffd9d
--- /dev/null
+++ b/frontend/src/views/Footer.js
@@ -0,0 +1,19 @@
+import React, {Component} from 'react';
+import './Footer.scss';
+
+class Footer extends Component {
+
+ render() {
+ return (
+ <footer className="footer container-fluid">
+ <div className="row">
+ <div className="col-12">
+ <div className="footer-timeline">timeline</div>
+ </div>
+ </div>
+ </footer>
+ )
+ }
+}
+
+export default Footer;
diff --git a/frontend/src/views/Footer.scss b/frontend/src/views/Footer.scss
new file mode 100644
index 0000000..9a8cacb
--- /dev/null
+++ b/frontend/src/views/Footer.scss
@@ -0,0 +1,14 @@
+@import '../colors.scss';
+
+.footer {
+ padding: 15px 30px;
+
+ >.row {
+ background-color: $color-primary-0;
+ }
+
+ .footer-timeline {
+ height: 100px;
+ }
+
+} \ No newline at end of file
diff --git a/frontend/src/views/Header.js b/frontend/src/views/Header.js
new file mode 100644
index 0000000..b3f919b
--- /dev/null
+++ b/frontend/src/views/Header.js
@@ -0,0 +1,48 @@
+import React, {Component} from 'react';
+import Typed from 'typed.js';
+import './Header.scss';
+
+class Header extends Component {
+
+ componentDidMount() {
+ const options = {
+ strings: ["caronte$ "],
+ typeSpeed: 50,
+ cursorChar: "❚"
+ };
+ this.typed = new Typed(this.el, options);
+ }
+
+ componentWillUnmount() {
+ this.typed.destroy();
+ }
+
+ render() {
+ return (
+ <header className="header container-fluid">
+ <div className="row">
+ <div className="col">
+ <h1 className="header-title type-wrap">
+ <span style={{ whiteSpace: 'pre' }} ref={(el) => { this.el = el; }} />
+ </h1>
+ </div>
+ <div className="col">
+ <div className="header-buttons">
+ <button className="btn-primary">
+ ➕ pcaps
+ </button>
+ <button className="btn-primary">
+ ➕ rules
+ </button>
+ <button className="btn-primary">
+ ➕ services
+ </button>
+ </div>
+ </div>
+ </div>
+ </header>
+ )
+ }
+}
+
+export default Header;
diff --git a/frontend/src/views/Header.scss b/frontend/src/views/Header.scss
new file mode 100644
index 0000000..16c2dbd
--- /dev/null
+++ b/frontend/src/views/Header.scss
@@ -0,0 +1,18 @@
+@import '../colors.scss';
+
+.header {
+ padding: 15px 30px;
+
+ >.row {
+ background-color: $color-primary-0;
+ }
+
+ .header-title {
+ margin: 5px 0 5px -5px;
+ }
+
+ .header-buttons {
+ margin: 5px 0;
+ text-align: right;
+ }
+} \ No newline at end of file
diff --git a/frontend/src/views/MainPane.js b/frontend/src/views/MainPane.js
new file mode 100644
index 0000000..88b5376
--- /dev/null
+++ b/frontend/src/views/MainPane.js
@@ -0,0 +1,49 @@
+import React, {Component} from 'react';
+import './MainPane.scss';
+import Connections from "./Connections";
+import ConnectionContent from "../components/ConnectionContent";
+import {withRouter} from "react-router-dom";
+import axios from 'axios'
+
+class MainPane extends Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ id: null,
+ };
+ }
+
+ componentDidUpdate() {
+ if (this.props.match.params.id !== this.state.id) {
+ const id = this.props.match.params.id;
+ this.setState({id: id});
+
+ axios.get(`/api/streams/${id}`).then(res => this.setState({connectionContent: res.data}))
+
+
+ }
+ }
+
+ componentDidMount() {
+ }
+
+ render() {
+ return (
+ <div className="main-pane">
+ <div className="container-fluid">
+ <div className="row">
+ <div className="col-md-6 pane">
+ <Connections/>
+ </div>
+ <div className="col-md-6 pl-0 pane">
+ <ConnectionContent connectionPayload={this.state.connectionContent}/>
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+}
+
+export default withRouter(MainPane);
diff --git a/frontend/src/views/MainPane.scss b/frontend/src/views/MainPane.scss
new file mode 100644
index 0000000..c1a2f7f
--- /dev/null
+++ b/frontend/src/views/MainPane.scss
@@ -0,0 +1,9 @@
+.main-pane {
+
+ .pane {
+ height: calc(100vh - 210px);
+ position: relative;
+ }
+
+
+} \ No newline at end of file