From 0185dbd8af5c5c64d6f90b9eb2ad244b2a8fa236 Mon Sep 17 00:00:00 2001 From: Rajnikant Date: Fri, 27 May 2022 12:57:56 +0530 Subject: [PATCH 1/5] I have modified the JWT Interceptor and added refresh token functionality --- src/app/components/login/login.component.ts | 1 + src/app/guards/login-guard.ts | 39 +++++++++++++------- src/app/interceptors/http.interceptor.ts | 41 ++++++++++++++++++++- src/app/services/login.service.ts | 6 ++- 4 files changed, 70 insertions(+), 17 deletions(-) diff --git a/src/app/components/login/login.component.ts b/src/app/components/login/login.component.ts index 171420cf..3b268a1f 100644 --- a/src/app/components/login/login.component.ts +++ b/src/app/components/login/login.component.ts @@ -74,6 +74,7 @@ export class LoginComponent implements OnInit { server.authToken = response.access_token; server.username = username; server.password = password; + server.tokenExpired = false; await this.serverService.update(server); if (this.returnUrl.length <= 1) { diff --git a/src/app/guards/login-guard.ts b/src/app/guards/login-guard.ts index b78565aa..5b99c17f 100644 --- a/src/app/guards/login-guard.ts +++ b/src/app/guards/login-guard.ts @@ -1,40 +1,51 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; import { LoginService } from '@services/login.service'; +import { ProjectService } from '@services/project.service'; import { Server } from '../models/server'; import { ServerService } from '../services/server.service'; @Injectable() export class LoginGuard implements CanActivate { constructor( - private serverService: ServerService, - private loginService: LoginService, - private router: Router - ) {} + private serverService: ServerService, + private loginService: LoginService, + private router: Router, + private projectService: ProjectService + ) { } async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) { const server_id = next.paramMap.get('server_id'); + this.loginService.server_id = server_id let server = await this.serverService.get(parseInt(server_id, 10)); + try { - await this.loginService.getLoggedUser(server).toPromise(); + await this.loginService.getLoggedUser(server) } catch (e) { if (e.status === 401) { - server.tokenExpired = true; - await this.serverService.update(server) + // this.test() + + // server.tokenExpired = true; + // await this.serverService.update(server) try { - let response = await this.loginService.login(server, server.username, server.password).toPromise(); - server.authToken = response.access_token; - server.tokenExpired = false; - await this.serverService.update(server) + // debugger + // alert('test') + + // let response = await this.loginService.getLoggedUserRefToken(server) + // server.authToken = response.access_token; + // server.tokenExpired = false; + // await this.serverService.update(server) } catch (e) { throw e; } } } - return this.serverService.get(parseInt(server_id, 10)).then((server: Server) => { - if (server.authToken) return true; - this.router.navigate(['/server', server.id, 'login'], { queryParams: { returnUrl: state.url }}); + if (server.authToken && !server.tokenExpired) { + return true + } + this.router.navigate(['/server', server.id, 'login'], { queryParams: { returnUrl: state.url } }); }); } + } diff --git a/src/app/interceptors/http.interceptor.ts b/src/app/interceptors/http.interceptor.ts index 6f94ef49..38d95dc8 100644 --- a/src/app/interceptors/http.interceptor.ts +++ b/src/app/interceptors/http.interceptor.ts @@ -1,10 +1,47 @@ import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpEvent, HttpResponse, HttpRequest, HttpHandler } from '@angular/common/http'; -import { Observable } from 'rxjs'; +import { Observable, throwError } from 'rxjs'; +import { catchError } from 'rxjs/operators'; +import { ServerService } from '@services/server.service'; +import { LoginService } from '@services/login.service'; @Injectable() export class HttpRequestsInterceptor implements HttpInterceptor { + constructor( + private serverService: ServerService, + private loginService: LoginService) { } intercept(httpRequest: HttpRequest, next: HttpHandler): Observable> { - return next.handle(httpRequest); + return next.handle(httpRequest).pipe(catchError(err => { + if (err.status === 401) { + this.call() + } else { + return throwError(err) + } + })) } + async call() { + const server_id = this.loginService.server_id + let server = await this.serverService.get(parseInt(server_id, 10)); + server.tokenExpired = true; + await this.serverService.update(server) + try { + let response = await this.loginService.getLoggedUserRefToken(server) + server.authToken = response.access_token; + server.tokenExpired = false; + await this.serverService.update(server) + await this.loginService.getLoggedUser(server) + this.reloadCurrentRoute() + } catch (e) { + throw e; + } + + + + } + reloadCurrentRoute() { + window.location.reload() + } + } + + diff --git a/src/app/services/login.service.ts b/src/app/services/login.service.ts index 2c3c64bc..5b42317b 100644 --- a/src/app/services/login.service.ts +++ b/src/app/services/login.service.ts @@ -7,6 +7,7 @@ import { AuthResponse } from '../models/authResponse'; @Injectable() export class LoginService { + server_id:string ='' constructor(private httpServer: HttpServer) {} login(server: Server, username: string, password: string) { @@ -22,6 +23,9 @@ export class LoginService { } getLoggedUser(server: Server) { - return this.httpServer.get(server, "/users/me"); + return this.httpServer.get(server, "/users/me").toPromise() + } + async getLoggedUserRefToken(server: Server):Promise { + return await this.httpServer.post(server, "/users/authenticate", {"username":server.username,"password":server.password}).toPromise() } } From 78da4f0efa2050672334ae48da1ddc931fafcc3f Mon Sep 17 00:00:00 2001 From: Rajnikant Date: Tue, 31 May 2022 10:47:32 +0530 Subject: [PATCH 2/5] I have added Remember me tickbox on login component and I resolve an error just before auto re-login --- src/app/components/login/login.component.html | 69 +++---- src/app/components/login/login.component.scss | 8 +- src/app/components/login/login.component.ts | 173 +++++++++++------- src/app/guards/login-guard.ts | 56 ++---- src/app/interceptors/http.interceptor.ts | 47 +++-- 5 files changed, 183 insertions(+), 170 deletions(-) diff --git a/src/app/components/login/login.component.html b/src/app/components/login/login.component.html index f4bc34d0..43035773 100644 --- a/src/app/components/login/login.component.html +++ b/src/app/components/login/login.component.html @@ -1,35 +1,42 @@
-
- -
-
- - -
-

GNS3

-
v{{version}}
-
-
-
- -
- - - You must enter username - - - - You must enter password - -
- -
- -
-
- -
- Authentication was unsuccessful +
+ +
+
+ + +
+

GNS3

+
v{{ version }}
+
+
+ +
+ + + You must enter username + + + + You must enter password + +
+ Remember me +
+ +
+
+ +
+ Authentication was unsuccessful
+
diff --git a/src/app/components/login/login.component.scss b/src/app/components/login/login.component.scss index dc32554b..dbdd4dd7 100644 --- a/src/app/components/login/login.component.scss +++ b/src/app/components/login/login.component.scss @@ -12,8 +12,8 @@ mat-form-field { } .mat-icon-login { - height: 100px!important; - width: 100px!important; + height: 100px !important; + width: 100px !important; } .loginTitle { @@ -35,3 +35,7 @@ mat-form-field { justify-content: center; margin-top: 20px; } + +.margin-left { + margin-left: 5px; +} \ No newline at end of file diff --git a/src/app/components/login/login.component.ts b/src/app/components/login/login.component.ts index 3b268a1f..eac9604e 100644 --- a/src/app/components/login/login.component.ts +++ b/src/app/components/login/login.component.ts @@ -1,90 +1,123 @@ -import { Component, ComponentFactoryResolver, OnInit, ViewEncapsulation } from '@angular/core'; +import { Component, DoCheck, OnInit, ViewEncapsulation } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; -import { ActivatedRoute, ParamMap, Router } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; +import { AuthResponse } from '../../models/authResponse'; import { Server } from '../../models/server'; +import { Version } from '../../models/version'; import { LoginService } from '../../services/login.service'; import { ServerDatabase } from '../../services/server.database'; import { ServerService } from '../../services/server.service'; -import { ToasterService } from '../../services/toaster.service'; -import { AuthResponse } from '../../models/authResponse'; -import { VersionService } from '../../services/version.service'; -import { Version } from '../../models/version'; import { ThemeService } from '../../services/theme.service'; +import { ToasterService } from '../../services/toaster.service'; +import { VersionService } from '../../services/version.service'; @Component({ - selector: 'app-login', - templateUrl: './login.component.html', - styleUrls: ['./login.component.scss'], - encapsulation: ViewEncapsulation.None, + selector: 'app-login', + templateUrl: './login.component.html', + styleUrls: ['./login.component.scss'], + encapsulation: ViewEncapsulation.None, }) -export class LoginComponent implements OnInit { - private server: Server; - public version: string; - public isLightThemeEnabled: boolean = false; - public loginError: boolean = false; - public returnUrl: string = ""; +export class LoginComponent implements OnInit, DoCheck { + private server: Server; + public version: string; + public isLightThemeEnabled: boolean = false; + public loginError: boolean = false; + public returnUrl: string = ''; + public isRememberMe: boolean = false; + public isRememberMeCheked: boolean = false; - loginForm = new FormGroup({ - username: new FormControl('', [Validators.required]), - password: new FormControl('', [Validators.required]) + loginForm = new FormGroup({ + username: new FormControl('', [Validators.required]), + password: new FormControl('', [Validators.required]), + }); + + constructor( + private loginService: LoginService, + private serverService: ServerService, + private serverDatabase: ServerDatabase, + private route: ActivatedRoute, + private router: Router, + private toasterService: ToasterService, + private versionService: VersionService, + private themeService: ThemeService + ) {} + + async ngOnInit() { + const server_id = this.route.snapshot.paramMap.get('server_id'); + this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/'; + this.serverService.get(parseInt(server_id, 10)).then((server: Server) => { + this.server = server; + + if (server.authToken) { + this.router.navigate(['/server', this.server.id, 'projects']); + } + + this.versionService.get(this.server).subscribe((version: Version) => { + this.version = version.version; + }); }); - constructor( - private loginService: LoginService, - private serverService: ServerService, - private serverDatabase: ServerDatabase, - private route: ActivatedRoute, - private router: Router, - private toasterService: ToasterService, - private versionService: VersionService, - private themeService: ThemeService - ) {} + this.themeService.getActualTheme() === 'light' + ? (this.isLightThemeEnabled = true) + : (this.isLightThemeEnabled = false); - async ngOnInit() { - const server_id = this.route.snapshot.paramMap.get('server_id'); - this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/'; - this.serverService.get(parseInt(server_id, 10)).then((server: Server) => { - this.server = server; + let getCurrentUser = JSON.parse(localStorage.getItem(`isRememberMe`)) ?? null; + if (getCurrentUser && getCurrentUser.isRememberMe) { + this.loginForm.get('username').setValue(getCurrentUser.username); + this.loginForm.get('password').setValue(getCurrentUser.password); + this.isRememberMeCheked = getCurrentUser.isRememberMe; + } + } - if (server.authToken) { - this.router.navigate(['/server', this.server.id, 'projects']); - } - - this.versionService.get(this.server).subscribe((version: Version) => { - this.version = version.version; - }); - }); - - this.themeService.getActualTheme() === 'light' - ? (this.isLightThemeEnabled = true) - : (this.isLightThemeEnabled = false); + public login() { + if (this.loginForm.get('username').invalid || this.loginForm.get('password').invalid) { + this.toasterService.error('Please enter username and password'); + return; } - public login() { - if (this.loginForm.get('username').invalid || this.loginForm.get('password').invalid) { - this.toasterService.error("Please enter username and password") - return; + let username = this.loginForm.get('username').value; + let password = this.loginForm.get('password').value; + + this.loginService.login(this.server, username, password).subscribe( + async (response: AuthResponse) => { + let server = this.server; + server.authToken = response.access_token; + server.username = username; + server.password = password; + server.tokenExpired = false; + await this.serverService.update(server); + + if (this.returnUrl.length <= 1) { + this.router.navigate(['/server', this.server.id, 'projects']); + } else { + this.router.navigateByUrl(this.returnUrl); } + }, + (error) => { + this.loginError = true; + } + ); + } - let username = this.loginForm.get('username').value; - let password = this.loginForm.get('password').value; - - this.loginService.login(this.server, username, password).subscribe(async (response: AuthResponse) => { - let server = this.server; - server.authToken = response.access_token; - server.username = username; - server.password = password; - server.tokenExpired = false; - await this.serverService.update(server); - - if (this.returnUrl.length <= 1) { - this.router.navigate(['/server', this.server.id, 'projects']) - } else { - this.router.navigateByUrl(this.returnUrl); - } - - }, error => { - this.loginError = true; - }); + rememberMe(ev) { + if (ev.checked) { + let curren_user = { + username: this.loginForm.get('username').value, + password: this.loginForm.get('password').value, + isRememberMe: ev.checked, + }; + this.isRememberMeCheked = ev.checked; + localStorage.setItem(`isRememberMe`, JSON.stringify(curren_user)); + } else { + localStorage.removeItem(`isRememberMe`); + this.loginForm.reset(); + this.isRememberMe = ev.checked; } + } + + ngDoCheck() { + if (this.loginForm.get('username').valid || this.loginForm.get('password').valid) { + this.isRememberMe = true; + } + } } diff --git a/src/app/guards/login-guard.ts b/src/app/guards/login-guard.ts index 5b99c17f..9be04166 100644 --- a/src/app/guards/login-guard.ts +++ b/src/app/guards/login-guard.ts @@ -1,51 +1,25 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; import { LoginService } from '@services/login.service'; -import { ProjectService } from '@services/project.service'; import { Server } from '../models/server'; import { ServerService } from '../services/server.service'; @Injectable() export class LoginGuard implements CanActivate { - constructor( - private serverService: ServerService, - private loginService: LoginService, - private router: Router, - private projectService: ProjectService - ) { } - - async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) { - const server_id = next.paramMap.get('server_id'); - this.loginService.server_id = server_id - let server = await this.serverService.get(parseInt(server_id, 10)); - - try { - await this.loginService.getLoggedUser(server) - } catch (e) { - if (e.status === 401) { - // this.test() - - // server.tokenExpired = true; - // await this.serverService.update(server) - try { - // debugger - // alert('test') - - // let response = await this.loginService.getLoggedUserRefToken(server) - // server.authToken = response.access_token; - // server.tokenExpired = false; - // await this.serverService.update(server) - } catch (e) { - throw e; - } - } - } - return this.serverService.get(parseInt(server_id, 10)).then((server: Server) => { - if (server.authToken && !server.tokenExpired) { - return true - } - this.router.navigate(['/server', server.id, 'login'], { queryParams: { returnUrl: state.url } }); - }); - } + constructor(private serverService: ServerService, private loginService: LoginService, private router: Router) {} + async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + const server_id = next.paramMap.get('server_id'); + this.loginService.server_id = server_id; + let server = await this.serverService.get(parseInt(server_id, 10)); + try { + await this.loginService.getLoggedUser(server); + } catch (e) {} + return this.serverService.get(parseInt(server_id, 10)).then((server: Server) => { + if (server.authToken && !server.tokenExpired) { + return true; + } + this.router.navigate(['/server', server.id, 'login'], { queryParams: { returnUrl: state.url } }); + }); + } } diff --git a/src/app/interceptors/http.interceptor.ts b/src/app/interceptors/http.interceptor.ts index 38d95dc8..4663a2a1 100644 --- a/src/app/interceptors/http.interceptor.ts +++ b/src/app/interceptors/http.interceptor.ts @@ -1,47 +1,42 @@ +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { HttpInterceptor, HttpEvent, HttpResponse, HttpRequest, HttpHandler } from '@angular/common/http'; +import { LoginService } from '@services/login.service'; +import { ServerService } from '@services/server.service'; import { Observable, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; -import { ServerService } from '@services/server.service'; -import { LoginService } from '@services/login.service'; @Injectable() export class HttpRequestsInterceptor implements HttpInterceptor { - constructor( - private serverService: ServerService, - private loginService: LoginService) { } + constructor(private serverService: ServerService, private loginService: LoginService) {} intercept(httpRequest: HttpRequest, next: HttpHandler): Observable> { - return next.handle(httpRequest).pipe(catchError(err => { - if (err.status === 401) { - this.call() - } else { - return throwError(err) - } - })) + return next.handle(httpRequest).pipe( + catchError((err) => { + if (err.status === 401 || err.status === 403) { + this.call(); + } else { + return throwError(err); + } + }) + ); } + async call() { - const server_id = this.loginService.server_id + const server_id = this.loginService.server_id; let server = await this.serverService.get(parseInt(server_id, 10)); server.tokenExpired = true; - await this.serverService.update(server) + await this.serverService.update(server); try { - let response = await this.loginService.getLoggedUserRefToken(server) + let response = await this.loginService.getLoggedUserRefToken(server); server.authToken = response.access_token; server.tokenExpired = false; - await this.serverService.update(server) - await this.loginService.getLoggedUser(server) - this.reloadCurrentRoute() + await this.serverService.update(server); + await this.loginService.getLoggedUser(server); + this.reloadCurrentRoute(); } catch (e) { throw e; } - - - } reloadCurrentRoute() { - window.location.reload() + location.reload(); } - } - - From eb07abe786688d4fe1e1138998a4e6aa03ed7d8c Mon Sep 17 00:00:00 2001 From: Rajnikant Date: Tue, 31 May 2022 13:18:52 +0530 Subject: [PATCH 3/5] Resolve/modified remember me check box user cases --- src/app/components/login/login.component.ts | 2 -- src/app/interceptors/http.interceptor.ts | 15 +++++++++------ src/app/services/login.service.ts | 4 ++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/app/components/login/login.component.ts b/src/app/components/login/login.component.ts index eac9604e..022e98c4 100644 --- a/src/app/components/login/login.component.ts +++ b/src/app/components/login/login.component.ts @@ -63,8 +63,6 @@ export class LoginComponent implements OnInit, DoCheck { let getCurrentUser = JSON.parse(localStorage.getItem(`isRememberMe`)) ?? null; if (getCurrentUser && getCurrentUser.isRememberMe) { - this.loginForm.get('username').setValue(getCurrentUser.username); - this.loginForm.get('password').setValue(getCurrentUser.password); this.isRememberMeCheked = getCurrentUser.isRememberMe; } } diff --git a/src/app/interceptors/http.interceptor.ts b/src/app/interceptors/http.interceptor.ts index 4663a2a1..0b1ea7b5 100644 --- a/src/app/interceptors/http.interceptor.ts +++ b/src/app/interceptors/http.interceptor.ts @@ -21,17 +21,20 @@ export class HttpRequestsInterceptor implements HttpInterceptor { } async call() { + let getCurrentUser = JSON.parse(localStorage.getItem(`isRememberMe`)) ?? null; const server_id = this.loginService.server_id; let server = await this.serverService.get(parseInt(server_id, 10)); server.tokenExpired = true; await this.serverService.update(server); try { - let response = await this.loginService.getLoggedUserRefToken(server); - server.authToken = response.access_token; - server.tokenExpired = false; - await this.serverService.update(server); - await this.loginService.getLoggedUser(server); - this.reloadCurrentRoute(); + if (getCurrentUser && getCurrentUser.isRememberMe) { + let response = await this.loginService.getLoggedUserRefToken(server, getCurrentUser); + server.authToken = response.access_token; + server.tokenExpired = false; + await this.serverService.update(server); + await this.loginService.getLoggedUser(server); + this.reloadCurrentRoute(); + } } catch (e) { throw e; } diff --git a/src/app/services/login.service.ts b/src/app/services/login.service.ts index 5b42317b..a5ff85b7 100644 --- a/src/app/services/login.service.ts +++ b/src/app/services/login.service.ts @@ -25,7 +25,7 @@ export class LoginService { getLoggedUser(server: Server) { return this.httpServer.get(server, "/users/me").toPromise() } - async getLoggedUserRefToken(server: Server):Promise { - return await this.httpServer.post(server, "/users/authenticate", {"username":server.username,"password":server.password}).toPromise() + async getLoggedUserRefToken(server: Server,current_user):Promise { + return await this.httpServer.post(server, "/users/authenticate", {"username":current_user.username,"password":current_user.password}).toPromise() } } From 07c505187decc1d81a61db4938f8d8111b906990 Mon Sep 17 00:00:00 2001 From: Rajnikant Date: Tue, 31 May 2022 13:40:00 +0530 Subject: [PATCH 4/5] update user case 2 --- src/app/components/login/login.component.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/components/login/login.component.ts b/src/app/components/login/login.component.ts index 022e98c4..eac9604e 100644 --- a/src/app/components/login/login.component.ts +++ b/src/app/components/login/login.component.ts @@ -63,6 +63,8 @@ export class LoginComponent implements OnInit, DoCheck { let getCurrentUser = JSON.parse(localStorage.getItem(`isRememberMe`)) ?? null; if (getCurrentUser && getCurrentUser.isRememberMe) { + this.loginForm.get('username').setValue(getCurrentUser.username); + this.loginForm.get('password').setValue(getCurrentUser.password); this.isRememberMeCheked = getCurrentUser.isRememberMe; } } From 18a014d73970073e25e4129980f4d33c4e72c427 Mon Sep 17 00:00:00 2001 From: Rajnikant Date: Tue, 31 May 2022 14:12:18 +0530 Subject: [PATCH 5/5] update --- src/app/components/login/login.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/login/login.component.ts b/src/app/components/login/login.component.ts index eac9604e..3d9ab2bf 100644 --- a/src/app/components/login/login.component.ts +++ b/src/app/components/login/login.component.ts @@ -116,7 +116,7 @@ export class LoginComponent implements OnInit, DoCheck { } ngDoCheck() { - if (this.loginForm.get('username').valid || this.loginForm.get('password').valid) { + if (this.loginForm.get('username').valid && this.loginForm.get('password').valid) { this.isRememberMe = true; } }