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 171420cf..3d9ab2bf 100644 --- a/src/app/components/login/login.component.ts +++ b/src/app/components/login/login.component.ts @@ -1,89 +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; - 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 b78565aa..9be04166 100644 --- a/src/app/guards/login-guard.ts +++ b/src/app/guards/login-guard.ts @@ -6,35 +6,20 @@ import { ServerService } from '../services/server.service'; @Injectable() export class LoginGuard implements CanActivate { - constructor( - private serverService: ServerService, - private loginService: LoginService, - private router: Router - ) {} + constructor(private serverService: ServerService, private loginService: LoginService, private router: Router) {} - async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) { - const server_id = next.paramMap.get('server_id'); - let server = await this.serverService.get(parseInt(server_id, 10)); - try { - await this.loginService.getLoggedUser(server).toPromise(); - } catch (e) { - if (e.status === 401) { - 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) - } 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 }}); - }); - } + 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 6f94ef49..0b1ea7b5 100644 --- a/src/app/interceptors/http.interceptor.ts +++ b/src/app/interceptors/http.interceptor.ts @@ -1,10 +1,45 @@ +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 { Observable } from 'rxjs'; +import { LoginService } from '@services/login.service'; +import { ServerService } from '@services/server.service'; +import { Observable, throwError } from 'rxjs'; +import { catchError } from 'rxjs/operators'; @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 || err.status === 403) { + this.call(); + } else { + return throwError(err); + } + }) + ); + } + + 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 { + 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; + } + } + reloadCurrentRoute() { + location.reload(); } } diff --git a/src/app/services/login.service.ts b/src/app/services/login.service.ts index 2c3c64bc..a5ff85b7 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,current_user):Promise { + return await this.httpServer.post(server, "/users/authenticate", {"username":current_user.username,"password":current_user.password}).toPromise() } }