Skip to content

Commit 229d8be

Browse files
committed
Merge remote-tracking branch 'origin/release/v11.2.1' into release/v11.2.1
2 parents 210a378 + 21514d4 commit 229d8be

File tree

10 files changed

+94
-88
lines changed

10 files changed

+94
-88
lines changed

frontend/src/app/app-management/layout/app-management-sidebar/app-management-sidebar.component.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@
4949
</span>
5050
</a>
5151

52-
<a class="list-group-item"
52+
<!-- <a class="list-group-item"
5353
*appHasAnyAuthority="adminAuth"
5454
routerLink="/app-management/settings/user-access-audit"
5555
routerLinkActive="router-link-active">
5656
<span class="font-weight-semibold">
5757
<i class="icon-user-block font-size-sm"></i>&nbsp;
5858
User access audit
5959
</span>
60-
</a>
60+
</a>-->
6161
<ng-container *ngIf="!inSass">
6262
<a *appHasAnyAuthority="adminAuth"
6363
class="list-group-item"
@@ -88,14 +88,14 @@
8888
Health checks
8989
</span>
9090
</a>
91-
<a *appHasAnyAuthority="adminAuth"
91+
<!--<a *appHasAnyAuthority="adminAuth"
9292
class="list-group-item"
9393
routerLink="/app-management/settings/app-logs"
9494
routerLinkActive="router-link-active">
9595
<span class="font-weight-semibold">
9696
<i class="icon-meter-slow font-size-sm"></i>&nbsp;
9797
Application logs</span>
98-
</a>
98+
</a>-->
9999
<a *appHasAnyAuthority="adminAuth"
100100
class="list-group-item"
101101
routerLink="/app-management/settings/application-theme"

frontend/src/app/rule-management/app-rule/components/add-rule/add-rule.component.html

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,11 @@
221221

222222
<div [hidden]="currentStep != RULE_FORM.STEP2">
223223
<div class="row mb-3">
224-
<div class="col-12">
225-
<app-deduplicate-fields [rule]="rule" [formGroup]="ruleForm"></app-deduplicate-fields>
224+
<div class="col-6">
225+
<app-fields-selector [controlName]="'deduplicateBy'" [rule]="rule" [formGroup]="ruleForm"></app-fields-selector>
226+
</div>
227+
<div class="col-6">
228+
<app-fields-selector [controlName]="'groupBy'" [rule]="rule" [formGroup]="ruleForm"></app-fields-selector>
226229
</div>
227230
</div>
228231
<div class="w-100 alert alert-info alert-styled-right mb-3">

