diff --git a/package-lock.json b/package-lock.json index 30a8de4..f3faaba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5102,6 +5102,11 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "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": { "version": "6.3.11", "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.11.tgz", diff --git a/package.json b/package.json index dcf849b..b0cd5d3 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@angular/platform-browser-dynamic": "~13.0.0", "@angular/router": "~13.0.0", "bootstrap": "^5.1.3", + "jwt-decode": "^3.1.2", "rxjs": "~7.4.0", "tslib": "^2.3.0", "zone.js": "~0.11.4" diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 0297262..ac4db0b 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,10 +1,40 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; +import { PageAccountComponent } from './pages/page-account/page-account.component'; +import { PageAccueilComponent } from './pages/page-accueil/page-accueil.component'; +import { PageAddMemberComponent } from './pages/page-add-member/page-add-member.component'; +import { PageAgendaComponent } from './pages/page-agenda/page-agenda.component'; +import { PageDashboardComponent } from './pages/page-dashboard/page-dashboard.component'; +import { PageDeleteMemberComponent } from './pages/page-delete-member/page-delete-member.component'; +import { PageForgotPasswordComponent } from './pages/page-forgot-password/page-forgot-password.component'; +import { PageMenuSemaineComponent } from './pages/page-menu-semaine/page-menu-semaine.component'; +import { PageNotFoundComponent } from './pages/page-not-found/page-not-found.component'; +import { PageRepertoireComponent } from './pages/page-repertoire/page-repertoire.component'; +import { PageResetPasswordComponent } from './pages/page-reset-password/page-reset-password.component'; +import { PageSignupComponent } from './pages/page-signup/page-signup.component'; +import { PageToDoListComponent } from './pages/page-to-do-list/page-to-do-list.component'; +import { PageUpdateMemberComponent } from './pages/page-update-member/page-update-member.component'; -const routes: Routes = []; +const routes: Routes = [ + { path: '', redirectTo: 'accueil', pathMatch: 'full' }, + { path: 'compte', component: PageAccountComponent }, + { path: 'accueil', component: PageAccueilComponent }, + { path: 'ajout-membre', component: PageAddMemberComponent }, + { path: 'agenda', component: PageAgendaComponent }, + { path: 'tableau-de-bord', component: PageDashboardComponent }, + { path: 'supprimer-membre', component: PageDeleteMemberComponent }, + { path: 'password-oublie', component: PageForgotPasswordComponent }, + { path: 'menu', component: PageMenuSemaineComponent }, + { path: 'repertoire', component: PageRepertoireComponent }, + { path: 'reinitialisation-password', component: PageResetPasswordComponent }, + { path: 'creation-compte', component: PageSignupComponent }, + { path: 'to-do-list', component: PageToDoListComponent }, + { path: 'modifier-membre', component: PageUpdateMemberComponent }, + { path: '**', component: PageNotFoundComponent }, +]; @NgModule({ imports: [RouterModule.forRoot(routes)], - exports: [RouterModule] + exports: [RouterModule], }) -export class AppRoutingModule { } +export class AppRoutingModule {} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index d268cf3..9b55ae7 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -31,6 +31,8 @@ import { CardMenuComponent } from './components/card-menu/card-menu.component'; import { FicheContactComponent } from './components/fiche-contact/fiche-contact.component'; import { PaginationComponent } from './components/pagination/pagination.component'; import { CreneauComponent } from './components/creneau/creneau.component'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [ @@ -64,7 +66,13 @@ import { CreneauComponent } from './components/creneau/creneau.component'; PaginationComponent, CreneauComponent, ], - imports: [BrowserModule, AppRoutingModule], + imports: [ + BrowserModule, + AppRoutingModule, + ReactiveFormsModule, + HttpClientModule, + FormsModule, + ], providers: [], bootstrap: [AppComponent], }) diff --git a/src/app/auth.guard.spec.ts b/src/app/auth.guard.spec.ts new file mode 100644 index 0000000..68889d2 --- /dev/null +++ b/src/app/auth.guard.spec.ts @@ -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(); + }); +}); diff --git a/src/app/auth.guard.ts b/src/app/auth.guard.ts new file mode 100644 index 0000000..86d4f28 --- /dev/null +++ b/src/app/auth.guard.ts @@ -0,0 +1,55 @@ +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 + | Promise + | boolean + | UrlTree { + const token = localStorage.getItem(this.tokenKey); + + if (token) { + const decodedToken = jwt_decode(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(['account/signin']); + return false; + } + } + + console.log("C'est ok ! "); + return true; + } else { + console.log('You shall not pass !!!!'); + this.router.navigate(['account/signin']); // redirection de notre utilisateur vers une url de notre application (dans notre code TS) + return false; + } + } +} diff --git a/src/app/components/header/header.component.html b/src/app/components/header/header.component.html index 4f5a95d..347e558 100644 --- a/src/app/components/header/header.component.html +++ b/src/app/components/header/header.component.html @@ -1 +1,10 @@ -

header works!

+ \ No newline at end of file diff --git a/src/app/components/header/header.component.scss b/src/app/components/header/header.component.scss index e69de29..d03081d 100644 --- a/src/app/components/header/header.component.scss +++ b/src/app/components/header/header.component.scss @@ -0,0 +1,4 @@ +.navbar-brand { + position: absolute; + margin-left: 10%; +} diff --git a/src/app/components/side-bar/side-bar.component.html b/src/app/components/side-bar/side-bar.component.html index 354c895..2d7f65e 100644 --- a/src/app/components/side-bar/side-bar.component.html +++ b/src/app/components/side-bar/side-bar.component.html @@ -1 +1,11 @@ -

side-bar works!

+ diff --git a/src/app/components/signin/signin.component.html b/src/app/components/signin/signin.component.html index cc1a2e3..626d9da 100644 --- a/src/app/components/signin/signin.component.html +++ b/src/app/components/signin/signin.component.html @@ -1 +1,45 @@ -

signin works!

+ + diff --git a/src/app/components/signin/signin.component.scss b/src/app/components/signin/signin.component.scss index e69de29..153a247 100644 --- a/src/app/components/signin/signin.component.scss +++ b/src/app/components/signin/signin.component.scss @@ -0,0 +1,31 @@ +.signin-form { + height: 100vh; + padding-top: 40px; + background-color: #f5f5f5; +} + +.form-signin { + width: 100%; + max-width: 330px; + padding: 15px; + margin: auto; + .checkbox { + font-weight: 400; + } + + .form-floating:focus-within { + z-index: 2; + } + + input[type="email"] { + margin-bottom: -1px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + } + + input[type="password"] { + margin-bottom: 10px; + border-top-left-radius: 0; + border-top-right-radius: 0; + } +} diff --git a/src/app/components/signin/signin.component.ts b/src/app/components/signin/signin.component.ts index d0789c3..8ec139b 100644 --- a/src/app/components/signin/signin.component.ts +++ b/src/app/components/signin/signin.component.ts @@ -1,15 +1,38 @@ import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { AuthService } from '../../services/auth.service'; +import { + FormBuilder, + FormControl, + FormGroup, + Validators, +} from '@angular/forms'; @Component({ selector: 'app-signin', templateUrl: './signin.component.html', - styleUrls: ['./signin.component.scss'] + styleUrls: ['./signin.component.scss'], }) export class SigninComponent implements OnInit { - - constructor() { } - - ngOnInit(): void { + public errorForm: boolean; + constructor(private authService: AuthService, private router: Router) { + this.errorForm = false; } + ngOnInit(): void {} + + public onSubmit(submittedForm: any): void { + console.log(submittedForm.form.value); + const email = submittedForm.form.value['email']; + const password = submittedForm.form.value['password']; + if (email !== '' && password !== '') { + this.authService.signin(email, password).subscribe((resp) => { + console.log('Component Signin: ', resp); + this.router.navigate(['tableau-de-bord']); + }); + } else { + // afficher une erreur à l'utilisateur + this.errorForm = true; + } + } } diff --git a/src/app/models/membre.ts b/src/app/models/membre.ts new file mode 100644 index 0000000..798a31c --- /dev/null +++ b/src/app/models/membre.ts @@ -0,0 +1,10 @@ +export interface Membre { + firstName: string; + lastName: string; + email: string; + password: string; + dateNaissance: Date; + teamName: string; + profil: boolean; + passwordConfirm: string; +} diff --git a/src/app/pages/page-account/page-account.component.html b/src/app/pages/page-account/page-account.component.html index ea9a0aa..2d3d7d1 100644 --- a/src/app/pages/page-account/page-account.component.html +++ b/src/app/pages/page-account/page-account.component.html @@ -1 +1,2 @@ -

page-account works!

+ + \ No newline at end of file diff --git a/src/app/pages/page-accueil/page-accueil.component.html b/src/app/pages/page-accueil/page-accueil.component.html index 0c10a7b..d6d0a80 100644 --- a/src/app/pages/page-accueil/page-accueil.component.html +++ b/src/app/pages/page-accueil/page-accueil.component.html @@ -1 +1,2 @@ -

page-accueil works!

+ + \ No newline at end of file diff --git a/src/app/pages/page-add-member/page-add-member.component.html b/src/app/pages/page-add-member/page-add-member.component.html index 762e361..e91fa55 100644 --- a/src/app/pages/page-add-member/page-add-member.component.html +++ b/src/app/pages/page-add-member/page-add-member.component.html @@ -1 +1 @@ -

page-add-member works!

+ diff --git a/src/app/pages/page-agenda/page-agenda.component.html b/src/app/pages/page-agenda/page-agenda.component.html index 72d8428..2d3d7d1 100644 --- a/src/app/pages/page-agenda/page-agenda.component.html +++ b/src/app/pages/page-agenda/page-agenda.component.html @@ -1 +1,2 @@ -

page-agenda works!

+ + \ No newline at end of file diff --git a/src/app/pages/page-dashboard/page-dashboard.component.html b/src/app/pages/page-dashboard/page-dashboard.component.html index 61383aa..2d3d7d1 100644 --- a/src/app/pages/page-dashboard/page-dashboard.component.html +++ b/src/app/pages/page-dashboard/page-dashboard.component.html @@ -1 +1,2 @@ -

page-dashboard works!

+ + \ No newline at end of file diff --git a/src/app/pages/page-delete-member/page-delete-member.component.html b/src/app/pages/page-delete-member/page-delete-member.component.html index ac3125c..e91fa55 100644 --- a/src/app/pages/page-delete-member/page-delete-member.component.html +++ b/src/app/pages/page-delete-member/page-delete-member.component.html @@ -1 +1 @@ -

page-delete-member works!

+ diff --git a/src/app/pages/page-forgot-password/page-forgot-password.component.html b/src/app/pages/page-forgot-password/page-forgot-password.component.html index 4b96e7e..dcdb48e 100644 --- a/src/app/pages/page-forgot-password/page-forgot-password.component.html +++ b/src/app/pages/page-forgot-password/page-forgot-password.component.html @@ -1 +1,2 @@ -

page-forgot-password works!

+ + diff --git a/src/app/pages/page-menu-semaine/page-menu-semaine.component.html b/src/app/pages/page-menu-semaine/page-menu-semaine.component.html index 12f35aa..2d3d7d1 100644 --- a/src/app/pages/page-menu-semaine/page-menu-semaine.component.html +++ b/src/app/pages/page-menu-semaine/page-menu-semaine.component.html @@ -1 +1,2 @@ -

page-menu-semaine works!

+ + \ No newline at end of file diff --git a/src/app/pages/page-not-found/page-not-found.component.html b/src/app/pages/page-not-found/page-not-found.component.html index cc75e49..c2ceff3 100644 --- a/src/app/pages/page-not-found/page-not-found.component.html +++ b/src/app/pages/page-not-found/page-not-found.component.html @@ -1 +1,2 @@ -

page-not-found works!

+ +

Error 404 Page Not FOUND!!!!!!!!!!!

\ No newline at end of file diff --git a/src/app/pages/page-repertoire/page-repertoire.component.html b/src/app/pages/page-repertoire/page-repertoire.component.html index 18ca94a..2d3d7d1 100644 --- a/src/app/pages/page-repertoire/page-repertoire.component.html +++ b/src/app/pages/page-repertoire/page-repertoire.component.html @@ -1 +1,2 @@ -

page-repertoire works!

+ + \ No newline at end of file diff --git a/src/app/pages/page-reset-password/page-reset-password.component.html b/src/app/pages/page-reset-password/page-reset-password.component.html index 763cd7f..e91fa55 100644 --- a/src/app/pages/page-reset-password/page-reset-password.component.html +++ b/src/app/pages/page-reset-password/page-reset-password.component.html @@ -1 +1 @@ -

page-reset-password works!

+ diff --git a/src/app/pages/page-signup/page-signup.component.html b/src/app/pages/page-signup/page-signup.component.html index c186c4f..a81e94b 100644 --- a/src/app/pages/page-signup/page-signup.component.html +++ b/src/app/pages/page-signup/page-signup.component.html @@ -1 +1,109 @@ -

page-signup works!

+ + diff --git a/src/app/pages/page-signup/page-signup.component.scss b/src/app/pages/page-signup/page-signup.component.scss index e69de29..333e617 100644 --- a/src/app/pages/page-signup/page-signup.component.scss +++ b/src/app/pages/page-signup/page-signup.component.scss @@ -0,0 +1,32 @@ +.login-form { + height: 100vh; + padding-top: 40px; + background-color: #f5f5f5; +} + +.form-signup { + width: 100%; + max-width: 330px; + padding: 15px; + margin: auto; +} + +.form-signup .checkbox { + font-weight: 400; +} + +.form-signup .form-floating:focus-within { + z-index: 2; +} + +.form-signup input[type="email"] { + margin-bottom: -1px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.form-signup input[type="password"] { + margin-bottom: 10px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} diff --git a/src/app/pages/page-signup/page-signup.component.ts b/src/app/pages/page-signup/page-signup.component.ts index 28d1fc4..4a5243a 100644 --- a/src/app/pages/page-signup/page-signup.component.ts +++ b/src/app/pages/page-signup/page-signup.component.ts @@ -1,15 +1,105 @@ import { Component, OnInit } from '@angular/core'; +import { + FormBuilder, + FormControl, + FormGroup, + Validators, +} from '@angular/forms'; +import { Router } from '@angular/router'; +import { Membre } from '../../models/membre'; +import { AuthService } from '../../services/auth.service'; @Component({ selector: 'app-page-signup', templateUrl: './page-signup.component.html', - styleUrls: ['./page-signup.component.scss'] + styleUrls: ['./page-signup.component.scss'], }) export class PageSignupComponent implements OnInit { - - constructor() { } - - ngOnInit(): void { + public signupForm: FormGroup; + constructor( + private authService: AuthService, + private router: Router, + private fb: FormBuilder + ) { + this.signupForm = new FormGroup({}); } + ngOnInit(): void { + // *********************************pensser a changer group car déprécié******************************** + this.signupForm = this.fb.group( + { + firstNameFc: new FormControl('', [Validators.required]), + lastNameFc: new FormControl('', [Validators.required]), + dateNaissanceFc: new FormControl('', [Validators.required]), + teamNameFc: new FormControl('', [Validators.required]), + profilFc: new FormControl('', [Validators.required]), + emailFc: new FormControl('', [ + Validators.email, + Validators.required, + Validators.pattern(/^([\w\.\-_]+)?\w+@[\w-_]+(\.\w+){1,}/gim), + ]), // chercher une meilleure regex + passwordFc: new FormControl('', [ + Validators.minLength(8), + Validators.required, + ]), + passwordConfirmFc: new FormControl('', [ + Validators.minLength(8), + Validators.required, + ]), + }, + { + validator: this.ConfirmedValidator('passwordFc', 'passwordConfirmFc'), + } + ); + } + + public onSubmit(): void { + console.log('value : ', this.signupForm.value); + console.log('form : ', this.signupForm); + const firstNameValue = this.signupForm.value['firstNameFc']; + const lastNameValue = this.signupForm.value['lastNameFc']; + const emailValue = this.signupForm.value['emailFc']; + const passwordValue = this.signupForm.value['passwordFc']; + const dateNaissanceValue = this.signupForm.value['dateNaissanceFc']; + const teamNameValue = this.signupForm.value['teamNameFc']; + const profilValue = this.signupForm.value['profilFc']; + const passwordConfirmValue = this.signupForm.value['passwordConfirmFc']; + + const membre: Membre = { + firstName: firstNameValue, + lastName: lastNameValue, + email: emailValue, + password: passwordValue, + dateNaissance: dateNaissanceValue, + teamName: teamNameValue, + profil: profilValue, + passwordConfirm: passwordConfirmValue, + }; + + if (membre.email !== '' && membre.password !== '') { + this.authService.signup(membre).subscribe((resp) => { + this.router.navigate(['account/signin']); + }); + } else { + // affichage erreur + } + } + + ConfirmedValidator(controlName: string, matchingControlName: string) { + return (formGroup: FormGroup) => { + const control = formGroup.controls[controlName]; + const matchingControl = formGroup.controls[matchingControlName]; + if ( + matchingControl.errors && + !matchingControl.errors['confirmedValidator'] + ) { + return; + } + if (control.value !== matchingControl.value) { + matchingControl.setErrors({ confirmedValidator: true }); + } else { + matchingControl.setErrors(null); + } + }; + } } diff --git a/src/app/pages/page-to-do-list/page-to-do-list.component.html b/src/app/pages/page-to-do-list/page-to-do-list.component.html index 289a45d..2d3d7d1 100644 --- a/src/app/pages/page-to-do-list/page-to-do-list.component.html +++ b/src/app/pages/page-to-do-list/page-to-do-list.component.html @@ -1 +1,2 @@ -

page-to-do-list works!

+ + \ No newline at end of file diff --git a/src/app/pages/page-update-member/page-update-member.component.html b/src/app/pages/page-update-member/page-update-member.component.html index 2c55184..e91fa55 100644 --- a/src/app/pages/page-update-member/page-update-member.component.html +++ b/src/app/pages/page-update-member/page-update-member.component.html @@ -1 +1 @@ -

page-update-member works!

+ diff --git a/src/app/services/auth.service.spec.ts b/src/app/services/auth.service.spec.ts new file mode 100644 index 0000000..f1251ca --- /dev/null +++ b/src/app/services/auth.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AuthService } from './auth.service'; + +describe('AuthService', () => { + let service: AuthService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(AuthService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts new file mode 100644 index 0000000..918bfd9 --- /dev/null +++ b/src/app/services/auth.service.ts @@ -0,0 +1,58 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { map, Observable } from 'rxjs'; +import { environment } from 'src/environments/environment'; +import { Membre } from '../models/membre'; + +@Injectable({ + providedIn: 'root', +}) +export class AuthService { + private apiUrl: string; + private tokenKey: string; + + constructor(private http: HttpClient) { + // On se sert des variables d'environnement de notre application + this.apiUrl = environment.apiUrl; + this.tokenKey = environment.tokenKey; + } + + signup(membre: Membre): Observable { + console.log(membre); + + return this.http.post(`${this.apiUrl}/creation-compte`, membre); + } + + signin(email: string, password: string): Observable { + const body = { + email: email, + password: password, + }; + + console.log('Mon body : ', body); + + // Modifier cette partie ci-dessous : + // - pour pouvoir stocker dans le localstorage notre accesstoken + // - Sous la clé "TOKEN-LBP" + + return this.http.post(`${this.apiUrl}/login`, body).pipe( + map((x: any) => { + console.log('Service : ', x.accessToken); + // Modification à faire ici + localStorage.setItem(this.tokenKey, x.accessToken); + return x; // permet de renvoyer la réponse à l'initiateur (page Signin) après le traitement du map + }) + ); + } + + forgotPassword(email: string, password: string): Observable { + const body = { + email: email, + password: password, + }; + + console.log('Mon body : ', body); + + return this.http.post(`${this.apiUrl}/forgot-psw`, body); + } +} diff --git a/src/assets/images/logo-organizee.png b/src/assets/images/logo-organizee.png new file mode 100644 index 0000000..8ed4e37 Binary files /dev/null and b/src/assets/images/logo-organizee.png differ diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 3612073..4b349b1 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,3 +1,5 @@ export const environment = { - production: true + production: true, + apiUrl: '', + tokenKey: '', }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index f56ff47..ecf1531 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -3,7 +3,9 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - production: false + production: false, + apiUrl: 'http://localhost:3306', + tokenKey: 'TOKEN-ORGANIZEE', }; /*