From 05e258f73d7e1341cb5bdba2743c852c220f192f Mon Sep 17 00:00:00 2001 From: Jeremias Arnstadt Date: Fri, 4 Mar 2022 10:15:47 +0100 Subject: [PATCH] #1 added possibility to authenticate against api and save accesstoken in cookie --- devday/angular.json | 5 ++- devday/package-lock.json | 21 ++++++++++ devday/package.json | 1 + devday/src/app/app.module.ts | 11 ++++- .../access-token.interceptor.spec.ts | 16 ++++++++ .../interceptors/access-token.interceptor.ts | 41 +++++++++++++++++++ .../app/interceptors/api.interceptor.spec.ts | 16 ++++++++ .../src/app/interceptors/api.interceptor.ts | 30 ++++++++++++++ .../pages/login/login/login.component.html | 6 +-- .../app/pages/login/login/login.component.ts | 18 +++++++- devday/src/app/services/login.service.spec.ts | 16 ++++++++ devday/src/app/services/login.service.ts | 21 ++++++++++ devday/src/environments/environment.prod.ts | 3 +- devday/src/environments/environment.ts | 3 +- devday/src/proxy.conf.json | 7 ++++ 15 files changed, 205 insertions(+), 10 deletions(-) create mode 100644 devday/src/app/interceptors/access-token.interceptor.spec.ts create mode 100644 devday/src/app/interceptors/access-token.interceptor.ts create mode 100644 devday/src/app/interceptors/api.interceptor.spec.ts create mode 100644 devday/src/app/interceptors/api.interceptor.ts create mode 100644 devday/src/app/services/login.service.spec.ts create mode 100644 devday/src/app/services/login.service.ts create mode 100644 devday/src/proxy.conf.json diff --git a/devday/angular.json b/devday/angular.json index b5a1bfc..e6d64ce 100644 --- a/devday/angular.json +++ b/devday/angular.json @@ -69,7 +69,8 @@ "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { - "browserTarget": "devday:build" + "browserTarget": "devday:build", + "proxyConfig": "src/proxy.conf.json" }, "configurations": { "production": { @@ -129,4 +130,4 @@ } }}, "defaultProject": "devday" -} \ No newline at end of file +} diff --git a/devday/package-lock.json b/devday/package-lock.json index 1b5a848..50146c6 100644 --- a/devday/package-lock.json +++ b/devday/package-lock.json @@ -20,6 +20,7 @@ "@angular/router": "~13.0.0", "@angular/service-worker": "~13.0.0", "angular-svg-icon": "^13.0.0", + "ngx-cookie-service": "^13.1.2", "rxjs": "~7.4.0", "tslib": "^2.3.1", "webpack-sources": "^3.2.1", @@ -8817,6 +8818,18 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/ngx-cookie-service": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-13.1.2.tgz", + "integrity": "sha512-CInzm1xjI51QA1gCJEnqfDFLnN7w/SzqM5+kGdpI+UiCeHKgYEXpKG1s7lFz4jbLDrL/jHKtrf92t7RGsm66Cg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": "^13.0.0", + "@angular/core": "^13.0.0" + } + }, "node_modules/nice-napi": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", @@ -20733,6 +20746,14 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "ngx-cookie-service": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-13.1.2.tgz", + "integrity": "sha512-CInzm1xjI51QA1gCJEnqfDFLnN7w/SzqM5+kGdpI+UiCeHKgYEXpKG1s7lFz4jbLDrL/jHKtrf92t7RGsm66Cg==", + "requires": { + "tslib": "^2.0.0" + } + }, "nice-napi": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", diff --git a/devday/package.json b/devday/package.json index 92e53f7..9fea8bf 100644 --- a/devday/package.json +++ b/devday/package.json @@ -23,6 +23,7 @@ "@angular/router": "~13.0.0", "@angular/service-worker": "~13.0.0", "angular-svg-icon": "^13.0.0", + "ngx-cookie-service": "^13.1.2", "rxjs": "~7.4.0", "tslib": "^2.3.1", "webpack-sources": "^3.2.1", diff --git a/devday/src/app/app.module.ts b/devday/src/app/app.module.ts index eefe5a4..c2a3069 100644 --- a/devday/src/app/app.module.ts +++ b/devday/src/app/app.module.ts @@ -7,7 +7,7 @@ import { environment } from '../environments/environment'; import { ComponentsModule } from './modules/components.module'; import { ExamplesPageComponent } from './pages/examples-page/examples-page.component'; import { AppRoutingModule } from './routing/app-routing.module'; -import { HttpClientModule } from '@angular/common/http'; +import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { RouterModule } from '@angular/router'; import { OverlayModule } from '@angular/cdk/overlay'; import { LoginComponent } from './pages/login/login/login.component'; @@ -17,6 +17,9 @@ import { FavouritesComponent } from './pages/favourites/favourites/favourites.co import { YourTicketComponent } from './pages/your-ticket/your-ticket/your-ticket.component'; import { SpeakersComponent } from './pages/speakers/speakers/speakers.component'; import { SpeakerComponent } from './pages/speaker/speaker/speaker.component'; +import { LoginService } from './services/login.service'; +import { ApiInterceptor } from './interceptors/api.interceptor'; +import { AccessTokenInterceptor } from './interceptors/access-token.interceptor'; @NgModule({ @@ -43,7 +46,11 @@ import { SpeakerComponent } from './pages/speaker/speaker/speaker.component'; exports: [ ComponentsModule ], - providers: [], + providers: [ + LoginService, + { provide: HTTP_INTERCEPTORS, useClass: ApiInterceptor, multi: true }, + { provide: HTTP_INTERCEPTORS, useClass: AccessTokenInterceptor, multi: true } + ], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/devday/src/app/interceptors/access-token.interceptor.spec.ts b/devday/src/app/interceptors/access-token.interceptor.spec.ts new file mode 100644 index 0000000..c645f1f --- /dev/null +++ b/devday/src/app/interceptors/access-token.interceptor.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { AccessTokenInterceptor } from './access-token.interceptor'; + +describe('AccessTokenInterceptor', () => { + beforeEach(() => TestBed.configureTestingModule({ + providers: [ + AccessTokenInterceptor + ] + })); + + it('should be created', () => { + const interceptor: AccessTokenInterceptor = TestBed.inject(AccessTokenInterceptor); + expect(interceptor).toBeTruthy(); + }); +}); diff --git a/devday/src/app/interceptors/access-token.interceptor.ts b/devday/src/app/interceptors/access-token.interceptor.ts new file mode 100644 index 0000000..7278fce --- /dev/null +++ b/devday/src/app/interceptors/access-token.interceptor.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@angular/core'; +import { + HttpRequest, + HttpHandler, + HttpEvent, + HttpInterceptor +} from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { LoginService } from '../services/login.service'; +import { CookieService } from 'ngx-cookie-service'; + +@Injectable() +export class AccessTokenInterceptor implements HttpInterceptor { + private token : string; + + constructor(private cookieService : CookieService) {} + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + if (!this.token) { + this.token = this.cookieService.get('sessionToken') + } + return next.handle(this.addToken(request)); + } + + addToken(request: HttpRequest) { + let withToken + if (this.token) { + withToken = request.clone({ + setHeaders: { + Authorization: `Bearer ${this.token}` + } + }) + } else { + withToken = request; + } + + console.log(withToken) + + return withToken + } +} diff --git a/devday/src/app/interceptors/api.interceptor.spec.ts b/devday/src/app/interceptors/api.interceptor.spec.ts new file mode 100644 index 0000000..f2bb20f --- /dev/null +++ b/devday/src/app/interceptors/api.interceptor.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ApiInterceptor } from './api.interceptor'; + +describe('ApiInterceptor', () => { + beforeEach(() => TestBed.configureTestingModule({ + providers: [ + ApiInterceptor + ] + })); + + it('should be created', () => { + const interceptor: ApiInterceptor = TestBed.inject(ApiInterceptor); + expect(interceptor).toBeTruthy(); + }); +}); diff --git a/devday/src/app/interceptors/api.interceptor.ts b/devday/src/app/interceptors/api.interceptor.ts new file mode 100644 index 0000000..0d8b565 --- /dev/null +++ b/devday/src/app/interceptors/api.interceptor.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@angular/core'; +import { + HttpRequest, + HttpHandler, + HttpEvent, + HttpInterceptor +} from '@angular/common/http'; +import { Observable } from 'rxjs'; + +@Injectable() +export class ApiInterceptor implements HttpInterceptor { + + constructor() {} + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + return next.handle(this.addContentType(request)); + } + + addContentType(request: HttpRequest) { + let withHeaders = request.clone({ + setHeaders: { + 'accept': 'application/json', + 'Content-Type': 'application/json' + } + }) + console.log(withHeaders) + + return withHeaders + } +} diff --git a/devday/src/app/pages/login/login/login.component.html b/devday/src/app/pages/login/login/login.component.html index e099e06..e2b63aa 100644 --- a/devday/src/app/pages/login/login/login.component.html +++ b/devday/src/app/pages/login/login/login.component.html @@ -3,9 +3,9 @@ - - - + + + diff --git a/devday/src/app/pages/login/login/login.component.ts b/devday/src/app/pages/login/login/login.component.ts index 9051aa2..9f61c3c 100644 --- a/devday/src/app/pages/login/login/login.component.ts +++ b/devday/src/app/pages/login/login/login.component.ts @@ -1,5 +1,7 @@ import { Component, OnInit } from '@angular/core'; +import { CookieService } from 'ngx-cookie-service'; import { Card } from 'src/app/classes/card'; +import { LoginData, LoginService } from 'src/app/services/login.service'; @Component({ selector: 'app-login', @@ -34,7 +36,12 @@ export class LoginComponent implements OnInit { } ]; - constructor() { } + public loginData : LoginData = { + username: null, + password: null, + } + + constructor(private loginService: LoginService, private cookieService: CookieService) { } ngOnInit(): void { } @@ -43,4 +50,13 @@ export class LoginComponent implements OnInit { this.loginTabs.activeIndex = tabIndex; } + public performLogin() { + this.loginService.login(this.loginData).subscribe( + (data : {token: string}) => { + console.log(data) + this.cookieService.set('sessionToken', data.token, { expires: 2, sameSite: 'Strict' }); + } + ) + } + } diff --git a/devday/src/app/services/login.service.spec.ts b/devday/src/app/services/login.service.spec.ts new file mode 100644 index 0000000..299b0d5 --- /dev/null +++ b/devday/src/app/services/login.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { LoginService } from './login.service'; + +describe('LoginService', () => { + let service: LoginService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(LoginService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/devday/src/app/services/login.service.ts b/devday/src/app/services/login.service.ts new file mode 100644 index 0000000..61fd02d --- /dev/null +++ b/devday/src/app/services/login.service.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@angular/core'; +import { map, Subject } from 'rxjs'; +import { environment } from 'src/environments/environment'; +import { BasicRestService } from './basic-rest.service'; + +export interface LoginData { + username: string; + password: string; +} + +@Injectable({ + providedIn: 'root' +}) +export class LoginService { + + constructor(private restService: BasicRestService) { } + + login(loginData : LoginData) { + return this.restService.post(environment.apiUrl + 'api-token-auth/', loginData) + } +} diff --git a/devday/src/environments/environment.prod.ts b/devday/src/environments/environment.prod.ts index 3612073..f0dabb6 100644 --- a/devday/src/environments/environment.prod.ts +++ b/devday/src/environments/environment.prod.ts @@ -1,3 +1,4 @@ export const environment = { - production: true + production: true, + apiUrl: 'https://www.devday.de/api/' }; diff --git a/devday/src/environments/environment.ts b/devday/src/environments/environment.ts index 7b4f817..22ff6ec 100644 --- a/devday/src/environments/environment.ts +++ b/devday/src/environments/environment.ts @@ -3,7 +3,8 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - production: false + production: false, + apiUrl: 'https://www.devday.de/' }; /* diff --git a/devday/src/proxy.conf.json b/devday/src/proxy.conf.json new file mode 100644 index 0000000..6f39649 --- /dev/null +++ b/devday/src/proxy.conf.json @@ -0,0 +1,7 @@ +{ + "/api/*": { + "target": "https://www.devday.de/api/", + "secure": false, + "logLevel": "debug" + } +}