Repository: metron Updated Branches: refs/heads/master 7b6a3da6d -> 2fbb98e7d
METRON-1204 UI does not time out after being idle, but stops functioning (merrimanr) closes apache/metron#771 Project: http://git-wip-us.apache.org/repos/asf/metron/repo Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/2fbb98e7 Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/2fbb98e7 Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/2fbb98e7 Branch: refs/heads/master Commit: 2fbb98e7da670b0f9170648cf0b8bfe259e7e65f Parents: 7b6a3da Author: merrimanr <[email protected]> Authored: Mon Oct 2 14:38:02 2017 -0500 Committer: merrimanr <[email protected]> Committed: Mon Oct 2 14:38:02 2017 -0500 ---------------------------------------------------------------------- .../src/app/login/login.component.ts | 10 ++- .../metron-alerts/src/app/utils/httpUtil.ts | 3 +- .../src/app/login/login.component.spec.ts | 66 +++++++++++++++----- .../src/app/login/login.component.ts | 8 ++- .../metron-config/src/app/login/login.module.ts | 7 ++- .../src/app/login/login.routing.ts | 3 +- .../sensor-parser-config-readonly.component.ts | 2 +- .../metron-config/src/app/util/httpUtil.ts | 5 +- 8 files changed, 77 insertions(+), 27 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metron/blob/2fbb98e7/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 index 877e05b..1d6c24f 100644 --- a/metron-interface/metron-alerts/src/app/login/login.component.ts +++ b/metron-interface/metron-alerts/src/app/login/login.component.ts @@ -17,6 +17,7 @@ */ import { Component } from '@angular/core'; import { AuthenticationService } from '../service/authentication.service'; +import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'metron-alerts-login', @@ -27,9 +28,14 @@ export class LoginComponent { user: string; password: string; - loginFailure = ''; + loginFailure: string = ''; - constructor(private authenticationService: AuthenticationService) { + constructor(private authenticationService: AuthenticationService, private activatedRoute: ActivatedRoute) { + this.activatedRoute.queryParams.subscribe(params => { + if (params['sessionExpired'] === 'true') { + this.loginFailure = 'Session has expired'; + } + }); } login(): void { http://git-wip-us.apache.org/repos/asf/metron/blob/2fbb98e7/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 89d309f..dfcb61f 100644 --- a/metron-interface/metron-alerts/src/app/utils/httpUtil.ts +++ b/metron-interface/metron-alerts/src/app/utils/httpUtil.ts @@ -36,8 +36,7 @@ export class HttpUtil { // We'd also dig deeper into the error to get a better message let restError: RestError; if (res.status === 401) { - restError = res.json(); - window.location.pathname = '/login'; + window.location.assign('/login?sessionExpired=true'); } else if (res.status !== 404) { restError = res.json(); } else { http://git-wip-us.apache.org/repos/asf/metron/blob/2fbb98e7/metron-interface/metron-config/src/app/login/login.component.spec.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-config/src/app/login/login.component.spec.ts b/metron-interface/metron-config/src/app/login/login.component.spec.ts index 0cf3554..5ad285a 100644 --- a/metron-interface/metron-config/src/app/login/login.component.spec.ts +++ b/metron-interface/metron-config/src/app/login/login.component.spec.ts @@ -15,9 +15,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {async, inject, TestBed} from '@angular/core/testing'; +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {AuthenticationService} from '../service/authentication.service'; import {LoginComponent} from './login.component'; +import {Observable} from 'rxjs/Observable'; +import {ActivatedRoute, Params} from '@angular/router'; +import {LoginModule} from './login.module'; +import {APP_CONFIG, METRON_REST_CONFIG} from '../app.config'; class MockAuthenticationService { @@ -32,34 +36,64 @@ class MockAuthenticationService { } } +class MockActivatedRoute { + queryParams: Observable<Params> = Observable.create(observer => { + observer.complete(); + }); + + setSessionExpired() { + this.queryParams = Observable.create(observer => { + observer.next({'sessionExpired': 'true'}); + observer.complete(); + }); + } +} + describe('LoginComponent', () => { + let component: LoginComponent; + let fixture: ComponentFixture<LoginComponent>; + let activatedRoute: MockActivatedRoute; + beforeEach(async(() => { TestBed.configureTestingModule({ + imports: [LoginModule], providers: [ - LoginComponent, - {provide: AuthenticationService, useClass: MockAuthenticationService} + {provide: ActivatedRoute, useClass: MockActivatedRoute}, + {provide: AuthenticationService, useClass: MockAuthenticationService}, + {provide: APP_CONFIG, useValue: METRON_REST_CONFIG} ] - }) - .compileComponents(); + }).compileComponents() + .then(() => { + fixture = TestBed.createComponent(LoginComponent); + component = fixture.componentInstance; + activatedRoute = fixture.debugElement.injector.get(ActivatedRoute); + }); })); - it('can instantiate login component', inject([LoginComponent], (loginComponent: LoginComponent) => { - expect(loginComponent instanceof LoginComponent).toBe(true); + it('should create an instance', async(() => { + expect(component).toBeDefined(); })); - it('can instantiate login component', inject([LoginComponent], (loginComponent: LoginComponent) => { - loginComponent.user = 'success'; - loginComponent.password = 'success'; - loginComponent.login(); - expect(loginComponent.loginFailure).toEqual(''); + it('can instantiate login component', async(() => { + component.user = 'success'; + component.password = 'success'; + component.login(); + expect(component.loginFailure).toEqual(''); + + component.user = 'failure'; + component.password = 'failure'; + component.login(); + expect(component.loginFailure).toEqual('Login failed for failure'); + + })); - loginComponent.user = 'failure'; - loginComponent.password = 'failure'; - loginComponent.login(); - expect(loginComponent.loginFailure).toEqual('Login failed for failure'); + it('can handle sessionExpired', async(() => { + activatedRoute.setSessionExpired(); + let sessionExpiredComponent = TestBed.createComponent(LoginComponent).componentInstance; + expect(sessionExpiredComponent.loginFailure).toEqual('Session has expired'); })); }); http://git-wip-us.apache.org/repos/asf/metron/blob/2fbb98e7/metron-interface/metron-config/src/app/login/login.component.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-config/src/app/login/login.component.ts b/metron-interface/metron-config/src/app/login/login.component.ts index cdd672a..bc3cf1a 100644 --- a/metron-interface/metron-config/src/app/login/login.component.ts +++ b/metron-interface/metron-config/src/app/login/login.component.ts @@ -17,6 +17,7 @@ */ import { Component } from '@angular/core'; import { AuthenticationService } from '../service/authentication.service'; +import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'metron-config-login', @@ -29,7 +30,12 @@ export class LoginComponent { password: string; loginFailure: string = ''; - constructor(private authenticationService: AuthenticationService) { + constructor(private authenticationService: AuthenticationService, private activatedRoute: ActivatedRoute) { + this.activatedRoute.queryParams.subscribe(params => { + if (params['sessionExpired'] === 'true') { + this.loginFailure = 'Session has expired'; + } + }); } login(): void { http://git-wip-us.apache.org/repos/asf/metron/blob/2fbb98e7/metron-interface/metron-config/src/app/login/login.module.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-config/src/app/login/login.module.ts b/metron-interface/metron-config/src/app/login/login.module.ts index 6efd125..bdc5640 100644 --- a/metron-interface/metron-config/src/app/login/login.module.ts +++ b/metron-interface/metron-config/src/app/login/login.module.ts @@ -16,9 +16,12 @@ * limitations under the License. */ import { NgModule } from '@angular/core'; -import {routing} from "./login.routing"; +import {routing} from './login.routing'; +import {LoginComponent} from './login.component'; +import {SharedModule} from '../shared/shared.module'; @NgModule ({ - imports: [ routing ] + imports: [ routing, SharedModule ], + declarations: [ LoginComponent ] }) export class LoginModule { } http://git-wip-us.apache.org/repos/asf/metron/blob/2fbb98e7/metron-interface/metron-config/src/app/login/login.routing.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-config/src/app/login/login.routing.ts b/metron-interface/metron-config/src/app/login/login.routing.ts index 7d2d22e..e0f1be8 100644 --- a/metron-interface/metron-config/src/app/login/login.routing.ts +++ b/metron-interface/metron-config/src/app/login/login.routing.ts @@ -17,8 +17,7 @@ */ import { ModuleWithProviders } from '@angular/core'; import { RouterModule } from '@angular/router'; -import {LoginComponent} from "./login.component"; - +import { LoginComponent } from './login.component'; export const routing: ModuleWithProviders = RouterModule.forChild([ { path: '', component: LoginComponent} http://git-wip-us.apache.org/repos/asf/metron/blob/2fbb98e7/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts index 7edc2c5..b2cfef1 100644 --- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts +++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts @@ -145,7 +145,7 @@ export class SensorParserConfigReadonlyComponent implements OnInit { getTopologyStatus(key: string): string { if (key === 'latency') { - return this.topologyStatus.latency >= 0? (this.topologyStatus.latency + 's') : '-'; + return this.topologyStatus.latency >= 0 ? (this.topologyStatus.latency + 's') : '-'; } else if (key === 'throughput') { return this.topologyStatus.throughput >= 0 ? ((Math.round(this.topologyStatus.throughput * 100) / 100) + 'kb/s') : '-'; } else if (key === 'emitted') { http://git-wip-us.apache.org/repos/asf/metron/blob/2fbb98e7/metron-interface/metron-config/src/app/util/httpUtil.ts ---------------------------------------------------------------------- diff --git a/metron-interface/metron-config/src/app/util/httpUtil.ts b/metron-interface/metron-config/src/app/util/httpUtil.ts index a93e66e..dfcb61f 100644 --- a/metron-interface/metron-config/src/app/util/httpUtil.ts +++ b/metron-interface/metron-config/src/app/util/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,9 @@ 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) { + window.location.assign('/login?sessionExpired=true'); + } else if (res.status !== 404) { restError = res.json(); } else { restError = new RestError();
