From 033f9de439a9f20cfca8cc66e2607d468c524414 Mon Sep 17 00:00:00 2001 From: FlayInAHook Date: Tue, 1 Dec 2020 20:53:20 +0100 Subject: [PATCH 1/3] Added user service --- src/app/models/user.ts | 11 +- src/app/pages/profile/profile.component.html | 13 ++ src/app/pages/profile/profile.component.scss | 0 src/app/pages/profile/profile.component.ts | 155 +++++++++++++++++++ src/app/services/auth.service.ts | 14 +- src/app/services/user.service.ts | 44 ++++++ 6 files changed, 229 insertions(+), 8 deletions(-) create mode 100644 src/app/pages/profile/profile.component.html create mode 100644 src/app/pages/profile/profile.component.scss create mode 100644 src/app/pages/profile/profile.component.ts create mode 100644 src/app/services/user.service.ts diff --git a/src/app/models/user.ts b/src/app/models/user.ts index c092e1a..472eaac 100644 --- a/src/app/models/user.ts +++ b/src/app/models/user.ts @@ -1,4 +1,4 @@ -export class User { +export class AuthUser { request_token: string; refresh_token: string; user: { @@ -10,4 +10,13 @@ export class User { } } +} + +export class User { + id: number; + name: string; + email: string; + attributes : { + profile_url: string; + } } \ No newline at end of file diff --git a/src/app/pages/profile/profile.component.html b/src/app/pages/profile/profile.component.html new file mode 100644 index 0000000..ecca39d --- /dev/null +++ b/src/app/pages/profile/profile.component.html @@ -0,0 +1,13 @@ + diff --git a/src/app/pages/profile/profile.component.scss b/src/app/pages/profile/profile.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/pages/profile/profile.component.ts b/src/app/pages/profile/profile.component.ts new file mode 100644 index 0000000..b970ac6 --- /dev/null +++ b/src/app/pages/profile/profile.component.ts @@ -0,0 +1,155 @@ +import { Component, OnInit } from '@angular/core'; +import { BikesService } from '../../services/bikes.service'; + +@Component({ + selector: 'app-profile', + templateUrl: './profile.component.html', + styleUrls: ['./profile.component.scss'], +}) +export class ProfileComponent implements OnInit { + columnInfo = [ + { + dataPath: 'name', + translation: 'Name', + sticky: true, + link: (row: any) => { + return '/bike/' + row.id; + }, + }, + { dataPath: 'id', translation: 'ID', readonly: true }, + { dataPath: 'group', translation: 'Gruppe' }, + { dataPath: 'modelName', translation: 'Modell' }, + { + dataPath: 'insuranceData.billing', + translation: 'Versicherung Abrechnung', + }, + { dataPath: 'insuranceData.hasFixedRate', translation: 'Pauschale j/n' }, + { dataPath: 'insuranceData.fixedRate', translation: 'Pauschale Betrag' }, + { dataPath: 'insuranceData.name', translation: 'Versicherer' }, + { dataPath: 'insuranceData.benefactor', translation: 'Kostenträger' }, + { dataPath: 'insuranceData.noPnP', translation: 'Nr. P&P' }, + { + dataPath: 'insuranceData.maintenanceResponsible', + translation: 'Wartung zuständig', + }, + { + dataPath: 'insuranceData.maintenanceBenefactor', + translation: 'Wartung Kostenträger', + }, + { + dataPath: 'insuranceData.maintenanceAgreement', + translation: 'Wartungsvereinbarung', + }, + { + dataPath: 'insuranceData.projectAllowance', + translation: 'Projektzuschuss', + }, + { dataPath: 'insuranceData.notes', translation: 'Sonstiges' }, + { dataPath: 'dimensionsAndLoad.bikeLength', translation: 'Länge' }, + { dataPath: 'dimensionsAndLoad.bikeWeight', translation: 'Gewicht' }, + { dataPath: 'dimensionsAndLoad.bikeHeight', translation: 'Höhe' }, + { dataPath: 'dimensionsAndLoad.bikeWidth', translation: 'Breite' }, + { dataPath: 'dimensionsAndLoad.boxHeightRange', translation: 'Boxhöhe' }, + { dataPath: 'dimensionsAndLoad.boxLengthRange', translation: 'Boxlänge' }, + { dataPath: 'dimensionsAndLoad.boxWidthRange', translation: 'Boxbreite' }, + { + dataPath: 'dimensionsAndLoad.hasCoverBox', + translation: 'Boxabdeckung j/n', + }, + { dataPath: 'dimensionsAndLoad.lockable', translation: 'Box abschließbar' }, + { + dataPath: 'dimensionsAndLoad.maxWeightBox', + translation: 'max Zuladung Box', + }, + { + dataPath: 'dimensionsAndLoad.maxWeightLuggageRack', + translation: 'max Zuladung Gepäckträger', + }, + { + dataPath: 'dimensionsAndLoad.maxWeightTotal', + translation: 'max Gesamtgewicht', + }, + { dataPath: 'numberOfChildren', translation: 'Anzahl Kinder' }, + { dataPath: 'numberOfWheels', translation: 'Anzahl Räder' }, + { dataPath: 'forCargo', translation: 'für Lasten j/n' }, + { dataPath: 'forChildren', translation: 'für Kinder j/n' }, + { dataPath: 'security.frameNumber', translation: 'Rahmennummer' }, + { dataPath: 'security.adfcCoding', translation: 'ADFC Codierung' }, + { + dataPath: 'security.keyNumberAXAChain', + translation: 'Schlüsselnrummer Rahmenschloss', + }, + { + dataPath: 'security.keyNumberFrameLock', + translation: 'Schlüsselnrummer AXA-Kette', + }, + { dataPath: 'security.policeCoding', translation: 'Polizei Codierung' }, + { dataPath: 'technicalEquipment.bicycleShift', translation: 'Schaltung' }, + { dataPath: 'technicalEquipment.isEBike', translation: 'E-Bike j/n' }, + { + dataPath: 'technicalEquipment.hasLightSystem', + translation: 'Lichtanlage j/n', + }, + { + dataPath: 'technicalEquipment.specialFeatures', + translation: 'Besonderheiten', + }, + { dataPath: 'stickerBikeNameState', translation: 'Aufkleber Status' }, + { dataPath: 'note', translation: 'Aufkleber Kommentar' }, + { dataPath: 'taxes.costCenter', translation: 'Steuern Kostenstelle' }, + { + dataPath: 'taxes.organisationArea', + translation: 'Steuern Vereinsbereich', + }, + { dataPath: 'provider.id', translation: '' }, + { dataPath: 'provider.formName', translation: '' }, + { dataPath: 'provider.privatePerson.id', translation: '' }, + { dataPath: 'provider.privatePerson.person.id', translation: '' }, + { dataPath: 'provider.privatePerson.person.name', translation: '' }, + { dataPath: 'provider.privatePerson.person.firstName', translation: '' }, + { + dataPath: 'provider.privatePerson.person.contactInformation.email', + translation: '', + }, + { dataPath: 'lendingStation.id', translation: '' }, + { dataPath: 'lendingStation.name', translation: '' }, + { dataPath: 'lendingStation.address.number', translation: '' }, + { dataPath: 'lendingStation.address.street', translation: '' }, + { dataPath: 'lendingStation.address.zip', translation: '' }, + ]; + + dataService: any; + + tableDataGQLType: string = 'CargoBike'; + tableDataGQLCreateInputType: string = 'CargoBikeCreateInput'; + tableDataGQLUpdateInputType: string = 'CargoBikeUpdateInput'; + + headline = 'Lastenräder'; + + loadingRowIds: string[] = []; + constructor(private bikesService: BikesService) {} + + ngOnInit() { + this.dataService = this.bikesService; + } + + create(object: { currentId: string; row: any }) { + this.bikesService.createBike(object.currentId, { bike: object.row }); + } + + lock(row: any) { + this.bikesService.lockBike({ id: row.id }); + } + + save(row: any) { + this.bikesService.updateBike({ bike: row }); + } + + cancel(row: any) { + this.bikesService.unlockBike({ id: row.id }); + } + + delete(row: any) { + this.bikesService.deleteBike({ id: row.id }); + } +} diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts index 975b2e6..aab18d8 100644 --- a/src/app/services/auth.service.ts +++ b/src/app/services/auth.service.ts @@ -3,22 +3,22 @@ import { HttpClient } from '@angular/common/http'; import { catchError, finalize, map, tap } from 'rxjs/operators'; import { environment } from '../../environments/environment'; import { Observable, BehaviorSubject, of } from 'rxjs'; -import { User } from "../models/user"; +import { AuthUser } from "../models/user"; @Injectable({ providedIn: 'root', }) export class AuthService { - private currentUserSubject: BehaviorSubject; - public currentUser: Observable; + private currentUserSubject: BehaviorSubject; + public currentUser: Observable; public loggedIn: BehaviorSubject; private readonly REQUEST_TOKEN = 'requestToken'; private readonly REFRESH_TOKEN = 'refreshToken'; private readonly CURRENT_USER = 'currentUser'; constructor(private http: HttpClient) { - this.currentUserSubject = new BehaviorSubject( + this.currentUserSubject = new BehaviorSubject( JSON.parse(localStorage.getItem(this.CURRENT_USER)) ); this.currentUser = this.currentUserSubject.asObservable(); @@ -29,10 +29,10 @@ export class AuthService { } - public get getCurrentUserValue(): User { + public get getCurrentUserValue(): AuthUser { var value = this.currentUserSubject.value; if (value === null){ - value = new User(); + value = new AuthUser(); } return value; } @@ -108,7 +108,7 @@ export class AuthService { //localStorage.setItem(this.REFRESH_TOKEN, tokens.refresh_token); } - private storeUser(usr: User){ + private storeUser(usr: AuthUser){ localStorage.setItem(this.CURRENT_USER, JSON.stringify(usr)); this.currentUserSubject.next(usr); } diff --git a/src/app/services/user.service.ts b/src/app/services/user.service.ts new file mode 100644 index 0000000..adfe31a --- /dev/null +++ b/src/app/services/user.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { catchError, finalize, map, tap } from 'rxjs/operators'; +import { environment } from '../../environments/environment'; +import { Observable, BehaviorSubject, of } from 'rxjs'; +import { User } from "../models/user"; +import { AuthService} from "./auth.service"; +import { ObserveOnSubscriber } from 'rxjs/internal/operators/observeOn'; + + +@Injectable({ + providedIn: 'root', +}) +export class UserService { + + constructor(private http: HttpClient, private authService: AuthService) { + + + + + } + + + public getAllUsers(): Observable { + return this.http.get(`${environment.authUrl}/users`); + } + + public getUser(email: string): Observable { + return this.http.get(`${environment.authUrl}/users/${email}`); + } + + public getUserPermissions(email: string): Observable { + return this.http.get(`${environment.authUrl}/users/${email}/permissions`) + } + + public updateUser(user: User): Observable { + return this.http.post(`${environment.authUrl}/users/${user.email}/update`, user); + } + + public deleteUser(email: string): Observable { + return this.http.delete(`${environment.authUrl}/users/` + email + "/delete"); + } + +} From ecc8a61102ef1e68c6bcfe609135d66388ec9a7e Mon Sep 17 00:00:00 2001 From: FlayInAHook Date: Tue, 1 Dec 2020 21:14:51 +0100 Subject: [PATCH 2/3] Added basic auth guard --- src/app/app-routing.module.ts | 19 ++++++++------- src/app/helper/auth.guard.ts | 30 +++++++++++++++++++++++ src/app/services/role.service.ts | 41 ++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 src/app/helper/auth.guard.ts create mode 100644 src/app/services/role.service.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 55b8e96..946fdb0 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -10,18 +10,19 @@ import { EquipmentComponent } from './pages/tables/equipment/equipment.component import { LendingStationsComponent } from './pages/tables/lending-stations/lending-stations.component'; import { ParticipantsComponent } from './pages/tables/participants/participants.component'; import { TimeFramesComponent } from './pages/tables/time-frames/time-frames.component'; +import {AuthGuard} from './helper/auth.guard'; const routes: Routes = [ { path: 'login', component: LoginComponent }, - { path: 'tableOverview', component: TableOverviewComponent }, - { path: 'table/bikes', component: BikesComponent }, - { path: 'bike/:id', component: BikeComponent }, - { path: 'table/participants', component: ParticipantsComponent }, - { path: 'table/lendingStations', component: LendingStationsComponent }, - { path: 'table/equipmentTypes', component: EquipmentTypesComponent }, - { path: 'table/engagementTypes', component: EngagementTypesComponent }, - { path: 'table/equipment', component: EquipmentComponent }, - { path: 'table/timeFrames', component: TimeFramesComponent }, + { path: 'tableOverview', component: TableOverviewComponent, canActivate: [AuthGuard]}, + { path: 'table/bikes', component: BikesComponent, canActivate: [AuthGuard] }, + { path: 'bike/:id', component: BikeComponent, canActivate: [AuthGuard] }, + { path: 'table/participants', component: ParticipantsComponent, canActivate: [AuthGuard] }, + { path: 'table/lendingStations', component: LendingStationsComponent, canActivate: [AuthGuard] }, + { path: 'table/equipmentTypes', component: EquipmentTypesComponent, canActivate: [AuthGuard] }, + { path: 'table/engagementTypes', component: EngagementTypesComponent, canActivate: [AuthGuard] }, + { path: 'table/equipment', component: EquipmentComponent, canActivate: [AuthGuard] }, + { path: 'table/timeFrames', component: TimeFramesComponent, canActivate: [AuthGuard] }, { path: '', redirectTo: 'tableOverview', pathMatch: 'full' }, { path: 'table', redirectTo: 'tableOverview', pathMatch: 'full' }, { path: '**', redirectTo: 'tableOverview' }, diff --git a/src/app/helper/auth.guard.ts b/src/app/helper/auth.guard.ts new file mode 100644 index 0000000..a05beec --- /dev/null +++ b/src/app/helper/auth.guard.ts @@ -0,0 +1,30 @@ +import { Injectable } from "@angular/core"; +import { + Router, + CanActivate, + ActivatedRouteSnapshot, + RouterStateSnapshot +} from "@angular/router"; +import { AuthUser } from '../models/user'; + +import { AuthService } from "../services/auth.service"; + +@Injectable({ providedIn: "root" }) +export class AuthGuard implements CanActivate { + constructor( + private router: Router, + private authService: AuthService + ) {} + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + const currentUser = this.authService.getCurrentUserValue; + if (Object.keys(currentUser).length != 0) { + // authorised so return true + return true; + } + + // not logged in so redirect to login page with the return url + this.router.navigate(["/login"], { queryParams: { returnUrl: state.url } }); + return false; + } +} \ No newline at end of file diff --git a/src/app/services/role.service.ts b/src/app/services/role.service.ts new file mode 100644 index 0000000..ce96cb4 --- /dev/null +++ b/src/app/services/role.service.ts @@ -0,0 +1,41 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { catchError, finalize, map, tap } from 'rxjs/operators'; +import { environment } from '../../environments/environment'; +import { Observable, BehaviorSubject, of } from 'rxjs'; +import { User } from "../models/user"; +import { AuthService} from "./auth.service"; +import { ObserveOnSubscriber } from 'rxjs/internal/operators/observeOn'; + + +@Injectable({ + providedIn: 'root', +}) +export class RoleService { + + constructor(private http: HttpClient, private authService: AuthService) { + + } + + + public getAllUsers(): Observable { + return this.http.get(`${environment.authUrl}/users`); + } + + public getUser(email: string): Observable { + return this.http.get(`${environment.authUrl}/users/${email}`); + } + + public getUserPermissions(email: string): Observable { + return this.http.get(`${environment.authUrl}/users/${email}/permissions`) + } + + public updateUser(user: User): Observable { + return this.http.post(`${environment.authUrl}/users/${user.email}/update`, user); + } + + public deleteUser(email: string): Observable { + return this.http.delete(`${environment.authUrl}/users/` + email + "/delete"); + } + +} From 4eb57f72e489150f69139c5a20452bc807dd6fd9 Mon Sep 17 00:00:00 2001 From: FlayInAHook Date: Tue, 1 Dec 2020 21:21:32 +0100 Subject: [PATCH 3/3] added return url --- src/app/pages/login/login.component.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/app/pages/login/login.component.ts b/src/app/pages/login/login.component.ts index 3835504..2933f3e 100644 --- a/src/app/pages/login/login.component.ts +++ b/src/app/pages/login/login.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; -import { Router } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { AuthService } from '../../services/auth.service'; @Component({ @@ -15,9 +15,14 @@ export class LoginComponent implements OnInit { loading = false; errorOccurred = false; errorMessage = ''; - constructor(private authService: AuthService, private router: Router) {} - ngOnInit(): void {} + returnUrl : string; + + constructor(private authService: AuthService, private router: Router, private route: ActivatedRoute) {} + + ngOnInit(): void { + this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/tableOverview'; + } login() { this.errorMessage = ''; @@ -29,7 +34,7 @@ export class LoginComponent implements OnInit { this.authService .login(this.email.value, this.password.value) .subscribe( - () => this.router.navigate(['tableOverview']), + () => this.router.navigateByUrl(this.returnUrl), (error) => { this.errorOccurred = true; this.errorMessage =