You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by ni...@apache.org on 2018/08/31 19:20:39 UTC
[43/50] [abbrv] metron git commit: METRON-1724 Date/time validation
missing in PCAP query (tiborm via nickwallen) closes apache/metron#1172
METRON-1724 Date/time validation missing in PCAP query (tiborm via nickwallen) closes apache/metron#1172
Project: http://git-wip-us.apache.org/repos/asf/metron/repo
Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/e66cfc80
Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/e66cfc80
Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/e66cfc80
Branch: refs/remotes/apache/feature/METRON-1699-create-batch-profiler
Commit: e66cfc80e6a6fa53110c3f2fa8ee0d31ea997bf6
Parents: 9fdccba
Author: tiborm <ti...@gmail.com>
Authored: Mon Aug 27 09:04:21 2018 -0400
Committer: nickallen <ni...@apache.org>
Committed: Mon Aug 27 09:04:21 2018 -0400
----------------------------------------------------------------------
.../src/app/pcap/model/pcap.mock.ts | 4 +-
.../src/app/pcap/model/pcap.request.ts | 18 +-
.../pcap-filters/pcap-filters.component.html | 55 +++--
.../pcap-filters/pcap-filters.component.scss | 13 +-
.../pcap-filters/pcap-filters.component.spec.ts | 207 ++++++++++---------
.../pcap/pcap-filters/pcap-filters.component.ts | 156 +++++++++++---
.../app/pcap/pcap-list/pcap-list.component.html | 4 +-
.../pcap-packet-line.component.spec.ts | 3 +-
.../pcap-packet-line.component.ts | 22 +-
.../pcap-panel/pcap-panel.component.spec.ts | 16 +-
.../app/pcap/pcap-panel/pcap-panel.component.ts | 6 +-
.../metron-alerts/src/app/pcap/pcap.module.ts | 5 +-
.../date-picker/date-picker.component.scss | 14 +-
.../shared/date-picker/date-picker.component.ts | 34 ++-
.../shared/date-picker/date-picker.module.ts | 3 +-
.../metron-alerts/src/app/utils/constants.ts | 3 +
.../metron-alerts/src/app/utils/utils.ts | 12 +-
17 files changed, 360 insertions(+), 215 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/model/pcap.mock.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/model/pcap.mock.ts b/metron-interface/metron-alerts/src/app/pcap/model/pcap.mock.ts
index bf02da8..c867fe9 100644
--- a/metron-interface/metron-alerts/src/app/pcap/model/pcap.mock.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/model/pcap.mock.ts
@@ -22,9 +22,9 @@ export const fakePcapRequest = {
startTimeMs: 0,
endTimeMs: 0,
ipSrcAddr: '0.0.0.0',
- ipSrcPort: 80,
+ ipSrcPort: '80',
ipDstAddr: '0.0.0.0',
- ipDstPort: 80,
+ ipDstPort: '80',
protocol: '*',
packetFilter: '*',
includeReverse: false
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/model/pcap.request.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/model/pcap.request.ts b/metron-interface/metron-alerts/src/app/pcap/model/pcap.request.ts
index 8afc963..3e00a4b 100644
--- a/metron-interface/metron-alerts/src/app/pcap/model/pcap.request.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/model/pcap.request.ts
@@ -17,13 +17,13 @@
*/
export class PcapRequest {
- startTimeMs: number = 0;
- endTimeMs: number = 150000000000000000;
- ipSrcAddr: string = '';
- ipSrcPort: number;
- ipDstAddr: string = '';
- ipDstPort: number;
- protocol: string = '';
- packetFilter: string = '';
- includeReverse: boolean = false;
+ startTimeMs: number;
+ endTimeMs: number;
+ ipSrcAddr = '';
+ ipSrcPort = '';
+ ipDstAddr = '';
+ ipDstPort = '';
+ protocol = '';
+ packetFilter = '';
+ includeReverse = false;
}
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.html b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.html
index 039307a..c7a4db5 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.html
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.html
@@ -11,52 +11,63 @@
OR CONDITIONS OF ANY KIND, either express or implied. See the License for
the specific language governing permissions and limitations under the License.
-->
-<form (ngSubmit)="onSubmit()" #f="ngForm" class="form-inline pcap-search">
+<form (ngSubmit)="onSubmit()" #f="ngForm" [formGroup]="filterForm" class="form-inline pcap-search">
<div class="form-group">
<label>From</label>
- <app-date-picker id="startTime" [(date)]="startTimeStr"> </app-date-picker>
+ <app-date-picker formControlName="startTime" data-qe-id="start-time"> </app-date-picker>
</div>
<div class="form-group">
<label>To</label>
- <app-date-picker id="endTime" [(date)]="endTimeStr"> </app-date-picker>
+ <app-date-picker formControlName="endTime" data-qe-id="end-time"> </app-date-picker>
</div>
<div class="form-group">
- <label for="ipSrcAddr">IP Source Address</label>
- <input name="ipSrcAddr" #ipSrcAddr="ngModel" class="form-control" pattern="^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}$" [(ngModel)]="model.ipSrcAddr" data-qe-id="ip-src-addr">
+ <label>IP Source Address</label>
+ <input class="form-control" formControlName="ipSrcAddr" data-qe-id="ip-src-addr">
</div>
<div class="form-group">
- <label for="ipSrcPort">IP Source Port</label>
- <input name="ipSrcPort" class="form-control" pattern="^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$" [(ngModel)]="ipSrcPort" data-qe-id="ip-src-port">
+ <label>IP Source Port</label>
+ <input class="form-control" formControlName="ipSrcPort" data-qe-id="ip-src-port">
</div>
- <div class="form-group"><label for="ipDstAddr">IP Dest Address</label>
- <input name="ipDstAddr" #ipDstAddr="ngModel" class="form-control" pattern="^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}$" [(ngModel)]="model.ipDstAddr" data-qe-id="ip-dst-addr">
+ <div class="form-group">
+ <label>IP Dest Address</label>
+ <input class="form-control" formControlName="ipDstAddr" data-qe-id="ip-dst-addr">
</div>
<div class="form-group">
- <label for="ipDstPort">IP Dest Port</label>
- <input id="ipDstPort" name="ipDstPort" class="form-control" pattern="^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$" [(ngModel)]="ipDstPort" data-qe-id="ip-dest-port">
+ <label>IP Dest Port</label>
+ <input class="form-control" formControlName="ipDstPort" data-qe-id="ip-dst-port">
</div>
- <div class="form-group">
- <label for="protocol">Protocol</label>
- <input id="protocol" name="protocol" #protocol="ngModel" class="form-control" [(ngModel)]="model.protocol">
- </div>
+ <div class="form-group">
+ <label>Protocol</label>
+ <input class="form-control" formControlName="protocol" data-qe-id="protocol">
+ </div>
- <div class="form-group">
- <label for="includeReverse">Include Reverse Traffic</label>
- <input id="includeReverse" name="includeReverse" #includeReverse="ngModel" class="form-control" type="checkbox" [(ngModel)]="model.includeReverse">
- </div>
+ <div class="form-group">
+ <label>Include Reverse Traffic</label>
+ <input class="form-control" type="checkbox" formControlName="includeReverse" data-qe-id="include-reverse">
+ </div>
<div class="form-group">
- <label for="filter">Filter</label>
- <input id="filter" name="filter" #filter="ngModel" class="form-control" [(ngModel)]="model.packetFilter">
+ <label>Filter</label>
+ <input class="form-control" formControlName="packetFilter" data-qe-id="packet-filter">
</div>
<div class="form-group">
- <button type="submit" [ngClass]="{'disabled':!f.form.valid || queryRunning}" class="btn btn-primary btn-search" [disabled]="!f.form.valid || queryRunning" data-qe-id="submit-button"></button>
+ <button type="submit" [ngClass]="{'disabled': filterForm.status === 'INVALID' || queryRunning}" class="btn btn-primary btn-search" [disabled]="filterForm.status === 'INVALID' || queryRunning" data-qe-id="submit-button"></button>
</div>
</form>
+<div class="pcap-search-validation-errors alert alert-danger" *ngIf="filterForm.invalid">
+ <h5 class="alert-heading">Validation errors</h5>
+ <ul>
+ <li *ngIf="filterForm.controls.startTime.invalid || filterForm.controls.endTime.invalid">Selected date range is invalid. The "To" date must be later than the "From" date and the "To" date cannot be in the future.</li>
+ <li *ngIf="filterForm.controls.ipSrcAddr.invalid">Source IP address format is invalid. Use valid v4IP format, for example, 192.168.0.1</li>
+ <li *ngIf="filterForm.controls.ipSrcPort.invalid">Source port is invalid. Port number must be within the range of 0-65535.</li>
+ <li *ngIf="filterForm.controls.ipDstAddr.invalid">Destination IP address format is invalid. Use valid v4IP format, for example, 192.168.0.1</li>
+ <li *ngIf="filterForm.controls.ipDstPort.invalid">Destination port is invalid. Port number must be within the range of 0-65535.</li>
+ </ul>
+</div>
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.scss
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.scss b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.scss
index b33e804..909ce02 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.scss
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.scss
@@ -19,11 +19,7 @@
@import "../../../styles.scss";
@import "../../../variables.scss";
-.ng-valid[required], .ng-valid.required {
-
-}
-
-.ng-invalid:not(form) {
+.ng-invalid:not(form) {
border-left: 5px solid #a94442; /* red */
}
@@ -35,7 +31,6 @@
}
.btn-search {
-
min-width: 42px;
padding-left: 0;
padding-right: 0;
@@ -67,3 +62,9 @@
background: $icon-button-background;
}
}
+
+.pcap-search-validation-errors {
+ & ul {
+ margin: 0
+ }
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.spec.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.spec.ts
index 3f1ab07..c707451 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.spec.ts
@@ -19,19 +19,14 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
+import { DebugElement, SimpleChange } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+
import { PcapFiltersComponent } from './pcap-filters.component';
-import { FormsModule } from '../../../../node_modules/@angular/forms';
-import { Component, Input, Output, EventEmitter, DebugElement, SimpleChange } from '@angular/core';
+import { DatePickerModule } from '../../shared/date-picker/date-picker.module';
import { PcapRequest } from '../model/pcap.request';
-
-@Component({
- selector: 'app-date-picker',
- template: '<input type="text" [(value)]="date">',
-})
-class FakeDatePickerComponent {
- @Input() date: string;
- @Output() dateChange = new EventEmitter<string>();
-}
+import { DEFAULT_TIMESTAMP_FORMAT } from '../../utils/constants';
+import * as moment from 'moment/moment';
describe('PcapFiltersComponent', () => {
let component: PcapFiltersComponent;
@@ -40,10 +35,11 @@ describe('PcapFiltersComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
- FormsModule
+ FormsModule,
+ ReactiveFormsModule,
+ DatePickerModule,
],
declarations: [
- FakeDatePickerComponent,
PcapFiltersComponent,
]
})
@@ -59,114 +55,113 @@ describe('PcapFiltersComponent', () => {
});
it('From date should be bound to the component', () => {
- let input = fixture.debugElement.query(By.css('#startTime'));
+ let input = fixture.debugElement.query(By.css('[data-qe-id="start-time"]'));
const dateString = '2020-11-11 11:11:11';
- input.componentInstance.dateChange.emit(dateString);
+ input.componentInstance.onChange(dateString);
fixture.detectChanges();
-
- expect(component.startTimeStr).toBe(dateString);
+ expect(component.filterForm.controls.startTime.value).toBe(dateString);
});
it('To date should be bound to the component', () => {
- let input = fixture.debugElement.query(By.css('#endTime'));
+ let input = fixture.debugElement.query(By.css('[data-qe-id="end-time"]'));
const dateString = '2030-11-11 11:11:11';
- input.componentInstance.dateChange.emit(dateString);
+ input.componentInstance.onChange(dateString);
fixture.detectChanges();
- expect(component.endTimeStr).toBe(dateString);
+ expect(component.filterForm.controls.endTime.value).toBe(dateString);
});
it('IP Source Address should be bound to the model', () => {
- let input: HTMLInputElement = fixture.nativeElement.querySelector('[name="ipSrcAddr"]');
+ let input: HTMLInputElement = fixture.nativeElement.querySelector('[data-qe-id="ip-src-addr"]');
input.value = '192.168.0.1';
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
- expect(component.model.ipSrcAddr).toBe('192.168.0.1');
+ expect(component.filterForm.controls.ipSrcAddr.value).toBe('192.168.0.1');
});
it('IP Source Port should be bound to the property', () => {
- let input: HTMLInputElement = fixture.nativeElement.querySelector('[name="ipSrcPort"]');
+ let input: HTMLInputElement = fixture.nativeElement.querySelector('[data-qe-id="ip-src-port"]');
input.value = '9345';
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
- expect(component.ipSrcPort).toBe('9345');
+ expect(component.filterForm.controls.ipSrcPort.value).toBe('9345');
});
it('IP Source Port should be converted to number on submit', () => {
- component.ipSrcPort = '42';
+ component.filterForm.patchValue({ ipSrcPort: '42' });
component.search.emit = (model: PcapRequest) => {
- expect(model.ipSrcPort).toBe(42);
+ expect(model.ipSrcPort).toBe('42');
};
component.onSubmit();
});
it('IP Dest Address should be bound to the model', () => {
- let input: HTMLInputElement = fixture.nativeElement.querySelector('[name="ipDstAddr"]');
+ let input: HTMLInputElement = fixture.nativeElement.querySelector('[data-qe-id="ip-dst-addr"]');
input.value = '256.0.0.7';
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
- expect(component.model.ipDstAddr).toBe('256.0.0.7');
+ expect(component.filterForm.controls.ipDstAddr.value).toBe('256.0.0.7');
});
it('IP Dest Port should be bound to the property', () => {
- let input: HTMLInputElement = fixture.nativeElement.querySelector('[name="ipDstPort"]');
+ let input: HTMLInputElement = fixture.nativeElement.querySelector('[data-qe-id="ip-dst-port"]');
input.value = '8989';
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
- expect(component.ipDstPort).toBe('8989');
+ expect(component.filterForm.controls.ipDstPort.value).toBe('8989');
});
it('IP Dest Port should be converted to number on submit', () => {
- component.ipDstPort = '42';
+ component.filterForm.patchValue({ ipDstPort: '42' });
component.search.emit = (model: PcapRequest) => {
- expect(model.ipDstPort).toBe(42);
+ expect(model.ipDstPort).toBe('42');
};
component.onSubmit();
});
it('Protocol should be bound to the model', () => {
- let input: HTMLInputElement = fixture.nativeElement.querySelector('[name="protocol"]');
+ let input: HTMLInputElement = fixture.nativeElement.querySelector('[data-qe-id="protocol"]');
input.value = 'TCP';
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
- expect(component.model.protocol).toBe('TCP');
+ expect(component.filterForm.controls.protocol.value).toBe('TCP');
});
it('Include Reverse Traffic should be bound to the model', () => {
- let input: HTMLInputElement = fixture.nativeElement.querySelector('[name="includeReverse"]');
+ let input: HTMLInputElement = fixture.nativeElement.querySelector('[data-qe-id="include-reverse"]');
input.click();
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
- expect(component.model.includeReverse).toBe(true);
+ expect(component.filterForm.controls.includeReverse.value).toBe(true);
});
it('Text filter should be bound to the model', () => {
- let input: HTMLInputElement = fixture.nativeElement.querySelector('[name="protocol"]');
+ let input: HTMLInputElement = fixture.nativeElement.querySelector('[data-qe-id="packet-filter"]');
input.value = 'TestStringFilter';
input.dispatchEvent(new Event('input'));
fixture.detectChanges();
- expect(component.model.protocol).toBe('TestStringFilter');
+ expect(component.filterForm.controls.packetFilter.value).toBe('TestStringFilter');
});
it('From date should be converted to timestamp on submit', () => {
- component.startTimeStr = '2220-12-12 12:12:12';
+ component.filterForm.patchValue({ startTime: '2220-12-12 12:12:12' });
component.search.emit = (model: PcapRequest) => {
- expect(model.startTimeMs).toBe(new Date(component.startTimeStr).getTime());
+ expect(model.startTimeMs).toBe(new Date(component.filterForm.controls.startTime.value).getTime());
};
component.onSubmit();
});
it('To date should be converted to timestamp on submit', () => {
- component.endTimeStr = '2320-03-13 13:13:13';
+ component.filterForm.patchValue({ endTimeStr: '2320-03-13 13:13:13' });
component.search.emit = (model: PcapRequest) => {
- expect(model.endTimeMs).toBe(new Date(component.endTimeStr).getTime());
+ expect(model.endTimeMs).toBe(new Date(component.filterForm.controls.endTime.value).getTime());
};
component.onSubmit();
});
@@ -179,19 +174,6 @@ describe('PcapFiltersComponent', () => {
component.onSubmit();
});
- it('Port fields should be removed from request when set to empty', () => {
- component.model.ipSrcPort = 44;
- component.model.ipDstPort = 44;
- component.ipSrcPort = '';
- component.ipDstPort = '';
-
- component.search.emit = (model: PcapRequest) => {
- expect(model.ipSrcPort).toBeFalsy();
- expect(model.ipDstPort).toBeFalsy();
- };
- component.onSubmit();
- });
-
it('Filter should have an output called search', () => {
component.search.subscribe((filterModel) => {
expect(filterModel).toBeDefined();
@@ -205,68 +187,43 @@ describe('PcapFiltersComponent', () => {
expect(component.search.emit).toHaveBeenCalled();
});
- it('Search event should contains the filter model', () => {
- spyOn(component.search, 'emit');
- component.onSubmit();
- expect(component.search.emit).toHaveBeenCalledWith(component.model);
- });
-
- it('Filter model structure aka PcapRequest', () => {
- expect(fixture.componentInstance.model.hasOwnProperty('startTimeMs')).toBeTruthy();
- expect(fixture.componentInstance.model.hasOwnProperty('endTimeMs')).toBeTruthy();
- expect(fixture.componentInstance.model.hasOwnProperty('ipSrcAddr')).toBeTruthy();
- expect(fixture.componentInstance.model.hasOwnProperty('ipSrcPort')).toBeFalsy();
- expect(fixture.componentInstance.model.hasOwnProperty('ipDstAddr')).toBeTruthy();
- expect(fixture.componentInstance.model.hasOwnProperty('ipDstPort')).toBeFalsy();
- expect(fixture.componentInstance.model.hasOwnProperty('protocol')).toBeTruthy();
- expect(fixture.componentInstance.model.hasOwnProperty('packetFilter')).toBeTruthy();
- expect(fixture.componentInstance.model.hasOwnProperty('includeReverse')).toBeTruthy();
- });
-
it('should update request on changes', () => {
+ const startTimeStr = '2220-12-12 12:12:12';
+ const endTimeStr = '2320-03-13 13:13:13';
- let startTimeStr = '2220-12-12 12:12:12';
- let endTimeStr = '2320-03-13 13:13:13';
-
- let newModel = {
- startTimeMs: new Date(startTimeStr).getTime(),
- endTimeMs: new Date(endTimeStr).getTime(),
- ipSrcPort: 9345,
- ipDstPort: 8989
- };
- component.model.startTimeMs = new Date(startTimeStr).getTime();
- component.model.endTimeMs = new Date(endTimeStr).getTime();
+ const newModel = new PcapRequest();
+ newModel.startTimeMs = new Date(startTimeStr).getTime();
+ newModel.endTimeMs = new Date(endTimeStr).getTime();
+ newModel.ipSrcPort = '9345';
+ newModel.ipDstPort = '8989';
component.ngOnChanges({
model: new SimpleChange(null, newModel, false)
});
- expect(component.startTimeStr).toBe(startTimeStr);
- expect(component.endTimeStr).toBe(endTimeStr);
- expect(component.ipSrcPort).toBe('9345');
- expect(component.ipDstPort).toBe('8989');
+ expect(component.filterForm.controls.startTime.value).toBe(startTimeStr);
+ expect(component.filterForm.controls.endTime.value).toBe(endTimeStr);
+ expect(component.filterForm.controls.ipSrcPort.value).toBe('9345');
+ expect(component.filterForm.controls.ipDstPort.value).toBe('8989');
});
it('should update request on changes with missing port filters', () => {
- let startTimeStr = '2220-12-12 12:12:12';
- let endTimeStr = '2320-03-13 13:13:13';
+ const startTimeStr = '2220-12-12 12:12:12';
+ const endTimeStr = '2320-03-13 13:13:13';
- let newModel = {
- startTimeMs: new Date(startTimeStr).getTime(),
- endTimeMs: new Date(endTimeStr).getTime()
- };
- component.model.startTimeMs = new Date(startTimeStr).getTime();
- component.model.endTimeMs = new Date(endTimeStr).getTime();
+ let newModel = new PcapRequest();
+ newModel.startTimeMs = new Date(startTimeStr).getTime();
+ newModel.endTimeMs = new Date(endTimeStr).getTime();
component.ngOnChanges({
model: new SimpleChange(null, newModel, false)
});
- expect(component.startTimeStr).toBe(startTimeStr);
- expect(component.endTimeStr).toBe(endTimeStr);
- expect(component.ipSrcPort).toBe('');
- expect(component.ipDstPort).toBe('');
+ expect(component.filterForm.controls.startTime.value).toBe(startTimeStr);
+ expect(component.filterForm.controls.endTime.value).toBe(endTimeStr);
+ expect(component.filterForm.controls.ipSrcPort.value).toBe('');
+ expect(component.filterForm.controls.ipDstPort.value).toBe('');
});
describe('Filter validation', () => {
@@ -379,7 +336,7 @@ describe('PcapFiltersComponent', () => {
];
invalidValues.forEach((value) => {
- const els = getFieldWithSubmit('ip-dest-port');
+ const els = getFieldWithSubmit('ip-dst-port');
expect(isFieldInvalid(els.field)).toBe(false, 'the field should be valid without ' + value);
expect(isSubmitDisabled(els.submit)).toBe(false, 'the submit button should be enabled without ' + value);
@@ -403,7 +360,7 @@ describe('PcapFiltersComponent', () => {
];
validValues.forEach((value) => {
- const els = getFieldWithSubmit('ip-dest-port');
+ const els = getFieldWithSubmit('ip-dst-port');
expect(isFieldInvalid(els.field)).toBe(false, 'the field should be valid without ' + value);
expect(isSubmitDisabled(els.submit)).toBe(false, 'the submit button should be enabled without ' + value);
@@ -453,11 +410,55 @@ describe('PcapFiltersComponent', () => {
setFieldValue(els.field, value);
- expect(isFieldInvalid(els.field)).toBe(false, 'tthe field should be valid with ' + value);
+ expect(isFieldInvalid(els.field)).toBe(false, 'the field should be valid with ' + value);
expect(isSubmitDisabled(els.submit)).toBe(false, 'the submit button should be enabled with ' + value);
tearDown(els.field);
});
});
+ it('start date should be valid by default', () => {
+ expect(component.filterForm.get('startTime').valid).toBe(true);
+ });
+
+ it('start date is invalid if it is bigger than end date', () => {
+ // start time is bigger than end time
+ component.filterForm.patchValue({
+ startTime: '2018-08-24 16:30:00',
+ endTime: '2018-08-23 16:30:00'
+ });
+
+ expect(component.filterForm.get('startTime').valid).toBe(false);
+ });
+
+ it('start date should be valid again based on the end date', () => {
+ // start time is bigger than end time
+ component.filterForm.patchValue({
+ startTime: '2018-08-24 16:30:00',
+ endTime: '2018-08-23 16:30:00'
+ });
+
+ expect(component.filterForm.get('startTime').valid).toBe(false);
+
+ component.filterForm.patchValue({
+ endTime: '2018-08-25 16:30:00'
+ });
+
+ expect(component.filterForm.get('startTime').valid).toBe(true);
+ });
+
+ it('end date should be valid by default', () => {
+ expect(component.filterForm.get('endTime').valid).toBe(true);
+ });
+
+ it('end date is invalid if it is in the future', () => {
+
+ expect(component.filterForm.get('endTime').valid).toBe(true);
+
+ component.filterForm.patchValue({
+ endTime: moment(new Date()).add(2, 'days').format(DEFAULT_TIMESTAMP_FORMAT)
+ });
+
+ expect(component.filterForm.get('endTime').valid).toBe(false);
+ });
});
});
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.ts
index b23a2e2..7cc8980 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-filters/pcap-filters.component.ts
@@ -15,63 +15,153 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import {Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges} from '@angular/core';
+import {Component, Input, Output, EventEmitter, OnChanges, OnInit, OnDestroy, SimpleChanges} from '@angular/core';
+import { FormGroup, FormControl, Validators, ValidationErrors } from '@angular/forms';
+
import * as moment from 'moment/moment';
-import { DEFAULT_TIMESTAMP_FORMAT } from '../../utils/constants';
+import { DEFAULT_START_TIME, DEFAULT_END_TIME, DEFAULT_TIMESTAMP_FORMAT } from '../../utils/constants';
import { PcapRequest } from '../model/pcap.request';
+import { Observable, Subscription } from 'rxjs';
+
+function validateStartDate(formControl: FormControl): ValidationErrors | null {
+ if (!formControl.parent) {
+ return null;
+ }
+ const filterForm = formControl.parent;
+ const startTimeMs = new Date(filterForm.controls['startTime'].value).getTime();
+ const endTimeMs = new Date(filterForm.controls['endTime'].value).getTime();
+ if (startTimeMs > endTimeMs) {
+ return { error: 'Start time cannot be bigger than end date.' };
+ }
+ return null;
+}
+
+function validateEndDate(formControl: FormControl): ValidationErrors | null {
+ if (!formControl.parent) {
+ return null;
+ }
+ const filterForm = formControl.parent;
+ const endTimeMs = new Date(filterForm.controls['endTime'].value).getTime();
+ if (endTimeMs > new Date().getTime()) {
+ return { error: 'End time cannot be in the future.' };
+ }
+ return null;
+}
+
+function transformPcapRequestToFormGroupValue(model: PcapRequest): PcapFilterFormValue {
+ const startTimeStr = moment(model.startTimeMs > 0 ? model.startTimeMs : DEFAULT_START_TIME).format(DEFAULT_TIMESTAMP_FORMAT);
+ let endTimeStr = moment(model.endTimeMs).format(DEFAULT_TIMESTAMP_FORMAT);
+ if (isNaN((new Date(model.endTimeMs).getTime()))) {
+ endTimeStr = moment(DEFAULT_END_TIME).format(DEFAULT_TIMESTAMP_FORMAT);
+ } else {
+ endTimeStr = moment(model.endTimeMs).format(DEFAULT_TIMESTAMP_FORMAT);
+ }
+
+ return {
+ startTime: startTimeStr,
+ endTime: endTimeStr,
+ ipSrcAddr: model.ipSrcAddr,
+ ipDstAddr: model.ipDstAddr,
+ ipSrcPort: model.ipSrcPort ? String(model.ipSrcPort) : '',
+ ipDstPort: model.ipDstPort ? String(model.ipDstPort) : '',
+ protocol: model.protocol,
+ includeReverse: model.includeReverse,
+ packetFilter: model.packetFilter
+ };
+}
+
+function transformFormGroupValueToPcapRequest(control: FormGroup): PcapRequest {
+ const pcapRequest = new PcapRequest();
+ pcapRequest.startTimeMs = new Date(control.value.startTime).getTime();
+ pcapRequest.endTimeMs = new Date(control.value.endTime).getTime();
+ pcapRequest.ipSrcAddr = control.value.ipSrcAddr;
+ pcapRequest.ipDstAddr = control.value.ipDstAddr;
+ pcapRequest.ipSrcPort = control.value.ipSrcPort;
+ pcapRequest.ipDstPort = control.value.ipDstPort;
+ pcapRequest.protocol = control.value.protocol;
+ pcapRequest.includeReverse = control.value.includeReverse;
+ pcapRequest.packetFilter = control.value.packetFilter;
+ return pcapRequest;
+}
+
+export type PcapFilterFormValue = {
+ startTime: string,
+ endTime: string,
+ ipSrcAddr: string,
+ ipDstAddr: string,
+ ipSrcPort: string,
+ ipDstPort: string,
+ protocol: string,
+ includeReverse: boolean,
+ packetFilter: string
+};
@Component({
selector: 'app-pcap-filters',
templateUrl: './pcap-filters.component.html',
styleUrls: ['./pcap-filters.component.scss']
})
-export class PcapFiltersComponent implements OnInit, OnChanges {
+export class PcapFiltersComponent implements OnInit, OnChanges, OnDestroy {
- @Input() queryRunning: boolean = true;
+ @Input() queryRunning = true;
@Input() model: PcapRequest = new PcapRequest();
@Output() search: EventEmitter<PcapRequest> = new EventEmitter<PcapRequest>();
- startTimeStr: string;
- endTimeStr: string;
- ipSrcPort: string = '';
- ipDstPort: string = '';
+ private validIp: RegExp = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}$/;
+ private validPort: RegExp = /^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/;
- constructor() { }
+ private dateRangeChangeSubscription: Subscription;
- ngOnInit() {
- const endTime = new Date();
- const startTime = new Date().setDate(endTime.getDate() - 5);
+ filterForm = new FormGroup({
+ startTime: new FormControl(moment(DEFAULT_START_TIME).format(DEFAULT_TIMESTAMP_FORMAT), validateStartDate),
+ endTime: new FormControl(moment(DEFAULT_END_TIME).format(DEFAULT_TIMESTAMP_FORMAT), validateEndDate),
+ ipSrcAddr: new FormControl('', Validators.pattern(this.validIp)),
+ ipSrcPort: new FormControl('', Validators.pattern(this.validPort)),
+ ipDstAddr: new FormControl('', Validators.pattern(this.validIp)),
+ ipDstPort: new FormControl('', Validators.pattern(this.validPort)),
+ protocol: new FormControl(''),
+ includeReverse: new FormControl(),
+ packetFilter: new FormControl(''),
+ });
+
+ subscribeToDateRangeChanges(callback: () => void): Subscription {
+ const startTimeChanges: Observable<string> = this.filterForm.get('startTime').valueChanges;
+ const endTimeChanges: Observable<string> = this.filterForm.get('endTime').valueChanges;
+ return startTimeChanges.merge(endTimeChanges).subscribe(callback);
+ }
- this.startTimeStr = moment(startTime).format(DEFAULT_TIMESTAMP_FORMAT);
- this.endTimeStr = moment(endTime).format(DEFAULT_TIMESTAMP_FORMAT);
+ forceValidateDateRangeFields() {
+ [
+ this.filterForm.get('startTime'),
+ this.filterForm.get('endTime'),
+ ].forEach((control: FormControl) => {
+ control.updateValueAndValidity({
+ emitEvent: false
+ });
+ });
+ }
+
+ ngOnInit() {
+ this.dateRangeChangeSubscription = this.subscribeToDateRangeChanges(() => {
+ this.forceValidateDateRangeFields();
+ });
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['model']) {
- this.startTimeStr = moment(changes['model'].currentValue.startTimeMs).format(DEFAULT_TIMESTAMP_FORMAT);
- this.endTimeStr = moment(changes['model'].currentValue.endTimeMs).format(DEFAULT_TIMESTAMP_FORMAT);
- let newIpSrcPort = changes['model'].currentValue.ipSrcPort;
- this.ipSrcPort = newIpSrcPort ? newIpSrcPort.toString() : '';
- let newIpDstPort = changes['model'].currentValue.ipDstPort;
- this.ipDstPort = newIpDstPort ? newIpDstPort.toString() : '';
+ const newModel: PcapRequest = changes['model'].currentValue;
+ const controlValue = transformPcapRequestToFormGroupValue(newModel);
+ this.filterForm.setValue(controlValue);
}
}
onSubmit() {
- this.model.startTimeMs = moment(this.startTimeStr, DEFAULT_TIMESTAMP_FORMAT).valueOf();
- this.model.endTimeMs = moment(this.endTimeStr, DEFAULT_TIMESTAMP_FORMAT).valueOf();
- if (this.ipSrcPort !== '') {
- this.model.ipSrcPort = +this.ipSrcPort;
- } else {
- delete this.model.ipSrcPort;
- }
- if (this.ipDstPort !== '') {
- this.model.ipDstPort = +this.ipDstPort;
- } else {
- delete this.model.ipDstPort;
- }
+ const pcapRequest = transformFormGroupValueToPcapRequest(this.filterForm);
+ this.search.emit(pcapRequest);
+ }
- this.search.emit(this.model);
+ ngOnDestroy() {
+ this.dateRangeChangeSubscription.unsubscribe();
}
}
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/pcap-list/pcap-list.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-list/pcap-list.component.html b/metron-interface/metron-alerts/src/app/pcap/pcap-list/pcap-list.component.html
index 5337935..10b7be2 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-list/pcap-list.component.html
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-list/pcap-list.component.html
@@ -16,9 +16,9 @@
<thead>
<tr>
<th scope="col">Timestamp</th>
- <th scope="col">Source Addr</th>
+ <th scope="col">Source Address</th>
<th scope="col">Source Port</th>
- <th scope="col">Dest Addr</th>
+ <th scope="col">Dest Address</th>
<th scope="col">Dest Port</th>
<th scope="col">Protocol</th>
</tr>
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts
index 00f081f..dccfaa2 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.spec.ts
@@ -16,8 +16,7 @@
* limitations under the License.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-import { fakePacket } from '../model/pdml.mock';
-import { fakeUdpPacket } from '../model/pdml.mock';
+import { fakePacket, fakeUdpPacket } from '../model/pdml.mock';
import { PcapPacketLineComponent } from './pcap-packet-line.component';
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts
index b1546af..913aff9 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-packet-line/pcap-packet-line.component.ts
@@ -16,7 +16,7 @@
* limitations under the License.
*/
import { Component, OnInit, Input } from '@angular/core';
-import { PdmlPacket, PdmlProto, PdmlField } from '../model/pdml'
+import { PdmlPacket, PdmlProto, PdmlField } from '../model/pdml';
@Component({
selector: '[app-pcap-packet-line]',
@@ -37,18 +37,18 @@ export class PcapPacketLineComponent implements OnInit {
constructor() { }
ngOnInit() {
- const genProto: PdmlProto = this.packet.protos.filter(p => p.name == "geninfo")[0];
- const ipProto: PdmlProto = this.packet.protos.filter(p => p.name == "ip")[0];
- const tcpProto: PdmlProto = this.packet.protos.filter(p => p.name == "tcp")[0];
- const udpProto: PdmlProto = this.packet.protos.filter(p => p.name == "udp")[0];
+ const genProto: PdmlProto = this.packet.protos.filter(p => p.name === 'geninfo')[0];
+ const ipProto: PdmlProto = this.packet.protos.filter(p => p.name === 'ip')[0];
+ const tcpProto: PdmlProto = this.packet.protos.filter(p => p.name === 'tcp')[0];
+ const udpProto: PdmlProto = this.packet.protos.filter(p => p.name === 'udp')[0];
this.ip = {
- timestamp: PdmlProto.findField(genProto,'timestamp'),
- ipSrcAddr: PdmlProto.findField(ipProto,'ip.src'),
- ipSrcPort: tcpProto ? PdmlProto.findField(tcpProto,'tcp.srcport') : PdmlProto.findField(udpProto,'udp.srcport'),
- ipDestAddr: PdmlProto.findField(ipProto,'ip.dst'),
- ipDestPort: tcpProto ? PdmlProto.findField(tcpProto,'tcp.dstport') : PdmlProto.findField(udpProto,'udp.dstport'),
- protocol: PdmlProto.findField(ipProto,'ip.proto')
+ timestamp: PdmlProto.findField(genProto, 'timestamp'),
+ ipSrcAddr: PdmlProto.findField(ipProto, 'ip.src'),
+ ipSrcPort: tcpProto ? PdmlProto.findField(tcpProto, 'tcp.srcport') : PdmlProto.findField(udpProto, 'udp.srcport'),
+ ipDestAddr: PdmlProto.findField(ipProto, 'ip.dst'),
+ ipDestPort: tcpProto ? PdmlProto.findField(tcpProto, 'tcp.dstport') : PdmlProto.findField(udpProto, 'udp.dstport'),
+ protocol: PdmlProto.findField(ipProto, 'ip.proto')
};
}
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
index fe4df1e..2ebf884 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.spec.ts
@@ -26,8 +26,8 @@ import { PcapPagination } from '../model/pcap-pagination';
import { By } from '../../../../node_modules/@angular/platform-browser';
import { PcapRequest } from '../model/pcap.request';
import { defer } from 'rxjs/observable/defer';
-import {Observable} from "rxjs/Observable";
-import {RestError} from "../../model/rest-error";
+import { Observable } from 'rxjs/Observable';
+import { RestError } from '../../model/rest-error';
@Component({
selector: 'app-pcap-filters',
@@ -349,7 +349,7 @@ describe('PcapPanelComponent', () => {
it('should hide the progress bar if the user clicks on the cancel button', fakeAsync(() => {
component.queryRunning = true;
- component.queryId = 'testid';
+ component.queryId = '42';
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('.pcap-progress'))).toBeDefined();
@@ -360,7 +360,7 @@ describe('PcapPanelComponent', () => {
tick();
fixture.detectChanges();
- expect(fixture.debugElement.query(By.css('.pcap-progress'))).toBeFalsy();
+ expect(fixture.debugElement.query(By.css('.pcap-progress')) == null).toBe(true);
}));
it('should hide the progress bar if the cancellation request fails', fakeAsync(() => {
@@ -370,7 +370,7 @@ describe('PcapPanelComponent', () => {
);
component.queryRunning = true;
- component.queryId = 'testid';
+ component.queryId = '42';
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('.pcap-progress'))).toBeDefined();
@@ -381,7 +381,7 @@ describe('PcapPanelComponent', () => {
tick();
fixture.detectChanges();
- expect(fixture.debugElement.query(By.css('.pcap-progress'))).toBeFalsy();
+ expect(fixture.debugElement.query(By.css('.pcap-progress')) == null).toBe(true);
}));
it('should show an error message if the cancellation request fails', fakeAsync(() => {
@@ -392,9 +392,9 @@ describe('PcapPanelComponent', () => {
);
component.queryRunning = true;
- component.queryId = 'testid';
+ component.queryId = '42';
fixture.detectChanges();
- expect(fixture.debugElement.query(By.css('[data-qe-id="error"]'))).toBeFalsy();
+ expect(fixture.debugElement.query(By.css('[data-qe-id="error"]')) == null).toBe(true);
const cancelBtn = fixture.debugElement.query(By.css('[data-qe-id="pcap-cancel-query-button"]'));
const cancelBtnEl = cancelBtn.nativeElement;
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
index 7c88007..4a017db 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap-panel/pcap-panel.component.ts
@@ -23,7 +23,7 @@ import { PcapRequest } from '../model/pcap.request';
import { Pdml } from '../model/pdml';
import { Subscription } from 'rxjs/Rx';
import { PcapPagination } from '../model/pcap-pagination';
-import { RestError } from "../../model/rest-error";
+import { RestError } from '../../model/rest-error';
@Component({
selector: 'app-pcap-panel',
@@ -40,9 +40,9 @@ export class PcapPanelComponent implements OnInit, OnDestroy {
cancelSubscription: Subscription;
submitSubscription: Subscription;
getSubscription: Subscription;
- queryRunning: boolean = false;
+ queryRunning = false;
queryId: string;
- progressWidth: number = 0;
+ progressWidth = 0;
pagination: PcapPagination = new PcapPagination();
savedPcapRequest: {};
errorMsg: string;
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/pcap/pcap.module.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/pcap/pcap.module.ts b/metron-interface/metron-alerts/src/app/pcap/pcap.module.ts
index 8c0db02..784bc93 100644
--- a/metron-interface/metron-alerts/src/app/pcap/pcap.module.ts
+++ b/metron-interface/metron-alerts/src/app/pcap/pcap.module.ts
@@ -17,7 +17,7 @@
*/
import {NgModule} from '@angular/core';
import { CommonModule } from '@angular/common';
-import { FormsModule } from '@angular/forms';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { routing } from './pcap.routing';
@@ -29,7 +29,7 @@ import { PcapPacketComponent } from './pcap-packet/pcap-packet.component';
import { PcapFiltersComponent } from './pcap-filters/pcap-filters.component';
import { PcapPanelComponent } from './pcap-panel/pcap-panel.component';
import { PcapPacketLineComponent } from './pcap-packet-line/pcap-packet-line.component';
-import { PcapPaginationComponent } from './pcap-pagination/pcap-pagination.component'
+import { PcapPaginationComponent } from './pcap-pagination/pcap-pagination.component';
import { PcapService } from './service/pcap.service';
@NgModule({
@@ -37,6 +37,7 @@ import { PcapService } from './service/pcap.service';
routing,
CommonModule,
FormsModule,
+ ReactiveFormsModule,
HttpModule,
DatePickerModule,
],
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.component.scss
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.component.scss b/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.component.scss
index 813b6a5..f46599a 100644
--- a/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.component.scss
+++ b/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.component.scss
@@ -28,4 +28,16 @@
font-family: "FontAwesome";
content: '\f073';
}
-}
\ No newline at end of file
+}
+
+:host(.ng-invalid):not(form) {
+ border-left: none !important;
+}
+
+:host(.ng-invalid) input {
+ border-left: 5px solid #a94442; /* red */
+
+ &:focus {
+ border-color: #4D4D4D;
+ }
+}
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.component.ts b/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.component.ts
index d58bb5f..9014058 100644
--- a/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.component.ts
+++ b/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.component.ts
@@ -15,21 +15,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
import { Component, OnInit, ViewChild, ElementRef, OnChanges, SimpleChanges, Input, Output, EventEmitter } from '@angular/core';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import * as moment from 'moment/moment';
-import * as Pikaday from "pikaday-time";
+import * as Pikaday from 'pikaday-time';
@Component({
selector: 'app-date-picker',
templateUrl: './date-picker.component.html',
+ providers : [{
+ provide : NG_VALUE_ACCESSOR,
+ useExisting: DatePickerComponent,
+ multi: true,
+ }],
styleUrls: ['./date-picker.component.scss']
})
-export class DatePickerComponent implements OnInit, OnChanges {
+export class DatePickerComponent implements OnInit, OnChanges, ControlValueAccessor {
defaultDateStr = 'now';
picker: Pikaday;
dateStr = this.defaultDateStr;
+ private onChange: Function;
+ private onTouched: Function;
+
@Input() date = '';
@Input() minDate = '';
@Output() dateChange = new EventEmitter<string>();
@@ -45,7 +53,12 @@ export class DatePickerComponent implements OnInit, OnChanges {
use24hour: true,
onSelect: function() {
_datePickerComponent.dateStr = this.getMoment().format('YYYY-MM-DD HH:mm:ss');
- setTimeout(() => _datePickerComponent.dateChange.emit(_datePickerComponent.dateStr), 0);
+ setTimeout(() => {
+ _datePickerComponent.dateChange.emit(_datePickerComponent.dateStr);
+ if (_datePickerComponent.onChange) {
+ _datePickerComponent.onChange(_datePickerComponent.dateStr);
+ }
+ }, 0);
}
};
this.picker = new Pikaday(pikadayConfig);
@@ -62,6 +75,19 @@ export class DatePickerComponent implements OnInit, OnChanges {
}
}
+ writeValue(value) {
+ this.date = value;
+ this.setDate();
+ }
+
+ registerOnChange(fn) {
+ this.onChange = fn;
+ }
+
+ registerOnTouched(fn) {
+ this.onTouched = fn;
+ }
+
setDate() {
if (this.date === '') {
this.dateStr = this.defaultDateStr;
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.module.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.module.ts b/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.module.ts
index d59d566..e5dfd6c 100644
--- a/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.module.ts
+++ b/metron-interface/metron-alerts/src/app/shared/date-picker/date-picker.module.ts
@@ -19,8 +19,7 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
-import {DatePickerComponent} from './date-picker.component';
-import {SharedModule} from '../shared.module';
+import { DatePickerComponent } from './date-picker.component';
@NgModule({
imports: [
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/utils/constants.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/utils/constants.ts b/metron-interface/metron-alerts/src/app/utils/constants.ts
index 74e887a..703e0f7 100644
--- a/metron-interface/metron-alerts/src/app/utils/constants.ts
+++ b/metron-interface/metron-alerts/src/app/utils/constants.ts
@@ -37,3 +37,6 @@ export let INDEXES = environment.indices ? environment.indices.split(',') : [];
export let POLLING_DEFAULT_STATE = environment.defaultPollingState;
export let MAX_ALERTS_IN_META_ALERTS = 350;
+
+export const DEFAULT_END_TIME = new Date();
+export const DEFAULT_START_TIME = new Date().setDate(DEFAULT_END_TIME.getDate() - 5);
http://git-wip-us.apache.org/repos/asf/metron/blob/e66cfc80/metron-interface/metron-alerts/src/app/utils/utils.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/utils/utils.ts b/metron-interface/metron-alerts/src/app/utils/utils.ts
index 61cc45b..4eb098a 100644
--- a/metron-interface/metron-alerts/src/app/utils/utils.ts
+++ b/metron-interface/metron-alerts/src/app/utils/utils.ts
@@ -17,12 +17,15 @@
*/
import * as moment from 'moment/moment';
-import {DEFAULT_TIMESTAMP_FORMAT, META_ALERTS_SENSOR_TYPE} from './constants';
-import {Alert} from '../model/alert';
-import {DateFilterValue} from '../model/date-filter-value';
-import { environment } from 'environments/environment';
+import { DEFAULT_START_TIME, DEFAULT_END_TIME, DEFAULT_TIMESTAMP_FORMAT, META_ALERTS_SENSOR_TYPE } from './constants';
+import { Alert } from '../model/alert';
+import { DateFilterValue } from '../model/date-filter-value';
+import { PcapRequest } from '../pcap/model/pcap.request';
+import { PcapFilterFormValue } from '../pcap/pcap-filters/pcap-filters.component';
+import { FormGroup } from '@angular/forms';
export class Utils {
+
public static escapeESField(field: string): string {
return field.replace(/:/g, '\\:');
}
@@ -201,5 +204,4 @@ export class Utils {
return {toDate: toDate, fromDate: fromDate};
}
-
}