import {EventEmitter, Injectable, OnInit} from '@angular/core'; import {AppConfig} from '../app.config'; import {ApiV1LoginResponse} from '../models/api-v1-login-response'; import {PeopleModel} from '../models/people.model'; import {HttpClient} from '@angular/common/http'; import {Router} from '@angular/router'; import {NotificationService} from '@progress/kendo-angular-notification'; import {debounce} from 'ts-debounce'; import {UserExtraModel} from '../models/user-extra.model'; import {WebSocketService} from '../websocket'; @Injectable() export class SessionService { public loggedIn = new ApiV1LoginResponse({}); loginResult = new EventEmitter (); logoutEvent = new EventEmitter (); private machineId = localStorage.getItem('mid') || ''; private socketId = ''; // only lives in memory debouncedLocalStorageMonitor = debounce( this.localStorageChange, 1000); // to avoid to frequent local storage changes constructor(private config: AppConfig, private http: HttpClient, private router: Router, private ns: NotificationService, private ws: WebSocketService){ // const self = this; this.AutoLogin(); window.addEventListener('storage', event => { if (event.storageArea === localStorage && event.key === this.config.storageKey) { // It's local storage self.debouncedLocalStorageMonitor(event).then( r => {}); } }, false); } private AutoLogin(): void { const sfm: ApiV1LoginResponse = JSON.parse(localStorage.getItem(this.config.storageKey)); if (!sfm) { return; } this.login(sfm); } public login( resp: ApiV1LoginResponse): void{ // console.log( 'login in session', this); this.loggedIn = new ApiV1LoginResponse(resp); if ( this.MachineId === '' || (resp.machineId !== '' && this.MachineId !== resp.machineId )) { this.MachineId = resp.machineId; // update machine id } if (this.loggedIn.session !== ''){ this.ws.SessionId = this.loggedIn.session; } if ( resp.UserExtra !== undefined ) { this.loggedIn.UserExtra = new UserExtraModel(resp.UserExtra); } this.loginResult.emit(this.loggedIn); } private localStorageChange(event: StorageEvent): void { console.log('local storage change', event); if ( event.key === this.config.storageKey ){ const newSigin: ApiV1LoginResponse = JSON.parse(localStorage.getItem(this.config.storageKey)); if ( newSigin && newSigin.session && newSigin.User && newSigin.User.Id && this.loggedIn.User.Id) { if ( newSigin.machineId === this.loggedIn.machineId && newSigin.User.Id !== this.loggedIn.User.Id){ this.logoutWithoutPersistingStorage(); // silently logout without touching any storage } } } } public saveSessionInfo(): void { localStorage.setItem(this.config.storageKey, JSON.stringify(this.loggedIn)); } public isAdmin(): boolean { return this.loggedIn.role === 'admin'; } public isBroker(): boolean { return this.loggedIn.role === 'broker'; } public isUser(): boolean { return this.loggedIn.login === true; } public get CurrentUser(): PeopleModel { if (this.isLoggedIn() ) { return this.loggedIn.User; }else{ return new PeopleModel({}); } } public isCurrentUser(id: string): boolean { return id !== '' && this.loggedIn.login === true && this.loggedIn.User !== undefined && this.loggedIn.User.Id === id; } public UpdatePeopleInfo(people: PeopleModel): void{ this.loggedIn.User.Display = people.Display; this.loggedIn.User.First = people.First; this.loggedIn.User.Last = people.Last; this.saveSessionInfo(); } logout(): void { if ( ! this.isLoggedIn() ){ return; } this.http.post(`${this.config.apiUrl}logout`, '').subscribe( resp => { this.ToastMessage(); }, event => { this.ToastMessage('logout from server (with warnings)'); this.reLogin(); }, () => { this.reLogin(); } ); } public isLoggedIn(): boolean{ if ( this.loggedIn.login !== undefined && this.loggedIn.login && this.machineId !== '' && this.loggedIn.session !== '' ) { return true; } return false; } private reLogin(): void { this.loggedIn = new ApiV1LoginResponse({}); localStorage.removeItem(this.config.storageKey); this.router.navigate(['/login']).then( () => { this.logoutEvent.emit(this.loggedIn); }); } logoutWithoutPersistingStorage(): void { if ( !this.isLoggedIn() ){ return; } console.log('logout without storate'); this.loggedIn = new ApiV1LoginResponse({}); this.logoutEvent.emit(this.loggedIn); this.router.navigate(['/login']).then(r => { this.ToastMessage(); } ); } logoutAndClearLocalStorage(): void { if ( !this.isLoggedIn() ){ return; } console.log('logout ++++++++++++++ storate'); localStorage.removeItem(this.config.storageKey); this.loggedIn = new ApiV1LoginResponse({}); this.logoutEvent.emit(this.loggedIn); this.router.navigate(['/login']).then(r => { this.ToastMessage(); } ); } public ToastMessage(msg: string = 'Successfully logged out'): void { this.ns.show({ content: msg, cssClass: 'button-notification', animation: { type: 'slide', duration: 400 }, position: { horizontal: 'right', vertical: 'top' }, type: { style: 'info', icon: true }, hideAfter : 2000 }); } public get MachineId(): string { return this.machineId || ''; } public set MachineId(mid) { if ( this.machineId === '' || this.machineId !== mid ){ this.machineId = mid; localStorage.setItem('mid', mid); } } public get SessionId(): string{ return this.loggedIn.session || ''; } public set SessionId(sid: string){ if ( this.loggedIn.session === '' || this.loggedIn.session !== sid ){ this.loggedIn.session = sid; this.saveSessionInfo(); this.ws.SessionId = sid; } } public get SocketId(): string{ return this.socketId; } public set SocketId(socketId: string ) { this.socketId = socketId; } }