Repository: metron
Updated Branches:
  refs/heads/feature/METRON-1136-extensions-parsers d6a66eb26 -> 5f7454e4a 
(forced update)


METRON-1068 Use Elasticsearch End Point in Alerts UI (iraghumitra via 
nickwallen) closes apache/metron#699


Project: http://git-wip-us.apache.org/repos/asf/metron/repo
Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/9bc9e0c5
Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/9bc9e0c5
Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/9bc9e0c5

Branch: refs/heads/feature/METRON-1136-extensions-parsers
Commit: 9bc9e0c524ab41c2d4df1f45f20fc58f4799103d
Parents: c8e84fa
Author: iraghumitra <raghumitra....@gmail.com>
Authored: Mon Aug 28 09:52:15 2017 -0400
Committer: nickallen <nickal...@apache.org>
Committed: Mon Aug 28 09:52:15 2017 -0400

----------------------------------------------------------------------
 metron-interface/metron-alerts/README.md        | 22 +++--
 .../metron-alerts/alerts-server-e2e.js          | 31 +++++--
 .../e2e/alerts-list/alerts-list.e2e-spec.ts     | 17 +++-
 .../configure-table/configure-table.e2e-spec.ts | 15 +++-
 .../save-search/save-search.e2e-spec.ts         | 11 +++
 .../metron-alerts/e2e/login/login.e2e-spec.ts   | 44 ++++++++++
 .../metron-alerts/e2e/login/login.po.ts         | 65 ++++++++++++++
 .../metron-alerts/e2e/utils/e2e_util.ts         | 30 +++++++
 .../metron-alerts/protractor.conf.js            | 13 ++-
 metron-interface/metron-alerts/proxy.conf.json  |  4 +-
 .../metron-alerts/scripts/alerts-server.js      | 12 ++-
 .../scripts/start-server-for-e2e.sh             |  3 +-
 .../metron-alerts/src/_variables.scss           |  3 +
 .../alert-details/alert-details.component.html  |  4 +-
 .../alert-details/alert-details.component.ts    | 44 ++++++----
 .../alert-details/alerts-details.routing.ts     |  2 +-
 .../alerts-list/alerts-list.component.html      |  6 +-
 .../alerts/alerts-list/alerts-list.component.ts | 32 +++----
 .../alerts/alerts-list/alerts-list.module.ts    |  2 +-
 .../src/app/alerts/alerts-list/query-builder.ts | 18 ++--
 .../metron-alerts/src/app/app-routing.module.ts | 12 ++-
 .../metron-alerts/src/app/app.component.html    |  5 +-
 .../metron-alerts/src/app/app.component.scss    | 12 +++
 .../metron-alerts/src/app/app.component.ts      |  8 ++
 .../metron-alerts/src/app/app.module.ts         | 14 ++-
 .../src/app/login/login.component.html          | 28 ++++++
 .../src/app/login/login.component.scss          | 55 ++++++++++++
 .../src/app/login/login.component.spec.ts       | 65 ++++++++++++++
 .../src/app/login/login.component.ts            | 43 +++++++++
 .../metron-alerts/src/app/login/login.module.ts | 28 ++++++
 .../src/app/login/login.routing.ts              | 25 ++++++
 .../metron-alerts/src/app/model/alert-source.ts | 52 +++++++++++
 .../metron-alerts/src/app/model/alert.ts        | 45 +---------
 .../src/app/model/search-request.ts             | 12 +--
 .../metron-alerts/src/app/model/sort-field.ts   | 21 +++++
 .../src/app/service/alert.service.ts            | 13 +--
 .../src/app/service/authentication.service.ts   | 91 ++++++++++++++++++++
 .../src/app/service/data-source.ts              |  5 +-
 .../service/elasticsearch-localstorage-impl.ts  | 11 ++-
 .../src/app/service/rest-api-impl.ts            | 46 ++++++++++
 .../metron-alerts/src/app/shared/auth-guard.ts  | 50 +++++++++++
 .../metron-alerts/src/app/shared/login-guard.ts | 40 +++++++++
 .../src/app/utils/elasticsearch-utils.ts        |  2 +-
 .../metron-alerts/src/app/utils/httpUtil.ts     |  6 +-
 .../src/environments/environment.prod.ts        |  3 +-
 45 files changed, 917 insertions(+), 153 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/README.md
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/README.md 
b/metron-interface/metron-alerts/README.md
index adba151..db7f038 100644
--- a/metron-interface/metron-alerts/README.md
+++ b/metron-interface/metron-alerts/README.md
@@ -17,15 +17,17 @@
 
 ## Development Setup
 
-Install all the dependent node_modules using the following command
-```
-cd metron/metron-interface/metron-alerts
-npm install
-```
-UI can be run by using the following command
-```
-./scripts/start-dev.sh
-```
+1. Install all the dependent node_modules using the following command
+    ```
+    cd metron/metron-interface/metron-alerts
+    npm install
+    ```
+1. UI can be run by using the following command
+    ```
+    ./scripts/start-dev.sh
+    ```
+1. You can view the GUI @http://localhost:4200 . The default credentials for 
login are admin/password
+
 **NOTE**: *In the development mode ui by default connects to ES at 
http://node1:9200 for fetching data. If you wish to change it you can change 
the ES url at metron/metron-interface/metron-alerts/proxy.conf.json*
 
 ## E2E Tests
