diff options
-rw-r--r-- | application_router.go | 2 | ||||
-rw-r--r-- | frontend/src/components/App.js | 29 | ||||
-rw-r--r-- | frontend/src/components/Header.js | 12 | ||||
-rw-r--r-- | frontend/src/components/fields/InputField.js | 2 | ||||
-rw-r--r-- | frontend/src/components/objects/CopyLinkPopover.js | 4 | ||||
-rw-r--r-- | frontend/src/components/pages/ConfigurationPage.js | 12 | ||||
-rw-r--r-- | frontend/src/components/pages/ConfigurationPage.scss | 30 | ||||
-rw-r--r-- | frontend/src/components/pages/MainPage.js | 50 | ||||
-rw-r--r-- | frontend/src/components/panels/ConnectionsPane.js | 4 | ||||
-rw-r--r-- | frontend/src/components/panels/SearchPane.js | 6 | ||||
-rw-r--r-- | rules_manager.go | 5 |
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 } |