aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--application_context.go8
-rw-r--r--application_router.go17
-rw-r--r--application_router_test.go2
-rw-r--r--connection_handler_test.go4
-rw-r--r--frontend/src/components/panels/RulesPane.js206
-rw-r--r--pcap_importer_test.go30
-rw-r--r--resources_controller.go2
-rw-r--r--rules_manager.go16
-rw-r--r--search_controller.go3
-rw-r--r--statistics_controller.go2
-rw-r--r--stream_handler.go4
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,