mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
79700: specs for modal, auth check for idleness tracking & stop blocking at token success
This commit is contained in:
@@ -263,7 +263,6 @@ export class AuthEffects {
|
||||
filter((action: Action) => !IDLE_TIMER_IGNORE_TYPES.includes(action.type)),
|
||||
// Using switchMap the timer will be interrupted and restarted if a new action comes in, so idleness timer restarts
|
||||
switchMap(() => {
|
||||
this.authService.isAuthenticated();
|
||||
return timer(environment.auth.ui.timeUntilIdle);
|
||||
}),
|
||||
map(() => {
|
||||
|
@@ -193,6 +193,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut
|
||||
return Object.assign({}, state, {
|
||||
authToken: (action as RefreshTokenSuccessAction).payload,
|
||||
refreshing: false,
|
||||
blocking: false
|
||||
});
|
||||
|
||||
case AuthActionTypes.ADD_MESSAGE:
|
||||
|
@@ -2,7 +2,12 @@ import { map, take } from 'rxjs/operators';
|
||||
import { Component, Inject, OnInit, Optional, Input } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { combineLatest as combineLatestObservable, Observable, of } from 'rxjs';
|
||||
import {
|
||||
combineLatest as observableCombineLatest,
|
||||
combineLatest as combineLatestObservable,
|
||||
Observable,
|
||||
of
|
||||
} from 'rxjs';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
||||
@@ -84,18 +89,19 @@ export class RootComponent implements OnInit {
|
||||
map(([collapsed, mobile]) => collapsed || mobile)
|
||||
);
|
||||
|
||||
this.authService.isUserIdle().subscribe((userIdle: boolean) => {
|
||||
if (userIdle) {
|
||||
if (!this.idleModalOpen) {
|
||||
const modalRef = this.modalService.open(IdleModalComponent);
|
||||
this.idleModalOpen = true;
|
||||
modalRef.componentInstance.response.pipe(take(1)).subscribe((closed: boolean) => {
|
||||
if (closed) {
|
||||
this.idleModalOpen = false;
|
||||
}
|
||||
});
|
||||
observableCombineLatest([this.authService.isUserIdle(), this.authService.isAuthenticated()])
|
||||
.subscribe(([userIdle, authenticated]) => {
|
||||
if (userIdle && authenticated) {
|
||||
if (!this.idleModalOpen) {
|
||||
const modalRef = this.modalService.open(IdleModalComponent);
|
||||
this.idleModalOpen = true;
|
||||
modalRef.componentInstance.response.pipe(take(1)).subscribe((closed: boolean) => {
|
||||
if (closed) {
|
||||
this.idleModalOpen = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
128
src/app/shared/idle-modal/idle-modal.component.spec.ts
Normal file
128
src/app/shared/idle-modal/idle-modal.component.spec.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { IdleModalComponent } from './idle-modal.component';
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
describe('IdleModalComponent', () => {
|
||||
let component: IdleModalComponent;
|
||||
let fixture: ComponentFixture<IdleModalComponent>;
|
||||
let debugElement: DebugElement;
|
||||
|
||||
const modalStub = jasmine.createSpyObj('modalStub', ['close']);
|
||||
const authServiceStub = jasmine.createSpyObj('authService', ['setIdle', 'logout']);
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot()],
|
||||
declarations: [IdleModalComponent],
|
||||
providers: [
|
||||
{ provide: NgbActiveModal, useValue: modalStub },
|
||||
{ provide: AuthService, useValue: authServiceStub }
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(IdleModalComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('extendSessionPressed', () => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
spyOn(component.response, 'next');
|
||||
component.extendSessionPressed();
|
||||
}));
|
||||
it('should set idle to false', () => {
|
||||
expect(authServiceStub.setIdle).toHaveBeenCalledWith(false);
|
||||
});
|
||||
it('should close the modal', () => {
|
||||
expect(modalStub.close).toHaveBeenCalled();
|
||||
});
|
||||
it('response \'closed\' should have true as next', () => {
|
||||
expect(component.response.next).toHaveBeenCalledWith(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('logOutPressed', () => {
|
||||
beforeEach(() => {
|
||||
component.logOutPressed();
|
||||
});
|
||||
it('should logout', () => {
|
||||
expect(authServiceStub.logout).toHaveBeenCalled();
|
||||
});
|
||||
it('should close the modal', () => {
|
||||
expect(modalStub.close).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('closePressed', () => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
spyOn(component.response, 'next');
|
||||
component.closePressed();
|
||||
}));
|
||||
it('should set idle to false', () => {
|
||||
expect(authServiceStub.setIdle).toHaveBeenCalledWith(false);
|
||||
});
|
||||
it('should close the modal', () => {
|
||||
expect(modalStub.close).toHaveBeenCalled();
|
||||
});
|
||||
it('response \'closed\' should have true as next', () => {
|
||||
expect(component.response.next).toHaveBeenCalledWith(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the click method emits on extend session button', () => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
spyOn(component, 'extendSessionPressed');
|
||||
debugElement.query(By.css('button.confirm')).triggerEventHandler('click', {
|
||||
preventDefault: () => {/**/
|
||||
}
|
||||
});
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
it('should call the extendSessionPressed method on the component', () => {
|
||||
expect(component.extendSessionPressed).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the click method emits on log out button', () => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
spyOn(component, 'logOutPressed');
|
||||
debugElement.query(By.css('button.cancel')).triggerEventHandler('click', {
|
||||
preventDefault: () => {/**/
|
||||
}
|
||||
});
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
it('should call the logOutPressed method on the component', () => {
|
||||
expect(component.logOutPressed).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the click method emits on close button', () => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
spyOn(component, 'closePressed');
|
||||
debugElement.query(By.css('.close')).triggerEventHandler('click', {
|
||||
preventDefault: () => {/**/
|
||||
}
|
||||
});
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
it('should call the closePressed method on the component', () => {
|
||||
expect(component.closePressed).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
@@ -3697,7 +3697,7 @@
|
||||
|
||||
"idle-modal.header": "Session will expire soon",
|
||||
|
||||
"idle-modal.info": "For security reasons, user sessions expire after {{ timeToExpire }} minutes of inactivity. Your session will expire soon. Would you like to extend it or log out?”",
|
||||
"idle-modal.info": "For security reasons, user sessions expire after {{ timeToExpire }} minutes of inactivity. Your session will expire soon. Would you like to extend it or log out?",
|
||||
|
||||
"idle-modal.log-out": "Log out",
|
||||
|
||||
|
@@ -48,17 +48,16 @@ export const environment: GlobalConfig = {
|
||||
ui: {
|
||||
// the amount of time before the idle warning is shown
|
||||
// timeUntilIdle: 15 * 60 * 1000, // 15 minutes
|
||||
timeUntilIdle: 1 * 60 * 1000, // 1 minutes
|
||||
timeUntilIdle: 30 * 1000, // 30 seconds
|
||||
// the amount of time the user has to react after the idle warning is shown before they are logged out.
|
||||
// idleGracePeriod: 5 * 60 * 1000, // 5 minutes
|
||||
idleGracePeriod: 1 * 60 * 1000, // 1 minutes
|
||||
idleGracePeriod: 1 * 60 * 1000, // 1 minute
|
||||
},
|
||||
// Authority REST settings
|
||||
rest: {
|
||||
// If the rest token expires in less than this amount of time, it will be refreshed automatically.
|
||||
// This is independent from the idle warning.
|
||||
// timeLeftBeforeTokenRefresh: 2 * 60 * 1000, // 2 minutes
|
||||
timeLeftBeforeTokenRefresh: 0.25 * 60 * 1000, // 25 seconds
|
||||
timeLeftBeforeTokenRefresh: 2 * 60 * 1000, // 2 minutes
|
||||
},
|
||||
},
|
||||
// Form settings
|
||||
|
Reference in New Issue
Block a user