diff options
author | VaiTon | 2023-04-29 15:15:10 +0000 |
---|---|---|
committer | VaiTon | 2023-04-29 15:15:10 +0000 |
commit | b2632528a8a74505fc399e30df2ce6f5fe89363b (patch) | |
tree | e3b8f326b411e7b13c9af8d0f4a02475e475781e | |
parent | c5b25cab8d38177140713306273e120c91c44510 (diff) |
Add delete button to rules pane.
Format go files via `go fmt`.
-rw-r--r-- | application_context.go | 8 | ||||
-rw-r--r-- | application_router.go | 17 | ||||
-rw-r--r-- | application_router_test.go | 2 | ||||
-rw-r--r-- | connection_handler_test.go | 4 | ||||
-rw-r--r-- | frontend/src/components/panels/RulesPane.js | 206 | ||||
-rw-r--r-- | pcap_importer_test.go | 30 | ||||
-rw-r--r-- | resources_controller.go | 2 | ||||
-rw-r--r-- | rules_manager.go | 16 | ||||
-rw-r--r-- | search_controller.go | 3 | ||||
-rw-r--r-- | statistics_controller.go | 2 | ||||
-rw-r--r-- | stream_handler.go | 4 |
11 files changed, 169 insertions, 125 deletions
diff --git a/application_context.go b/application_context.go index 0410b88..fc3005a 100644 --- a/application_context.go +++ b/application_context.go @@ -65,10 +65,10 @@ func CreateApplicationContext(storage Storage, version string) (*ApplicationCont } applicationContext := &ApplicationContext{ - Storage: storage, - Config: configWrapper.Config, - Accounts: accountsWrapper.Accounts, - Version: version, + Storage: storage, + Config: configWrapper.Config, + Accounts: accountsWrapper.Accounts, + Version: version, } return applicationContext, nil diff --git a/application_router.go b/application_router.go index 1288eb1..d51843a 100644 --- a/application_router.go +++ b/application_router.go @@ -115,6 +115,23 @@ func CreateApplicationRouter(applicationContext *ApplicationContext, } }) + api.DELETE("/rules/:id", func(c *gin.Context) { + hex := c.Param("id") + id, err := RowIDFromHex(hex) + if err != nil { + badRequest(c, err) + return + } + + err = applicationContext.RulesManager.DeleteRule(c, id) + if err != nil { + notFound(c, UnorderedDocument{"id": id}) + } else { + success(c, UnorderedDocument{}) + notificationController.Notify("rules.delete", UnorderedDocument{"id": id}) + } + }) + api.PUT("/rules/:id", func(c *gin.Context) { hex := c.Param("id") id, err := RowIDFromHex(hex) diff --git a/application_router_test.go b/application_router_test.go index 27c3651..d4b545f 100644 --- a/application_router_test.go +++ b/application_router_test.go @@ -149,7 +149,7 @@ func TestPcapImporterApi(t *testing.T) { assert.Equal(t, http.StatusAccepted, toolkit.MakeRequest("DELETE", "/api/pcap/sessions/"+sessionID.Session, nil).Code) - time.Sleep(1*time.Second) // wait for termination + time.Sleep(1 * time.Second) // wait for termination toolkit.wrapper.Destroy(t) } diff --git a/connection_handler_test.go b/connection_handler_test.go index d980041..3f959c7 100644 --- a/connection_handler_test.go +++ b/connection_handler_test.go @@ -174,9 +174,9 @@ func TestConnectionFactory(t *testing.T) { timeout := time.Tick(10 * time.Second) for i := 0; i < n; i++ { select { - case <- completed: + case <-completed: continue - case <- timeout: + case <-timeout: t.Fatal("timeout") } } diff --git a/frontend/src/components/panels/RulesPane.js b/frontend/src/components/panels/RulesPane.js index dd1765d..771c764 100644 --- a/frontend/src/components/panels/RulesPane.js +++ b/frontend/src/components/panels/RulesPane.js @@ -15,8 +15,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import React, {Component} from "react"; -import {Col, Container, Row} from "react-bootstrap"; +import React, { Component } from "react"; +import { Col, Container, Row } from "react-bootstrap"; import Table from "react-bootstrap/Table"; import backend from "../../backend"; import dispatcher from "../../dispatcher"; @@ -103,31 +103,42 @@ class RulesPane extends Component { }; loadRules = () => { - backend.get("/api/rules").then((res) => this.setState({rules: res.json, rulesStatusCode: res.status})) - .catch((res) => this.setState({rulesStatusCode: res.status, rulesResponse: JSON.stringify(res.json)})); + backend.get("/api/rules").then((res) => this.setState({ rules: res.json, rulesStatusCode: res.status })) + .catch((res) => this.setState({ rulesStatusCode: res.status, rulesResponse: JSON.stringify(res.json) })); }; addRule = () => { if (this.validateRule(this.state.newRule)) { backend.post("/api/rules", this.state.newRule).then((res) => { this.reset(); - this.setState({ruleStatusCode: res.status}); + this.setState({ ruleStatusCode: res.status }); this.loadRules(); }).catch((res) => { - this.setState({ruleStatusCode: res.status, ruleResponse: JSON.stringify(res.json)}); + this.setState({ ruleStatusCode: res.status, ruleResponse: JSON.stringify(res.json) }); }); } }; + deleteRule = () => { + const rule = this.state.selectedRule; + backend.delete(`/api/rules/${rule.id}`).then((res) => { + this.reset(); + this.setState({ ruleStatusCode: res.status }); + this.loadRules(); + }).catch((res) => { + this.setState({ ruleStatusCode: res.status, ruleResponse: JSON.stringify(res.json) }); + }); + } + updateRule = () => { const rule = this.state.selectedRule; if (this.validateRule(rule)) { backend.put(`/api/rules/${rule.id}`, rule).then((res) => { this.reset(); - this.setState({ruleStatusCode: res.status}); + this.setState({ ruleStatusCode: res.status }); this.loadRules(); }).catch((res) => { - this.setState({ruleStatusCode: res.status, ruleResponse: JSON.stringify(res.json)}); + this.setState({ ruleStatusCode: res.status, ruleResponse: JSON.stringify(res.json) }); }); } }; @@ -135,35 +146,35 @@ class RulesPane extends Component { validateRule = (rule) => { let valid = true; if (rule.name.length < 3) { - this.setState({ruleNameError: "name.length < 3"}); + this.setState({ ruleNameError: "name.length < 3" }); valid = false; } if (!validation.isValidColor(rule.color)) { - this.setState({ruleColorError: "color is not hexcolor"}); + this.setState({ ruleColorError: "color is not hexcolor" }); valid = false; } if (!validation.isValidPort(rule.filter["service_port"])) { - this.setState({ruleServicePortError: "service_port > 65565"}); + this.setState({ ruleServicePortError: "service_port > 65565" }); valid = false; } if (!validation.isValidPort(rule.filter["client_port"])) { - this.setState({ruleClientPortError: "client_port > 65565"}); + this.setState({ ruleClientPortError: "client_port > 65565" }); valid = false; } if (!validation.isValidAddress(rule.filter["client_address"])) { - this.setState({ruleClientAddressError: "client_address is not ip_address"}); + this.setState({ ruleClientAddressError: "client_address is not ip_address" }); valid = false; } if (rule.filter["min_duration"] > rule.filter["max_duration"]) { - this.setState({ruleDurationError: "min_duration > max_dur."}); + this.setState({ ruleDurationError: "min_duration > max_dur." }); valid = false; } if (rule.filter["min_bytes"] > rule.filter["max_bytes"]) { - this.setState({ruleBytesError: "min_bytes > max_bytes"}); + this.setState({ ruleBytesError: "min_bytes > max_bytes" }); valid = false; } if (rule.patterns.length < 1) { - this.setState({rulePatternsError: "patterns.length < 1"}); + this.setState({ rulePatternsError: "patterns.length < 1" }); valid = false; } @@ -198,7 +209,7 @@ class RulesPane extends Component { updateParam = (callback) => { const updatedRule = this.currentRule(); callback(updatedRule); - this.setState({newRule: updatedRule}); + this.setState({ newRule: updatedRule }); }; currentRule = () => this.state.selectedRule != null ? this.state.selectedRule : this.state.newRule; @@ -210,7 +221,7 @@ class RulesPane extends Component { const newPattern = _.cloneDeep(this.emptyPattern); this.currentRule().patterns.push(pattern); - this.setState({newPattern}); + this.setState({ newPattern }); }; editPattern = (pattern) => { @@ -233,11 +244,11 @@ class RulesPane extends Component { let valid = true; if (pattern.regex === "") { valid = false; - this.setState({patternRegexFocused: true}); + this.setState({ patternRegexFocused: true }); } if (pattern["min_occurrences"] > pattern["max_occurrences"]) { valid = false; - this.setState({patternOccurrencesFocused: true}); + this.setState({ patternOccurrencesFocused: true }); } return valid; }; @@ -250,54 +261,54 @@ class RulesPane extends Component { let rules = this.state.rules.map((r) => <tr key={r.id} onClick={() => { this.reset(); - this.setState({selectedRule: _.cloneDeep(r)}); - }} className={classNames("row-small", "row-clickable", {"row-selected": rule.id === r.id})}> - <td><CopyLinkPopover text={r["id"].substring(0, 8)} value={r["id"]}/></td> + this.setState({ selectedRule: _.cloneDeep(r) }); + }} className={classNames("row-small", "row-clickable", { "row-selected": rule.id === r.id })}> + <td><CopyLinkPopover text={r["id"].substring(0, 8)} value={r["id"]} /></td> <td>{r["name"]}</td> - <td><ButtonField name={r["color"]} color={r["color"]} small/></td> + <td><ButtonField name={r["color"]} color={r["color"]} small /></td> <td>{r["notes"]}</td> </tr> ); 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 ? <tr key={"new_pattern"}> - <td style={{"width": "500px"}}> + <td style={{ "width": "500px" }}> <InputField small active={this.state.patternRegexFocused} value={pattern.regex} - onChange={(v) => { - this.updateParam(() => pattern.regex = v); - this.setState({patternRegexFocused: pattern.regex === ""}); - }}/> + onChange={(v) => { + this.updateParam(() => pattern.regex = v); + this.setState({ patternRegexFocused: pattern.regex === "" }); + }} /> </td> <td><CheckField small checked={pattern.flags["caseless"]} - onChange={(v) => this.updateParam(() => pattern.flags["caseless"] = v)}/></td> + onChange={(v) => this.updateParam(() => pattern.flags["caseless"] = v)} /></td> <td><CheckField small checked={pattern.flags["dot_all"]} - onChange={(v) => this.updateParam(() => pattern.flags["dot_all"] = v)}/></td> + onChange={(v) => this.updateParam(() => pattern.flags["dot_all"] = v)} /></td> <td><CheckField small checked={pattern.flags["multi_line"]} - onChange={(v) => this.updateParam(() => pattern.flags["multi_line"] = v)}/></td> + onChange={(v) => this.updateParam(() => pattern.flags["multi_line"] = v)} /></td> <td><CheckField small checked={pattern.flags["utf_8_mode"]} - onChange={(v) => this.updateParam(() => pattern.flags["utf_8_mode"] = v)}/></td> + onChange={(v) => this.updateParam(() => pattern.flags["utf_8_mode"] = v)} /></td> <td><CheckField small checked={pattern.flags["unicode_property"]} - onChange={(v) => this.updateParam(() => pattern.flags["unicode_property"] = v)}/></td> - <td style={{"width": "70px"}}> + onChange={(v) => this.updateParam(() => pattern.flags["unicode_property"] = v)} /></td> + <td style={{ "width": "70px" }}> <NumericField small value={pattern["min_occurrences"]} - active={this.state.patternOccurrencesFocused} - onChange={(v) => this.updateParam(() => pattern["min_occurrences"] = v)}/> + active={this.state.patternOccurrencesFocused} + onChange={(v) => this.updateParam(() => pattern["min_occurrences"] = v)} /> </td> - <td style={{"width": "70px"}}> + <td style={{ "width": "70px" }}> <NumericField small value={pattern["max_occurrences"]} - active={this.state.patternOccurrencesFocused} - onChange={(v) => this.updateParam(() => pattern["max_occurrences"] = v)}/> + active={this.state.patternOccurrencesFocused} + onChange={(v) => this.updateParam(() => pattern["max_occurrences"] = v)} /> </td> <td><ChoiceField inline small keys={[0, 1, 2]} values={["both", "c->s", "s->c"]} - value={this.directions[pattern.direction]} - onChange={(v) => this.updateParam(() => pattern.direction = v)}/></td> + value={this.directions[pattern.direction]} + onChange={(v) => this.updateParam(() => pattern.direction = v)} /></td> <td>{this.state.selectedPattern == null ? - <ButtonField variant="green" small name="add" inline rounded onClick={() => this.addPattern(p)}/> : + <ButtonField variant="green" small name="add" inline rounded onClick={() => this.addPattern(p)} /> : <ButtonField variant="green" small name="save" inline rounded - onClick={() => this.updatePattern(p)}/>} + onClick={() => this.updatePattern(p)} />} </td> </tr> : @@ -312,7 +323,7 @@ class RulesPane extends Component { <td>{p["max_occurrences"]}</td> <td>{this.directions[p.direction]}</td> {!isUpdate && <td><ButtonField variant="blue" small rounded name="edit" - onClick={() => this.editPattern(p)}/></td>} + onClick={() => this.editPattern(p)} /></td>} </tr> ); @@ -322,24 +333,24 @@ class RulesPane extends Component { <div className="section-header"> <span className="api-request">GET /api/rules</span> {this.state.rulesStatusCode && - <span className="api-response"><LinkPopover text={this.state.rulesStatusCode} - content={this.state.rulesResponse} - placement="left"/></span>} + <span className="api-response"><LinkPopover text={this.state.rulesStatusCode} + content={this.state.rulesResponse} + placement="left" /></span>} </div> <div className="section-content"> <div className="section-table"> <Table borderless size="sm"> <thead> - <tr> - <th>id</th> - <th>name</th> - <th>color</th> - <th>notes</th> - </tr> + <tr> + <th>id</th> + <th>name</th> + <th>color</th> + <th>notes</th> + </tr> </thead> <tbody> - {rules} + {rules} </tbody> </Table> </div> @@ -352,8 +363,8 @@ class RulesPane extends Component { {isUpdate ? `PUT /api/rules/${this.state.selectedRule.id}` : "POST /api/rules"} </span> <span className="api-response"><LinkPopover text={this.state.ruleStatusCode} - content={this.state.ruleResponse} - placement="left"/></span> + content={this.state.ruleResponse} + placement="left" /></span> </div> <div className="section-content"> @@ -361,42 +372,42 @@ class RulesPane extends Component { <Row> <Col> <InputField name="name" inline value={rule.name} - onChange={(v) => this.updateParam((r) => r.name = v)} - error={this.state.ruleNameError}/> + onChange={(v) => this.updateParam((r) => r.name = v)} + error={this.state.ruleNameError} /> <ColorField inline value={rule.color} error={this.state.ruleColorError} - onChange={(v) => this.updateParam((r) => r.color = v)}/> + onChange={(v) => this.updateParam((r) => r.color = v)} /> <TextField name="notes" rows={2} value={rule.notes} - onChange={(v) => this.updateParam((r) => r.notes = v)}/> + onChange={(v) => this.updateParam((r) => r.notes = v)} /> </Col> - <Col style={{"paddingTop": "6px"}}> + <Col style={{ "paddingTop": "6px" }}> <span>filters:</span> <NumericField name="service_port" inline value={rule.filter["service_port"]} - onChange={(v) => this.updateParam((r) => r.filter["service_port"] = v)} - min={0} max={65565} error={this.state.ruleServicePortError} - readonly={isUpdate}/> + onChange={(v) => this.updateParam((r) => r.filter["service_port"] = v)} + min={0} max={65565} error={this.state.ruleServicePortError} + readonly={isUpdate} /> <NumericField name="client_port" inline value={rule.filter["client_port"]} - onChange={(v) => this.updateParam((r) => r.filter["client_port"] = v)} - min={0} max={65565} error={this.state.ruleClientPortError} - readonly={isUpdate}/> + onChange={(v) => this.updateParam((r) => r.filter["client_port"] = v)} + min={0} max={65565} error={this.state.ruleClientPortError} + readonly={isUpdate} /> <InputField name="client_address" value={rule.filter["client_address"]} - error={this.state.ruleClientAddressError} readonly={isUpdate} - onChange={(v) => this.updateParam((r) => r.filter["client_address"] = v)}/> + error={this.state.ruleClientAddressError} readonly={isUpdate} + onChange={(v) => this.updateParam((r) => r.filter["client_address"] = v)} /> </Col> - <Col style={{"paddingTop": "11px"}}> + <Col style={{ "paddingTop": "11px" }}> <NumericField name="min_duration" inline value={rule.filter["min_duration"]} - error={this.state.ruleDurationError} readonly={isUpdate} - onChange={(v) => this.updateParam((r) => r.filter["min_duration"] = v)}/> + error={this.state.ruleDurationError} readonly={isUpdate} + onChange={(v) => this.updateParam((r) => r.filter["min_duration"] = v)} /> <NumericField name="max_duration" inline value={rule.filter["max_duration"]} - error={this.state.ruleDurationError} readonly={isUpdate} - onChange={(v) => this.updateParam((r) => r.filter["max_duration"] = v)}/> + error={this.state.ruleDurationError} readonly={isUpdate} + onChange={(v) => this.updateParam((r) => r.filter["max_duration"] = v)} /> <NumericField name="min_bytes" inline value={rule.filter["min_bytes"]} - error={this.state.ruleBytesError} readonly={isUpdate} - onChange={(v) => this.updateParam((r) => r.filter["min_bytes"] = v)}/> + error={this.state.ruleBytesError} readonly={isUpdate} + onChange={(v) => this.updateParam((r) => r.filter["min_bytes"] = v)} /> <NumericField name="max_bytes" inline value={rule.filter["max_bytes"]} - error={this.state.ruleBytesError} readonly={isUpdate} - onChange={(v) => this.updateParam((r) => r.filter["max_bytes"] = v)}/> + error={this.state.ruleBytesError} readonly={isUpdate} + onChange={(v) => this.updateParam((r) => r.filter["max_bytes"] = v)} /> </Col> </Row> </Container> @@ -404,32 +415,33 @@ class RulesPane extends Component { <div className="section-table"> <Table borderless size="sm"> <thead> - <tr> - <th>regex</th> - <th>!Aa</th> - <th>.*</th> - <th>\n+</th> - <th>UTF8</th> - <th>Uni_</th> - <th>min</th> - <th>max</th> - <th>direction</th> - {!isUpdate && <th>actions</th>} - </tr> + <tr> + <th>regex</th> + <th>!Aa</th> + <th>.*</th> + <th>\n+</th> + <th>UTF8</th> + <th>Uni_</th> + <th>min</th> + <th>max</th> + <th>direction</th> + {!isUpdate && <th>actions</th>} + </tr> </thead> <tbody> - {patterns} + {patterns} </tbody> </Table> {this.state.rulePatternsError != null && - <span className="table-error">error: {this.state.rulePatternsError}</span>} + <span className="table-error">error: {this.state.rulePatternsError}</span>} </div> </div> <div className="section-footer"> - {<ButtonField variant="red" name="cancel" bordered onClick={this.reset}/>} + {<ButtonField variant="red" name="cancel" bordered onClick={this.reset} />} <ButtonField variant={isUpdate ? "blue" : "green"} name={isUpdate ? "update_rule" : "add_rule"} - bordered onClick={isUpdate ? this.updateRule : this.addRule}/> + bordered onClick={isUpdate ? this.updateRule : this.addRule} /> + <ButtonField variant="red" name="delete_rule" bordered onClick={this.deleteRule} /> </div> </div> </div> diff --git a/pcap_importer_test.go b/pcap_importer_test.go index bc519ac..4761927 100644 --- a/pcap_importer_test.go +++ b/pcap_importer_test.go @@ -45,7 +45,7 @@ func TestImportPcap(t *testing.T) { duplicateSessionID, err := pcapImporter.ImportPcap(duplicatePcapFileName, false) require.Error(t, err) assert.Equal(t, sessionID, duplicateSessionID) - assert.Error(t, os.Remove(ProcessingPcapsBasePath + duplicatePcapFileName)) + assert.Error(t, os.Remove(ProcessingPcapsBasePath+duplicatePcapFileName)) _, isPresent := pcapImporter.GetSession("invalid") assert.False(t, isPresent) @@ -58,8 +58,8 @@ func TestImportPcap(t *testing.T) { checkSessionEquals(t, wrapper, session) - assert.Error(t, os.Remove(ProcessingPcapsBasePath + fileName)) - assert.NoError(t, os.Remove(PcapsBasePath + session.ID + ".pcap")) + assert.Error(t, os.Remove(ProcessingPcapsBasePath+fileName)) + assert.NoError(t, os.Remove(PcapsBasePath+session.ID+".pcap")) wrapper.Destroy(t) } @@ -85,8 +85,8 @@ func TestCancelImportSession(t *testing.T) { checkSessionEquals(t, wrapper, session) - assert.Error(t, os.Remove(ProcessingPcapsBasePath + fileName)) - assert.Error(t, os.Remove(PcapsBasePath + sessionID + ".pcap")) + assert.Error(t, os.Remove(ProcessingPcapsBasePath+fileName)) + assert.Error(t, os.Remove(PcapsBasePath+sessionID+".pcap")) wrapper.Destroy(t) } @@ -108,8 +108,8 @@ func TestImportNoTcpPackets(t *testing.T) { checkSessionEquals(t, wrapper, session) - assert.Error(t, os.Remove(ProcessingPcapsBasePath + fileName)) - assert.NoError(t, os.Remove(PcapsBasePath + sessionID + ".pcap")) + assert.Error(t, os.Remove(ProcessingPcapsBasePath+fileName)) + assert.NoError(t, os.Remove(PcapsBasePath+sessionID+".pcap")) wrapper.Destroy(t) } @@ -120,13 +120,13 @@ func newTestPcapImporter(wrapper *TestStorageWrapper, serverAddress string) *Pca streamPool := tcpassembly.NewStreamPool(&testStreamFactory{}) return &PcapImporter{ - storage: wrapper.Storage, - streamPool: streamPool, - assemblers: make([]*tcpassembly.Assembler, 0, initialAssemblerPoolSize), - sessions: make(map[string]ImportingSession), - mAssemblers: sync.Mutex{}, - mSessions: sync.Mutex{}, - serverNet: *ParseIPNet(serverAddress), + storage: wrapper.Storage, + streamPool: streamPool, + assemblers: make([]*tcpassembly.Assembler, 0, initialAssemblerPoolSize), + sessions: make(map[string]ImportingSession), + mAssemblers: sync.Mutex{}, + mSessions: sync.Mutex{}, + serverNet: *ParseIPNet(serverAddress), notificationController: NewNotificationController(nil), } } @@ -160,7 +160,7 @@ func checkSessionEquals(t *testing.T, wrapper *TestStorageWrapper, session Impor func copyToProcessing(t *testing.T, fileName string) string { newFile := fmt.Sprintf("test-%v-%s", time.Now().UnixNano(), fileName) - require.NoError(t, CopyFile(ProcessingPcapsBasePath + newFile, "test_data/" + fileName)) + require.NoError(t, CopyFile(ProcessingPcapsBasePath+newFile, "test_data/"+fileName)) return newFile } diff --git a/resources_controller.go b/resources_controller.go index 0576e0f..5ff4ca9 100644 --- a/resources_controller.go +++ b/resources_controller.go @@ -29,7 +29,7 @@ import ( ) const ( - averageCPUPercentAlertThreshold = 90.0 + averageCPUPercentAlertThreshold = 90.0 averageCPUPercentAlertMinInterval = 120.0 ) diff --git a/rules_manager.go b/rules_manager.go index ed1932d..2e32573 100644 --- a/rules_manager.go +++ b/rules_manager.go @@ -83,6 +83,7 @@ type RulesManager interface { AddRule(context context.Context, rule Rule) (RowID, error) GetRule(id RowID) (Rule, bool) UpdateRule(context context.Context, id RowID, rule Rule) (bool, error) + DeleteRule(context context.Context, id RowID) error GetRules() []Rule FillWithMatchedRules(connection *Connection, clientMatches map[uint][]PatternSlice, serverMatches map[uint][]PatternSlice) DatabaseUpdateChannel() chan RulesDatabase @@ -209,6 +210,21 @@ func (rm *rulesManagerImpl) UpdateRule(context context.Context, id RowID, rule R return updated, nil } +func (rm *rulesManagerImpl) DeleteRule(context context.Context, id RowID) error { + err := rm.storage.Delete(Rules).Context(context).Filter(OrderedDocument{{"_id", id}}).One() + if err != nil { + log.WithError(err).WithField("id", id).Panic("failed to delete rule on database") + } else { + rm.mutex.Lock() + rule := rm.rules[id] + delete(rm.rules, id) + delete(rm.rulesByName, rule.Name) + rm.mutex.Unlock() + } + + return err +} + func (rm *rulesManagerImpl) GetRules() []Rule { rules := make([]Rule, 0, len(rm.rules)) diff --git a/search_controller.go b/search_controller.go index 5ed762a..e41926c 100644 --- a/search_controller.go +++ b/search_controller.go @@ -151,8 +151,7 @@ func (sc *SearchController) PerformSearch(c context.Context, options SearchOptio if options.RegexSearch.Pattern != "" { regex = UnorderedDocument{"$regex": options.RegexSearch.Pattern, "$options": regexOptions} } else { - regex = UnorderedDocument{"$not": - UnorderedDocument{"$regex": options.RegexSearch.NotPattern, "$options": regexOptions}} + regex = UnorderedDocument{"$not": UnorderedDocument{"$regex": options.RegexSearch.NotPattern, "$options": regexOptions}} } findQuery = findQuery.Filter(OrderedDocument{{"payload_string", regex}}) diff --git a/statistics_controller.go b/statistics_controller.go index 989a2e4..56bcce4 100644 --- a/statistics_controller.go +++ b/statistics_controller.go @@ -116,7 +116,7 @@ func (sc *StatisticsController) GetTotalStatistics(context context.Context, filt } totalStats.RangeStart = statisticsPerMinute[0].RangeStart - totalStats.RangeEnd = statisticsPerMinute[len(statisticsPerMinute) - 1].RangeEnd + totalStats.RangeEnd = statisticsPerMinute[len(statisticsPerMinute)-1].RangeEnd if statisticsPerMinute[0].ConnectionsPerService != nil { totalStats.ConnectionsPerService = make(map[uint16]int64) diff --git a/stream_handler.go b/stream_handler.go index 8042bcb..01c0b08 100644 --- a/stream_handler.go +++ b/stream_handler.go @@ -61,7 +61,7 @@ func NewStreamHandler(connection ConnectionHandler, streamFlow StreamFlow, scann indexes: make([]int, 0, InitialBlockCount), timestamps: make([]time.Time, 0, InitialBlockCount), lossBlocks: make([]bool, 0, InitialBlockCount), - documentsIDs: make([]RowID, 0, 1), // most of the time the stream fit in one document + documentsIDs: make([]RowID, 0, 1), // most of the time the stream fit in one document patternMatches: make(map[uint][]PatternSlice, connection.PatternsDatabaseSize()), scanner: scanner, isClient: isClient, @@ -179,7 +179,7 @@ func (sh *StreamHandler) storageCurrentDocument() { ConnectionID: ZeroRowID, DocumentIndex: len(sh.documentsIDs), Payload: sh.buffer.Bytes(), - PayloadString: strings.ToValidUTF8(string(sh.buffer.Bytes()), ""), + PayloadString: strings.ToValidUTF8(string(sh.buffer.Bytes()), ""), BlocksIndexes: sh.indexes, BlocksTimestamps: sh.timestamps, BlocksLoss: sh.lossBlocks, |