frontend/src/app/rule-management/app-rule/components/add-rule/add-rule.component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ export class AddRuleComponent implements OnInit, OnDestroy {
174174
definition: [rule ? rule.definition : '', [Validators.required, minWordsValidator(2, 3)]],
175175
systemOwner: [rule ? rule.systemOwner : false],
176176
deduplicateBy: [rule ? rule.deduplicateBy || [] : []],
177+
groupBy: [rule ? rule.groupBy || [] : []],
177178
afterEvents: this.fb.array(
178179
rule && rule.afterEvents && rule.afterEvents.length
179180
? rule.afterEvents.map(event => this.buildSearchRequest(event))

frontend/src/app/rule-management/app-rule/components/deduplicate-fields/deduplicate-fields.component.css renamed to frontend/src/app/rule-management/app-rule/components/fields-selector/fields-selector.component.css

File renamed without changes.

frontend/src/app/rule-management/app-rule/components/deduplicate-fields/deduplicate-fields.component.html renamed to frontend/src/app/rule-management/app-rule/components/fields-selector/fields-selector.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<div class="form-group-select">
2-
<label>Deduplicated by:</label>
2+
<label> {{ controlName && controlName === 'deduplicateBy' ? 'Deduplicated by:' : 'GroupBy:'}}</label>
33
<div [formGroup]="formGroup" class="p-2">
44
<ng-select
5-
formControlName="deduplicateBy"
5+
[formControlName]="controlName"
66
[items]="fields$ | async"
77
bindLabel="name"
88
[multiple]="true"

frontend/src/app/rule-management/app-rule/components/deduplicate-fields/deduplicate-fields.component.ts renamed to frontend/src/app/rule-management/app-rule/components/fields-selector/fields-selector.component.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,21 @@ import {FormGroup} from '@angular/forms';
33
import {Observable, of} from 'rxjs';
44
import {catchError, map} from 'rxjs/operators';
55
import {UtmToastService} from '../../../../shared/alert/utm-toast.service';
6-
import {ALERT_INDEX_PATTERN} from '../../../../shared/constants/main-index-pattern.constant';
6+
import {ALERT_INDEX_PATTERN, LOG_INDEX_PATTERN} from '../../../../shared/constants/main-index-pattern.constant';
77
import {FieldDataService} from '../../../../shared/services/elasticsearch/field-data.service';
88
import {ElasticSearchFieldInfoType} from '../../../../shared/types/elasticsearch/elastic-search-field-info.type';
99
import {Rule} from '../../../models/rule.model';
1010

1111

1212
@Component({
13-
selector: 'app-deduplicate-fields',
14-
templateUrl: './deduplicate-fields.component.html',
15-
styleUrls: ['./deduplicate-fields.component.css']
13+
selector: 'app-fields-selector',
14+
templateUrl: './fields-selector.component.html',
15+
styleUrls: ['./fields-selector.component.css']
1616
})
17-
export class DeduplicateFieldsComponent implements OnInit {
17+
export class FieldsSelectorComponent implements OnInit {
1818
@Input() formGroup: FormGroup;
1919
@Input() rule: Rule;
20+
@Input() controlName: 'groupBy' | 'deduplicateBy';
2021

2122
fields$: Observable<ElasticSearchFieldInfoType[]>;
2223
operators = [
@@ -28,7 +29,7 @@ export class DeduplicateFieldsComponent implements OnInit {
2829
private fieldDataService: FieldDataService) { }
2930

3031
ngOnInit() {
31-
this.fields$ = this.fieldDataService.getFields(ALERT_INDEX_PATTERN).pipe(
32+
this.fields$ = this.fieldDataService.getFields(LOG_INDEX_PATTERN).pipe(
3233
map((fields) => fields || []),
3334
catchError((error) => {
3435
this.toastService.showError('Error', 'Failed to load fields');

frontend/src/app/rule-management/app-rule/components/import-rules/import-rule.component.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ export class ImportRuleComponent implements OnInit, OnDestroy {
160160
};
161161
const {isValid, errors} = this.importRuleService.isValidRule(rule);
162162

163-
// move null fields (required and not sended) upper than others
164163
Object.keys(rule).forEach(key => {
165164
if (rule[key] === null) {
166165
rule = {[key]: null, ...rule};

frontend/src/app/rule-management/app-rule/components/import-rules/import-rule.service.ts

Lines changed: 72 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export class ImportRuleService {
1414
}
1515

1616
private minWordsCheck(value: string, min: number, minLengthPerWord: number): boolean {
17-
if (!value) return false;
17+
if (!value) { return false; }
1818
const words = value.trim().split(/\s+/).filter(word => word.length >= minLengthPerWord);
1919
return words.length >= min;
2020

@@ -29,150 +29,151 @@ export class ImportRuleService {
2929

3030
// dataTypes
3131
if (!Array.isArray(obj.dataTypes) || obj.dataTypes.length === 0) {
32-
if(!obj.dataTypes){
33-
obj.dataTypes=null
32+
if (!obj.dataTypes) {
33+
obj.dataTypes = null;
3434
}
35-
errors['dataTypes'] = ['dataTypes are required'];
35+
errors.dataTypes = ['dataTypes are required'];
3636
}
3737

3838
// name
3939
if (typeof obj.name !== 'string' || obj.name.trim() === '') {
4040

41-
if(!obj.name){
42-
obj.name=null
41+
if (!obj.name) {
42+
obj.name = null;
4343
}
44-
errors['name'] = ['Name is required'];
44+
errors.name = ['Name is required'];
4545
} else if (!this.minWordsCheck(obj.name, 2, 3)) {
46-
errors['name'] = ['Name must contain between 2 and 3 words'];
46+
errors.name = ['Name must contain between 2 and 3 words'];
4747
}
4848

4949
// adversary
5050
if (typeof obj.adversary !== 'string' || obj.adversary.trim() === '') {
51-
if(!obj.adversary){
52-
obj.adversary=null
51+
if (!obj.adversary) {
52+
obj.adversary = null;
5353
}
54-
errors['adversary'] = ['Adversary is required'];
55-
}else if(!['origin','target'].includes(obj.adversary) ){
56-
errors['adversary'] = ['Adversary must be one of these: "origin", "target"'];
54+
errors.adversary = ['Adversary is required'];
55+
} else if (!['origin', 'target'].includes(obj.adversary) ) {
56+
errors.adversary = ['Adversary must be one of these: "origin", "target"'];
5757
}
5858

5959
// confidentiality
6060
if (typeof obj.confidentiality !== 'number') {
61-
if(!obj.confidentiality){
62-
obj.confidentiality=null
63-
errors['confidentiality'] = ['Confidentiality is required'];
64-
}else{
65-
errors['confidentiality'] = ['Confidentiality must be a number'];
61+
if (!obj.confidentiality) {
62+
obj.confidentiality = null;
63+
errors.confidentiality = ['Confidentiality is required'];
64+
} else {
65+
errors.confidentiality = ['Confidentiality must be a number'];
6666
}
6767
} else if (obj.confidentiality < 0 || obj.confidentiality > 3) {
68-
errors['confidentiality'] = ['Confidentiality must be between 0 and 3'];
68+
errors.confidentiality = ['Confidentiality must be between 0 and 3'];
6969
}
7070

7171
// integrity
7272
if (typeof obj.integrity !== 'number') {
73-
if(!obj.integrity){
74-
obj.integrity=null
75-
errors['integrity'] = ['Integrity is required'];
76-
}else{
77-
errors['integrity'] = ['Integrity must be a number'];
73+
if (!obj.integrity) {
74+
obj.integrity = null;
75+
errors.integrity = ['Integrity is required'];
76+
} else {
77+
errors.integrity = ['Integrity must be a number'];
7878
}
7979
} else if (obj.integrity < 0 || obj.integrity > 3) {
80-
errors['integrity'] = ['Integrity must be between 0 and 3'];
80+
errors.integrity = ['Integrity must be between 0 and 3'];
8181
}
8282

8383
// availability
8484
if (typeof obj.availability !== 'number') {
8585

86-
if(!obj.availability){
87-
obj.availability=null
88-
errors['availability'] = ['Availability is required'];
89-
}else{
90-
errors['availability'] = ['Availability must be a number'];
86+
if (!obj.availability) {
87+
obj.availability = null;
88+
errors.availability = ['Availability is required'];
89+
} else {
90+
errors.availability = ['Availability must be a number'];
9191
}
9292
} else if (obj.availability < 0 || obj.availability > 3) {
93-
errors['availability'] = ['Availability must be between 0 and 3'];
93+
errors.availability = ['Availability must be between 0 and 3'];
9494
}
9595

9696
// category
9797
if (typeof obj.category !== 'string' || obj.category.trim() === '') {
9898

99-
if(!obj.category){
100-
obj.category=null
99+
if (!obj.category) {
100+
obj.category = null;
101101
}
102-
errors['category'] = ['Category is required'];
102+
errors.category = ['Category is required'];
103103
} else if (!this.minWordsCheck(obj.category, 1, 3)) {
104-
errors['category'] = ['Category must contain between 1 and 3 words'];
104+
errors.category = ['Category must contain between 1 and 3 words'];
105105
}
106106

107107
// technique
108108
if (typeof obj.technique !== 'string' || obj.technique.trim() === '') {
109109

110-
if(!obj.technique){
111-
obj.technique=null
110+
if (!obj.technique) {
111+
obj.technique = null;
112112
}
113-
errors['technique'] = ['Technique is required'];
113+
errors.technique = ['Technique is required'];
114114
} else if (!this.minWordsCheck(obj.technique, 1, 3)) {
115-
errors['technique'] = ['Technique must contain between 1 and 3 words'];
115+
errors.technique = ['Technique must contain between 1 and 3 words'];
116116
}
117117

118118
// description
119119
if (typeof obj.description !== 'string' || obj.description.trim() === '') {
120-
if(!obj.description){
121-
obj={description:null,...obj}
120+
if (!obj.description) {
121+
obj = {description: null, ...obj};
122122
}
123-
errors['description'] = ['Description is required'];
123+
errors.description = ['Description is required'];
124124
} else if (!this.minWordsCheck(obj.description, 2, 3)) {
125-
errors['description'] = ['Description must contain between 2 and 3 words'];
125+
errors.description = ['Description must contain between 2 and 3 words'];
126126
}
127127

128128
// definition
129129
if (typeof obj.definition !== 'string' || obj.definition.trim() === '') {
130-
if(!obj.definition){
131-
obj.definition=null
130+
if (!obj.definition) {
131+
obj.definition = null;
132132
}
133-
errors['definition'] = ['Definition is required'];
133+
errors.definition = ['Definition is required'];
134134
} else if (!this.minWordsCheck(obj.definition, 2, 3)) {
135-
errors['definition'] = ['Definition must contain between 2 and 3 words'];
135+
errors.definition = ['Definition must contain between 2 and 3 words'];
136136
}
137137

138138
// references
139139
if (!Array.isArray(obj.references)) {
140-
if(!obj.references){
141-
obj.references=null
142-
errors['references'] = ['References is required'];
143-
}else{
144-
errors['references'] = ['References must be an array'];
140+
if (!obj.references) {
141+
obj.references = null;
142+
errors.references = ['References is required'];
143+
} else {
144+
errors.references = ['References must be an array'];
145145
}
146146
} else {
147147
const invalidRefs = obj.references.filter((ref: any) => typeof ref !== 'string' || !this.isValidURL(ref));
148148
if (invalidRefs.length > 0) {
149-
errors['references'] = ['All references must be valid URLs'];
149+
errors.references = ['All references must be valid URLs'];
150150
}
151151
}
152152

153153

154154
const allowedFields = [
155-
"id",
156-
"dataTypes",
157-
"impact",
158-
"where",
159-
"afterEvents",
160-
"name",
161-
"adversary",
162-
"confidentiality",
163-
"integrity",
164-
"availability",
155+
'id',
156+
'dataTypes',
157+
'impact',
158+
'where',
159+
'afterEvents',
160+
'name',
161+
'adversary',
162+
'confidentiality',
163+
'integrity',
164+
'availability',
165165
'references',
166-
"category",
167-
"technique",
168-
"description",
169-
"definition",
170-
"systemOwner",
171-
"deduplicateBy"
166+
'category',
167+
'technique',
168+
'description',
169+
'definition',
170+
'systemOwner',
171+
'deduplicateBy',
172+
'groupBy'
172173
];
173174

174-
Object.keys(obj).filter(key=>!allowedFields.includes(key)).forEach(key=>{
175-
errors[key]=[`uknowed field: ${key}`]
175+
Object.keys(obj).filter(key => !allowedFields.includes(key)).forEach(key => {
176+
errors[key] = [`uknowed field: ${key}`];
176177
});
177178

178179

frontend/src/app/rule-management/models/rule.model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export interface Rule {
7474
isLoading: boolean;
7575
afterEvents: SearchRequest[];
7676
deduplicateBy?: string[];
77+
groupBy?: string[];
7778
}
7879

7980
export interface Expression {

frontend/src/app/rule-management/rule-management.module.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {AppRuleComponent} from './app-rule/app-rule.component';
2929
import {AddAfterEventComponent} from './app-rule/components/add-after-event/add-after-event.component';
3030
import {AddRuleComponent} from './app-rule/components/add-rule/add-rule.component';
3131
import {AddVariableComponent} from './app-rule/components/add-variable/add-variable.component';
32-
import {DeduplicateFieldsComponent} from './app-rule/components/deduplicate-fields/deduplicate-fields.component';
32+
import {FieldsSelectorComponent} from './app-rule/components/fields-selector/fields-selector.component';
3333
import {ExpressionConsoleComponent} from './app-rule/components/expression-console/expression-console.component';
3434
import {ImportRuleComponent} from './app-rule/components/import-rules/import-rule.component';
3535
import {ImportRuleService} from './app-rule/components/import-rules/import-rule.service';
@@ -71,7 +71,7 @@ import {RuleDetailComponent} from "./app-rule/components/rule-list/components/ru
7171
AddReferenceComponent,
7272
AddVariableComponent,
7373
AddAfterEventComponent,
74-
DeduplicateFieldsComponent,
74+
FieldsSelectorComponent,
7575
ExpressionConsoleComponent,
7676
RuleDetailComponent
7777

0 commit comments

Comments
 (0)