aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--application_router.go2
-rw-r--r--frontend/src/components/App.js29
-rw-r--r--frontend/src/components/Header.js12
-rw-r--r--frontend/src/components/fields/InputField.js2
-rw-r--r--frontend/src/components/objects/CopyLinkPopover.js4
-rw-r--r--frontend/src/components/pages/ConfigurationPage.js12
-rw-r--r--frontend/src/components/pages/ConfigurationPage.scss30
-rw-r--r--frontend/src/components/pages/MainPage.js50
-rw-r--r--frontend/src/components/panels/ConnectionsPane.js4
-rw-r--r--frontend/src/components/panels/SearchPane.js6
-rw-r--r--rules_manager.go5
11 files changed, 93 insertions, 63 deletions
diff --git a/application_router.go b/application_router.go
index 656b63e..4048dc5 100644
--- a/application_router.go
+++ b/application_router.go
@@ -39,7 +39,7 @@ func CreateApplicationRouter(applicationContext *ApplicationContext,
router.Use(static.Serve("/", static.LocalFile("./frontend/build", true)))
- for _, path := range []string{"/connections/:id", "/pcaps", "/rules", "/services", "/config"} {
+ for _, path := range []string{"/connections/:id", "/pcaps", "/rules", "/services", "/config", "/searches"} {
router.GET(path, func(c *gin.Context) {
c.File("./frontend/build/index.html")
})
diff --git a/frontend/src/components/App.js b/frontend/src/components/App.js
index e12a99d..96083cd 100644
--- a/frontend/src/components/App.js
+++ b/frontend/src/components/App.js
@@ -16,6 +16,7 @@
*/
import React, {Component} from "react";
+import {BrowserRouter as Router} from "react-router-dom";
import dispatcher from "../dispatcher";
import Notifications from "./Notifications";
import ConfigurationPage from "./pages/ConfigurationPage";
@@ -27,15 +28,7 @@ class App extends Component {
state = {};
componentDidMount() {
- dispatcher.register("notifications", (payload) => {
- if (payload.event === "connected") {
- this.setState({
- connected: true,
- configured: payload.message["is_configured"],
- version: payload.message["version"]
- });
- }
- });
+ dispatcher.register("notifications", this.handleNotifications);
setInterval(() => {
if (document.title.endsWith("❚")) {
@@ -46,16 +39,30 @@ class App extends Component {
}, 500);
}
+ componentWillUnmount() {
+ dispatcher.unregister(this.handleNotifications);
+ }
+
+ handleNotifications = (payload) => {
+ if (payload.event === "connected") {
+ this.setState({
+ connected: true,
+ configured: payload.message["is_configured"],
+ version: payload.message["version"]
+ });
+ }
+ };
+
render() {
return (
- <>
+ <Router>
<Notifications/>
{this.state.connected ?
(this.state.configured ? <MainPage version={this.state.version}/> :
<ConfigurationPage onConfigured={() => this.setState({configured: true})}/>) :
<ServiceUnavailablePage/>
}
- </>
+ </Router>
);
}
}
diff --git a/frontend/src/components/Header.js b/frontend/src/components/Header.js
index ab16dd1..c46d768 100644
--- a/frontend/src/components/Header.js
+++ b/frontend/src/components/Header.js
@@ -27,6 +27,8 @@ import RulesConnectionsFilter from "./filters/RulesConnectionsFilter";
import StringConnectionsFilter from "./filters/StringConnectionsFilter";
import "./Header.scss";
+const classNames = require("classnames");
+
class Header extends Component {
componentDidMount() {
@@ -46,7 +48,7 @@ class Header extends Component {
return (
<header className="header container-fluid">
<div className="row">
- <div className="col-auto">
+ <div className={classNames({"col-auto": this.props.configured, "col": !this.props.configured})}>
<h1 className="header-title type-wrap">
<Link to="/">
<span style={{whiteSpace: "pre"}} ref={(el) => {
@@ -56,7 +58,7 @@ class Header extends Component {
</h1>
</div>
- <div className="col-auto">
+ {this.props.configured && <div className="col-auto">
<div className="filters-bar">
<StringConnectionsFilter filterName="service_port"
defaultFilterValue="all_ports"
@@ -69,9 +71,9 @@ class Header extends Component {
<ExitSearchFilter/>
<AdvancedFilters onClick={this.props.onOpenFilters}/>
</div>
- </div>
+ </div>}
- <div className="col">
+ {this.props.configured && <div className="col">
<div className="header-buttons">
<Link to={"/searches" + this.props.location.search}>
<ButtonField variant="pink" name="searches" bordered/>
@@ -89,7 +91,7 @@ class Header extends Component {
<ButtonField variant="blue" name="config" bordered/>
</Link>
</div>
- </div>
+ </div>}
</div>
</header>
);
diff --git a/frontend/src/components/fields/InputField.js b/frontend/src/components/fields/InputField.js
index 823989d..e2ea020 100644
--- a/frontend/src/components/fields/InputField.js
+++ b/frontend/src/components/fields/InputField.js
@@ -75,7 +75,7 @@ class InputField extends Component {
aria-describedby={this.id} onChange={handler} {...inputProps}
readOnly={this.props.readonly}/>
</div>
- {type !== "file" && value !== "" &&
+ {type !== "file" && value !== "" && !this.props.readonly &&
<div className="field-clear">
<span onClick={() => handler(null)}>del</span>
</div>
diff --git a/frontend/src/components/objects/CopyLinkPopover.js b/frontend/src/components/objects/CopyLinkPopover.js
index fa9266f..b951603 100644
--- a/frontend/src/components/objects/CopyLinkPopover.js
+++ b/frontend/src/components/objects/CopyLinkPopover.js
@@ -37,10 +37,10 @@ class CopyLinkPopover extends Component {
};
render() {
- const copyPopoverContent = <div style={{"width": "400px"}}>
+ const copyPopoverContent = <div style={{"width": "250px"}}>
{this.state.copiedMessage ? <span><strong>Copied!</strong></span> :
<span>Click to <strong>copy</strong></span>}
- <TextField readonly rows={1} value={this.props.value} textRef={this.copyTextarea}/>
+ <TextField readonly rows={2} value={this.props.value} textRef={this.copyTextarea}/>
</div>;
return (
diff --git a/frontend/src/components/pages/ConfigurationPage.js b/frontend/src/components/pages/ConfigurationPage.js
index 4f0ce21..8f9b68b 100644
--- a/frontend/src/components/pages/ConfigurationPage.js
+++ b/frontend/src/components/pages/ConfigurationPage.js
@@ -25,8 +25,10 @@ import ButtonField from "../fields/ButtonField";
import CheckField from "../fields/CheckField";
import InputField from "../fields/InputField";
import TextField from "../fields/TextField";
+import Header from "../Header";
import LinkPopover from "../objects/LinkPopover";
import "../panels/common.scss";
+import "./common.scss";
import "./ConfigurationPage.scss";
class ConfigurationPage extends Component {
@@ -113,9 +115,13 @@ class ConfigurationPage extends Component {
</tr>);
return (
- <div className="configuration-page">
- <div className="pane">
- <div className="pane-container">
+ <div className="page configuration-page">
+ <div className="page-header">
+ <Header />
+ </div>
+
+ <div className="page-content">
+ <div className="pane-container configuration-pane">
<div className="pane-section">
<div className="section-header">
<span className="api-request">POST /setup</span>
diff --git a/frontend/src/components/pages/ConfigurationPage.scss b/frontend/src/components/pages/ConfigurationPage.scss
index 4509865..4254547 100644
--- a/frontend/src/components/pages/ConfigurationPage.scss
+++ b/frontend/src/components/pages/ConfigurationPage.scss
@@ -1,18 +1,30 @@
@import "../../colors";
.configuration-page {
- display: flex;
- align-items: center;
- justify-content: center;
- height: 100%;
background-color: $color-primary-0;
- .pane {
- flex-basis: 900px;
- margin-bottom: 200px;
+ .header-title {
+ margin: 50px auto;
}
- .pane-container {
- padding-bottom: 1px;
+ .configuration-pane {
+ display: flex;
+ justify-content: center;
+ height: 100%;
+ padding-top: 100px;
+
+ .section-content {
+ background-color: $color-primary-3;
+ margin-top: 15px;
+ }
+
+ .section-table table {
+ background-color: red !important;
+ }
+
+ .section-footer {
+ background-color: $color-primary-3;
+ }
}
}
+
diff --git a/frontend/src/components/pages/MainPage.js b/frontend/src/components/pages/MainPage.js
index a542e3f..c4dcd20 100644
--- a/frontend/src/components/pages/MainPage.js
+++ b/frontend/src/components/pages/MainPage.js
@@ -16,7 +16,7 @@
*/
import React, {Component} from "react";
-import {BrowserRouter as Router, Route, Switch} from "react-router-dom";
+import {Route, Switch} from "react-router-dom";
import Filters from "../dialogs/Filters";
import Header from "../Header";
import Connections from "../panels/ConnectionsPane";
@@ -42,34 +42,32 @@ class MainPage extends Component {
return (
<div className="page main-page">
- <Router>
- <div className="page-header">
- <Header onOpenFilters={() => this.setState({filterWindowOpen: true})}/>
- </div>
-
- <div className="page-content">
- <div className="pane connections-pane">
- <Connections onSelected={(c) => this.setState({selectedConnection: c})}/>
- </div>
- <div className="pane details-pane">
- <Switch>
- <Route path="/searches" children={<SearchPane/>}/>
- <Route path="/pcaps" children={<PcapsPane/>}/>
- <Route path="/rules" children={<RulesPane/>}/>
- <Route path="/services" children={<ServicesPane/>}/>
- <Route exact path="/connections/:id"
- children={<StreamsPane connection={this.state.selectedConnection}/>}/>
- <Route children={<MainPane version={this.props.version}/>}/>
- </Switch>
- </div>
+ <div className="page-header">
+ <Header onOpenFilters={() => this.setState({filterWindowOpen: true})} configured={true}/>
+ </div>
- {modal}
+ <div className="page-content">
+ <div className="pane connections-pane">
+ <Connections onSelected={(c) => this.setState({selectedConnection: c})}/>
</div>
-
- <div className="page-footer">
- <Timeline/>
+ <div className="pane details-pane">
+ <Switch>
+ <Route path="/searches" children={<SearchPane/>}/>
+ <Route path="/pcaps" children={<PcapsPane/>}/>
+ <Route path="/rules" children={<RulesPane/>}/>
+ <Route path="/services" children={<ServicesPane/>}/>
+ <Route exact path="/connections/:id"
+ children={<StreamsPane connection={this.state.selectedConnection}/>}/>
+ <Route children={<MainPane version={this.props.version}/>}/>
+ </Switch>
</div>
- </Router>
+
+ {modal}
+ </div>
+
+ <div className="page-footer">
+ <Timeline/>
+ </div>
</div>
);
}
diff --git a/frontend/src/components/panels/ConnectionsPane.js b/frontend/src/components/panels/ConnectionsPane.js
index 457c249..6418b3e 100644
--- a/frontend/src/components/panels/ConnectionsPane.js
+++ b/frontend/src/components/panels/ConnectionsPane.js
@@ -226,11 +226,11 @@ class ConnectionsPane extends Component {
}
loadRules = async () => {
- return backend.get("/api/rules").then(res => this.setState({rules: res.json}));
+ 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}));
+ return backend.get("/api/services").then((res) => this.setState({services: res.json}));
};
render() {
diff --git a/frontend/src/components/panels/SearchPane.js b/frontend/src/components/panels/SearchPane.js
index 4c9f229..4ef5632 100644
--- a/frontend/src/components/panels/SearchPane.js
+++ b/frontend/src/components/panels/SearchPane.js
@@ -236,13 +236,13 @@ class SearchPane extends Component {
})}
name="terms" min={3} inline allowNew={true}
readonly={regexOptionsModified || options["text_search"]["exact_phrase"]}
- onChange={(tags) => this.updateParam((s) => s["text_search"].terms = tags.map(t => t.name))}/>
- <TagField tags={(options["text_search"]["excluded_terms"] || []).map(t => {
+ onChange={(tags) => this.updateParam((s) => s["text_search"].terms = tags.map((t) => t.name))}/>
+ <TagField tags={(options["text_search"]["excluded_terms"] || []).map((t) => {
return {name: t};
})}
name="excluded_terms" min={3} inline allowNew={true}
readonly={regexOptionsModified || options["text_search"]["exact_phrase"]}
- onChange={(tags) => this.updateParam((s) => s["text_search"]["excluded_terms"] = tags.map(t => t.name))}/>
+ onChange={(tags) => this.updateParam((s) => s["text_search"]["excluded_terms"] = tags.map((t) => t.name))}/>
<span className="exclusive-separator">or</span>
diff --git a/rules_manager.go b/rules_manager.go
index a6d969f..5d6cded 100644
--- a/rules_manager.go
+++ b/rules_manager.go
@@ -24,6 +24,7 @@ import (
"github.com/flier/gohs/hyperscan"
"github.com/go-playground/validator/v10"
log "github.com/sirupsen/logrus"
+ "sort"
"sync"
"time"
)
@@ -213,6 +214,10 @@ func (rm *rulesManagerImpl) GetRules() []Rule {
rules = append(rules, rule)
}
+ sort.Slice(rules, func(i, j int) bool {
+ return rules[i].ID.Timestamp().Before(rules[j].ID.Timestamp())
+ })
+
return rules
}