diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index c390f54..02e222f 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -23,6 +23,7 @@ import { NewTravelComponent } from './pages/new-travel/new-travel.component';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { NgxMatMomentModule } from '@angular-material-components/moment-adapter';
import { AppRouterModule } from './router.module';
+import { AvailablePlacesPipe } from './pipes/available-places.pipe';
// We need a factory, since localStorage is not available during AOT build time.
export function storageFactory(): OAuthStorage {
@@ -57,7 +58,8 @@ export function storageFactory(): OAuthStorage {
HeaderComponent,
ListComponent,
TravelFormComponent,
- NewTravelComponent
+ NewTravelComponent,
+ AvailablePlacesPipe
],
providers: [
{ provide: OAuthStorage, useFactory: storageFactory }
diff --git a/src/app/entities/travel.ts b/src/app/entities/travel.ts
index 255fa36..1b92123 100644
--- a/src/app/entities/travel.ts
+++ b/src/app/entities/travel.ts
@@ -1,12 +1,12 @@
-import { UserInfo } from './user-info';
+import { User } from './user';
export type TravelId = number;
export class Travel {
constructor(
public id: TravelId = -1,
- public driverInfo: UserInfo = null,
- public travelersInfo: UserInfo[] = [],
+ public driverInfo: User = null,
+ public travelersInfo: User[] = [],
public departureDate: string = '',
public origin: string = '',
public destination: string = '',
@@ -14,4 +14,8 @@ export class Travel {
public matrixRoomId: string = '',
public description?: string
) { }
+
+ availablePlaces(): number {
+ return this.places - this.travelersInfo.length;
+ }
}
diff --git a/src/app/entities/user-info.ts b/src/app/entities/user-info.ts
deleted file mode 100644
index e3f9c8d..0000000
--- a/src/app/entities/user-info.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export type UserId = string;
-
-export interface UserInfo {
- id: UserId;
- username: string;
- matrixId?: string;
- name: string;
-}
diff --git a/src/app/entities/user.ts b/src/app/entities/user.ts
index 9f11ae2..b9a71a5 100644
--- a/src/app/entities/user.ts
+++ b/src/app/entities/user.ts
@@ -1,8 +1,24 @@
export type UserId = string;
-export interface User {
- id: UserId;
- username: string;
- matrixId?: string;
- name: string;
+export class User {
+ constructor(
+ public id: UserId,
+ public username: string,
+ public matrixId: string = null,
+ public name: string,
+ public admin: boolean = false
+ ) { }
+
+ static fromClaims(claims: object): User {
+ if (claims == null) {
+ return null;
+ }
+ return new User(
+ claims["sub"].toString(),
+ claims["preferred_username"].toString(),
+ claims["preferred_username"] + ':fosil.eu',
+ claims["name"].toString(),
+ claims["admin"] === true
+ );
+ }
}
diff --git a/src/app/pages/edit-travel/edit-travel.component.html b/src/app/pages/edit-travel/edit-travel.component.html
index 585a22b..d857b71 100644
--- a/src/app/pages/edit-travel/edit-travel.component.html
+++ b/src/app/pages/edit-travel/edit-travel.component.html
@@ -1,4 +1,5 @@
\ No newline at end of file
diff --git a/src/app/pages/travel/travel.component.html b/src/app/pages/travel/travel.component.html
index e20d2b2..1f7349b 100644
--- a/src/app/pages/travel/travel.component.html
+++ b/src/app/pages/travel/travel.component.html
@@ -13,4 +13,4 @@
-
+
diff --git a/src/app/pages/travel/travel.component.ts b/src/app/pages/travel/travel.component.ts
index 4830eaa..3161dd5 100644
--- a/src/app/pages/travel/travel.component.ts
+++ b/src/app/pages/travel/travel.component.ts
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
-import { OAuthService } from 'angular-oauth2-oidc';
+import { AuthService } from 'src/app/services/auth.service';
import { Travel, TravelId } from '../../entities/travel';
import { ApiService } from '../../services/api.service';
@@ -16,7 +16,7 @@ export class TravelComponent implements OnInit {
constructor(
private router: Router,
- private oauthService: OAuthService,
+ private authService: AuthService,
private apiService: ApiService,
private route: ActivatedRoute
) { }
@@ -45,8 +45,7 @@ export class TravelComponent implements OnInit {
this.router.navigateByUrl(`/travel/${this.travelId}/edit`);
}
- get logged(): boolean {
- return this.oauthService.getIdentityClaims() != null;
- // return this.oauthService.hasValidIdToken() && this.oauthService.hasValidAccessToken();
+ get canEdit(): boolean {
+ return this.authService.canEditTravel(this.travel);
}
}
diff --git a/src/app/pipes/available-places.pipe.ts b/src/app/pipes/available-places.pipe.ts
new file mode 100644
index 0000000..7f31ab4
--- /dev/null
+++ b/src/app/pipes/available-places.pipe.ts
@@ -0,0 +1,9 @@
+import { Pipe, PipeTransform } from '@angular/core';
+import { Travel } from '../entities/travel';
+
+@Pipe({ name: 'availablePlaces' })
+export class AvailablePlacesPipe implements PipeTransform {
+ transform(travel: Travel): number {
+ return travel.places - travel.travelersInfo.length;
+ }
+}
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..be8d431
--- /dev/null
+++ b/src/app/services/auth.service.ts
@@ -0,0 +1,26 @@
+import { Injectable } from '@angular/core';
+import { OAuthService } from 'angular-oauth2-oidc';
+import { Travel } from '../entities/travel';
+import { User } from '../entities/user';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthService {
+
+ constructor(private oauthService: OAuthService) { }
+
+ currentUser(): User {
+ const claims = this.oauthService.getIdentityClaims();
+ return User.fromClaims(claims);
+ }
+
+ canEditTravel(travel: Travel): boolean {
+ const user = this.currentUser();
+ if (user == null) {
+ return false;
+ }
+
+ return user.admin || (user.id === travel.driverInfo.id);
+ }
+}
diff --git a/src/app/views/list/list.component.css b/src/app/views/list/list.component.css
index 4086ae4..5c596e2 100644
--- a/src/app/views/list/list.component.css
+++ b/src/app/views/list/list.component.css
@@ -4,19 +4,8 @@
margin: 0 auto;
}
-.description-cell {
+.mat-cell {
text-align: left;
- margin: 10px auto;
-}
-
-.duration-cell {
- text-align: center;
-}
-
-.duration-cell mat-icon {
- display: inline-block;
- vertical-align: middle;
- font-size: 20px;
}
.spinner-container {
@@ -26,8 +15,8 @@
}
.travel-table {
- min-height: 150px;
- margin-top: 10px;
+ min-height: 100px;
+ margin: 10px;
}
.spinner-container mat-spinner {
diff --git a/src/app/views/list/list.component.html b/src/app/views/list/list.component.html
index 14f3609..fe97424 100644
--- a/src/app/views/list/list.component.html
+++ b/src/app/views/list/list.component.html
@@ -7,7 +7,7 @@
-
Departure date
@@ -32,7 +32,7 @@
Available places
- {{ travel.places - travel.travelersInfo.length }}
+ {{ travel | availablePlaces }}
diff --git a/src/styles.css b/src/styles.css
index fc5bdef..c417663 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -4,5 +4,5 @@ html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
.mat-card {
- margin: 20px;
+ margin: 40px;
}
\ No newline at end of file