diff --git a/angular.json b/angular.json index 1f3c173..ed528bf 100644 --- a/angular.json +++ b/angular.json @@ -28,6 +28,7 @@ "src/assets" ], "styles": [ + "src/custom-theme.scss", "src/styles.css" ], "scripts": [] @@ -123,6 +124,7 @@ } } } - }}, + } + }, "defaultProject": "sample-oauth" -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ce544de..1243483 100644 --- a/package-lock.json +++ b/package-lock.json @@ -249,6 +249,28 @@ } } }, + "@angular/cdk": { + "version": "10.2.7", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-10.2.7.tgz", + "integrity": "sha512-ZQjDfTRTn7JuAKsf3jiIdU2XBaxxGBi/ZWYv5Pb3HCl6B4PISsIE5VWRhkoUogoAB0MiFHpjnWeIqknJEm11YQ==", + "requires": { + "parse5": "^5.0.0", + "tslib": "^2.0.0" + }, + "dependencies": { + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, "@angular/cli": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-10.2.1.tgz", @@ -512,6 +534,21 @@ } } }, + "@angular/material": { + "version": "10.2.7", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-10.2.7.tgz", + "integrity": "sha512-uk6JkRrKHaM9VFMzX7pWC83YNLVgXPB3D8U1yjSOafCdWwrRZgUHGr8MPlSILCr3o2nxgg5SsKdWcWwHuXXUZA==", + "requires": { + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, "@angular/platform-browser": { "version": "10.2.4", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-10.2.4.tgz", diff --git a/package.json b/package.json index 3bcc5bb..b44acdf 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,12 @@ "private": true, "dependencies": { "@angular/animations": "~10.2.4", + "@angular/cdk": "^10.2.7", "@angular/common": "~10.2.4", "@angular/compiler": "~10.2.4", "@angular/core": "~10.2.4", "@angular/forms": "~10.2.4", + "@angular/material": "^10.2.7", "@angular/platform-browser": "~10.2.4", "@angular/platform-browser-dynamic": "~10.2.4", "@angular/router": "~10.2.4", diff --git a/src/app/app.component.html b/src/app/app.component.html index d713365..6aa0064 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,12 +1,4 @@ - +
@@ -17,5 +9,3 @@
- - diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 451dc24..1c506c0 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -2,12 +2,12 @@ import { Component } from '@angular/core'; import { OAuthService, NullValidationHandler } from 'angular-oauth2-oidc'; import { Router } from '@angular/router'; import { filter } from 'rxjs/operators'; -import { authCodeFlowConfig } from './auth-code-flow.config'; +import { authConfig } from './auth.config'; import { useHash } from '../flags'; @Component({ // tslint:disable-next-line:component-selector - selector: 'flight-app', + selector: 'app-root', templateUrl: './app.component.html', }) export class AppComponent { @@ -24,7 +24,7 @@ export class AppComponent { } private configureCodeFlow(): void { - this.oauthService.configure(authCodeFlowConfig); + this.oauthService.configure(authConfig); this.oauthService.loadDiscoveryDocumentAndTryLogin().then((_) => { if (useHash) { this.router.navigate(['/']); @@ -32,6 +32,8 @@ export class AppComponent { }); // Optional - this.oauthService.setupAutomaticSilentRefresh(); + if (authConfig.useSilentRefresh) { + this.oauthService.setupAutomaticSilentRefresh(); + } } } diff --git a/src/app/app.config.ts b/src/app/app.config.ts new file mode 100644 index 0000000..848f8d3 --- /dev/null +++ b/src/app/app.config.ts @@ -0,0 +1,3 @@ +export const API_BASE_URL = 'http://localhost:8080'; +export const API_RELATIVE_PATH = '/api'; +export const API_URL = API_BASE_URL + API_RELATIVE_PATH; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index d92cb77..1d5b3cc 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -6,17 +6,19 @@ import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; import { APP_ROUTES } from './app.routes'; -import { BASE_URL } from './app.tokens'; +import { API_URL } from './app.config'; import { FlightHistoryComponent } from './flight-history/flight-history.component'; import { HomeComponent } from './home/home.component'; import { SharedModule } from './shared/shared.module'; import { RouterModule, ExtraOptions } from '@angular/router'; import { useHash } from '../flags'; +import { HeaderComponent } from './header/header.component'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; const ROUTING_OPTIONS: ExtraOptions = { // preloadingStrategy: CustomPreloadingStrategy, useHash, - initialNavigation: !useHash + initialNavigation: !useHash, }; @NgModule({ @@ -29,23 +31,25 @@ const ROUTING_OPTIONS: ExtraOptions = { SharedModule.forRoot(), OAuthModule.forRoot({ resourceServer: { - allowedUrls: ['http://localhost:8080/api'], - sendAccessToken: true - } - }) + allowedUrls: [API_URL], + sendAccessToken: true, + }, + }), + BrowserAnimationsModule, ], declarations: [ AppComponent, HomeComponent, - FlightHistoryComponent + FlightHistoryComponent, + HeaderComponent ], providers: [ // (useHash) ? { provide: LocationStrategy, useClass: HashLocationStrategy } : [], // {provide: AuthConfig, useValue: authConfig }, // { provide: OAuthStorage, useValue: localStorage }, // { provide: ValidationHandler, useClass: JwksValidationHandler }, - { provide: BASE_URL, useValue: 'http://localhost:8080' } + // { provide: BASE_URL, useValue: 'http://localhost:8080' } ], - bootstrap: [AppComponent] + bootstrap: [AppComponent], }) export class AppModule {} diff --git a/src/app/app.tokens.ts b/src/app/app.tokens.ts deleted file mode 100644 index 8ca1a03..0000000 --- a/src/app/app.tokens.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { InjectionToken } from '@angular/core'; - -export const BASE_URL = new InjectionToken('http://localhost:8080'); diff --git a/src/app/auth-code-flow.config.ts b/src/app/auth.config.ts similarity index 94% rename from src/app/auth-code-flow.config.ts rename to src/app/auth.config.ts index d8b64cc..07c13e5 100644 --- a/src/app/auth-code-flow.config.ts +++ b/src/app/auth.config.ts @@ -1,7 +1,7 @@ import { AuthConfig } from 'angular-oauth2-oidc'; import { useSilentRefreshForCodeFlow } from '../flags'; -export const authCodeFlowConfig: AuthConfig = { +export const authConfig: AuthConfig = { issuer: 'https://auth.fosil.eu/auth/realms/fosil', // URL of the SPA to redirect the user to after login @@ -45,8 +45,9 @@ export const authCodeFlowConfig: AuthConfig = { showDebugInformation: true, sessionChecksEnabled: true, + sessionCheckIntervall: 10000, - timeoutFactor: 0.5, + timeoutFactor: 0.75, // disablePKCI: true, clearHashAfterLogin: false diff --git a/src/app/flight-booking/flight-booking.routes.ts b/src/app/flight-booking/flight-booking.routes.ts index ffbed7b..8e7ad7c 100644 --- a/src/app/flight-booking/flight-booking.routes.ts +++ b/src/app/flight-booking/flight-booking.routes.ts @@ -6,7 +6,7 @@ import { FlightBookingComponent } from './flight-booking.component'; import { AuthGuard } from '../shared/auth/auth.guard'; import { LeaveComponentGuard } from '../shared/deactivation/LeaveComponentGuard'; -let FLIGHT_BOOKING_ROUTES: Routes = [ +const FLIGHT_BOOKING_ROUTES: Routes = [ { path: '', component: FlightBookingComponent, diff --git a/src/app/flight-booking/services/flight.service.ts b/src/app/flight-booking/services/flight.service.ts index 27171c6..0667830 100644 --- a/src/app/flight-booking/services/flight.service.ts +++ b/src/app/flight-booking/services/flight.service.ts @@ -1,6 +1,6 @@ import { Injectable, Inject } from '@angular/core'; import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; -import { BASE_URL } from '../../app.tokens'; +import { API_URL } from '../../app.config'; import { Observable } from 'rxjs'; import { Flight } from '../../entities/flight'; import { OAuthService } from 'angular-oauth2-oidc'; @@ -9,14 +9,13 @@ import { OAuthService } from 'angular-oauth2-oidc'; export class FlightService { constructor( private oauthService: OAuthService, - private http: HttpClient, - @Inject(BASE_URL) private baseUrl: string + private http: HttpClient ) {} public flights: Array = []; find(from: string, to: string): void { - let url = this.baseUrl + '/api/flight'; + let url = API_URL + '/flight'; let headers = new HttpHeaders().set('Accept', 'application/json'); //.set('Authorization', 'Bearer ' + this.oauthService.getAccessToken()); diff --git a/src/app/header/header.component.css b/src/app/header/header.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/header/header.component.html b/src/app/header/header.component.html new file mode 100644 index 0000000..e09d086 --- /dev/null +++ b/src/app/header/header.component.html @@ -0,0 +1,13 @@ +
+ + +
+ + {{ name }} + + + + + + +
diff --git a/src/app/header/header.component.spec.ts b/src/app/header/header.component.spec.ts new file mode 100644 index 0000000..7efd662 --- /dev/null +++ b/src/app/header/header.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LoginComponent } from './header.component'; + +describe('LoginComponent', () => { + let component: LoginComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ LoginComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(LoginComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/header/header.component.ts b/src/app/header/header.component.ts new file mode 100644 index 0000000..3b3d50d --- /dev/null +++ b/src/app/header/header.component.ts @@ -0,0 +1,37 @@ +import { Component, OnInit } from '@angular/core'; +import { OAuthService } from 'angular-oauth2-oidc'; +import { authConfig } from '../auth.config'; + +@Component({ + selector: 'app-header', + templateUrl: './header.component.html', + styleUrls: ['./header.component.css'], +}) +export class HeaderComponent implements OnInit { + constructor(private oauthService: OAuthService) {} + + ngOnInit(): void {} + + async login(): Promise { + // Tweak config for code flow + this.oauthService.configure(authConfig); + console.log('login pre'); + await this.oauthService.loadDiscoveryDocument(); + console.log('login post'); + sessionStorage.setItem('flow', 'code'); + + this.oauthService.initLoginFlow(); + } + + logout(): void { + this.oauthService.revokeTokenAndLogout(); + } + + get name(): any { + const claims = this.oauthService.getIdentityClaims(); + if (!claims) { + return null; + } + return claims['name']; + } +} diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html index 92ca2f3..f2f502b 100644 --- a/src/app/home/home.component.html +++ b/src/app/home/home.component.html @@ -1,60 +1,3 @@ -Status: {{ givenName ? 'logged in' : 'logged out' }} -

Welcome!

-

Welcome, {{ givenName }} {{ familyName }}!

- -
- You have to login before you can search for flights. -
- -
-
-

Login with Authorization Server

-
- -
-
-
-

Test settings

-
- -
-
-
- -
-
-

Login with Code Flow

-

- - -

- Username/Password: alice/alice -
-
- -
-
-

Login with Code Flow in popup

-

- - -

-

Username/Password: alice/alice

-

- Note: When using IE, some security settings block the communication - with popups. This prevents that this feature works. -

-
-
-

access_token_expiration: {{ access_token_expiration }}

diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index 3e5b50c..aa4fe97 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -1,6 +1,5 @@ import { Component, OnInit } from '@angular/core'; import { OAuthService } from 'angular-oauth2-oidc'; -import { authCodeFlowConfig } from '../auth-code-flow.config'; import { ActivatedRoute } from '@angular/router'; @Component({ @@ -33,27 +32,6 @@ export class HomeComponent implements OnInit { */ } - async loginCode(): Promise { - // Tweak config for code flow - this.oauthService.configure(authCodeFlowConfig); - await this.oauthService.loadDiscoveryDocument(); - sessionStorage.setItem('flow', 'code'); - - this.oauthService.initLoginFlow('/some-state;p1=1;p2=2?p3=3&p4=4'); - // the parameter here is optional. It's passed around and can be used after logging in - } - - async loginCodeInPopup(): Promise { - // Tweak config for code flow - this.oauthService.configure(authCodeFlowConfig); - await this.oauthService.loadDiscoveryDocument(); - sessionStorage.setItem('flow', 'code'); - - this.oauthService.initLoginFlowInPopup().then(() => { - this.loadUserProfile(); - }); - } - logout(): void { // this.oauthService.logOut(); this.oauthService.revokeTokenAndLogout(); diff --git a/src/assets/img/logo.png b/src/assets/img/logo.png new file mode 100644 index 0000000..32bc79a Binary files /dev/null and b/src/assets/img/logo.png differ diff --git a/src/custom-theme.scss b/src/custom-theme.scss new file mode 100644 index 0000000..2eae6fb --- /dev/null +++ b/src/custom-theme.scss @@ -0,0 +1,35 @@ + +// Custom Theming for Angular Material +// For more information: https://material.angular.io/guide/theming +@import '~@angular/material/theming'; +// Plus imports for other components in your app. + +// Include the common styles for Angular Material. We include this here so that you only +// have to load a single css file for Angular Material in your app. +// Be sure that you only ever include this mixin once! +@include mat-core(); + +// Define the palettes for your theme using the Material Design palettes available in palette.scss +// (imported above). For each palette, you can optionally specify a default, lighter, and darker +// hue. Available color palettes: https://material.io/design/color/ +$sample-oauth-primary: mat-palette($mat-indigo); +$sample-oauth-accent: mat-palette($mat-pink, A200, A100, A400); + +// The warn palette is optional (defaults to red). +$sample-oauth-warn: mat-palette($mat-red); + +// Create the theme object. A theme consists of configurations for individual +// theming systems such as "color" or "typography". +$sample-oauth-theme: mat-light-theme(( + color: ( + primary: $sample-oauth-primary, + accent: $sample-oauth-accent, + warn: $sample-oauth-warn, + ) +)); + +// Include theme styles for core and each component used in your app. +// Alternatively, you can import and @include the theme mixins for each component +// that you are using. +@include angular-material-theme($sample-oauth-theme); + diff --git a/src/index.html b/src/index.html index 3b3807a..63736d2 100644 --- a/src/index.html +++ b/src/index.html @@ -2,13 +2,15 @@ - Sample + Okupa mi coche - - - + + + + + diff --git a/src/styles.css b/src/styles.css index 90d4ee0..7e7239a 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1 +1,4 @@ /* You can add global styles to this file, and also import other style files */ + +html, body { height: 100%; } +body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }