From d5f94b76986615b255b77b2a7b7ed336e5ad4838 Mon Sep 17 00:00:00 2001 From: Emiliano Ciavatta Date: Wed, 7 Oct 2020 14:58:48 +0200 Subject: Implement notifications --- frontend/src/components/panels/PcapPane.js | 33 ++++---- frontend/src/components/panels/RulePane.js | 116 ++++++++++++++------------ frontend/src/components/panels/ServicePane.js | 35 ++++---- frontend/src/components/panels/common.scss | 4 +- 4 files changed, 99 insertions(+), 89 deletions(-) (limited to 'frontend/src/components/panels') diff --git a/frontend/src/components/panels/PcapPane.js b/frontend/src/components/panels/PcapPane.js index 31d8815..13f7cb3 100644 --- a/frontend/src/components/panels/PcapPane.js +++ b/frontend/src/components/panels/PcapPane.js @@ -9,28 +9,31 @@ import CheckField from "../fields/CheckField"; import TextField from "../fields/TextField"; import ButtonField from "../fields/ButtonField"; import LinkPopover from "../objects/LinkPopover"; +import dispatcher from "../../dispatcher"; class PcapPane extends Component { - constructor(props) { - super(props); - - this.state = { - sessions: [], - isUploadFileValid: true, - isUploadFileFocused: false, - uploadFlushAll: false, - isFileValid: true, - isFileFocused: false, - fileValue: "", - processFlushAll: false, - deleteOriginalFile: false - }; - } + state = { + sessions: [], + isUploadFileValid: true, + isUploadFileFocused: false, + uploadFlushAll: false, + isFileValid: true, + isFileFocused: false, + fileValue: "", + processFlushAll: false, + deleteOriginalFile: false + }; componentDidMount() { this.loadSessions(); + dispatcher.register("notifications", payload => { + if (payload.event === "pcap.upload" || payload.event === "pcap.file") { + this.loadSessions(); + } + }); + document.title = "caronte:~/pcaps$"; } diff --git a/frontend/src/components/panels/RulePane.js b/frontend/src/components/panels/RulePane.js index 4641378..76f3ac0 100644 --- a/frontend/src/components/panels/RulePane.js +++ b/frontend/src/components/panels/RulePane.js @@ -14,35 +14,13 @@ import ButtonField from "../fields/ButtonField"; import validation from "../../validation"; import LinkPopover from "../objects/LinkPopover"; import {randomClassName} from "../../utils"; +import dispatcher from "../../dispatcher"; const classNames = require('classnames'); const _ = require('lodash'); class RulePane extends Component { - constructor(props) { - super(props); - - this.state = { - rules: [], - newRule: this.emptyRule, - newPattern: this.emptyPattern - }; - - this.directions = { - 0: "both", - 1: "c->s", - 2: "s->c" - }; - } - - componentDidMount() { - this.reset(); - this.loadRules(); - - document.title = "caronte:~/rules$"; - } - emptyRule = { "name": "", "color": "", @@ -60,7 +38,6 @@ class RulePane extends Component { }, "version": 0 }; - emptyPattern = { "regex": "", "flags": { @@ -74,6 +51,34 @@ class RulePane extends Component { "max_occurrences": 0, "direction": 0 }; + state = { + rules: [], + newRule: this.emptyRule, + newPattern: this.emptyPattern + }; + + constructor(props) { + super(props); + + this.directions = { + 0: "both", + 1: "c->s", + 2: "s->c" + }; + } + + componentDidMount() { + this.reset(); + this.loadRules(); + + dispatcher.register("notifications", payload => { + if (payload.event === "rules.new" || payload.event === "rules.edit") { + this.loadRules(); + } + }); + + document.title = "caronte:~/rules$"; + } loadRules = () => { backend.get("/api/rules").then(res => this.setState({rules: res.json, rulesStatusCode: res.status})) @@ -226,17 +231,17 @@ class RulePane extends Component { { this.reset(); this.setState({selectedRule: _.cloneDeep(r)}); - }} className={classNames("row-small", "row-clickable", {"row-selected": rule.id === r.id })}> + }} className={classNames("row-small", "row-clickable", {"row-selected": rule.id === r.id})}> {r["id"].substring(0, 8)} {r["name"]} - + {r["notes"]} ); let patterns = (this.state.selectedPattern == null && !isUpdate ? - rule.patterns.concat(this.state.newPattern) : - rule.patterns + rule.patterns.concat(this.state.newPattern) : + rule.patterns ).map(p => p === pattern ? @@ -244,7 +249,7 @@ class RulePane extends Component { onChange={(v) => { this.updateParam(() => pattern.regex = v); this.setState({patternRegexFocused: pattern.regex === ""}); - }} /> + }}/> this.updateParam(() => pattern.flags.caseless = v)}/> @@ -259,34 +264,35 @@ class RulePane extends Component { this.updateParam(() => pattern.min_occurrences = v)} /> + onChange={(v) => this.updateParam(() => pattern.min_occurrences = v)}/> this.updateParam(() => pattern.max_occurrences = v)} /> + onChange={(v) => this.updateParam(() => pattern.max_occurrences = v)}/> s", "s->c"]} value={this.directions[pattern.direction]} - onChange={(v) => this.updateParam(() => pattern.direction = v)} /> + onChange={(v) => this.updateParam(() => pattern.direction = v)}/> {this.state.selectedPattern == null ? this.addPattern(p)}/> : - this.updatePattern(p)}/>} + this.updatePattern(p)}/>} : {p.regex} - {p.flags.caseless ? "yes": "no"} - {p.flags.dot_all ? "yes": "no"} - {p.flags.multi_line ? "yes": "no"} - {p.flags.utf_8_mode ? "yes": "no"} - {p.flags.unicode_property ? "yes": "no"} + {p.flags.caseless ? "yes" : "no"} + {p.flags.dot_all ? "yes" : "no"} + {p.flags.multi_line ? "yes" : "no"} + {p.flags.utf_8_mode ? "yes" : "no"} + {p.flags.unicode_property ? "yes" : "no"} {p.min_occurrences} {p.max_occurrences} {this.directions[p.direction]} {!isUpdate && this.editPattern(p) }/>} + onClick={() => this.editPattern(p)}/>} ); @@ -296,9 +302,9 @@ class RulePane extends Component {
GET /api/rules {this.state.rulesStatusCode && - } + }
@@ -327,7 +333,7 @@ class RulePane extends Component { + placement="left"/>
@@ -336,11 +342,11 @@ class RulePane extends Component { this.updateParam((r) => r.name = v)} - error={this.state.ruleNameError} /> + error={this.state.ruleNameError}/> this.updateParam((r) => r.color = v)} /> + onChange={(v) => this.updateParam((r) => r.color = v)}/> this.updateParam((r) => r.notes = v)} /> + onChange={(v) => this.updateParam((r) => r.notes = v)}/> @@ -348,29 +354,29 @@ class RulePane extends Component { this.updateParam((r) => r.filter.service_port = v)} min={0} max={65565} error={this.state.ruleServicePortError} - readonly={isUpdate} /> + readonly={isUpdate}/> this.updateParam((r) => r.filter.client_port = v)} min={0} max={65565} error={this.state.ruleClientPortError} - readonly={isUpdate} /> + readonly={isUpdate}/> this.updateParam((r) => r.filter.client_address = v)} /> + onChange={(v) => this.updateParam((r) => r.filter.client_address = v)}/> this.updateParam((r) => r.filter.min_duration = v)} /> + onChange={(v) => this.updateParam((r) => r.filter.min_duration = v)}/> this.updateParam((r) => r.filter.max_duration = v)} /> + onChange={(v) => this.updateParam((r) => r.filter.max_duration = v)}/> this.updateParam((r) => r.filter.min_bytes = v)} /> + onChange={(v) => this.updateParam((r) => r.filter.min_bytes = v)}/> this.updateParam((r) => r.filter.max_bytes = v)} /> + onChange={(v) => this.updateParam((r) => r.filter.max_bytes = v)}/> @@ -388,7 +394,7 @@ class RulePane extends Component { min max direction - {!isUpdate && actions } + {!isUpdate && actions} @@ -403,7 +409,7 @@ class RulePane extends Component {
{} + bordered onClick={isUpdate ? this.updateRule : this.addRule}/>
diff --git a/frontend/src/components/panels/ServicePane.js b/frontend/src/components/panels/ServicePane.js index 0e99652..22c6655 100644 --- a/frontend/src/components/panels/ServicePane.js +++ b/frontend/src/components/panels/ServicePane.js @@ -12,28 +12,13 @@ import ButtonField from "../fields/ButtonField"; import validation from "../../validation"; import LinkPopover from "../objects/LinkPopover"; import {createCurlCommand} from "../../utils"; +import dispatcher from "../../dispatcher"; const classNames = require('classnames'); const _ = require('lodash'); class ServicePane extends Component { - constructor(props) { - super(props); - - this.state = { - services: [], - currentService: this.emptyService, - }; - - document.title = "caronte:~/services$"; - } - - componentDidMount() { - this.reset(); - this.loadServices(); - } - emptyService = { "port": 0, "name": "", @@ -41,6 +26,24 @@ class ServicePane extends Component { "notes": "" }; + state = { + services: [], + currentService: this.emptyService, + }; + + componentDidMount() { + this.reset(); + this.loadServices(); + + dispatcher.register("notifications", payload => { + if (payload.event === "services.edit") { + this.loadServices(); + } + }); + + document.title = "caronte:~/services$"; + } + loadServices = () => { backend.get("/api/services") .then(res => this.setState({services: Object.values(res.json), servicesStatusCode: res.status})) diff --git a/frontend/src/components/panels/common.scss b/frontend/src/components/panels/common.scss index 121a917..1468f35 100644 --- a/frontend/src/components/panels/common.scss +++ b/frontend/src/components/panels/common.scss @@ -2,11 +2,9 @@ .pane-container { height: 100%; - padding: 10px 10px 0; background-color: $color-primary-3; .pane-section { - margin-bottom: 10px; background-color: $color-primary-0; .section-header { @@ -14,7 +12,7 @@ font-weight: 500; display: flex; padding: 5px 10px; - background-color: $color-primary-2; + background-color: $color-primary-3; .api-request { flex: 1; -- cgit v1.2.3-70-g09d2