diff options
Diffstat (limited to 'frontend/src/components/panels/ConnectionsPane.jsx')
-rw-r--r-- | frontend/src/components/panels/ConnectionsPane.jsx | 310 |
1 files changed, 0 insertions, 310 deletions
diff --git a/frontend/src/components/panels/ConnectionsPane.jsx b/frontend/src/components/panels/ConnectionsPane.jsx deleted file mode 100644 index 2c7fadd..0000000 --- a/frontend/src/components/panels/ConnectionsPane.jsx +++ /dev/null @@ -1,310 +0,0 @@ -/* - * This file is part of caronte (https://github.com/eciavatta/caronte). - * Copyright (c) 2020 Emiliano Ciavatta. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import React, {Component} from "react"; -import Table from "react-bootstrap/Table"; -import {Redirect} from "react-router"; -import {withRouter} from "react-router-dom"; -import backend from "../../backend"; -import dispatcher from "../../dispatcher"; -import log from "../../log"; -import {updateParams} from "../../utils"; -import ButtonField from "../fields/ButtonField"; -import Connection from "../objects/Connection"; -import ConnectionMatchedRules from "../objects/ConnectionMatchedRules"; -import "./ConnectionsPane.scss"; - -import classNames from 'classnames'; - -class ConnectionsPane extends Component { - - state = { - loading: false, - connections: [], - firstConnection: null, - lastConnection: null, - }; - - constructor(props) { - super(props); - - this.scrollTopThreashold = 0.00001; - this.scrollBottomThreashold = 0.99999; - this.maxConnections = 200; - this.queryLimit = 50; - this.connectionsListRef = React.createRef(); - this.lastScrollPosition = 0; - } - - componentDidMount() { - let urlParams = new URLSearchParams(this.props.location.search); - this.setState({urlParams}); - - const additionalParams = {limit: this.queryLimit}; - - const match = this.props.location.pathname.match(/^\/connections\/([a-f0-9]{24})$/); - if (match != null) { - const id = match[1]; - additionalParams.from = id; - backend.get(`/api/connections/${id}`) - .then((res) => this.connectionSelected(res.json)) - .catch((error) => log.error("Error loading initial connection", error)); - } - - this.loadConnections(additionalParams, urlParams, true).then(() => log.debug("Connections loaded")); - - dispatcher.register("connections_filters", this.handleConnectionsFilters); - dispatcher.register("timeline_updates", this.handleTimelineUpdates); - dispatcher.register("notifications", this.handleNotifications); - dispatcher.register("pulse_connections_view", this.handlePulseConnectionsView); - } - - componentWillUnmount() { - dispatcher.unregister(this.handleConnectionsFilters); - dispatcher.unregister(this.handleTimelineUpdates); - dispatcher.unregister(this.handleNotifications); - dispatcher.unregister(this.handlePulseConnectionsView); - } - - handleConnectionsFilters = (payload) => { - const newParams = updateParams(this.state.urlParams, payload); - if (this.state.urlParams.toString() === newParams.toString()) { - return; - } - - log.debug("Update following url params:", payload); - this.queryStringRedirect = true; - this.setState({urlParams: newParams}); - - this.loadConnections({limit: this.queryLimit}, newParams) - .then(() => log.info("ConnectionsPane reloaded after query string update")); - }; - - handleTimelineUpdates = (payload) => { - this.connectionsListRef.current.scrollTop = 0; - this.loadConnections({ - "started_after": Math.round(payload.from.getTime() / 1000), - "started_before": Math.round(payload.to.getTime() / 1000), - limit: this.maxConnections - }).then(() => log.info(`Loading connections between ${payload.from} and ${payload.to}`)); - }; - - handleNotifications = (payload) => { - if (payload.event === "rules.new" || payload.event === "rules.edit") { - this.loadRules().then(() => log.debug("Loaded connection rules after notification update")); - } - if (payload.event === "services.edit") { - this.loadServices().then(() => log.debug("Services reloaded after notification update")); - } - }; - - handlePulseConnectionsView = (payload) => { - this.setState({pulseConnectionsView: true}); - setTimeout(() => this.setState({pulseConnectionsView: false}), payload.duration); - }; - - connectionSelected = (c) => { - this.connectionSelectedRedirect = true; - this.setState({selected: c.id}); - this.props.onSelected(c); - log.debug(`Connection ${c.id} selected`); - }; - - handleScroll = (e) => { - if (this.disableScrollHandler) { - this.lastScrollPosition = e.currentTarget.scrollTop; - return; - } - - let relativeScroll = e.currentTarget.scrollTop / (e.currentTarget.scrollHeight - e.currentTarget.clientHeight); - if (!this.state.loading && relativeScroll > this.scrollBottomThreashold) { - this.loadConnections({from: this.state.lastConnection.id, limit: this.queryLimit,}) - .then(() => log.info("Following connections loaded")); - } - if (!this.state.loading && relativeScroll < this.scrollTopThreashold) { - this.loadConnections({to: this.state.firstConnection.id, limit: this.queryLimit,}) - .then(() => log.info("Previous connections loaded")); - if (this.state.showMoreRecentButton) { - this.setState({showMoreRecentButton: false}); - } - } else { - if (this.lastScrollPosition > e.currentTarget.scrollTop) { - if (!this.state.showMoreRecentButton) { - this.setState({showMoreRecentButton: true}); - } - } else { - if (this.state.showMoreRecentButton) { - this.setState({showMoreRecentButton: false}); - } - } - } - this.lastScrollPosition = e.currentTarget.scrollTop; - }; - - async loadConnections(additionalParams, initialParams = null, isInitial = false) { - if (!initialParams) { - initialParams = this.state.urlParams; - } - const urlParams = new URLSearchParams(initialParams.toString()); - for (const [name, value] of Object.entries(additionalParams)) { - urlParams.set(name, value); - } - - this.setState({loading: true}); - if (!this.state.rules) { - await this.loadRules(); - } - if (!this.state.services) { - await this.loadServices(); - } - - let res = (await backend.get(`/api/connections?${urlParams}`)).json; - - let connections = this.state.connections; - let firstConnection = this.state.firstConnection; - let lastConnection = this.state.lastConnection; - - if (additionalParams && additionalParams.from && !additionalParams.to) { - if (res.length > 0) { - if (!isInitial) { - res = res.slice(1); - } - connections = this.state.connections.concat(res); - lastConnection = connections[connections.length - 1]; - if (isInitial) { - firstConnection = connections[0]; - } - if (connections.length > this.maxConnections) { - connections = connections.slice(connections.length - this.maxConnections, - connections.length - 1); - firstConnection = connections[0]; - } - } - } else if (additionalParams && additionalParams.to && !additionalParams.from) { - if (res.length > 0) { - connections = res.slice(0, res.length - 1).concat(this.state.connections); - firstConnection = connections[0]; - if (connections.length > this.maxConnections) { - connections = connections.slice(0, this.maxConnections); - lastConnection = connections[this.maxConnections - 1]; - } - } - } else { - if (res.length > 0) { - connections = res; - firstConnection = connections[0]; - lastConnection = connections[connections.length - 1]; - } else { - connections = []; - firstConnection = null; - lastConnection = null; - } - } - - this.setState({loading: false, connections, firstConnection, lastConnection}); - - if (firstConnection != null && lastConnection != null) { - dispatcher.dispatch("connection_updates", { - from: new Date(lastConnection["started_at"]), - to: new Date(firstConnection["started_at"]) - }); - } - } - - loadRules = async () => { - return backend.get("/api/rules").then((res) => this.setState({rules: res.json})); - }; - - loadServices = async () => { - return backend.get("/api/services").then((res) => this.setState({services: res.json})); - }; - - render() { - let redirect; - if (this.connectionSelectedRedirect) { - redirect = <Redirect push to={`/connections/${this.state.selected}?${this.state.urlParams}`}/>; - this.connectionSelectedRedirect = false; - } else if (this.queryStringRedirect) { - redirect = <Redirect push to={`${this.props.location.pathname}?${this.state.urlParams}`}/>; - this.queryStringRedirect = false; - } - - let loading = null; - if (this.state.loading) { - loading = <tr> - <td colSpan={10}>Loading...</td> - </tr>; - } - - return ( - <div className="connections-container"> - {this.state.showMoreRecentButton && <div className="most-recent-button"> - <ButtonField name="most_recent" variant="green" bordered onClick={() => { - this.disableScrollHandler = true; - this.connectionsListRef.current.scrollTop = 0; - this.loadConnections({limit: this.queryLimit}) - .then(() => { - this.disableScrollHandler = false; - log.info("Most recent connections loaded"); - }); - }}/> - </div>} - - <div className={classNames("connections", {"connections-pulse": this.state.pulseConnectionsView})} - onScroll={this.handleScroll} ref={this.connectionsListRef}> - <Table borderless size="sm"> - <thead> - <tr> - <th>service</th> - <th>srcip</th> - <th>srcport</th> - <th>dstip</th> - <th>dstport</th> - <th>started_at</th> - <th>duration</th> - <th>up</th> - <th>down</th> - <th>actions</th> - </tr> - </thead> - <tbody> - { - this.state.connections.flatMap((c) => { - return [<Connection key={c.id} data={c} onSelected={() => this.connectionSelected(c)} - selected={this.state.selected === c.id} - onMarked={(marked) => c.marked = marked} - onCommented={(comment) => c.comment = comment} - services={this.state.services}/>, - c.matched_rules.length > 0 && - <ConnectionMatchedRules key={c.id + "_m"} matchedRules={c.matched_rules} - rules={this.state.rules}/> - ]; - }) - } - {loading} - </tbody> - </Table> - - {redirect} - </div> - </div> - ); - } - -} - -export default withRouter(ConnectionsPane); |