From fc1c96552d4ceaade7e78385f439540bae1a83b3 Mon Sep 17 00:00:00 2001 From: ThomasFransolet Date: Sun, 14 Jul 2019 02:41:31 +0200 Subject: [PATCH] CP #0 JWT Interceptor + HttpError (WIP?) + New generated model (Swagger) + Navigation small changes --- ng-swagger-gen.json | 2 +- src/app/{api => _api}/api-configuration.ts | 0 src/app/{api => _api}/api.module.ts | 2 + src/app/{api => _api}/base-service.ts | 0 src/app/{api => _api}/models.ts | 1 + .../models/azure-adauth-model.ts | 0 src/app/{api => _api}/models/book.ts | 0 .../models/facebook-auth-model.ts | 0 .../{api => _api}/models/google-auth-model.ts | 0 .../models/smart-garden-message.ts | 0 .../models/smart-printer-message.ts | 0 .../models/twitter-auth-model.ts | 0 src/app/_api/models/user-info.ts | 11 +++ src/app/{api => _api}/models/user.ts | 0 src/app/{api => _api}/services.ts | 1 + .../{api => _api}/services/azure.service.ts | 0 .../{api => _api}/services/books.service.ts | 0 .../services/facebook.service.ts | 0 .../{api => _api}/services/google.service.ts | 0 src/app/{api => _api}/services/iot.service.ts | 0 .../{api => _api}/services/mqtt.service.ts | 0 .../{api => _api}/services/token.service.ts | 0 .../{api => _api}/services/twitter.service.ts | 0 src/app/_api/services/user.service.ts | 98 +++++++++++++++++++ .../{api => _api}/services/values.service.ts | 0 src/app/{api => _api}/strict-http-response.ts | 0 .../border-card.directive.spec.ts | 2 +- .../_directives}/border-card.directive.ts | 0 .../{utils => _helpers}/auth.guard.spec.ts | 0 src/app/{utils => _helpers}/auth.guard.ts | 4 +- src/app/_helpers/error.interceptor.ts | 24 +++++ src/app/_helpers/jwt.interceptor.ts | 24 +++++ src/app/{ => _services}/app.service.ts | 8 +- src/app/_services/authentication.service.ts | 56 +++++++++++ src/app/app-routing.module.ts | 2 +- src/app/app.component.html | 2 +- src/app/app.component.ts | 55 +++++++++-- src/app/app.module.ts | 16 +-- .../profile/profile/profile.component.ts | 18 +++- src/app/utils/auth.service.ts | 27 ----- src/environments/environment.prod.ts | 3 +- swagger.json | 2 +- 42 files changed, 304 insertions(+), 54 deletions(-) rename src/app/{api => _api}/api-configuration.ts (100%) rename src/app/{api => _api}/api.module.ts (95%) rename src/app/{api => _api}/base-service.ts (100%) rename src/app/{api => _api}/models.ts (90%) rename src/app/{api => _api}/models/azure-adauth-model.ts (100%) rename src/app/{api => _api}/models/book.ts (100%) rename src/app/{api => _api}/models/facebook-auth-model.ts (100%) rename src/app/{api => _api}/models/google-auth-model.ts (100%) rename src/app/{api => _api}/models/smart-garden-message.ts (100%) rename src/app/{api => _api}/models/smart-printer-message.ts (100%) rename src/app/{api => _api}/models/twitter-auth-model.ts (100%) create mode 100644 src/app/_api/models/user-info.ts rename src/app/{api => _api}/models/user.ts (100%) rename src/app/{api => _api}/services.ts (90%) rename src/app/{api => _api}/services/azure.service.ts (100%) rename src/app/{api => _api}/services/books.service.ts (100%) rename src/app/{api => _api}/services/facebook.service.ts (100%) rename src/app/{api => _api}/services/google.service.ts (100%) rename src/app/{api => _api}/services/iot.service.ts (100%) rename src/app/{api => _api}/services/mqtt.service.ts (100%) rename src/app/{api => _api}/services/token.service.ts (100%) rename src/app/{api => _api}/services/twitter.service.ts (100%) create mode 100644 src/app/_api/services/user.service.ts rename src/app/{api => _api}/services/values.service.ts (100%) rename src/app/{api => _api}/strict-http-response.ts (100%) rename src/app/{directives => _helpers/_directives}/border-card.directive.spec.ts (73%) rename src/app/{directives => _helpers/_directives}/border-card.directive.ts (100%) rename src/app/{utils => _helpers}/auth.guard.spec.ts (100%) rename src/app/{utils => _helpers}/auth.guard.ts (77%) create mode 100644 src/app/_helpers/error.interceptor.ts create mode 100644 src/app/_helpers/jwt.interceptor.ts rename src/app/{ => _services}/app.service.ts (50%) create mode 100644 src/app/_services/authentication.service.ts delete mode 100644 src/app/utils/auth.service.ts diff --git a/ng-swagger-gen.json b/ng-swagger-gen.json index 9e608c3..1cf511a 100644 --- a/ng-swagger-gen.json +++ b/ng-swagger-gen.json @@ -1,7 +1,7 @@ { "$schema": "./node_modules/ng-swagger-gen/ng-swagger-gen-schema.json", "swagger": "swagger.json", - "output": "src/app/api", + "output": "src/app/_api", "prefix": "Api", "ignoreUnusedModels": true, "minParamsForContainer": 2, diff --git a/src/app/api/api-configuration.ts b/src/app/_api/api-configuration.ts similarity index 100% rename from src/app/api/api-configuration.ts rename to src/app/_api/api-configuration.ts diff --git a/src/app/api/api.module.ts b/src/app/_api/api.module.ts similarity index 95% rename from src/app/api/api.module.ts rename to src/app/_api/api.module.ts index a1411d4..f39c1ce 100644 --- a/src/app/api/api.module.ts +++ b/src/app/_api/api.module.ts @@ -11,6 +11,7 @@ import { IOTService } from './services/iot.service'; import { MQTTService } from './services/mqtt.service'; import { TokenService } from './services/token.service'; import { TwitterService } from './services/twitter.service'; +import { UserService } from './services/user.service'; import { ValuesService } from './services/values.service'; /** @@ -34,6 +35,7 @@ import { ValuesService } from './services/values.service'; MQTTService, TokenService, TwitterService, + UserService, ValuesService ], }) diff --git a/src/app/api/base-service.ts b/src/app/_api/base-service.ts similarity index 100% rename from src/app/api/base-service.ts rename to src/app/_api/base-service.ts diff --git a/src/app/api/models.ts b/src/app/_api/models.ts similarity index 90% rename from src/app/api/models.ts rename to src/app/_api/models.ts index 99c4ab5..b8743ec 100644 --- a/src/app/api/models.ts +++ b/src/app/_api/models.ts @@ -6,3 +6,4 @@ export { SmartPrinterMessage } from './models/smart-printer-message'; export { SmartGardenMessage } from './models/smart-garden-message'; export { User } from './models/user'; export { TwitterAuthModel } from './models/twitter-auth-model'; +export { UserInfo } from './models/user-info'; diff --git a/src/app/api/models/azure-adauth-model.ts b/src/app/_api/models/azure-adauth-model.ts similarity index 100% rename from src/app/api/models/azure-adauth-model.ts rename to src/app/_api/models/azure-adauth-model.ts diff --git a/src/app/api/models/book.ts b/src/app/_api/models/book.ts similarity index 100% rename from src/app/api/models/book.ts rename to src/app/_api/models/book.ts diff --git a/src/app/api/models/facebook-auth-model.ts b/src/app/_api/models/facebook-auth-model.ts similarity index 100% rename from src/app/api/models/facebook-auth-model.ts rename to src/app/_api/models/facebook-auth-model.ts diff --git a/src/app/api/models/google-auth-model.ts b/src/app/_api/models/google-auth-model.ts similarity index 100% rename from src/app/api/models/google-auth-model.ts rename to src/app/_api/models/google-auth-model.ts diff --git a/src/app/api/models/smart-garden-message.ts b/src/app/_api/models/smart-garden-message.ts similarity index 100% rename from src/app/api/models/smart-garden-message.ts rename to src/app/_api/models/smart-garden-message.ts diff --git a/src/app/api/models/smart-printer-message.ts b/src/app/_api/models/smart-printer-message.ts similarity index 100% rename from src/app/api/models/smart-printer-message.ts rename to src/app/_api/models/smart-printer-message.ts diff --git a/src/app/api/models/twitter-auth-model.ts b/src/app/_api/models/twitter-auth-model.ts similarity index 100% rename from src/app/api/models/twitter-auth-model.ts rename to src/app/_api/models/twitter-auth-model.ts diff --git a/src/app/_api/models/user-info.ts b/src/app/_api/models/user-info.ts new file mode 100644 index 0000000..189050d --- /dev/null +++ b/src/app/_api/models/user-info.ts @@ -0,0 +1,11 @@ +/* tslint:disable */ +export interface UserInfo { + id?: string; + role?: string; + username?: string; + password?: string; + firstName?: string; + lastName?: string; + token?: string; + birthday?: string; +} diff --git a/src/app/api/models/user.ts b/src/app/_api/models/user.ts similarity index 100% rename from src/app/api/models/user.ts rename to src/app/_api/models/user.ts diff --git a/src/app/api/services.ts b/src/app/_api/services.ts similarity index 90% rename from src/app/api/services.ts rename to src/app/_api/services.ts index 94a6431..e2aa904 100644 --- a/src/app/api/services.ts +++ b/src/app/_api/services.ts @@ -6,4 +6,5 @@ export { IOTService } from './services/iot.service'; export { MQTTService } from './services/mqtt.service'; export { TokenService } from './services/token.service'; export { TwitterService } from './services/twitter.service'; +export { UserService } from './services/user.service'; export { ValuesService } from './services/values.service'; diff --git a/src/app/api/services/azure.service.ts b/src/app/_api/services/azure.service.ts similarity index 100% rename from src/app/api/services/azure.service.ts rename to src/app/_api/services/azure.service.ts diff --git a/src/app/api/services/books.service.ts b/src/app/_api/services/books.service.ts similarity index 100% rename from src/app/api/services/books.service.ts rename to src/app/_api/services/books.service.ts diff --git a/src/app/api/services/facebook.service.ts b/src/app/_api/services/facebook.service.ts similarity index 100% rename from src/app/api/services/facebook.service.ts rename to src/app/_api/services/facebook.service.ts diff --git a/src/app/api/services/google.service.ts b/src/app/_api/services/google.service.ts similarity index 100% rename from src/app/api/services/google.service.ts rename to src/app/_api/services/google.service.ts diff --git a/src/app/api/services/iot.service.ts b/src/app/_api/services/iot.service.ts similarity index 100% rename from src/app/api/services/iot.service.ts rename to src/app/_api/services/iot.service.ts diff --git a/src/app/api/services/mqtt.service.ts b/src/app/_api/services/mqtt.service.ts similarity index 100% rename from src/app/api/services/mqtt.service.ts rename to src/app/_api/services/mqtt.service.ts diff --git a/src/app/api/services/token.service.ts b/src/app/_api/services/token.service.ts similarity index 100% rename from src/app/api/services/token.service.ts rename to src/app/_api/services/token.service.ts diff --git a/src/app/api/services/twitter.service.ts b/src/app/_api/services/twitter.service.ts similarity index 100% rename from src/app/api/services/twitter.service.ts rename to src/app/_api/services/twitter.service.ts diff --git a/src/app/_api/services/user.service.ts b/src/app/_api/services/user.service.ts new file mode 100644 index 0000000..df316d8 --- /dev/null +++ b/src/app/_api/services/user.service.ts @@ -0,0 +1,98 @@ +/* tslint:disable */ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpRequest, HttpResponse, HttpHeaders } from '@angular/common/http'; +import { BaseService as __BaseService } from '../base-service'; +import { ApiConfiguration as __Configuration } from '../api-configuration'; +import { StrictHttpResponse as __StrictHttpResponse } from '../strict-http-response'; +import { Observable as __Observable } from 'rxjs'; +import { map as __map, filter as __filter } from 'rxjs/operators'; + +import { UserInfo } from '../models/user-info'; +@Injectable({ + providedIn: 'root', +}) +class UserService extends __BaseService { + static readonly GetPath = '/api/user'; + static readonly Get_1Path = '/api/user/{id}'; + + constructor( + config: __Configuration, + http: HttpClient + ) { + super(config, http); + } + + /** + * @return Success + */ + GetResponse(): __Observable<__StrictHttpResponse>> { + let __params = this.newParams(); + let __headers = new HttpHeaders(); + let __body: any = null; + let req = new HttpRequest( + 'GET', + this.rootUrl + `/api/user`, + __body, + { + headers: __headers, + params: __params, + responseType: 'json' + }); + + return this.http.request(req).pipe( + __filter(_r => _r instanceof HttpResponse), + __map((_r) => { + return _r as __StrictHttpResponse>; + }) + ); + } + /** + * @return Success + */ + Get(): __Observable> { + return this.GetResponse().pipe( + __map(_r => _r.body as Array) + ); + } + + /** + * @param id id user + * @return Success + */ + Get_1Response(id: string): __Observable<__StrictHttpResponse> { + let __params = this.newParams(); + let __headers = new HttpHeaders(); + let __body: any = null; + + let req = new HttpRequest( + 'GET', + this.rootUrl + `/api/user/${id}`, + __body, + { + headers: __headers, + params: __params, + responseType: 'json' + }); + + return this.http.request(req).pipe( + __filter(_r => _r instanceof HttpResponse), + __map((_r) => { + return _r as __StrictHttpResponse; + }) + ); + } + /** + * @param id id user + * @return Success + */ + Get_1(id: string): __Observable { + return this.Get_1Response(id).pipe( + __map(_r => _r.body as UserInfo) + ); + } +} + +module UserService { +} + +export { UserService } diff --git a/src/app/api/services/values.service.ts b/src/app/_api/services/values.service.ts similarity index 100% rename from src/app/api/services/values.service.ts rename to src/app/_api/services/values.service.ts diff --git a/src/app/api/strict-http-response.ts b/src/app/_api/strict-http-response.ts similarity index 100% rename from src/app/api/strict-http-response.ts rename to src/app/_api/strict-http-response.ts diff --git a/src/app/directives/border-card.directive.spec.ts b/src/app/_helpers/_directives/border-card.directive.spec.ts similarity index 73% rename from src/app/directives/border-card.directive.spec.ts rename to src/app/_helpers/_directives/border-card.directive.spec.ts index 1aafd98..afa3007 100644 --- a/src/app/directives/border-card.directive.spec.ts +++ b/src/app/_helpers/_directives/border-card.directive.spec.ts @@ -1,4 +1,4 @@ -import { BorderCardDirective } from '../border-card.directive'; +import { BorderCardDirective } from './border-card.directive'; describe('BorderCardDirective', () => { it('should create an instance', () => { diff --git a/src/app/directives/border-card.directive.ts b/src/app/_helpers/_directives/border-card.directive.ts similarity index 100% rename from src/app/directives/border-card.directive.ts rename to src/app/_helpers/_directives/border-card.directive.ts diff --git a/src/app/utils/auth.guard.spec.ts b/src/app/_helpers/auth.guard.spec.ts similarity index 100% rename from src/app/utils/auth.guard.spec.ts rename to src/app/_helpers/auth.guard.spec.ts diff --git a/src/app/utils/auth.guard.ts b/src/app/_helpers/auth.guard.ts similarity index 77% rename from src/app/utils/auth.guard.ts rename to src/app/_helpers/auth.guard.ts index 403d4d4..6d284ef 100644 --- a/src/app/utils/auth.guard.ts +++ b/src/app/_helpers/auth.guard.ts @@ -2,14 +2,14 @@ import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; -import { AuthService } from './auth.service'; +import { AuthenticationService } from '../_services/authentication.service'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { - constructor(private _authService: AuthService, private router: Router){} + constructor(private _authService: AuthenticationService, private router: Router){} canActivate( next: ActivatedRouteSnapshot, diff --git a/src/app/_helpers/error.interceptor.ts b/src/app/_helpers/error.interceptor.ts new file mode 100644 index 0000000..8ba1034 --- /dev/null +++ b/src/app/_helpers/error.interceptor.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@angular/core'; +import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; +import { Observable, throwError } from 'rxjs'; +import { catchError } from 'rxjs/operators'; + +import { AuthenticationService } from '../_services/authentication.service'; + +@Injectable() +export class ErrorInterceptor implements HttpInterceptor { + constructor(private _authService: AuthenticationService) { } + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + return next.handle(request).pipe(catchError(err => { + if (err.status === 401) { + // auto logout if 401 response returned from api + this._authService.Logout(); + location.reload(true); + } + + const error = err.error.message || err.statusText; + return throwError(error); + })) + } +} \ No newline at end of file diff --git a/src/app/_helpers/jwt.interceptor.ts b/src/app/_helpers/jwt.interceptor.ts new file mode 100644 index 0000000..e425579 --- /dev/null +++ b/src/app/_helpers/jwt.interceptor.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@angular/core'; +import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { AuthenticationService } from '../_services/authentication.service'; + +@Injectable() +export class JwtInterceptor implements HttpInterceptor { + constructor(private _authService: AuthenticationService) { } + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + // add authorization header with jwt token if available + let currentUser = this._authService.currentUserValue; + if (currentUser && currentUser.token) { + request = request.clone({ + setHeaders: { + Authorization: 'Bearer ' + currentUser.token + } + }); + } + + return next.handle(request); + } +} \ No newline at end of file diff --git a/src/app/app.service.ts b/src/app/_services/app.service.ts similarity index 50% rename from src/app/app.service.ts rename to src/app/_services/app.service.ts index 9d5c714..ae5aab1 100644 --- a/src/app/app.service.ts +++ b/src/app/_services/app.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; -import { TokenService } from './api/services/token.service'; +import { BooksService } from '../_api/services/books.service'; @Injectable({ @@ -11,11 +11,11 @@ import { TokenService } from './api/services/token.service'; export class AppService { constructor( protected http: HttpClient, - private _tokenService: TokenService + private _bookService: BooksService ) { } - public GetToken(username: string, password: string): Observable { - return this._tokenService.Create({username: username, password: password}); + public ConnectionTest(): Observable { + return this._bookService.Get(); } } diff --git a/src/app/_services/authentication.service.ts b/src/app/_services/authentication.service.ts new file mode 100644 index 0000000..0f90ecc --- /dev/null +++ b/src/app/_services/authentication.service.ts @@ -0,0 +1,56 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable, BehaviorSubject } from 'rxjs'; +import { TokenService } from '../_api/services/token.service'; +import { UserInfo } from '../_api/models/user-info'; +import { map } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) + +export class AuthenticationService { + + private currentUserSubject: BehaviorSubject; + public currentUser: Observable; + + public IsLoggedIn = false; + + constructor( + protected http: HttpClient, + private _tokenService: TokenService + ) { + this.currentUserSubject = new BehaviorSubject(JSON.parse(localStorage.getItem('currentUser'))); + this.currentUser = this.currentUserSubject.asObservable(); + } + + public GetToken(username: string, password: string): Observable { + return this._tokenService.Create({username: username, password: password}); + } + + public GetAuthStatus() { + return this.IsLoggedIn; + } + + public Login(username: string, password: string) { + return this._tokenService.Create({username: username, password: password}) + .pipe(map(user => { + // store user details and jwt token in local storage to keep user logged in between page refreshes + localStorage.setItem('currentUser', JSON.stringify(user)); + this.currentUserSubject.next(user); + console.log('This is USER = ',user) + return user; + })); + } + + public Logout() { + localStorage.removeItem('currentUser'); + this.currentUserSubject.next(null); + this.IsLoggedIn = false; + } + + public get currentUserValue(): UserInfo { + return this.currentUserSubject.value; + } + +} diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 707e46a..ae77cca 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './control-panel/home/home.component'; import { ConfigComponent } from './control-panel/profile/config/config.component'; -import { AuthGuard } from './utils/auth.guard'; +import { AuthGuard } from './_helpers/auth.guard'; import { NotFoundComponent } from './control-panel/not-found/not-found.component'; import { ProfileComponent } from './control-panel/profile/profile/profile.component'; import { EditProfileComponent } from './control-panel/profile/edit-profile/edit-profile.component'; diff --git a/src/app/app.component.html b/src/app/app.component.html index 39d6c8e..0f465a4 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -6,7 +6,7 @@
- + diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 6ee99ce..dffc625 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,9 +1,10 @@ import { Component, OnInit } from '@angular/core'; import { MenuItem } from 'primeng/api'; -import { AppService } from './app.service'; +import { AppService } from './_services/app.service'; import { TranslateService } from '@ngx-translate/core'; -import { AuthService } from './utils/auth.service'; +import { AuthenticationService } from './_services/authentication.service'; import { Router } from '@angular/router'; +import { first } from 'rxjs/operators'; @Component({ @@ -30,7 +31,7 @@ export class AppComponent implements OnInit{ constructor( private _appService: AppService, private _translateService: TranslateService, - private _authService: AuthService, + private _authService: AuthenticationService, private _router: Router ){} @@ -38,15 +39,28 @@ export class AppComponent implements OnInit{ this.items = [ {label: 'Update', icon: 'pi pi-refresh'}, {label: 'Delete', icon: 'pi pi-times'} - ]; - // To Include in a fonction of a dropdown language chose - this._translateService.setDefaultLang('fr'); + ]; + // To Include in a fonction of a dropdown language chose + this._translateService.setDefaultLang('fr'); + + let currentUser = this._authService.currentUserValue; + console.log(currentUser); + + if (currentUser && currentUser.token) { + this.Connected = true; + this.DisplayLoginModal = false; + this.Username = null; + this.Password = null; + this._authService.IsLoggedIn = true; + } + + } public LogIn() { - this._appService.GetToken(this.Username, this.Password) + /*this._appService.GetToken(this.Username, this.Password) .subscribe(res => { console.log(res.Token); this.Connected = true; @@ -58,10 +72,35 @@ export class AppComponent implements OnInit{ this._router.navigate(['/profile/01']); }, () => { console.log('ERROR'); - }); + });*/ + + this._authService.Login(this.Username, this.Password) + .pipe(first()) + .subscribe( + data => { + console.log(data); + this.Connected = true; + this.DisplayLoginModal = false; + this.Username = null; + this.Password = null; + this._authService.IsLoggedIn = true; + this._router.navigate(['/profile/01']); + }, + error => { + console.log('ERROR'); + }); // change route -> /config view } + + public Logout() { + this._authService.Logout(); + this.Connected = false; + this.Username = null; + this.Password = null; + this._authService.IsLoggedIn = false; + this._router.navigate(['/home']); + } public SignUp() { this.DisplaySignInModal = true; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 5314c62..131a0d4 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -5,30 +5,32 @@ import { NgModule, Provider, APP_INITIALIZER } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { HomeComponent } from './control-panel/home/home.component'; -import { HttpClientModule, HttpClient } from '@angular/common/http'; +import { HttpClientModule, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http'; import { AlertModule } from 'ngx-bootstrap/alert'; import { BsDatepickerModule } from 'ngx-bootstrap/datepicker'; import { BsDropdownModule } from 'ngx-bootstrap/dropdown'; import { CarouselModule } from 'ngx-bootstrap/carousel'; -import { BorderCardDirective } from './directives/border-card.directive'; +import { BorderCardDirective } from './_helpers/_directives/border-card.directive'; import { ToolbarModule } from 'primeng/toolbar'; import { ButtonModule } from 'primeng/button'; import { SplitButtonModule } from 'primeng/splitbutton'; import { DialogModule } from 'primeng/dialog'; import { InputTextModule } from 'primeng/inputtext'; -import { ApiConfiguration } from './api/api-configuration'; -import { AppService } from './app.service'; +import { ApiConfiguration } from './_api/api-configuration'; +import { AppService } from './_services/app.service'; import { FormsModule } from '@angular/forms'; import { CalendarModule } from 'primeng/calendar'; import {TranslateModule, TranslateLoader} from '@ngx-translate/core'; import {TranslateHttpLoader} from '@ngx-translate/http-loader'; -import { AuthService } from './utils/auth.service'; +import { AuthenticationService } from './_services/authentication.service'; import { ConfigComponent } from './control-panel/profile/config/config.component'; import { NotFoundComponent } from './control-panel/not-found/not-found.component'; import { ProfileComponent } from './control-panel/profile/profile/profile.component'; import { EditProfileComponent } from './control-panel/profile/edit-profile/edit-profile.component'; +import { JwtInterceptor } from './_helpers/jwt.interceptor'; +import { ErrorInterceptor } from './_helpers/error.interceptor'; @@ -89,7 +91,9 @@ export function HttpLoaderFactory(http: HttpClient) { providers: [ INIT_API_CONFIGURATION, AppService, - AuthService + AuthenticationService, + { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true }, + { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }, ], bootstrap: [AppComponent] }) diff --git a/src/app/control-panel/profile/profile/profile.component.ts b/src/app/control-panel/profile/profile/profile.component.ts index a747936..a6eceb3 100644 --- a/src/app/control-panel/profile/profile/profile.component.ts +++ b/src/app/control-panel/profile/profile/profile.component.ts @@ -1,4 +1,8 @@ import { Component, OnInit } from '@angular/core'; +import { AppService } from '../../../_services/app.service'; +import { TranslateService } from '@ngx-translate/core'; +import { AuthenticationService } from '../../../_services/authentication.service'; +import { Router } from '@angular/router'; @Component({ selector: 'app-profile', @@ -7,9 +11,21 @@ import { Component, OnInit } from '@angular/core'; }) export class ProfileComponent implements OnInit { - constructor() { } + constructor( + private _appService: AppService, + private _translateService: TranslateService, + private _router: Router + ) { } ngOnInit() { + this._appService.ConnectionTest().subscribe( + res => { + console.log(res); + console.log('SUCCESS !!'); + }, () => { + console.log('error in test'); + } + ); } } diff --git a/src/app/utils/auth.service.ts b/src/app/utils/auth.service.ts deleted file mode 100644 index d4cf31b..0000000 --- a/src/app/utils/auth.service.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; -import { Observable } from 'rxjs'; -import { TokenService } from '../api/services/token.service'; - -@Injectable({ - providedIn: 'root' -}) - -export class AuthService { - - public IsLoggedIn = false; - - constructor( - protected http: HttpClient, - private _tokenService: TokenService - ) { } - - public GetToken(username: string, password: string): Observable { - return this._tokenService.Create({username: username, password: password}); - } - - public GetAuthStatus() { - return this.IsLoggedIn; - } - -} diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 3612073..1cd6bc1 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,3 +1,4 @@ export const environment = { - production: true + production: false, + apiUrl: 'https://localhost:5001' }; diff --git a/swagger.json b/swagger.json index 2bfdff3..abe177a 100644 --- a/swagger.json +++ b/swagger.json @@ -1 +1 @@ -{"swagger":"2.0","info":{"version":"v1","title":"MyCoreApi"},"paths":{"/azure":{"post":{"tags":["Azure"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["application/json"],"parameters":[{"name":"user","in":"body","required":false,"schema":{"$ref":"#/definitions/AzureADAuthModel"}}],"responses":{"200":{"description":"Success"}}}},"/api/books":{"get":{"tags":["Books"],"operationId":"Get","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[],"responses":{"200":{"description":"Success","schema":{"uniqueItems":false,"type":"array","items":{"$ref":"#/definitions/Book"}}}}},"post":{"tags":["Books"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["text/plain","application/json","text/json"],"parameters":[{"name":"book","in":"body","required":false,"schema":{"$ref":"#/definitions/Book"}}],"responses":{"200":{"description":"Success","schema":{"$ref":"#/definitions/Book"}}}}},"/api/books/{id}":{"get":{"tags":["Books"],"operationId":"GetBook","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[{"name":"id","in":"path","required":true,"type":"string"}],"responses":{"200":{"description":"Success","schema":{"$ref":"#/definitions/Book"}}}},"put":{"tags":["Books"],"operationId":"Update","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":[],"parameters":[{"name":"id","in":"path","required":true,"type":"string"},{"name":"bookIn","in":"body","required":false,"schema":{"$ref":"#/definitions/Book"}}],"responses":{"200":{"description":"Success"}}},"delete":{"tags":["Books"],"operationId":"Delete","consumes":[],"produces":[],"parameters":[{"name":"id","in":"path","required":true,"type":"string"}],"responses":{"200":{"description":"Success"}}}},"/facebook":{"post":{"tags":["Facebook"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["application/json"],"parameters":[{"name":"user","in":"body","required":false,"schema":{"$ref":"#/definitions/FacebookAuthModel"}}],"responses":{"200":{"description":"Success"}}}},"/google":{"post":{"tags":["Google"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["application/json"],"parameters":[{"name":"user","in":"body","required":false,"schema":{"$ref":"#/definitions/GoogleAuthModel"}}],"responses":{"200":{"description":"Success"}}}},"/api/iot/smartprinter/{idDevice}":{"get":{"tags":["IOT"],"summary":"Retrieve all SmartPrinterMessage","operationId":"GetSmartPrinterMessages","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[{"name":"id","in":"query","description":"Id of the smart printer message","required":false,"type":"integer","format":"int32"},{"name":"idDevice","in":"path","required":true,"type":"string"}],"responses":{"200":{"description":"Success","schema":{"uniqueItems":false,"type":"array","items":{"$ref":"#/definitions/SmartPrinterMessage"}}}}},"post":{"tags":["IOT"],"summary":"It's the method to post data from mqtt broker to Database (Thanks Rpi!)","operationId":"PostToDBPrinter","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":[],"parameters":[{"name":"idDevice","in":"path","description":"Id of the device to upload to DB","required":true,"type":"integer","format":"int32"},{"name":"content","in":"body","description":"Content that will be uploaded","required":false,"schema":{"uniqueItems":false,"type":"array","items":{"$ref":"#/definitions/SmartPrinterMessage"}}}],"responses":{"200":{"description":"Success"},"201":{"description":"Content successfully posted to DB"},"500":{"description":"Unexpected error"}}}},"/api/iot/smartgarden/{idDevice}":{"post":{"tags":["IOT"],"summary":"It's the method to post data from mqtt broker to Database (Thanks Rpi!)","operationId":"PostToDBSmartGarden","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":[],"parameters":[{"name":"idDevice","in":"path","required":true,"type":"integer","format":"int32"},{"name":"content","in":"body","required":false,"schema":{"uniqueItems":false,"type":"array","items":{"$ref":"#/definitions/SmartGardenMessage"}}}],"responses":{"200":{"description":"Success"}}}},"/api/mqtt":{"get":{"tags":["MQTT"],"summary":"It's a mqtt publish test ! :)","operationId":"GetToPublishMqtt","consumes":[],"produces":[],"parameters":[],"responses":{"200":{"description":"Success"}}}},"/api/token":{"post":{"tags":["Token"],"operationId":"Create","consumes":[],"produces":[],"parameters":[{"name":"username","in":"query","required":false,"type":"string"},{"name":"password","in":"query","required":false,"type":"string"}],"responses":{"200":{"description":"Success"}}}},"/token":{"post":{"tags":["Token"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["application/json"],"parameters":[{"name":"user","in":"body","required":false,"schema":{"$ref":"#/definitions/User"}}],"responses":{"200":{"description":"Success"}}}},"/twitter":{"post":{"tags":["Twitter"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["application/json"],"parameters":[{"name":"user","in":"body","required":false,"schema":{"$ref":"#/definitions/TwitterAuthModel"}}],"responses":{"200":{"description":"Success"}}}},"/api/test":{"get":{"tags":["Values"],"summary":"It's a test ! :)","operationId":"Get","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[],"responses":{"200":{"description":"Success","schema":{"uniqueItems":false,"type":"array","items":{"type":"string"}}}}},"post":{"tags":["Values"],"operationId":"Post","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":[],"parameters":[{"name":"value","in":"body","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"}}}},"/api/test/{id}":{"get":{"tags":["Values"],"operationId":"Get","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[{"name":"id","in":"path","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"Success","schema":{"type":"string"}}}},"put":{"tags":["Values"],"operationId":"Put","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":[],"parameters":[{"name":"id","in":"path","required":true,"type":"integer","format":"int32"},{"name":"value","in":"body","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"}}},"delete":{"tags":["Values"],"operationId":"Delete","consumes":[],"produces":[],"parameters":[{"name":"id","in":"path","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"Success"}}}}},"definitions":{"AzureADAuthModel":{"type":"object","properties":{"apiKey":{"type":"string"}}},"Book":{"type":"object","properties":{"id":{"type":"string"},"bookName":{"type":"string"},"price":{"format":"double","type":"number"},"category":{"type":"string"},"author":{"type":"string"}}},"FacebookAuthModel":{"type":"object","properties":{"userAccessToken":{"type":"string"}}},"GoogleAuthModel":{"type":"object","properties":{"authorizationCode":{"type":"string"},"apiKey":{"type":"string"}}},"SmartPrinterMessage":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"time":{"type":"string"},"temperature":{"format":"double","type":"number"},"pressure":{"format":"double","type":"number"},"smoke":{"format":"int32","type":"integer"}}},"SmartGardenMessage":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"time":{"type":"string"},"temperature":{"format":"double","type":"number"},"pressure":{"format":"double","type":"number"},"humidity":{"format":"double","type":"number"},"water":{"format":"int32","type":"integer"},"light":{"format":"int32","type":"integer"}}},"User":{"type":"object","properties":{"id":{"type":"string"},"password":{"type":"string"}}},"TwitterAuthModel":{"type":"object","properties":{"apiKey":{"type":"string"}}}},"securityDefinitions":{"Bearer":{"name":"Authorization","in":"header","type":"apiKey","description":"Please enter JWT with Bearer into field"}},"security":[{"Bearer":[]}]} \ No newline at end of file +{"swagger":"2.0","info":{"version":"v1","title":"MyCoreApi"},"paths":{"/azure":{"post":{"tags":["Azure"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["application/json"],"parameters":[{"name":"user","in":"body","required":false,"schema":{"$ref":"#/definitions/AzureADAuthModel"}}],"responses":{"200":{"description":"Success"}}}},"/api/books":{"get":{"tags":["Books"],"operationId":"Get","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[],"responses":{"200":{"description":"Success","schema":{"uniqueItems":false,"type":"array","items":{"$ref":"#/definitions/Book"}}}}},"post":{"tags":["Books"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["text/plain","application/json","text/json"],"parameters":[{"name":"book","in":"body","required":false,"schema":{"$ref":"#/definitions/Book"}}],"responses":{"200":{"description":"Success","schema":{"$ref":"#/definitions/Book"}}}}},"/api/books/{id}":{"get":{"tags":["Books"],"operationId":"GetBook","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[{"name":"id","in":"path","required":true,"type":"string"}],"responses":{"200":{"description":"Success","schema":{"$ref":"#/definitions/Book"}}}},"put":{"tags":["Books"],"operationId":"Update","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":[],"parameters":[{"name":"id","in":"path","required":true,"type":"string"},{"name":"bookIn","in":"body","required":false,"schema":{"$ref":"#/definitions/Book"}}],"responses":{"200":{"description":"Success"}}},"delete":{"tags":["Books"],"operationId":"Delete","consumes":[],"produces":[],"parameters":[{"name":"id","in":"path","required":true,"type":"string"}],"responses":{"200":{"description":"Success"}}}},"/facebook":{"post":{"tags":["Facebook"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["application/json"],"parameters":[{"name":"user","in":"body","required":false,"schema":{"$ref":"#/definitions/FacebookAuthModel"}}],"responses":{"200":{"description":"Success"}}}},"/google":{"post":{"tags":["Google"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["application/json"],"parameters":[{"name":"user","in":"body","required":false,"schema":{"$ref":"#/definitions/GoogleAuthModel"}}],"responses":{"200":{"description":"Success"}}}},"/api/iot/smartprinter/{idDevice}":{"get":{"tags":["IOT"],"summary":"Retrieve all SmartPrinterMessage","operationId":"GetSmartPrinterMessages","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[{"name":"id","in":"query","description":"Id of the smart printer message","required":false,"type":"integer","format":"int32"},{"name":"idDevice","in":"path","required":true,"type":"string"}],"responses":{"200":{"description":"Success","schema":{"uniqueItems":false,"type":"array","items":{"$ref":"#/definitions/SmartPrinterMessage"}}}}},"post":{"tags":["IOT"],"summary":"It's the method to post data from mqtt broker to Database (Thanks Rpi!)","operationId":"PostToDBPrinter","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":[],"parameters":[{"name":"idDevice","in":"path","description":"Id of the device to upload to DB","required":true,"type":"integer","format":"int32"},{"name":"content","in":"body","description":"Content that will be uploaded","required":false,"schema":{"uniqueItems":false,"type":"array","items":{"$ref":"#/definitions/SmartPrinterMessage"}}}],"responses":{"200":{"description":"Success"},"201":{"description":"Content successfully posted to DB"},"500":{"description":"Unexpected error"}}}},"/api/iot/smartgarden/{idDevice}":{"post":{"tags":["IOT"],"summary":"It's the method to post data from mqtt broker to Database (Thanks Rpi!)","operationId":"PostToDBSmartGarden","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":[],"parameters":[{"name":"idDevice","in":"path","required":true,"type":"integer","format":"int32"},{"name":"content","in":"body","required":false,"schema":{"uniqueItems":false,"type":"array","items":{"$ref":"#/definitions/SmartGardenMessage"}}}],"responses":{"200":{"description":"Success"}}}},"/api/mqtt":{"get":{"tags":["MQTT"],"summary":"It's a mqtt publish test ! :)","operationId":"GetToPublishMqtt","consumes":[],"produces":[],"parameters":[],"responses":{"200":{"description":"Success"}}}},"/api/token":{"post":{"tags":["Token"],"operationId":"Create","consumes":[],"produces":[],"parameters":[{"name":"username","in":"query","required":false,"type":"string"},{"name":"password","in":"query","required":false,"type":"string"}],"responses":{"200":{"description":"Success"}}}},"/token":{"post":{"tags":["Token"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["application/json"],"parameters":[{"name":"user","in":"body","required":false,"schema":{"$ref":"#/definitions/User"}}],"responses":{"200":{"description":"Success"}}}},"/twitter":{"post":{"tags":["Twitter"],"operationId":"Create","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["application/json"],"parameters":[{"name":"user","in":"body","required":false,"schema":{"$ref":"#/definitions/TwitterAuthModel"}}],"responses":{"200":{"description":"Success"}}}},"/api/user":{"get":{"tags":["User"],"summary":"Get a list of user","operationId":"Get","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[],"responses":{"200":{"description":"Success","schema":{"uniqueItems":false,"type":"array","items":{"$ref":"#/definitions/UserInfo"}}}}}},"/api/user/{id}":{"get":{"tags":["User"],"summary":"Get a specific user","operationId":"Get","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[{"name":"id","in":"path","description":"id user","required":true,"type":"string"}],"responses":{"200":{"description":"Success","schema":{"$ref":"#/definitions/UserInfo"}}}}},"/api/test":{"get":{"tags":["Values"],"summary":"It's a test ! :)","operationId":"Get","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[],"responses":{"200":{"description":"Success","schema":{"uniqueItems":false,"type":"array","items":{"type":"string"}}}}},"post":{"tags":["Values"],"operationId":"Post","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":[],"parameters":[{"name":"value","in":"body","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"}}}},"/api/test/{id}":{"get":{"tags":["Values"],"operationId":"Get","consumes":[],"produces":["text/plain","application/json","text/json"],"parameters":[{"name":"id","in":"path","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"Success","schema":{"type":"string"}}}},"put":{"tags":["Values"],"operationId":"Put","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":[],"parameters":[{"name":"id","in":"path","required":true,"type":"integer","format":"int32"},{"name":"value","in":"body","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success"}}},"delete":{"tags":["Values"],"operationId":"Delete","consumes":[],"produces":[],"parameters":[{"name":"id","in":"path","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"Success"}}}}},"definitions":{"AzureADAuthModel":{"type":"object","properties":{"apiKey":{"type":"string"}}},"Book":{"type":"object","properties":{"id":{"type":"string"},"bookName":{"type":"string"},"price":{"format":"double","type":"number"},"category":{"type":"string"},"author":{"type":"string"}}},"FacebookAuthModel":{"type":"object","properties":{"userAccessToken":{"type":"string"}}},"GoogleAuthModel":{"type":"object","properties":{"authorizationCode":{"type":"string"},"apiKey":{"type":"string"}}},"SmartPrinterMessage":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"time":{"type":"string"},"temperature":{"format":"double","type":"number"},"pressure":{"format":"double","type":"number"},"smoke":{"format":"int32","type":"integer"}}},"SmartGardenMessage":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"time":{"type":"string"},"temperature":{"format":"double","type":"number"},"pressure":{"format":"double","type":"number"},"humidity":{"format":"double","type":"number"},"water":{"format":"int32","type":"integer"},"light":{"format":"int32","type":"integer"}}},"User":{"type":"object","properties":{"id":{"type":"string"},"password":{"type":"string"}}},"TwitterAuthModel":{"type":"object","properties":{"apiKey":{"type":"string"}}},"UserInfo":{"type":"object","properties":{"id":{"type":"string"},"role":{"type":"string"},"username":{"type":"string"},"password":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"token":{"type":"string"},"birthday":{"type":"string"}}}},"securityDefinitions":{"Bearer":{"name":"Authorization","in":"header","type":"apiKey","description":"Please enter JWT with Bearer into field"}},"security":[{"Bearer":[]}]} \ No newline at end of file