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};
   }
-
 }