Skip to content

Commit 5aebb0b

Browse files
authored
Merge pull request #888 from utmstack/bugfix/v10.5.15/False-positive-alerts-displayed-in-dashboard-overview
fix: escape ':' character in FilterType JSON conditions to prevent query parsing issues
2 parents eb680cc + 2fa37fd commit 5aebb0b

File tree

6 files changed

+60
-33
lines changed

6 files changed

+60
-33
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# UTMStack 10.5.16 Release Notes
22
## Bugfix
3-
- False positive alerts displayed in Dashboard Overview
3+
- False positive alerts displayed in Dashboard Overview
4+
- Correct query parsing for filterType conditions with special characters

backend/src/main/java/com/park/utmstack/service/elasticsearch/SearchUtil.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,9 @@ private static void buildContainOperator(BoolQuery.Builder bool, FilterType filt
127127
final String ctx = CLASSNAME + ".buildContainOperator";
128128
try {
129129
filter.validate();
130+
String value = CustomStringEscapeUtil.openSearchQueryStringEscap(String.valueOf(filter.getValue()));
130131
bool.filter(f -> f.queryString(s -> s.fields(filter.getField())
131-
.query("*" + filter.getValue() + "*")
132+
.query("*" + value + "*")
132133
.defaultOperator(Operator.And)
133134
.lenient(true)
134135
.type(TextQueryType.BestFields)));
@@ -141,8 +142,9 @@ private static void buildDoesNotContainOperator(BoolQuery.Builder bool, FilterTy
141142
final String ctx = CLASSNAME + ".buildDoesNotContainOperator";
142143
try {
143144
filter.validate();
145+
String value = CustomStringEscapeUtil.openSearchQueryStringEscap(String.valueOf(filter.getValue()));
144146
bool.mustNot(n -> n.queryString(s -> s.fields(filter.getField())
145-
.query("*" + filter.getValue() + "*")
147+
.query("*" + value + "*")
146148
.defaultOperator(Operator.And)
147149
.lenient(true)
148150
.type(TextQueryType.BestFields)));

backend/src/main/java/com/park/utmstack/util/AlertUtil.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public Long countAlertsByStatus(int status) {
3333

3434
List<FilterType> filters = new ArrayList<>();
3535
filters.add(new FilterType(Constants.alertStatus, OperatorType.IS, status));
36-
filters.add(new FilterType(Constants.alertTags, OperatorType.IS_NOT, Constants.FALSE_POSITIVE_TAG));
36+
filters.add(new FilterType(Constants.alertTags, OperatorType.DOES_NOT_CONTAIN, Constants.FALSE_POSITIVE_TAG));
3737

3838
SearchRequest.Builder srb = new SearchRequest.Builder();
3939
srb.query(SearchUtil.toQuery(filters))

frontend/src/app/data-management/alert-management/alert-view/alert-view.component.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ export class AlertViewComponent implements OnInit, OnDestroy {
148148
this.changeParamsByDataType(type).then(() => this.setDefaultParams());
149149
});
150150
}
151-
this.setDefaultParams();
152151
});
153152
});
154153
} else {
@@ -428,14 +427,14 @@ export class AlertViewComponent implements OnInit, OnDestroy {
428427
this.filters = filters;
429428
this.page = 1;
430429
this.getAlert('on generic filter change');
431-
this.updateStatusServiceBehavior.$updateStatus.next(true);
430+
// this.updateStatusServiceBehavior.$updateStatus.next(true);
432431
this.alertFiltersBehavior.$filters.next(this.filters);
433432
});
434433
}
435434

