From dad29ce7743e53d4fcb03c5d86e15b420b63d3db Mon Sep 17 00:00:00 2001 From: Hugo SUBTIL <ext.sopra.husubtil@grandlyon.com> Date: Fri, 11 Dec 2020 17:36:03 +0100 Subject: [PATCH] feat(profile): add profile module and component. --- src/app/app-routing.module.ts | 7 +++++ src/app/app.module.ts | 13 ++++++-- src/app/config/http-interceptor.ts | 34 +++++++++++++++++++++ src/app/guards/auth.guard.ts | 19 ++++++++++++ src/app/header/header.component.html | 7 +++-- src/app/map/map.module.ts | 3 +- src/app/models/user.model.ts | 2 +- src/app/profile/profile.component.html | 9 ++++++ src/app/profile/profile.component.scss | 0 src/app/profile/profile.component.spec.ts | 25 +++++++++++++++ src/app/profile/profile.component.ts | 20 ++++++++++++ src/app/profile/profile.module.ts | 12 ++++++++ src/app/profile/services/profile.service.ts | 15 +++++++++ 13 files changed, 160 insertions(+), 6 deletions(-) create mode 100644 src/app/config/http-interceptor.ts create mode 100644 src/app/guards/auth.guard.ts create mode 100644 src/app/profile/profile.component.html create mode 100644 src/app/profile/profile.component.scss create mode 100644 src/app/profile/profile.component.spec.ts create mode 100644 src/app/profile/profile.component.ts create mode 100644 src/app/profile/profile.module.ts create mode 100644 src/app/profile/services/profile.service.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index cc9f16a25..e7e52edb3 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,8 +1,10 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { AboutComponent } from './about/about.component'; +import { AuthGuard } from './guards/auth.guard'; import { HomeComponent } from './home/home.component'; import { LegalNoticeComponent } from './legal-notice/legal-notice.component'; +import { ProfileComponent } from './profile/profile.component'; import { StructureDetailsComponent } from './structure-list/components/structure-details/structure-details.component'; import { StructureListComponent } from './structure-list/structure-list.component'; import { UserVerificationComponent } from './user-verification/user-verification.component'; @@ -41,6 +43,11 @@ const routes: Routes = [ path: 'users/verify/:id', component: UserVerificationComponent, }, + { + path: 'profile', + canActivate: [AuthGuard], + component: ProfileComponent, + }, { path: '**', redirectTo: 'home', diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 02649bb09..c5162db74 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,5 +1,5 @@ import { LOCALE_ID, NgModule } from '@angular/core'; -import { HttpClientModule } from '@angular/common/http'; +import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { BrowserModule } from '@angular/platform-browser'; import { FlexLayoutModule } from '@angular/flex-layout'; @@ -23,6 +23,9 @@ import { LegalNoticeComponent } from './legal-notice/legal-notice.component'; import { AboutComponent } from './about/about.component'; import { MenuPhoneComponent } from './menu-phone/menu-phone.component'; import { UserVerificationComponent } from './user-verification/user-verification.component'; +import { AuthGuard } from './guards/auth.guard'; +import { CustomHttpInterceptor } from './config/http-interceptor'; +import { ProfileModule } from './profile/profile.module'; @NgModule({ declarations: [ @@ -50,8 +53,14 @@ import { UserVerificationComponent } from './user-verification/user-verification MapModule, FormsModule, ReactiveFormsModule, + ProfileModule, + ], + providers: [ + { provide: LOCALE_ID, useValue: 'fr' }, + { provide: HTTP_INTERCEPTORS, useClass: CustomHttpInterceptor, multi: true }, + CustomBreakPointsProvider, + AuthGuard, ], - providers: [{ provide: LOCALE_ID, useValue: 'fr' }, CustomBreakPointsProvider], bootstrap: [AppComponent], }) export class AppModule {} diff --git a/src/app/config/http-interceptor.ts b/src/app/config/http-interceptor.ts new file mode 100644 index 000000000..caa70fa29 --- /dev/null +++ b/src/app/config/http-interceptor.ts @@ -0,0 +1,34 @@ +import { Observable } from 'rxjs'; +import { Injectable } from '@angular/core'; +import { HttpInterceptor } from '@angular/common/http'; +import { HttpRequest } from '@angular/common/http'; +import { HttpHandler } from '@angular/common/http'; +import { HttpEvent } from '@angular/common/http'; +import { HttpHeaders } from '@angular/common/http'; +import { AuthService } from '../services/auth.service'; + +@Injectable() +export class CustomHttpInterceptor implements HttpInterceptor { + constructor(private authService: AuthService) {} + + intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { + const token = this.authService.token; + let changedRequest = request; + // HttpHeader object immutable - copy values + const headerSettings: { [name: string]: string | string[] } = {}; + + for (const key of request.headers.keys()) { + headerSettings[key] = request.headers.getAll(key); + } + if (token) { + headerSettings['Authorization'] = 'Bearer ' + token; + } + headerSettings['Content-Type'] = 'application/json'; + const newHeader = new HttpHeaders(headerSettings); + + changedRequest = request.clone({ + headers: newHeader, + }); + return next.handle(changedRequest); + } +} diff --git a/src/app/guards/auth.guard.ts b/src/app/guards/auth.guard.ts new file mode 100644 index 000000000..3d3205c2e --- /dev/null +++ b/src/app/guards/auth.guard.ts @@ -0,0 +1,19 @@ +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; +import { Injectable } from '@angular/core'; +import { AuthService } from '../services/auth.service'; +import { Observable } from 'rxjs'; + +/** + * Guard to assert that we are logged in. Otherwise redirect to home + */ +@Injectable() +export class AuthGuard implements CanActivate { + constructor(private authService: AuthService, private router: Router) {} + + canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): UrlTree | boolean { + if (this.authService.isLoggedIn()) { + return true; + } + return this.router.parseUrl('/home'); + } +} diff --git a/src/app/header/header.component.html b/src/app/header/header.component.html index f933d061e..863bf211b 100644 --- a/src/app/header/header.component.html +++ b/src/app/header/header.component.html @@ -14,12 +14,15 @@ <a routerLink="/projects" [routerLinkActive]="'active'" i18n>Projets</a> --> <a routerLink="/about" [routerLinkActive]="'active'" i18n>Qui sommes-nous ?</a> <!-- <a routerLink="/login" [routerLinkActive]="'active'" i18n><span class="clickable ico-mglass purple"></span></a> --> - <button *ngIf="!isLoggedIn" (click)="isPopUpOpen = !isPopUpOpen"> + <a *ngIf="!isLoggedIn" (click)="isPopUpOpen = !isPopUpOpen"> <span class="ico-profile" fxLayout="column" fxLayoutAlign="center center"> <span class="head"></span> <span class="body"></span> </span> - </button> + </a> + <a *ngIf="isLoggedIn" routerLink="/profile" [routerLinkActive]="'active'" fxLayout="row" fxLayoutGap="1.5vh"> + <app-svg-icon [type]="'ico'" [iconClass]="'icon-32'" [icon]="'user'" [iconColor]="'currentColor'"></app-svg-icon> + </a> <button *ngIf="isLoggedIn" (click)="logout()">Logout</button> </div> </div> diff --git a/src/app/map/map.module.ts b/src/app/map/map.module.ts index 3487eb49d..521ecc678 100644 --- a/src/app/map/map.module.ts +++ b/src/app/map/map.module.ts @@ -4,8 +4,9 @@ import { SharedModule } from '../shared/shared.module'; import { MapComponents } from './components'; import { LeafletModule } from '@asymmetrik/ngx-leaflet'; import { NgxLeafletLocateModule } from '@runette/ngx-leaflet-locate'; +import { BrowserModule } from '@angular/platform-browser'; @NgModule({ - imports: [CommonModule, SharedModule, NgxLeafletLocateModule, LeafletModule], + imports: [CommonModule, BrowserModule, SharedModule, NgxLeafletLocateModule, LeafletModule], declarations: [MapComponents], providers: [DatePipe], exports: [MapComponents], diff --git a/src/app/models/user.model.ts b/src/app/models/user.model.ts index 3269aeea7..aa2391853 100644 --- a/src/app/models/user.model.ts +++ b/src/app/models/user.model.ts @@ -1,7 +1,7 @@ export class User { _id: string; email: string; - password: string; + password?: string; emailVerified: boolean; role: number; validationToken: string; diff --git a/src/app/profile/profile.component.html b/src/app/profile/profile.component.html new file mode 100644 index 000000000..ac9939990 --- /dev/null +++ b/src/app/profile/profile.component.html @@ -0,0 +1,9 @@ +<div fxLayout="column" class="content-container"> + <div class="section-container" fxLayout="colum" fxLayoutAlign="center center"> + <h1>Profil</h1> + <div *ngIf="userProfile" fxLayout="column" fxLayoutAlign="center" fxLayoutGap="10px"> + <p>Id: {{ userProfile._id }}</p> + <p>Email: {{ userProfile.email }}</p> + </div> + </div> +</div> diff --git a/src/app/profile/profile.component.scss b/src/app/profile/profile.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/profile/profile.component.spec.ts b/src/app/profile/profile.component.spec.ts new file mode 100644 index 000000000..e88012e7a --- /dev/null +++ b/src/app/profile/profile.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProfileComponent } from './profile.component'; + +describe('ProfileComponent', () => { + let component: ProfileComponent; + let fixture: ComponentFixture<ProfileComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ProfileComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ProfileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/profile/profile.component.ts b/src/app/profile/profile.component.ts new file mode 100644 index 000000000..04a353c04 --- /dev/null +++ b/src/app/profile/profile.component.ts @@ -0,0 +1,20 @@ +import { Component, OnInit } from '@angular/core'; +import { User } from '../models/user.model'; +import { ProfileService } from './services/profile.service'; + +@Component({ + selector: 'app-profile', + templateUrl: './profile.component.html', + styleUrls: ['./profile.component.scss'], +}) +export class ProfileComponent implements OnInit { + public userProfile: User; + + constructor(private profileService: ProfileService) {} + + ngOnInit(): void { + this.profileService.getProfile().subscribe((profile) => { + this.userProfile = profile; + }); + } +} diff --git a/src/app/profile/profile.module.ts b/src/app/profile/profile.module.ts new file mode 100644 index 000000000..a9427003f --- /dev/null +++ b/src/app/profile/profile.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { ProfileComponent } from './profile.component'; +import { SharedModule } from '../shared/shared.module'; +import { CommonModule } from '@angular/common'; +import { BrowserModule } from '@angular/platform-browser'; + +@NgModule({ + imports: [CommonModule, BrowserModule, SharedModule], + declarations: [ProfileComponent], + exports: [ProfileComponent], +}) +export class ProfileModule {} diff --git a/src/app/profile/services/profile.service.ts b/src/app/profile/services/profile.service.ts new file mode 100644 index 000000000..5e43c8784 --- /dev/null +++ b/src/app/profile/services/profile.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { User } from '../../models/user.model'; + +@Injectable({ + providedIn: 'root', +}) +export class ProfileService { + constructor(private http: HttpClient) {} + + public getProfile(): Observable<User> { + return this.http.get<User>('api/users/profile'); + } +} -- GitLab