@@ -44,6 +46,8 @@ An expressjs server is available for mocking the elastic 
search api.
     npm run e2e
     ```
 
+1. E2E tests uses data from full-dev wherever applicable. The tests assume 
rest-api's are available @http://node1:8082
+
 **NOTE**: *e2e tests covers all the general workflows and we will extend them 
as we need*
 
 ## Mpack Integration

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/alerts-server-e2e.js
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/alerts-server-e2e.js 
b/metron-interface/metron-alerts/alerts-server-e2e.js
index e30ef44..2a5f80b 100644
--- a/metron-interface/metron-alerts/alerts-server-e2e.js
+++ b/metron-interface/metron-alerts/alerts-server-e2e.js
@@ -29,9 +29,10 @@ var serveStatic = require('serve-static');
 var favicon     = require('serve-favicon');
 var proxy       = require('http-proxy-middleware');
 var argv        = require('optimist')
-                  .demand(['p'])
+                  .demand(['p', 'r'])
                   .usage('Usage: server.js -p [port]')
                   .describe('p', 'Port to run metron alerts ui')
+                  .describe('r', 'Url where metron rest application is 
available')
                   .argv;
 
 var port = argv.p;
@@ -73,13 +74,19 @@ var searchResult = function(req, res){
       return;
     }
 
-    var filter = req.body.query.query_string.query;
+    var responseMap = {
+      total: 0,
+      results: obj.hits.hits
+    };
+    
+    var filter = req.body.query;
+
     if (filter !== '*') {
       filter = filter.replace(/\\/g, '');
       var lastIndex = filter.lastIndexOf(':');
       var key = filter.substr(0, lastIndex);
       var value = filter.substr(lastIndex+1);
-      obj.hits.hits =  obj.hits.hits.filter(function (hits) {
+      responseMap.results =  obj.hits.hits.filter(function (hits) {
         return hits._source[key] === value;
       });
     }
@@ -88,7 +95,7 @@ var searchResult = function(req, res){
     if (sortField) {
       var key = Object.keys(sortField)[0];
       var order = sortField[key].order;
-      obj.hits.hits = obj.hits.hits.sort(function(o1, o2) {
+      responseMap.results = obj.hits.hits.sort(function(o1, o2) {
         if (!o1._source[key] || !o2._source[key]) {
           return -1;
         } 
@@ -102,9 +109,15 @@ var searchResult = function(req, res){
       });
     }
 
-    obj.hits.total = obj.hits.hits.length;
-    obj.hits.hits = obj.hits.hits.splice(req.body.from, req.body.size);
-    res.json(obj);
+    responseMap.total = responseMap.results.length;
+    responseMap.results = responseMap.results.splice(req.body.from, 
req.body.size);
+
+    responseMap.results.map(function (obj) {
+      obj.id = obj._id;
+      obj.source = obj._source;
+    });
+
+    res.json(responseMap);
   });
 };
 
@@ -128,7 +141,9 @@ app.use(serveStatic(path.join(__dirname, 'dist'), {
   setHeaders: setCustomCacheControl
 }));
 
-app.post('^/search/*', searchResult);
+app.use('/api/v1/user', proxy(conf.elastic));
+app.use('/logout', proxy(conf.elastic));
+app.post('/api/v1/search/search', searchResult);
 app.use('/_cluster', clusterState);
 app.get('/alerts-list', indexHTML);
 app.get('', indexHTML);

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/e2e/alerts-list/alerts-list.e2e-spec.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/e2e/alerts-list/alerts-list.e2e-spec.ts 
b/metron-interface/metron-alerts/e2e/alerts-list/alerts-list.e2e-spec.ts
index 454ee6e..b27df7e 100644
--- a/metron-interface/metron-alerts/e2e/alerts-list/alerts-list.e2e-spec.ts
+++ b/metron-interface/metron-alerts/e2e/alerts-list/alerts-list.e2e-spec.ts
@@ -18,14 +18,25 @@
  */
 import { MetronAlertsPage } from './alerts-list.po';
 import { customMatchers } from  '../matchers/custom-matchers';
+import { LoginPage } from '../login/login.po';
 
 describe('metron-alerts App', function() {
   let page: MetronAlertsPage;
-  let columnNames = [ 'Score', '_id', 'timestamp', 'source:type', 
'ip_src_addr', 'enrichm...:country',
+  let loginPage: LoginPage;
+  let columnNames = [ 'Score', 'id', 'timestamp', 'source:type', 
'ip_src_addr', 'enrichm...:country',
                       'ip_dst_addr', 'host', 'alert_status', '', '' ];
-  let colNamesColumnConfig = [ 'score', '_id', 'timestamp', 'source:type', 
'ip_src_addr', 'enrichments:geo:ip_dst_addr:country',
+  let colNamesColumnConfig = [ 'score', 'id', 'timestamp', 'source:type', 
'ip_src_addr', 'enrichments:geo:ip_dst_addr:country',
                                 'ip_dst_addr', 'host', 'alert_status' ];
 
+  beforeAll(() => {
+    loginPage = new LoginPage();
+    loginPage.login();
+  });
+
+  afterAll(() => {
+    loginPage.logout();
+  });
+
   beforeEach(() => {
     page = new MetronAlertsPage();
     jasmine.addMatchers(customMatchers);
@@ -126,7 +137,7 @@ describe('metron-alerts App', function() {
 
     page.clickConfigureTable();
     expect(page.getSelectedColumnNames()).toEqual(colNamesColumnConfig, 'for 
default selected column names');
-    page.toggleSelectCol('_id');
+    page.toggleSelectCol('id');
     page.toggleSelectCol('guid', 'method');
     expect(page.getSelectedColumnNames()).toEqual(newColNamesColumnConfig, 
'for guid added to selected column names');
     page.saveConfigureColumns();

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/e2e/alerts-list/configure-table/configure-table.e2e-spec.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/e2e/alerts-list/configure-table/configure-table.e2e-spec.ts
 
b/metron-interface/metron-alerts/e2e/alerts-list/configure-table/configure-table.e2e-spec.ts
index 55d2a6e..fb3e3cd 100644
--- 
a/metron-interface/metron-alerts/e2e/alerts-list/configure-table/configure-table.e2e-spec.ts
+++ 
b/metron-interface/metron-alerts/e2e/alerts-list/configure-table/configure-table.e2e-spec.ts
@@ -18,12 +18,23 @@
  */
 import { MetronAlertsPage } from '../alerts-list.po';
 import {customMatchers} from '../../matchers/custom-matchers';
+import {LoginPage} from '../../login/login.po';
 
 describe('metron-alerts configure table', function() {
   let page: MetronAlertsPage;
-  let colNamesColumnConfig = [ 'score', '_id', 'timestamp', 'source:type', 
'ip_src_addr', 'enrichments:geo:ip_dst_addr:country',
+  let loginPage: LoginPage;
+  let colNamesColumnConfig = [ 'score', 'id', 'timestamp', 'source:type', 
'ip_src_addr', 'enrichments:geo:ip_dst_addr:country',
     'ip_dst_addr', 'host', 'alert_status' ];
 
+  beforeAll(() => {
+    loginPage = new LoginPage();
+    loginPage.login();
+  });
+
+  afterAll(() => {
+    loginPage.logout();
+  });
+
   beforeEach(() => {
     page = new MetronAlertsPage();
     jasmine.addMatchers(customMatchers);
@@ -38,7 +49,7 @@ describe('metron-alerts configure table', function() {
 
     page.clickConfigureTable();
     expect(page.getSelectedColumnNames()).toEqual(colNamesColumnConfig, 'for 
default selected column names');
-    page.toggleSelectCol('_id');
+    page.toggleSelectCol('id');
     page.toggleSelectCol('guid', 'method');
     expect(page.getSelectedColumnNames()).toEqual(newColNamesColumnConfig, 
'for guid added to selected column names');
     page.saveConfigureColumns();

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/e2e/alerts-list/save-search/save-search.e2e-spec.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/e2e/alerts-list/save-search/save-search.e2e-spec.ts
 
b/metron-interface/metron-alerts/e2e/alerts-list/save-search/save-search.e2e-spec.ts
index fc02e12..85127dc 100644
--- 
a/metron-interface/metron-alerts/e2e/alerts-list/save-search/save-search.e2e-spec.ts
+++ 
b/metron-interface/metron-alerts/e2e/alerts-list/save-search/save-search.e2e-spec.ts
@@ -18,9 +18,20 @@
  */
 import { customMatchers } from  '../../matchers/custom-matchers';
 import {MetronAlertsPage} from '../alerts-list.po';
+import {LoginPage} from '../../login/login.po';
 
 describe('metron-alerts Search', function() {
   let page: MetronAlertsPage;
+  let loginPage: LoginPage;
+
+  beforeAll(() => {
+    loginPage = new LoginPage();
+    loginPage.login();
+  });
+
+  afterAll(() => {
+    loginPage.logout();
+  });
 
   beforeEach(() => {
     page = new MetronAlertsPage();

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/e2e/login/login.e2e-spec.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/e2e/login/login.e2e-spec.ts 
b/metron-interface/metron-alerts/e2e/login/login.e2e-spec.ts
new file mode 100644
index 0000000..dc53889
--- /dev/null
+++ b/metron-interface/metron-alerts/e2e/login/login.e2e-spec.ts
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { LoginPage } from './login.po';
+
+describe('login to application', function() {
+    let page: LoginPage;
+
+    beforeEach(() => {
+        page = new LoginPage();
+    });
+
+    it('should display error message for invalid credentials', () => {
+        page.navigateToLogin();
+        page.setUserNameAndPassword('admin', 'admin');
+        page.submitLoginForm();
+        expect(page.getErrorMessage()).toEqual('Login failed for admin');
+    });
+
+    it('should login for valid credentials', () => {
+        page.navigateToLogin();
+        page.setUserNameAndPassword('admin', 'password');
+        page.submitLoginForm();
+    });
+
+    it('should logout', () => {
+        page.logout();
+        expect(page.getLocation()).toEqual('http://localhost:4200/login');
+    });
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/e2e/login/login.po.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/e2e/login/login.po.ts 
b/metron-interface/metron-alerts/e2e/login/login.po.ts
new file mode 100644
index 0000000..b3e9769
--- /dev/null
+++ b/metron-interface/metron-alerts/e2e/login/login.po.ts
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { browser, element, by } from 'protractor';
+import {waitForElementVisibility} from '../utils/e2e_util';
+
+export class LoginPage {
+    navigateToLogin() {
+        return browser.get('/');
+    }
+
+    login() {
+        browser.wait(function() {return 
element(by.css('input.form-control')).isPresent(); });
+        this.setUserNameAndPassword('admin', 'password');
+        this.submitLoginForm();
+        browser.waitForAngularEnabled(false);
+        browser.wait(function() {return 
element(by.css('.logout')).isPresent(); });
+    }
+
+    logout() {
+        browser.waitForAngularEnabled(false);
+        element.all(by.css('.alert .close')).click();
+        element.all(by.css('.logout-link')).click();
+        browser.sleep(2000);
+    }
+
+    setUserNameAndPassword(userName: string, password: string) {
+        element.all(by.css('input.form-control')).get(0).sendKeys(userName);
+        element.all(by.css('input.form-control')).get(1).sendKeys(password);
+    }
+
+    submitLoginForm() {
+        return element.all(by.buttonText('LOG IN')).click();
+    }
+
+    getErrorMessage() {
+        browser.waitForAngularEnabled(false);
+        let errElement = element(by.css('div[style="color:#a94442"]'));
+        return waitForElementVisibility(errElement).then(() => {
+            return errElement.getText().then((message) => {
+                return message.replace(/\n/, '').replace(/LOG\ IN$/, '');
+            });
+        });
+    }
+
+    getLocation() {
+        return browser.getCurrentUrl().then(url => {
+            return url;
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/e2e/utils/e2e_util.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/e2e/utils/e2e_util.ts 
b/metron-interface/metron-alerts/e2e/utils/e2e_util.ts
new file mode 100644
index 0000000..836818e
--- /dev/null
+++ b/metron-interface/metron-alerts/e2e/utils/e2e_util.ts
@@ -0,0 +1,30 @@
+import { browser, protractor } from 'protractor';
+
+export function changeURL(url: string) {
+    return browser.get(url).then(() => {
+        return browser.getCurrentUrl().then((newURL) => {
+            return newURL;
+        });
+    });
+}
+
+export function waitForElementInVisibility (_element ) {
+    let EC = protractor.ExpectedConditions;
+    return browser.wait(EC.invisibilityOf(_element));
+}
+
+export function waitForElementPresence (_element ) {
+    let EC = protractor.ExpectedConditions;
+    return browser.wait(EC.presenceOf(_element));
+}
+
+export function waitForElementVisibility (_element ) {
+    let EC = protractor.ExpectedConditions;
+    return browser.wait(EC.visibilityOf(_element));
+}
+
+export function waitForStalenessOf (_element ) {
+    let EC = protractor.ExpectedConditions;
+    return browser.wait(EC.stalenessOf(_element));
+}
+

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/protractor.conf.js
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/protractor.conf.js 
b/metron-interface/metron-alerts/protractor.conf.js
index 082f1bf..189195c 100644
--- a/metron-interface/metron-alerts/protractor.conf.js
+++ b/metron-interface/metron-alerts/protractor.conf.js
@@ -25,10 +25,19 @@ var SpecReporter = 
require('jasmine-spec-reporter').SpecReporter;
 exports.config = {
   allScriptsTimeout: 25000,
   specs: [
-    './e2e/**/*.e2e-spec.ts'
+    './e2e/login/login.e2e-spec.ts',
+    '/e2e/alerts-list/alerts-list.e2e-spec.ts',
+    './e2e/alerts-list/configure-table/configure-table.e2e-spec.ts',
+    './e2e/alerts-list/save-search/save-search.e2e-spec.ts'
   ],
   capabilities: {
-    'browserName': 'chrome'
+    'browserName': 'chrome',
+    'chromeOptions': {
+      'prefs': {
+        'credentials_enable_service': false,
+        'profile': { 'password_manager_enabled': false}
+      }
+    }
   },
   directConnect: true,
   baseUrl: 'http://localhost:4200/',

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/proxy.conf.json
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/proxy.conf.json 
b/metron-interface/metron-alerts/proxy.conf.json
index 38f3e90..27d1ee9 100644
--- a/metron-interface/metron-alerts/proxy.conf.json
+++ b/metron-interface/metron-alerts/proxy.conf.json
@@ -1,10 +1,10 @@
 {
   "/api/v1": {
-    "target": "http://localhost:8080";,
+    "target": "http://node1:8082";,
     "secure": false
   },
   "/logout": {
-    "target": "http://localhost:8080";,
+    "target": "http://node1:8082";,
     "secure": false
   },
   "/search": {

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/scripts/alerts-server.js
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/scripts/alerts-server.js 
b/metron-interface/metron-alerts/scripts/alerts-server.js
index 84504cc..6fb35c9 100644
--- a/metron-interface/metron-alerts/scripts/alerts-server.js
+++ b/metron-interface/metron-alerts/scripts/alerts-server.js
@@ -27,9 +27,10 @@ var serveStatic = require('serve-static');
 var favicon     = require('serve-favicon');
 var proxy       = require('http-proxy-middleware');
 var argv        = require('optimist')
-                  .demand(['p', 'r'])
+                  .demand(['p', 'r', 'e'])
                   .alias('r', 'resturl')
-                  .usage('Usage: server.js -p [port] -r [restUrl]')
+                  .alias('e', 'elasticurl')
+                  .usage('Usage: server.js -p [port] -r [restUrl] -e 
[elasticURL]')
                   .describe('p', 'Port to run metron management ui')
                   .describe('r', 'Url where metron rest application is 
available')
                   .argv;
@@ -38,8 +39,13 @@ var port = argv.p;
 var metronUIAddress = '';
 var ifaces = os.networkInterfaces();
 var restUrl =  argv.r || argv.resturl;
+var elasticUrl =  argv.e || argv.elasticurl;
 var conf = {
   "elastic": {
+    "target": elasticUrl,
+    "secure": false
+  },
+  "rest": {
     "target": restUrl,
     "secure": false
   }
@@ -71,7 +77,7 @@ var rewriteSearchProxy = proxy({
 
 app.use(compression());
 
-app.use('/search', rewriteSearchProxy);
+app.use('/api', proxy(conf.rest));
 app.use('/_cluster', proxy(conf.elastic));
 
 app.use(favicon(path.join(__dirname, '../alerts-ui/favicon.ico')));

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/scripts/start-server-for-e2e.sh
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/scripts/start-server-for-e2e.sh 
b/metron-interface/metron-alerts/scripts/start-server-for-e2e.sh
index 0c97f88..7516fd0 100755
--- a/metron-interface/metron-alerts/scripts/start-server-for-e2e.sh
+++ b/metron-interface/metron-alerts/scripts/start-server-for-e2e.sh
@@ -17,4 +17,5 @@
 #
 SCRIPTS_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 cd $SCRIPTS_ROOT/.. && npm run build
-node $SCRIPTS_ROOT/../alerts-server-e2e.js -p 4200
+node $SCRIPTS_ROOT/../alerts-server-e2e.js -p 4200 -r http://node1:8082
+

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/_variables.scss
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/_variables.scss 
b/metron-interface/metron-alerts/src/_variables.scss
index 8bb37b2..1a5fa86 100644
--- a/metron-interface/metron-alerts/src/_variables.scss
+++ b/metron-interface/metron-alerts/src/_variables.scss
@@ -87,6 +87,9 @@ $placeholder-color: $dove-grey;
 
 $nav-content-nav-width: 200px;
 
+$login-label: #606060;
+$black: #000000;
+
 @mixin place-holder-text
 {
   font-family: Roboto;

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.html
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.html
 
b/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.html
index afc93eb..703b676 100644
--- 
a/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.html
+++ 
b/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.html
@@ -15,7 +15,7 @@
     <div class="container-fluid">
         <div class="row mb-3">
             <div class="col-md-10">
-                <div class="form-title" appAlertSeverity 
[severity]="alert['threat:triage:score']"> {{ alert['threat:triage:score'] }} 
{{ alert._id }}</div>
+                <div class="form-title" appAlertSeverity 
[severity]="alertSource['threat:triage:score']"> {{ 
alertSource['threat:triage:score'] }} {{ alertSource.guid }}</div>
             </div>
             <div class="col-md-2"><i class="fa fa-times pull-right 
close-button" aria-hidden="true" (click)="goBack()"></i></div>
         </div>
@@ -40,7 +40,7 @@
         </div>
         <div class="ml-1 my-4 form">
             <div *ngFor="let field of alertFields" class="row">
-              <div class="col-6 mb-1 key">{{ field }}</div>   <div 
class="col-6"> {{ alert._source[field] }} </div>
+              <div class="col-6 mb-1 key">{{ field }}</div>   <div 
class="col-6"> {{ alertSource[field] }} </div>
             </div>
         </div>
     </div>

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts
 
b/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts
index 218ceff..915c0c1 100644
--- 
a/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts
+++ 
b/metron-interface/metron-alerts/src/app/alerts/alert-details/alert-details.component.ts
@@ -20,6 +20,7 @@ import {Router, ActivatedRoute} from '@angular/router';
 import {AlertService} from '../../service/alert.service';
 import {Alert} from '../../model/alert';
 import {WorkflowService} from '../../service/workflow.service';
+import {AlertSource} from '../../model/alert-source';
 
 export enum AlertState {
   NEW, OPEN, ESCALATE, DISMISS, RESOLVE
@@ -33,11 +34,10 @@ export enum AlertState {
 export class AlertDetailsComponent implements OnInit {
 
   alertId = '';
-  alertIndex = '';
-  alertType = '';
+  alertSourceType = '';
   alertState = AlertState;
   selectedAlertState: AlertState = AlertState.NEW;
-  alert: Alert = new Alert();
+  alertSource: AlertSource = new AlertSource();
   alertFields: string[] = [];
 
   constructor(private router: Router,
@@ -51,54 +51,68 @@ export class AlertDetailsComponent implements OnInit {
   }
 
   getData() {
-    this.alertsService.getAlert(this.alertIndex, this.alertType, 
this.alertId).subscribe(alert => {
-      this.alert = alert;
-      this.alertFields = Object.keys(alert._source).filter(field => 
!field.includes(':ts') && field !== 'original_string').sort();
+    this.alertsService.getAlert(this.alertSourceType, 
this.alertId).subscribe(alert => {
+      this.alertSource = alert;
+      this.alertFields = Object.keys(alert).filter(field => 
!field.includes(':ts') && field !== 'original_string').sort();
     });
   }
 
   ngOnInit() {
     this.activatedRoute.params.subscribe(params => {
-      this.alertId = params['id'];
-      this.alertIndex = params['index'];
-      this.alertType = params['type'];
+      this.alertId = params['guid'];
+      this.alertSourceType = params['sourceType'];
       this.getData();
     });
   }
 
   processOpen() {
+    let tAlert = new Alert();
+    tAlert.source = this.alertSource;
+
     this.selectedAlertState = AlertState.OPEN;
-    this.alertsService.updateAlertState([this.alert], 'OPEN', 
'').subscribe(results => {
+    this.alertsService.updateAlertState([tAlert], 'OPEN', 
'').subscribe(results => {
       this.getData();
     });
   }
 
   processNew() {
+    let tAlert = new Alert();
+    tAlert.source = this.alertSource;
+
     this.selectedAlertState = AlertState.NEW;
-    this.alertsService.updateAlertState([this.alert], 'NEW', 
'').subscribe(results => {
+    this.alertsService.updateAlertState([tAlert], 'NEW', '').subscribe(results 
=> {
       this.getData();
     });
   }
 
   processEscalate() {
+    let tAlert = new Alert();
+    tAlert.source = this.alertSource;
+
     this.selectedAlertState = AlertState.ESCALATE;
-    this.workflowService.start([this.alert]).subscribe(workflowId => {
-      this.alertsService.updateAlertState([this.alert], 'ESCALATE', 
workflowId).subscribe(results => {
+    this.workflowService.start([tAlert]).subscribe(workflowId => {
+      this.alertsService.updateAlertState([tAlert], 'ESCALATE', 
workflowId).subscribe(results => {
         this.getData();
       });
     });
   }
 
   processDismiss() {
+    let tAlert = new Alert();
+    tAlert.source = this.alertSource;
+
     this.selectedAlertState = AlertState.DISMISS;
-    this.alertsService.updateAlertState([this.alert], 'DISMISS', 
'').subscribe(results => {
+    this.alertsService.updateAlertState([tAlert], 'DISMISS', 
'').subscribe(results => {
       this.getData();
     });
   }
 
   processResolve() {
+    let tAlert = new Alert();
+    tAlert.source = this.alertSource;
+
     this.selectedAlertState = AlertState.RESOLVE;
-    this.alertsService.updateAlertState([this.alert], 'RESOLVE', 
'').subscribe(results => {
+    this.alertsService.updateAlertState([tAlert], 'RESOLVE', 
'').subscribe(results => {
       this.getData();
     });
   }

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/alerts/alert-details/alerts-details.routing.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/alerts/alert-details/alerts-details.routing.ts
 
b/metron-interface/metron-alerts/src/app/alerts/alert-details/alerts-details.routing.ts
index 11cf61c..bc4dd5b 100644
--- 
a/metron-interface/metron-alerts/src/app/alerts/alert-details/alerts-details.routing.ts
+++ 
b/metron-interface/metron-alerts/src/app/alerts/alert-details/alerts-details.routing.ts
@@ -20,5 +20,5 @@ import { RouterModule } from '@angular/router';
 import {AlertDetailsComponent} from './alert-details.component';
 
 export const routing: ModuleWithProviders = RouterModule.forChild([
-    { path: 'details/:index/:type/:id', component: AlertDetailsComponent, 
outlet: 'dialog'}
+    { path: 'details/:sourceType/:guid', component: AlertDetailsComponent, 
outlet: 'dialog'}
 ]);

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html
 
b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html
index 1fb01bf..3707e9a 100644
--- 
a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html
+++ 
b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.html
@@ -77,14 +77,14 @@
                     </thead>
                     <tbody>
                     <tr *ngFor="let alert of alerts" 
(click)="showDetails($event, alert)" [ngClass]="{'selected' : 
selectedAlerts.indexOf(alert) != -1}">
-                        <td (click)="onAddFilter(threatScoreFieldName, 
alert._source[threatScoreFieldName])">
-                            <div appAlertSeverity 
[severity]="alert._source[threatScoreFieldName]"> <a> {{ 
alert._source[threatScoreFieldName] ? alert._source[threatScoreFieldName] : '-' 
}} </a> </div>
+                        <td (click)="onAddFilter(threatScoreFieldName, 
alert.source[threatScoreFieldName])">
+                            <div appAlertSeverity 
[severity]="alert.source[threatScoreFieldName]"> <a> {{ 
alert.source[threatScoreFieldName] ? alert.source[threatScoreFieldName] : '-' 
}} </a> </div>
                         </td>
                         <td *ngFor="let column of alertsColumnsToDisplay" 
#cell>
                             <a (click)="onAddFilter(column.name, 
getValue(alert, column, false))" title="{{getValue(alert, column, true)}}" 
style="color:#689AA9">{{ getValue(alert, column, true) | centerEllipses:20:cell 
}}</a>
                         </td>
                         <td></td>
-                        <td><input id="{{ alert._id }}" 
class="fontawesome-checkbox" type="checkbox" name="{{alert._id}}" 
(click)="selectRow($event, alert)" [checked]="selectedAlerts.indexOf(alert) != 
-1"><label attr.for="{{ alert._id }}"></label></td>
+                        <td><input id="{{ alert.id }}" 
class="fontawesome-checkbox" type="checkbox" name="{{alert.id}}" 
(click)="selectRow($event, alert)" [checked]="selectedAlerts.indexOf(alert) != 
-1"><label attr.for="{{ alert.id }}"></label></td>
                     </tr>
                     </tbody>
                 </table>

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
 
b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
index e014ede..35cbeff 100644
--- 
a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
+++ 
b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.component.ts
@@ -15,7 +15,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {Component, OnInit, ViewChild, ElementRef} from '@angular/core';
+import {Component, OnInit, ViewChild, ElementRef, OnDestroy} from 
'@angular/core';
 import {Router, NavigationStart} from '@angular/router';
 import {Observable, Subscription} from 'rxjs/Rx';
 
@@ -44,7 +44,7 @@ import {ElasticsearchUtils} from 
'../../utils/elasticsearch-utils';
   styleUrls: ['./alerts-list.component.scss']
 })
 
-export class AlertsListComponent implements OnInit {
+export class AlertsListComponent implements OnInit, OnDestroy {
 
   alertsColumns: ColumnMetadata[] = [];
   alertsColumnsToDisplay: ColumnMetadata[] = [];
@@ -148,31 +148,23 @@ export class AlertsListComponent implements OnInit {
 
   getColumnNamesForQuery() {
     let fieldNames = this.alertsColumns.map(columnMetadata => 
columnMetadata.name);
-    fieldNames = fieldNames.filter(name => !(name === '_id' || name === 
'alert_status'));
+    fieldNames = fieldNames.filter(name => !(name === 'id' || name === 
'alert_status'));
     fieldNames.push(this.threatScoreFieldName);
     return fieldNames;
   }
 
-  getDataType(name: string): string {
-    if (name === this.threatScoreFieldName || name === '_id') {
-      return 'number';
-    }
-
-    return this.alertsColumns.filter(colMetaData => colMetaData.name === 
name)[0].type;
-  }
-
-  getValue(alert: any, column: ColumnMetadata, formatData: boolean) {
+  getValue(alert: Alert, column: ColumnMetadata, formatData: boolean) {
     let returnValue = '';
     try {
       switch (column.name) {
-        case '_id':
+        case 'id':
           returnValue = alert[column.name];
           break;
         case 'alert_status':
           returnValue = 'NEW';
           break;
         default:
-          returnValue = alert['_source'][column.name];
+          returnValue = alert.source[column.name];
           break;
       }
     } catch (e) {}
@@ -184,6 +176,10 @@ export class AlertsListComponent implements OnInit {
     return returnValue;
   }
 
+  ngOnDestroy() {
+    this.tryStopPolling();
+  }
+
   ngOnInit() {
     this.getAlertColumnNames(true);
     this.addAlertColChangedListner();
@@ -233,8 +229,8 @@ export class AlertsListComponent implements OnInit {
 
   onSort(sortEvent: SortEvent) {
     let sortOrder = (sortEvent.sortOrder === Sort.ASC ? 'asc' : 'desc');
-    let sortBy = sortEvent.sortBy === '_id' ? '_uid' : sortEvent.sortBy;
-    this.queryBuilder.setSort(sortBy, sortOrder, 
this.getDataType(sortEvent.sortBy));
+    let sortBy = sortEvent.sortBy === 'id' ? '_uid' : sortEvent.sortBy;
+    this.queryBuilder.setSort(sortBy, sortOrder);
     this.search();
   }
 
@@ -345,12 +341,12 @@ export class AlertsListComponent implements OnInit {
     this.router.navigateByUrl('/alerts-list(dialog:configure-table)');
   }
 
-  showDetails($event, alert: any) {
+  showDetails($event, alert: Alert) {
     if ($event.target.type !== 'checkbox' && 
$event.target.parentElement.firstChild.type !== 'checkbox' && 
$event.target.nodeName !== 'A') {
       this.selectedAlerts = [];
       this.selectedAlerts = [alert];
       this.saveRefreshState();
-      this.router.navigateByUrl('/alerts-list(dialog:details/' + alert._index 
+ '/' + alert._type + '/' + alert._id + ')');
+      this.router.navigateByUrl('/alerts-list(dialog:details/' + 
alert.source['source:type'] + '/' + alert.source.guid + ')');
     }
   }
 

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts
 
b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts
index 1a39e51..adc8cbb 100644
--- 
a/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts
+++ 
b/metron-interface/metron-alerts/src/app/alerts/alerts-list/alerts-list.module.ts
@@ -30,7 +30,7 @@ import {ConfigureRowsModule} from 
'../configure-rows/configure-rows.module';
 @NgModule({
     imports: [routing, SharedModule, ConfigureRowsModule, MetronSorterModule, 
MetronTablePaginationModule,
                 ListGroupModule, CollapseModule],
-    exports: [],
+    exports: [AlertsListComponent],
     declarations: [AlertsListComponent],
     providers: [AlertService],
 })

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/alerts/alerts-list/query-builder.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/alerts/alerts-list/query-builder.ts 
b/metron-interface/metron-alerts/src/app/alerts/alerts-list/query-builder.ts
index b651d26..9816f46 100644
--- a/metron-interface/metron-alerts/src/app/alerts/alerts-list/query-builder.ts
+++ b/metron-interface/metron-alerts/src/app/alerts/alerts-list/query-builder.ts
@@ -18,6 +18,7 @@
 import {Filter} from '../../model/filter';
 import {ColumnNamesService} from '../../service/column-names.service';
 import {SearchRequest} from '../../model/search-request';
+import {SortField} from '../../model/sort-field';
 
 export class QueryBuilder {
   private _searchRequest = new SearchRequest();
@@ -102,7 +103,7 @@ export class QueryBuilder {
   }
 
   setFields(fieldNames: string[]) {
-      this.searchRequest._source = fieldNames;
+      // this.searchRequest._source = fieldNames;
   }
 
   setFromAndSize(from: number, size: number) {
@@ -110,15 +111,12 @@ export class QueryBuilder {
     this.searchRequest.size = size;
   }
 
-  setSort(sortBy: string, order: string, dataType: string) {
-    let sortQuery = {};
-    sortQuery[sortBy] = {
-      order: order,
-      ignore_unmapped: true,
-      unmapped_type: dataType,
-      missing: '_last'
-    };
-    this.searchRequest.sort = [sortQuery];
+  setSort(sortBy: string, order: string) {
+    let sortField = new SortField();
+    sortField.field = sortBy;
+    sortField.sortOrder = order;
+
+    this.searchRequest.sort = [sortField];
   }
 
   private updateFilters(tQuery: string, updateNameTransform = false) {

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/app-routing.module.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/app-routing.module.ts 
b/metron-interface/metron-alerts/src/app/app-routing.module.ts
index d214650..8357d66 100644
--- a/metron-interface/metron-alerts/src/app/app-routing.module.ts
+++ b/metron-interface/metron-alerts/src/app/app-routing.module.ts
@@ -17,12 +17,16 @@
  */
 import { NgModule } from '@angular/core';
 import { Routes, RouterModule } from '@angular/router';
+import {AuthGuard} from './shared/auth-guard';
+import {LoginGuard} from './shared/login-guard';
 
 const routes: Routes = [
-  { path: '',  redirectTo: 'alerts-list', pathMatch: 'full'},
-  { path: 'alerts-list', loadChildren: 
'app/alerts/alerts-list/alerts-list.module#AlertsListModule'},
-  { path: 'save-search', loadChildren: 
'app/alerts/save-search/save-search.module#SaveSearchModule'},
-  { path: 'saved-searches', loadChildren: 
'app/alerts/saved-searches/saved-searches.module.ts#SavedSearchesModule'}
+  { path: '',  redirectTo: 'login', pathMatch: 'full'},
+  { path: 'login', loadChildren: 'app/login/login.module#LoginModule', 
canActivate: [LoginGuard]},
+  { path: 'alerts-list', loadChildren: 
'app/alerts/alerts-list/alerts-list.module#AlertsListModule', canActivate: 
[AuthGuard]},
+  { path: 'save-search', loadChildren: 
'app/alerts/save-search/save-search.module#SaveSearchModule', canActivate: 
[AuthGuard]},
+  { path: 'saved-searches', loadChildren: 
'app/alerts/saved-searches/saved-searches.module.ts#SavedSearchesModule',
+      canActivate: [AuthGuard]}
 ];
 
 @NgModule({

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/app.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/app.component.html 
b/metron-interface/metron-alerts/src/app/app.component.html
index 103642a..8867a9b 100644
--- a/metron-interface/metron-alerts/src/app/app.component.html
+++ b/metron-interface/metron-alerts/src/app/app.component.html
@@ -12,10 +12,11 @@
   the specific language governing permissions and limitations under the 
License.
   -->
 <div class="container-fluid px-0">
-    <nav class="navbar">
-        <a class="navbar-brand" href="#">
+    <nav class="navbar" *ngIf="loggedIn">
+        <a class="" href="#">
             <img alt="" src="../assets/images/logo.png" width="135" 
height="45">
         </a>
+        <div class="logout ml-auto">Logged in as {{authService.currentUser}} - 
<span class="logout-link" (click)="authService.logout()">Logout</span></div>
     </nav>
     <div class="container-fluid">
         <router-outlet></router-outlet>

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/app.component.scss
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/app.component.scss 
b/metron-interface/metron-alerts/src/app/app.component.scss
index ce52c56..8358e7f 100644
--- a/metron-interface/metron-alerts/src/app/app.component.scss
+++ b/metron-interface/metron-alerts/src/app/app.component.scss
@@ -19,7 +19,19 @@
 
 .navbar
 {
+  flex-direction: row;
   background: $nav-bar-bg;
   padding: 0rem 1rem;
+  height: 50px;
+  line-height: 50px;
   max-height: 50px;
 }
+
+.logout {
+  padding-left: 10px;
+}
+
+.logout-link{
+  color: $all-ports;
+  cursor: pointer;
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/app.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/app.component.ts 
b/metron-interface/metron-alerts/src/app/app.component.ts
index 73cce38..e5e0bf2 100644
--- a/metron-interface/metron-alerts/src/app/app.component.ts
+++ b/metron-interface/metron-alerts/src/app/app.component.ts
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 import { Component } from '@angular/core';
+import {AuthenticationService} from './service/authentication.service';
 
 @Component({
   selector: 'metron-alerts-root',
@@ -23,4 +24,11 @@ import { Component } from '@angular/core';
   styleUrls: ['./app.component.scss']
 })
 export class AppComponent {
+  loggedIn = false;
+
+  constructor(private authService: AuthenticationService) {
+    this.authService.onLoginEvent.subscribe(result => {
+      this.loggedIn = result;
+    });
+  }
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/app.module.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/app.module.ts 
b/metron-interface/metron-alerts/src/app/app.module.ts
index 26ea5f2..295c748 100644
--- a/metron-interface/metron-alerts/src/app/app.module.ts
+++ b/metron-interface/metron-alerts/src/app/app.module.ts
@@ -35,9 +35,13 @@ import {MetronDialogBox} from './shared/metron-dialog-box';
 import {ConfigureRowsModule} from 
'./alerts/configure-rows/configure-rows.module';
 import {SwitchModule} from './shared/switch/switch.module';
 import {ColumnNamesService} from './service/column-names.service';
-import {ElasticSearchLocalstorageImpl} from 
'./service/elasticsearch-localstorage-impl';
 import {DataSource} from './service/data-source';
-import {environment} from '../environments/environment.prod';
+import {RestApiImpl} from './service/rest-api-impl';
+import {LoginModule} from './login/login.module';
+import {AuthGuard} from './shared/auth-guard';
+import {AuthenticationService} from './service/authentication.service';
+import {LoginGuard} from './shared/login-guard';
+
 
 
 export function initConfig(config: ColumnNamesService) {
@@ -53,6 +57,7 @@ export function initConfig(config: ColumnNamesService) {
     FormsModule,
     HttpModule,
     MetronAlertsRoutingModule,
+    LoginModule,
     AlertsListModule,
     AlertDetailsModule,
     ConfigureTableModule,
@@ -62,7 +67,10 @@ export function initConfig(config: ColumnNamesService) {
     SwitchModule
   ],
   providers: [{ provide: APP_INITIALIZER, useFactory: initConfig, deps: 
[ColumnNamesService], multi: true },
-              { provide: DataSource, useClass: environment.dataSource === 
'elastic' ? ElasticSearchLocalstorageImpl : null},
+              { provide: DataSource, useClass: RestApiImpl },
+              AuthenticationService,
+              AuthGuard,
+              LoginGuard,
               ConfigureTableService,
               SaveSearchService,
               MetronDialogBox,

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/login/login.component.html
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/login/login.component.html 
b/metron-interface/metron-alerts/src/app/login/login.component.html
new file mode 100644
index 0000000..5ae746f
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/login/login.component.html
@@ -0,0 +1,28 @@
+<!--
+  Licensed to the Apache Software
+       Foundation (ASF) under one or more contributor license agreements. See 
the
+       NOTICE file distributed with this work for additional information 
regarding
+       copyright ownership. The ASF licenses this file to You under the Apache 
License,
+       Version 2.0 (the "License"); you may not use this file except in 
compliance
+       with the License. You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software 
distributed
+       under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+       OR CONDITIONS OF ANY KIND, either express or implied. See the License 
for
+  the specific language governing permissions and limitations under the 
License.
+  -->
+<div class="fill login-pane" style="">
+  <form (ngSubmit)="login()" class="login-card">
+    <img class="logo-img-card" src="assets/images/logo.png"/>
+    <label class="label"> USERNAME </label>
+    <input class="form-control" name="user" [(ngModel)]="user" required 
autofocus>
+    <label class="label"> PASSWORD </label>
+    <input type="password" name="password" class="form-control" 
[(ngModel)]="password" required>
+    <div class="my-4" style="color:#a94442">
+      {{loginFailure}}
+      <button class="btn btn-primary pull-right" type="submit" 
(click)="login()">LOG IN</button>
+    </div>
+  </form>
+</div>

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/login/login.component.scss
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/login/login.component.scss 
b/metron-interface/metron-alerts/src/app/login/login.component.scss
new file mode 100644
index 0000000..b8d5416
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/login/login.component.scss
@@ -0,0 +1,55 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@import "../../_variables.scss";
+
+.login-pane {
+  position: fixed;
+  background: url(../../assets/images/login.jpg);
+  width: 100%;
+  height: 100%;
+  top: 0;
+  left: 0;
+}
+
+.label
+{
+  font-size: 0.8em;
+  color: $login-label;
+}
+
+.login-card
+{
+  top: 25%;
+  height: 380px;
+  width: 480px;
+  opacity: 0.8;
+  margin: 0 auto;
+  border: none;
+  padding: 20px 25px 30px;
+  background-color: $black;
+  display: block;
+  position: relative;
+}
+
+.logo-img-card
+{
+  margin: 0 auto 10px;
+  display: block;
+  width: 390px;
+  height: 120px;
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/login/login.component.spec.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/login/login.component.spec.ts 
b/metron-interface/metron-alerts/src/app/login/login.component.spec.ts
new file mode 100644
index 0000000..0cf3554
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/login/login.component.spec.ts
@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {async, inject, TestBed} from '@angular/core/testing';
+import {AuthenticationService} from '../service/authentication.service';
+import {LoginComponent} from './login.component';
+
+class MockAuthenticationService {
+
+  public login(username: string, password: string, onError): void {
+    if (username === 'success') {
+      onError({status: 200});
+    }
+
+    if (username === 'failure') {
+      onError({status: 401});
+    }
+  }
+}
+
+describe('LoginComponent', () => {
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      providers: [
+        LoginComponent,
+        {provide: AuthenticationService, useClass: MockAuthenticationService}
+      ]
+    })
+      .compileComponents();
+
+  }));
+
+  it('can instantiate login component', inject([LoginComponent], 
(loginComponent: LoginComponent) => {
+      expect(loginComponent instanceof LoginComponent).toBe(true);
+  }));
+
+  it('can instantiate login component', inject([LoginComponent], 
(loginComponent: LoginComponent) => {
+    loginComponent.user = 'success';
+    loginComponent.password = 'success';
+    loginComponent.login();
+    expect(loginComponent.loginFailure).toEqual('');
+
+    loginComponent.user = 'failure';
+    loginComponent.password = 'failure';
+    loginComponent.login();
+    expect(loginComponent.loginFailure).toEqual('Login failed for failure');
+
+  }));
+
+});

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/login/login.component.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/login/login.component.ts 
b/metron-interface/metron-alerts/src/app/login/login.component.ts
new file mode 100644
index 0000000..877e05b
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/login/login.component.ts
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Component } from '@angular/core';
+import { AuthenticationService } from '../service/authentication.service';
+
+@Component({
+  selector: 'metron-alerts-login',
+  templateUrl: 'login.component.html',
+  styleUrls: ['login.component.scss'],
+})
+export class LoginComponent {
+
+  user: string;
+  password: string;
+  loginFailure = '';
+
+  constructor(private authenticationService: AuthenticationService) {
+  }
+
+  login(): void {
+    this.authenticationService.login(this.user, this.password, error => {
+      if (error.status === 401) {
+        this.loginFailure = 'Login failed for ' + this.user;
+      }
+    });
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/login/login.module.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/login/login.module.ts 
b/metron-interface/metron-alerts/src/app/login/login.module.ts
new file mode 100644
index 0000000..8e14df3
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/login/login.module.ts
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { NgModule } from '@angular/core';
+import {routing} from './login.routing';
+import {LoginComponent} from './login.component';
+import {SharedModule} from '../shared/shared.module';
+
+@NgModule ({
+  imports: [ SharedModule, routing ],
+  declarations: [LoginComponent],
+  exports: [LoginComponent]
+})
+export class LoginModule { }

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/login/login.routing.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/login/login.routing.ts 
b/metron-interface/metron-alerts/src/app/login/login.routing.ts
new file mode 100644
index 0000000..c810fd9
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/login/login.routing.ts
@@ -0,0 +1,25 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { ModuleWithProviders }  from '@angular/core';
+import { RouterModule } from '@angular/router';
+import {LoginComponent} from './login.component';
+
+
+export const routing: ModuleWithProviders = RouterModule.forChild([
+  { path: '', component: LoginComponent}
+]);

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/model/alert-source.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/model/alert-source.ts 
b/metron-interface/metron-alerts/src/app/model/alert-source.ts
new file mode 100644
index 0000000..cbf83d3
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/model/alert-source.ts
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export class AlertSource {
+  msg: string;
+  sig_rev: number;
+  ip_dst_port: number;
+  ethsrc: string;
+  tcpseq: number;
+  dgmlen: number;
+  tcpwindow: number;
+  tcpack: number;
+  protocol: string;
+  'source:type': string;
+  ip_dst_addr: number;
+  original_string: string;
+  tos: number;
+  id: number;
+  ip_src_addr: string;
+  timestamp: number;
+  ethdst: string;
+  is_alert: boolean;
+  ttl: number;
+  ethlen: number;
+  iplen: number;
+  ip_src_port: number;
+  tcpflags: string;
+  guid: string;
+  sig_id: number;
+  sig_generator: number;
+  'threat:triage:score': number;
+  'threatinteljoinbolt:joiner:ts': number;
+  'enrichmentsplitterbolt:splitter:begin:ts': number;
+  'enrichmentjoinbolt:joiner:ts': number;
+  'threatintelsplitterbolt:splitter:end:ts': number;
+  'enrichmentsplitterbolt:splitter:end:ts': number;
+  'threatintelsplitterbolt:splitter:begin:ts': number;
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/model/alert.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/model/alert.ts 
b/metron-interface/metron-alerts/src/app/model/alert.ts
index de8113d..59843a0 100644
--- a/metron-interface/metron-alerts/src/app/model/alert.ts
+++ b/metron-interface/metron-alerts/src/app/model/alert.ts
@@ -1,3 +1,4 @@
+import {AlertSource} from './alert-source';
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,46 +17,8 @@
  * limitations under the License.
  */
 export class Alert {
-  _index: string;
-  _type: string;
-  _id: string;
-  _score: number;
-  _timestamp: number;
-  _source: {
-    msg: string;
-    sig_rev: number;
-    ip_dst_port: number;
-    ethsrc: string;
-    tcpseq: number;
-    dgmlen: number;
-    tcpwindow: number;
-    tcpack: number;
-    protocol: string;
-    'source:type': string;
-    ip_dst_addr: number;
-    original_string: string;
-    tos: number;
-    id: number;
-    ip_src_addr: string;
-    timestamp: number;
-    ethdst: string;
-    is_alert: boolean;
-    ttl: number;
-    ethlen: number;
-    iplen: number;
-    ip_src_port: number;
-    tcpflags: string;
-    guid: string;
-    sig_id: number;
-    sig_generator: number;
-    'threat:triage:score': number;
-    'threatinteljoinbolt:joiner:ts': number;
-    'enrichmentsplitterbolt:splitter:begin:ts': number;
-    'enrichmentjoinbolt:joiner:ts': number;
-    'threatintelsplitterbolt:splitter:end:ts': number;
-    'enrichmentsplitterbolt:splitter:end:ts': number;
-    'threatintelsplitterbolt:splitter:begin:ts': number;
-  };
-
+  id: string;
+  score: number;
+  source: AlertSource;
   status: string;
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/model/search-request.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/model/search-request.ts 
b/metron-interface/metron-alerts/src/app/model/search-request.ts
index 3c7443e..2150f2b 100644
--- a/metron-interface/metron-alerts/src/app/model/search-request.ts
+++ b/metron-interface/metron-alerts/src/app/model/search-request.ts
@@ -1,3 +1,4 @@
+import {SortField} from './sort-field';
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,9 +17,10 @@
  * limitations under the License.
  */
 export class SearchRequest {
-  _source: string[];
-  query = '*';
-  from = 0;
-  size = 15;
-  sort: {}[] = [{ timestamp: {order : 'desc', ignore_unmapped: true, 
unmapped_type: 'date'} }];
+  // _source: string[]; //TODO: This needs to be removed
+  from: number;
+  indices: string[] = ['websphere', 'snort', 'asa', 'bro', 'yaf'];
+  query: string;
+  size: number;
+  sort: SortField[];
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/model/sort-field.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/model/sort-field.ts 
b/metron-interface/metron-alerts/src/app/model/sort-field.ts
new file mode 100644
index 0000000..601b370
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/model/sort-field.ts
@@ -0,0 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export class SortField {
+  field: string;
+  sortOrder: string;
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/service/alert.service.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/service/alert.service.ts 
b/metron-interface/metron-alerts/src/app/service/alert.service.ts
index 6412dde..7dabc4f 100644
--- a/metron-interface/metron-alerts/src/app/service/alert.service.ts
+++ b/metron-interface/metron-alerts/src/app/service/alert.service.ts
@@ -26,6 +26,7 @@ import {Http} from '@angular/http';
 import {DataSource} from './data-source';
 import {AlertsSearchResponse} from '../model/alerts-search-response';
 import {SearchRequest} from '../model/search-request';
+import {AlertSource} from '../model/alert-source';
 
 @Injectable()
 export class AlertService {
@@ -43,20 +44,22 @@ export class AlertService {
 
   public pollSearch(searchRequest: SearchRequest): 
Observable<AlertsSearchResponse> {
     return this.ngZone.runOutsideAngular(() => {
-      return Observable.interval(this.interval * 1000).switchMap(() => {
-        return this.dataSource.getAlerts(searchRequest);
+      return this.ngZone.run(() => {
+        return Observable.interval(this.interval * 1000).switchMap(() => {
+          return this.dataSource.getAlerts(searchRequest);
+        });
       });
     });
   }
 
-  public getAlert(index: string, type: string, alertId: string): 
Observable<Alert> {
-    return this.dataSource.getAlert(index, type, alertId);
+  public getAlert(sourceType: string, alertId: string): 
Observable<AlertSource> {
+    return this.dataSource.getAlert(sourceType, alertId);
   }
 
   public updateAlertState(alerts: Alert[], state: string, workflowId: string) {
     let request = '';
     for (let alert of alerts) {
-      request += '{ "update" : { "_index" : "' + alert._index + '", "_type" : 
"' + alert._type + '", "_id" : "' + alert._id + '" } }\n' +
+      request += '{ "update" : { "sensorType" : "' + 
alert.source['source:type'] + '", "guid" : "' + alert.source.guid + '" } }\n' +
                   '{ "doc": { "alert_status": "' + state + '"';
       if (workflowId) {
         request += ', "workflow_id": "' + workflowId + '"';

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/service/authentication.service.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/service/authentication.service.ts 
b/metron-interface/metron-alerts/src/app/service/authentication.service.ts
new file mode 100644
index 0000000..f4924a5
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/service/authentication.service.ts
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {Injectable, EventEmitter}     from '@angular/core';
+import {Http, Headers, RequestOptions, Response} from '@angular/http';
+import {Router} from '@angular/router';
+import {Observable}     from 'rxjs/Observable';
+
+@Injectable()
+export class AuthenticationService {
+
+  private static USER_NOT_VERIFIED = 'USER-NOT-VERIFIED';
+  private currentUser: string = AuthenticationService.USER_NOT_VERIFIED;
+  loginUrl = '/api/v1/user';
+  logoutUrl = '/logout';
+  defaultHeaders = {'Content-Type': 'application/json', 'X-Requested-With': 
'XMLHttpRequest'};
+  onLoginEvent: EventEmitter<boolean> = new EventEmitter<boolean>();
+
+  constructor(private http: Http, private router: Router) {
+    this.init();
+  }
+
+  public init() {
+      this.getCurrentUser(new RequestOptions({headers: new 
Headers(this.defaultHeaders)})).subscribe((response: Response) => {
+        this.currentUser = response.text();
+        if (this.currentUser) {
+          this.onLoginEvent.emit(true);
+        }
+      }, error => {
+        this.onLoginEvent.emit(false);
+      });
+  }
+
+  public login(username: string, password: string, onError): void {
+    let loginHeaders: Headers = new Headers(this.defaultHeaders);
+    loginHeaders.append('authorization', 'Basic ' + btoa(username + ':' + 
password));
+    let loginOptions: RequestOptions = new RequestOptions({headers: 
loginHeaders});
+    this.getCurrentUser(loginOptions).subscribe((response: Response) => {
+        this.currentUser = response.text();
+        this.router.navigateByUrl('/alerts-list');
+        this.onLoginEvent.emit(true);
+      },
+      error => {
+        onError(error);
+      });
+  }
+
+  public logout(): void {
+    this.http.post(this.logoutUrl, {}, new RequestOptions({headers: new 
Headers(this.defaultHeaders)})).subscribe(response => {
+        this.currentUser = AuthenticationService.USER_NOT_VERIFIED;
+        this.onLoginEvent.emit(false);
+        this.router.navigateByUrl('/login');
+      },
+      error => {
+        console.log('Logout failed:', error);
+        this.router.navigateByUrl('/login');
+      });
+  }
+
+  public checkAuthentication() {
+    if (!this.isAuthenticated()) {
+      this.router.navigateByUrl('/login');
+    }
+  }
+
+  public getCurrentUser(options: RequestOptions): Observable<Response> {
+    return this.http.get(this.loginUrl, options);
+  }
+
+  public isAuthenticationChecked(): boolean {
+    return this.currentUser !== AuthenticationService.USER_NOT_VERIFIED;
+  }
+
+  public isAuthenticated(): boolean {
+    return this.currentUser !== AuthenticationService.USER_NOT_VERIFIED && 
this.currentUser != null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/service/data-source.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/service/data-source.ts 
b/metron-interface/metron-alerts/src/app/service/data-source.ts
index 242fa3a..28ee384 100644
--- a/metron-interface/metron-alerts/src/app/service/data-source.ts
+++ b/metron-interface/metron-alerts/src/app/service/data-source.ts
@@ -18,14 +18,13 @@
 import {Observable} from 'rxjs/Rx';
 import {Injectable} from '@angular/core';
 import {Http} from '@angular/http';
-
-import {Alert} from '../model/alert';
 import {ColumnMetadata} from '../model/column-metadata';
 import {ColumnNames} from '../model/column-names';
 import {TableMetadata} from '../model/table-metadata';
 import {SaveSearch} from '../model/save-search';
 import {AlertsSearchResponse} from '../model/alerts-search-response';
 import {SearchRequest} from '../model/search-request';
+import {AlertSource} from '../model/alert-source';
 
 @Injectable()
 export abstract class DataSource {
@@ -35,7 +34,7 @@ export abstract class DataSource {
 
   // Calls to fetch alerts
   abstract getAlerts(searchRequest: SearchRequest): 
Observable<AlertsSearchResponse>
-  abstract getAlert(index: string, type: string, alertId: string): 
Observable<Alert>
+  abstract getAlert(sourceType: string, alertId: string): 
Observable<AlertSource>
   abstract updateAlertState(request: any): Observable<{}>
 
   // Calls to fetch default alert table column names and all the field names 
across all indexes

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/service/elasticsearch-localstorage-impl.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/service/elasticsearch-localstorage-impl.ts
 
b/metron-interface/metron-alerts/src/app/service/elasticsearch-localstorage-impl.ts
index 0cd2bce..f4e43d5 100644
--- 
a/metron-interface/metron-alerts/src/app/service/elasticsearch-localstorage-impl.ts
+++ 
b/metron-interface/metron-alerts/src/app/service/elasticsearch-localstorage-impl.ts
@@ -20,7 +20,6 @@ import {Headers, RequestOptions} from '@angular/http';
 
 import {HttpUtil} from '../utils/httpUtil';
 import {DataSource} from './data-source';
-import {Alert} from '../model/alert';
 import {ColumnMetadata} from '../model/column-metadata';
 import {ElasticsearchUtils} from '../utils/elasticsearch-utils';
 import {
@@ -33,11 +32,12 @@ import {TableMetadata} from '../model/table-metadata';
 import {SaveSearch} from '../model/save-search';
 import {AlertsSearchResponse} from '../model/alerts-search-response';
 import {SearchRequest} from '../model/search-request';
+import {AlertSource} from '../model/alert-source';
 
 export class ElasticSearchLocalstorageImpl extends DataSource {
 
   private defaultColumnMetadata = [
-    new ColumnMetadata('_id', 'string'),
+    new ColumnMetadata('id', 'string'),
     new ColumnMetadata('timestamp', 'date'),
     new ColumnMetadata('source:type', 'string'),
     new ColumnMetadata('ip_src_addr', 'ip'),
@@ -59,12 +59,11 @@ export class ElasticSearchLocalstorageImpl extends 
DataSource {
       .onErrorResumeNext();
   }
 
-  getAlert(index: string, type: string, alertId: string): Observable<Alert> {
-    return this.http.get('/search/' + index + '/' + type + '/' + alertId, new 
RequestOptions({headers: new Headers(this.defaultHeaders)}))
-      .map(HttpUtil.extractData);
+  getAlert(sourceType: string, alertId: string): Observable<AlertSource> {
+    return Observable.throw('Method not implemented in 
ElasticSearchLocalstorageImpl');
   }
 
-  updateAlertState(request: any) {
+  updateAlertState(request: any): Observable<{}> {
     return this.http.post('/search/_bulk', request, new 
RequestOptions({headers: new Headers(this.defaultHeaders)}))
       .map(HttpUtil.extractData)
       .catch(HttpUtil.handleError);

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/service/rest-api-impl.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/service/rest-api-impl.ts 
b/metron-interface/metron-alerts/src/app/service/rest-api-impl.ts
new file mode 100644
index 0000000..061708d
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/service/rest-api-impl.ts
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {Observable} from 'rxjs/Rx';
+import {Headers, RequestOptions} from '@angular/http';
+
+import {HttpUtil} from '../utils/httpUtil';
+import {AlertsSearchResponse} from '../model/alerts-search-response';
+import {SearchRequest} from '../model/search-request';
+import {ElasticSearchLocalstorageImpl} from 
'./elasticsearch-localstorage-impl';
+import {AlertSource} from '../model/alert-source';
+
+export class RestApiImpl extends ElasticSearchLocalstorageImpl {
+
+  getAlerts(searchRequest: SearchRequest): Observable<AlertsSearchResponse> {
+    let url = '/api/v1/search/search';
+    return this.http.post(url, searchRequest, new RequestOptions({headers: new 
Headers(this.defaultHeaders)}))
+      .map(HttpUtil.extractData)
+      .catch(HttpUtil.handleError)
+      .onErrorResumeNext();
+  }
+
+  getAlert(sourceType: string, alertId: string): Observable<AlertSource> {
+    let url = '/api/v1/search/findOne';
+    let requestSchema = { guid: alertId, sensorType: sourceType};
+
+    return this.http.post(url, requestSchema, new RequestOptions({headers: new 
Headers(this.defaultHeaders)}))
+    .map(HttpUtil.extractData)
+    .catch(HttpUtil.handleError)
+    .onErrorResumeNext();
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/shared/auth-guard.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/auth-guard.ts 
b/metron-interface/metron-alerts/src/app/shared/auth-guard.ts
new file mode 100644
index 0000000..66c27cf
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/auth-guard.ts
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Injectable } from '@angular/core';
+import {
+  CanActivate,
+  Router,
+  ActivatedRouteSnapshot,
+  RouterStateSnapshot
+} from '@angular/router';
+import { Observable } from 'rxjs/Observable';
+import { AuthenticationService } from '../service/authentication.service';
+
+@Injectable()
+export class AuthGuard implements CanActivate {
+
+  constructor(private authService: AuthenticationService, private router: 
Router) {}
+
+  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
+    if (!this.authService.isAuthenticationChecked()) {
+      return Observable.create(observer => {
+        this.authService.onLoginEvent.subscribe(isLoggedIn => {
+          if (isLoggedIn) {
+            observer.next(true);
+            observer.complete();
+          } else {
+            observer.next(false);
+            observer.complete();
+            this.router.navigateByUrl('/login');
+          }
+        });
+      });
+    }
+    return this.authService.isAuthenticated();
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/shared/login-guard.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/shared/login-guard.ts 
b/metron-interface/metron-alerts/src/app/shared/login-guard.ts
new file mode 100644
index 0000000..d8b8f0d
--- /dev/null
+++ b/metron-interface/metron-alerts/src/app/shared/login-guard.ts
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Injectable } from '@angular/core';
+import {
+  CanActivate,
+  Router,
+  ActivatedRouteSnapshot,
+  RouterStateSnapshot
+} from '@angular/router';
+import { AuthenticationService } from '../service/authentication.service';
+
+// This guard will ensure that logout is called even if you call /login 
manually
+@Injectable()
+export class LoginGuard implements CanActivate {
+
+  constructor(private authService: AuthenticationService, private router: 
Router) {}
+
+  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
+
+    this.authService.logout();
+
+    return true;
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/utils/elasticsearch-utils.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/app/utils/elasticsearch-utils.ts 
b/metron-interface/metron-alerts/src/app/utils/elasticsearch-utils.ts
index 62b7464..a86907b 100644
--- a/metron-interface/metron-alerts/src/app/utils/elasticsearch-utils.ts
+++ b/metron-interface/metron-alerts/src/app/utils/elasticsearch-utils.ts
@@ -50,7 +50,7 @@ export class ElasticsearchUtils {
       }
     }
 
-    columnMetadata.push(new ColumnMetadata('_id', 'string'));
+    columnMetadata.push(new ColumnMetadata('id', 'string'));
     return columnMetadata;
   }
 

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/app/utils/httpUtil.ts
----------------------------------------------------------------------
diff --git a/metron-interface/metron-alerts/src/app/utils/httpUtil.ts 
b/metron-interface/metron-alerts/src/app/utils/httpUtil.ts
index a93e66e..89d309f 100644
--- a/metron-interface/metron-alerts/src/app/utils/httpUtil.ts
+++ b/metron-interface/metron-alerts/src/app/utils/httpUtil.ts
@@ -18,6 +18,7 @@
 import {Response} from '@angular/http';
 import {Observable}     from 'rxjs/Observable';
 import {RestError} from '../model/rest-error';
+
 export class HttpUtil {
 
   public static extractString(res: Response): string {
@@ -34,7 +35,10 @@ export class HttpUtil {
     // In a real world app, we might use a remote logging infrastructure
     // We'd also dig deeper into the error to get a better message
     let restError: RestError;
-    if (res.status !== 404) {
+    if (res.status === 401) {
+      restError = res.json();
+      window.location.pathname = '/login';
+    } else if (res.status !== 404) {
       restError = res.json();
     } else {
       restError = new RestError();

http://git-wip-us.apache.org/repos/asf/metron/blob/9bc9e0c5/metron-interface/metron-alerts/src/environments/environment.prod.ts
----------------------------------------------------------------------
diff --git 
a/metron-interface/metron-alerts/src/environments/environment.prod.ts 
b/metron-interface/metron-alerts/src/environments/environment.prod.ts
index 53fca2d..1b628e3 100644
--- a/metron-interface/metron-alerts/src/environments/environment.prod.ts
+++ b/metron-interface/metron-alerts/src/environments/environment.prod.ts
@@ -16,6 +16,5 @@
  * limitations under the License.
  */
 export const environment = {
-  production: true,
-  dataSource: 'elastic'
+  production: true
 };

Reply via email to