436435
processFilters(filter: ElasticFilterType): Promise<ElasticFilterType[]> {
437436
return new Promise<ElasticFilterType[]>(resolve => {
438-
const indexFilters = this.filters.findIndex(value => filter.field.includes(value.field));
437+
const indexFilters = this.filters.findIndex(value => filter.field === value.field && value.value !== FALSE_POSITIVE_OBJECT.tagName);
439438
if (indexFilters === -1) {
440439
this.filters.push(filter);
441440
} else {

frontend/src/app/data-management/alert-management/shared/components/filters/alert-generic-filter/alert-generic-filter.component.ts

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
1+
import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';
2+
import {Subject} from 'rxjs';
3+
import {takeUntil} from 'rxjs/operators';
24
import {ALERT_TAGS_FIELD} from '../../../../../../shared/constants/alert/alert-field.constant';
35
import {ALERT_INDEX_PATTERN} from '../../../../../../shared/constants/main-index-pattern.constant';
46
import {ElasticDataTypesEnum} from '../../../../../../shared/enums/elastic-data-types.enum';
@@ -14,7 +16,7 @@ import {AlertUpdateTagBehavior} from '../../../behavior/alert-update-tag.behavio
1416
templateUrl: './alert-generic-filter.component.html',
1517
styleUrls: ['./alert-generic-filter.component.scss']
1618
})
17-
export class AlertGenericFilterComponent implements OnInit {
19+
export class AlertGenericFilterComponent implements OnInit, OnDestroy {
1820
@Output() filterGenericChange = new EventEmitter<ElasticFilterType>();
1921
@Input() fieldFilter: UtmFieldType;
2022
activeFilters: ElasticFilterType[] = [];
@@ -27,6 +29,7 @@ export class AlertGenericFilterComponent implements OnInit {
2729
top = 6;
2830
filter: ElasticFilterType;
2931
sort: { orderByCount: boolean, sortAsc: boolean } = {orderByCount: true, sortAsc: false};
32+
destroy$: Subject<void> = new Subject<void>();
3033

3134
constructor(private elasticSearchIndexService: ElasticSearchIndexService,
3235
private alertFiltersBehavior: AlertFiltersBehavior,
@@ -39,7 +42,9 @@ export class AlertGenericFilterComponent implements OnInit {
3942
* If filter is tags subscribe to changes to reload data on add new tag on alert
4043
*/
4144
if (this.fieldFilter.field === ALERT_TAGS_FIELD) {
42-
this.alertUpdateTagBehavior.$tagRefresh.subscribe(tagUpdate => {
45+
this.alertUpdateTagBehavior.$tagRefresh
46+
.pipe(takeUntil(this.destroy$))
47+
.subscribe(tagUpdate => {
4348
if (tagUpdate) {
4449
this.getFieldValues();
4550
}
@@ -48,12 +53,16 @@ export class AlertGenericFilterComponent implements OnInit {
4853
/**
4954
* Reset all values of selected filter
5055
*/
51-
this.alertFiltersBehavior.$resetFilter.subscribe(reset => {
56+
this.alertFiltersBehavior.$resetFilter
57+
.pipe(takeUntil(this.destroy$))
58+
.subscribe(reset => {
5259
if (reset) {
5360
this.selected = [];
5461
}
5562
});
56-
this.alertFiltersBehavior.$deleteFilterValue.subscribe(deleteFilter => {
63+
this.alertFiltersBehavior.$deleteFilterValue
64+
.pipe(takeUntil(this.destroy$))
65+
.subscribe(deleteFilter => {
5766
if (deleteFilter) {
5867
const deleteField = deleteFilter.field.replace('.keyword', '');
5968
if (this.fieldFilter.field === deleteField) {
@@ -64,7 +73,9 @@ export class AlertGenericFilterComponent implements OnInit {
6473
}
6574
}
6675
});
67-
this.alertFiltersBehavior.$filters.subscribe((filters: ElasticFilterType[]) => {
76+
this.alertFiltersBehavior.$filters
77+
.pipe(takeUntil(this.destroy$))
78+
.subscribe((filters: ElasticFilterType[]) => {
6879
if (filters) {
6980
this.activeFilters = filters;
7081
this.getFieldValues();
@@ -160,4 +171,9 @@ export class AlertGenericFilterComponent implements OnInit {
160171
this.sort = $event;
161172
this.getFieldValues();
162173
}
174+
175+
ngOnDestroy() {
176+
this.destroy$.next();
177+
this.destroy$.complete();
178+
}
163179
}

frontend/src/app/data-management/alert-management/shared/components/filters/status-filter/status-filter.component.ts

+29-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
1+
import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';
2+
import {merge, Subject} from 'rxjs';
3+
import {filter, map, takeUntil} from "rxjs/operators";
24
import {ALERT_STATUS_FIELD} from '../../../../../../shared/constants/alert/alert-field.constant';
35
import {ALL_STATUS, AUTOMATIC_REVIEW, CLOSED, IGNORED, OPEN, REVIEW} from '../../../../../../shared/constants/alert/alert-status.constant';
46
import {ALERT_INDEX_PATTERN} from '../../../../../../shared/constants/main-index-pattern.constant';
@@ -16,7 +18,7 @@ import {getCurrentAlertStatus} from '../../../util/alert-util-function';
1618
templateUrl: './status-filter.component.html',
1719
styleUrls: ['./status-filter.component.scss']
1820
})
19-
export class StatusFilterComponent implements OnInit {
21+
export class StatusFilterComponent implements OnInit, OnDestroy {
2022
@Input() dataNature: DataNatureTypeEnum;
2123
@Input() filters: ElasticFilterType[];
2224
@Input() dataType: EventDataTypeEnum;
@@ -35,6 +37,7 @@ export class StatusFilterComponent implements OnInit {
3537
];
3638
allStatusValue = ALL_STATUS;
3739
autoReview = AUTOMATIC_REVIEW;
40+
destroy$: Subject<void> = new Subject();
3841

3942
constructor(private elasticSearchIndexService: ElasticSearchIndexService,
4043
private alertFiltersBehavior: AlertFiltersBehavior,
@@ -45,25 +48,26 @@ export class StatusFilterComponent implements OnInit {
4548
if (typeof this.statusFilter === 'string') {
4649
this.statusFilter = Number(this.statusFilter);
4750
}
48-
this.getValuesOfStatus();
49-
/**
50-
* Update amount on alert status change
51-
*/
52-
this.updateStatusServiceBehavior.$updateStatus.subscribe((update) => {
53-
if (update) {
54-
this.getValuesOfStatus();
55-
}
56-
});
57-
/**
58-
* Update amount on filter change
59-
*/
60-
this.alertFiltersBehavior.$filters.subscribe(value => {
61-
if (value) {
62-
this.filters = value;
63-
this.statusFilter = getCurrentAlertStatus(this.filters);
51+
52+
merge(
53+
this.updateStatusServiceBehavior.$updateStatus.pipe(
54+
filter(value => !!value),
55+
map(() => ({source: 'updateStatus', filters: null}))
56+
),
57+
this.alertFiltersBehavior.$filters.pipe(
58+
filter(value => !!value),
59+
map((filters) => ({source: 'filters', filters}))
60+
)
61+
)
62+
.pipe(takeUntil(this.destroy$))
63+
.subscribe((event) => {
64+
if (event.source === 'filters') {
65+
this.filters = event.filters;
66+
this.statusFilter = getCurrentAlertStatus(this.filters);
67+
}
6468
this.getValuesOfStatus();
65-
}
66-
});
69+
});
70+
6771
}
6872

6973
getValuesOfStatus() {
@@ -137,4 +141,9 @@ export class StatusFilterComponent implements OnInit {
137141
return true;
138142
}
139143
}
144+
145+
ngOnDestroy() {
146+
this.destroy$.next();
147+
this.destroy$.complete();
148+
}
140149
}

0 commit comments

Comments
 (0)