aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/views/Connections.js
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/views/Connections.js')
-rw-r--r--frontend/src/views/Connections.js158
1 files changed, 101 insertions, 57 deletions
diff --git a/frontend/src/views/Connections.js b/frontend/src/views/Connections.js
index 73979c4..fe655b3 100644
--- a/frontend/src/views/Connections.js
+++ b/frontend/src/views/Connections.js
@@ -6,26 +6,31 @@ import {Redirect} from 'react-router';
import {withRouter} from "react-router-dom";
import backend from "../backend";
import ConnectionMatchedRules from "../components/ConnectionMatchedRules";
+import dispatcher from "../globals";
+import log from "../log";
+import ButtonField from "../components/fields/ButtonField";
class Connections extends Component {
+ state = {
+ loading: false,
+ connections: [],
+ firstConnection: null,
+ lastConnection: null,
+ flagRule: null,
+ rules: null,
+ queryString: null
+ };
+
constructor(props) {
super(props);
- this.state = {
- loading: false,
- connections: [],
- firstConnection: null,
- lastConnection: null,
- prevParams: null,
- flagRule: null,
- rules: null,
- queryString: null
- };
this.scrollTopThreashold = 0.00001;
this.scrollBottomThreashold = 0.99999;
- this.maxConnections = 500;
+ this.maxConnections = 200;
this.queryLimit = 50;
+ this.connectionsListRef = React.createRef();
+ this.lastScrollPosition = 0;
}
componentDidMount() {
@@ -35,6 +40,17 @@ class Connections extends Component {
this.setState({selected: this.props.initialConnection.id});
// TODO: scroll to initial connection
}
+
+ dispatcher.register((payload) => {
+ if (payload.actionType === "timeline-update") {
+ 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}`));
+ }
+ });
}
connectionSelected = (c) => {
@@ -46,7 +62,7 @@ class Connections extends Component {
if (this.state.loaded && prevProps.location.search !== this.props.location.search) {
this.setState({queryString: this.props.location.search});
this.loadConnections({limit: this.queryLimit})
- .then(() => console.log("Connections reloaded after query string update"));
+ .then(() => log.info("Connections reloaded after query string update"));
}
}
@@ -54,12 +70,26 @@ class Connections extends Component {
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(() => console.log("Following connections loaded"));
+ .then(() => log.info("Following connections loaded"));
}
if (!this.state.loading && relativeScroll < this.scrollTopThreashold) {
this.loadConnections({to: this.state.firstConnection.id, limit: this.queryLimit,})
- .then(() => console.log("Previous connections loaded"));
+ .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;
};
addServicePortFilter = (port) => {
@@ -85,14 +115,14 @@ class Connections extends Component {
urlParams.set(name, value);
}
- this.setState({loading: true, prevParams: params});
+ this.setState({loading: true});
let res = (await backend.get(`${url}?${urlParams}`)).json;
let connections = this.state.connections;
let firstConnection = this.state.firstConnection;
let lastConnection = this.state.lastConnection;
- if (params !== undefined && params.from !== undefined) {
+ if (params !== undefined && params.from !== undefined && params.to === undefined) {
if (res.length > 0) {
connections = this.state.connections.concat(res);
lastConnection = connections[connections.length - 1];
@@ -102,7 +132,7 @@ class Connections extends Component {
firstConnection = connections[0];
}
}
- } else if (params !== undefined && params.to !== undefined) {
+ } else if (params !== undefined && params.to !== undefined && params.from === undefined) {
if (res.length > 0) {
connections = res.concat(this.state.connections);
firstConnection = connections[0];
@@ -112,6 +142,7 @@ class Connections extends Component {
}
}
} else {
+ this.connectionsListRef.current.scrollTop = 0;
if (res.length > 0) {
connections = res;
firstConnection = connections[0];
@@ -124,7 +155,7 @@ class Connections extends Component {
}
let rules = this.state.rules;
- if (rules === null) {
+ if (rules == null) {
rules = (await backend.get("/api/rules")).json;
}
@@ -135,15 +166,21 @@ class Connections extends Component {
firstConnection: firstConnection,
lastConnection: lastConnection
});
+
+ if (firstConnection != null && lastConnection != null) {
+ dispatcher.dispatch({
+ actionType: "connections-update",
+ from: new Date(lastConnection["started_at"]),
+ to: new Date(firstConnection["started_at"])
+ });
+ }
}
render() {
let redirect;
let queryString = this.state.queryString !== null ? this.state.queryString : "";
if (this.state.selected) {
- let format = this.props.match.params.format;
- format = format !== undefined ? "/" + format : "";
- redirect = <Redirect push to={`/connections/${this.state.selected}${format}${queryString}`} />;
+ redirect = <Redirect push to={`/connections/${this.state.selected}${queryString}`}/>;
}
let loading = null;
@@ -154,48 +191,55 @@ class Connections extends Component {
}
return (
- <div className="connections" onScroll={this.handleScroll}>
- <div className="connections-header-padding"/>
- <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}
- onEnabled={enabled => c.hidden = !enabled}
- addServicePortFilter={this.addServicePortFilter} />,
- c.matched_rules.length > 0 &&
+ <div className="connections-container">
+ {this.state.showMoreRecentButton && <div className="most-recent-button">
+ <ButtonField name="most_recent" variant="green" onClick={() =>
+ this.loadConnections({limit: this.queryLimit})
+ .then(() => log.info("Most recent connections loaded"))
+ }/>
+ </div>}
+
+ <div className="connections" 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}
+ onEnabled={enabled => c.hidden = !enabled}
+ addServicePortFilter={this.addServicePortFilter}/>,
+ c.matched_rules.length > 0 &&
<ConnectionMatchedRules key={c.id + "_m"} matchedRules={c.matched_rules}
rules={this.state.rules}
- addMatchedRulesFilter={this.addMatchedRulesFilter} />
- ];
- })
- }
- {loading}
- </tbody>
- </Table>
-
- {redirect}
+ addMatchedRulesFilter={this.addMatchedRulesFilter}/>
+ ];
+ })
+ }
+ {loading}
+ </tbody>
+ </Table>
+
+ {redirect}
+ </div>
</div>
);
}
}
-
export default withRouter(Connections);