ajout sécu signin

This commit is contained in:
Romain Verger 2022-03-01 15:02:17 +01:00
parent 6c1f0338eb
commit 01b68c0899
12 changed files with 205 additions and 27 deletions

11
package-lock.json generated
View File

@ -18,6 +18,7 @@
"@angular/router": "~13.0.0", "@angular/router": "~13.0.0",
"bootstrap": "^5.1.3", "bootstrap": "^5.1.3",
"bootstrap-icons": "^1.7.2", "bootstrap-icons": "^1.7.2",
"jwt-decode": "^3.1.2",
"rxjs": "~7.4.0", "rxjs": "~7.4.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.11.4" "zone.js": "~0.11.4"
@ -6887,6 +6888,11 @@
"node >= 0.2.0" "node >= 0.2.0"
] ]
}, },
"node_modules/jwt-decode": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
"node_modules/karma": { "node_modules/karma": {
"version": "6.3.11", "version": "6.3.11",
"resolved": "https://registry.npmjs.org/karma/-/karma-6.3.11.tgz", "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.11.tgz",
@ -17654,6 +17660,11 @@
"integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
"dev": true "dev": true
}, },
"jwt-decode": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
"karma": { "karma": {
"version": "6.3.11", "version": "6.3.11",
"resolved": "https://registry.npmjs.org/karma/-/karma-6.3.11.tgz", "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.11.tgz",

View File

@ -21,6 +21,7 @@
"@angular/router": "~13.0.0", "@angular/router": "~13.0.0",
"bootstrap": "^5.1.3", "bootstrap": "^5.1.3",
"bootstrap-icons": "^1.7.2", "bootstrap-icons": "^1.7.2",
"jwt-decode": "^3.1.2",
"rxjs": "~7.4.0", "rxjs": "~7.4.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.11.4" "zone.js": "~0.11.4"

View File

@ -8,6 +8,7 @@ import { PageNotFoundComponent } from './pages/page-not-found/page-not-found.com
import { FiltersPageComponent } from './pages/filters-page/filters-page.component'; import { FiltersPageComponent } from './pages/filters-page/filters-page.component';
import { SigninComponent } from './pages/signin/signin.component'; import { SigninComponent } from './pages/signin/signin.component';
import { AdminPageComponent } from './pages/admin-page/admin-page.component'; import { AdminPageComponent } from './pages/admin-page/admin-page.component';
import { AuthGuard } from './services/auth.guard';
const routes: Routes = [ const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' }, { path: '', redirectTo: 'home', pathMatch: 'full' },
@ -16,7 +17,7 @@ const routes: Routes = [
{ path: 'favoris', component: FavorisUserComponent }, { path: 'favoris', component: FavorisUserComponent },
{ path: 'filtres', component: FiltersPageComponent }, { path: 'filtres', component: FiltersPageComponent },
{ path: 'Deconnexion', redirectTo: 'home'}, { path: 'Deconnexion', redirectTo: 'home'},
{path: 'restaurants',component: RestoPageComponent}, {path: 'restaurants', canActivate: [AuthGuard], component: RestoPageComponent},
{path: 'page-not-found',component: PageNotFoundComponent}, {path: 'page-not-found',component: PageNotFoundComponent},
{path: 'signin', component: SigninComponent}, {path: 'signin', component: SigninComponent},
{path: 'admin', component: AdminPageComponent}, {path: 'admin', component: AdminPageComponent},

View File

@ -9,7 +9,7 @@ import { CardCategoryComponent } from './card-category/card-category.component';
import { CardRestoComponent } from './card-resto/card-resto.component'; import { CardRestoComponent } from './card-resto/card-resto.component';
import { FooterComponent } from './footer/footer.component'; import { FooterComponent } from './footer/footer.component';
import { HomePageComponent } from './pages/home-page/home-page.component'; import { HomePageComponent } from './pages/home-page/home-page.component';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { ListCategoriesComponent } from './pages/list-categories/list-categories.component'; import { ListCategoriesComponent } from './pages/list-categories/list-categories.component';
import { SigninComponent } from './pages/signin/signin.component'; import { SigninComponent } from './pages/signin/signin.component';
import { RestoPageComponent } from './pages/resto-page/resto-page.component'; import { RestoPageComponent } from './pages/resto-page/resto-page.component';
@ -20,6 +20,7 @@ import { IconComponent } from './filters/icon/icon.component';
import { TemplatePageComponent } from './components/template-page/template-page.component'; import { TemplatePageComponent } from './components/template-page/template-page.component';
import { AdminPageComponent } from './pages/admin-page/admin-page.component'; import { AdminPageComponent } from './pages/admin-page/admin-page.component';
import { AddRestauComponent } from './admin-component/add-restau/add-restau.component'; import { AddRestauComponent } from './admin-component/add-restau/add-restau.component';
import { AuthInterceptor } from './services/auth.interceptor';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -48,7 +49,9 @@ import { AddRestauComponent } from './admin-component/add-restau/add-restau.comp
FormsModule, FormsModule,
ReactiveFormsModule ReactiveFormsModule
], ],
providers: [], providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { } export class AppModule { }

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from '../../services/auth.service'; import { AuthService } from '../../services/auth.service';
@Component({ @Component({
@ -8,7 +9,8 @@ import { AuthService } from '../../services/auth.service';
}) })
export class SigninComponent implements OnInit { export class SigninComponent implements OnInit {
public errorForm: boolean; public errorForm: boolean;
constructor(private authService: AuthService) {
constructor(private authService: AuthService , private router: Router) {
this.errorForm = false; this.errorForm = false;
} }
@ -21,7 +23,9 @@ export class SigninComponent implements OnInit {
const password = submittedForm.form.value['password']; const password = submittedForm.form.value['password'];
if(email !== '' && password !== '') { if(email !== '' && password !== '') {
this.authService.signin(email, password).subscribe( this.authService.signin(email, password).subscribe(
resp => console.log('Component Page Signin: ', resp) resp => {console.log('Component Page Signin ', resp)
this.router.navigate(['home'])
}
) )
} else { } else {
// afficher une erreur à l'utilisateur // afficher une erreur à l'utilisateur

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { AuthGuard } from './auth.guard';
describe('AuthGuard', () => {
let guard: AuthGuard;
beforeEach(() => {
TestBed.configureTestingModule({});
guard = TestBed.inject(AuthGuard);
});
it('should be created', () => {
expect(guard).toBeTruthy();
});
});

View File

@ -0,0 +1,46 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import jwt_decode from 'jwt-decode';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
private tokenKey: string;
constructor(private router: Router){
this.tokenKey = environment.tokenKey;
}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
const token = localStorage.getItem(this.tokenKey);
if(token) {
const decodedToken = jwt_decode<any>(token);
console.log('decodedToken : ', decodedToken);
if(decodedToken.exp) {
console.log('Date d\'exp decodedToken : ', decodedToken.exp);
const dateExp = new Date(decodedToken.exp * 1000);
if(new Date() >= dateExp) {
// le token a expiré, je n'autorise pas l'accès
this.router.navigate(['signin']);
return false;
}
}
console.log("C'est ok ! ")
return true;
} else {
console.log("You shall not pass !!!!")
this.router.navigate(['signin']); // redirection de notre utilisateur vers une url de notre application (dans notre code TS)
return false;
}
}
}

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { AuthInterceptor } from './auth.interceptor';
describe('AuthInterceptor', () => {
beforeEach(() => TestBed.configureTestingModule({
providers: [
AuthInterceptor
]
}));
it('should be created', () => {
const interceptor: AuthInterceptor = TestBed.inject(AuthInterceptor);
expect(interceptor).toBeTruthy();
});
});

View File

@ -0,0 +1,31 @@
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { TokenService } from './token.service';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private tokenService: TokenService) {}
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
console.log('Coucou je suis le videur ! ');
const token = this.tokenService.getToken();
if(token) {
const authReq = request.clone(
{
headers : request.headers.set('Authorization', `Bearer ${token}`)
}
)
return next.handle(authReq);
} else {
return next.handle(request);
}
}
}

View File

@ -18,18 +18,18 @@ export class AuthService {
this.tokenKey = environment.tokenKey; this.tokenKey = environment.tokenKey;
} }
signup(newUser: User): Observable<any> { // signup(): Observable<any> {
// const body = { // // const body = {
// firstName: firstName, // // firstName: firstName,
// lastName: lastName, // // lastName: lastName,
// email: email, // // email: email,
// password: password // // password: password
// }; // // };
console.log("Mon nouvel utilisateur : ", newUser); // console.log("Mon nouvel utilisateur : ", newUser);
return this.http.post(`${this.apiUrl}/register`, newUser); // return this.http.post(`${this.apiUrl}/register`, newUser);
} // }
signin(email: string, password: string): Observable<any> { signin(email: string, password: string): Observable<any> {
const body = { const body = {
@ -41,27 +41,28 @@ export class AuthService {
// Modifier cette partie ci-dessous : // Modifier cette partie ci-dessous :
// - pour pouvoir stocker dans le localstorage notre accesstoken // - pour pouvoir stocker dans le localstorage notre accesstoken
// - Sous la clé "TOKEN-LBP" // - Sous la clé "TOKEN-SIMPLEAT"
return this.http.post(`${this.apiUrl}/login`, body).pipe( return this.http.post(`${this.apiUrl}/signin`, body).pipe(
map((x: any) => { map((x: any) => {
console.log('Service : ', x.accessToken);
console.log('Service : ', x.token);
// Modification à faire ici // Modification à faire ici
localStorage.setItem(this.tokenKey, x.accessToken); localStorage.setItem(this.tokenKey, x.token);
return x; // permet de renvoyer la réponse à l'initiateur (page Signin) après le traitement du map return x; // permet de renvoyer la réponse à l'initiateur (page Signin) après le traitement du map
}) })
); );
} }
forgotPassword(email: string, password: string): Observable<any> { // forgotPassword(email: string, password: string): Observable<any> {
const body = { // const body = {
email: email, // email: email,
password: password // password: password
}; // };
console.log("Mon body : ", body); // console.log("Mon body : ", body);
return this.http.post(`${this.apiUrl}/forgot-psw`, body); // return this.http.post(`${this.apiUrl}/forgot-psw`, body);
} // }
} }

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { TokenService } from './token.service';
describe('TokenService', () => {
let service: TokenService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(TokenService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,32 @@
import { Injectable } from '@angular/core';
import { environment } from 'src/environments/environment';
import jwt_decode from 'jwt-decode';
@Injectable({
providedIn: 'root'
})
export class TokenService {
tokenKey = environment.tokenKey;
constructor() { }
public getToken(): string | null {
const token = localStorage.getItem(this.tokenKey);
if(token) {
return token;
} else {
return null;
}
}
public getCurrentUserId(): number | null {
const token = this.getToken();
if(token) {
const decodedToken = jwt_decode<any>(token);
const userId = decodedToken.sub;
return userId;
} else {
return null;
}
}
}