auth stuff
This commit is contained in:
@ -1,11 +1,15 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { LoginComponent } from './login/login.component';
|
||||||
|
import { LogoutComponent } from './logout/logout.component';
|
||||||
import { TestOutputComponent } from './test-output/test-output.component';
|
import { TestOutputComponent } from './test-output/test-output.component';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: 'test', component: TestOutputComponent }
|
{ path: 'test', component: TestOutputComponent },
|
||||||
|
{ path: 'logout', component: LogoutComponent },
|
||||||
|
{ path: 'login', component: LoginComponent }
|
||||||
]
|
]
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -17,13 +17,20 @@ import { MatCardModule } from '@angular/material/card';
|
|||||||
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||||
import { ErrorHandlerInterceptor } from './error-handler.interceptor';
|
import { ErrorHandlerInterceptor } from './error-handler.interceptor';
|
||||||
import { AuthHandlerInterceptor } from './auth-handler.interceptor';
|
import { AuthHandlerInterceptor } from './auth-handler.interceptor';
|
||||||
|
import { LogoutComponent } from './logout/logout.component';
|
||||||
|
import { LoginComponent } from './login/login.component';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
NavigationComponent,
|
NavigationComponent,
|
||||||
MessagesComponent,
|
MessagesComponent,
|
||||||
TestOutputComponent
|
TestOutputComponent,
|
||||||
|
LogoutComponent,
|
||||||
|
LoginComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@ -36,7 +43,10 @@ import { AuthHandlerInterceptor } from './auth-handler.interceptor';
|
|||||||
MatIconModule,
|
MatIconModule,
|
||||||
MatListModule,
|
MatListModule,
|
||||||
MatCardModule,
|
MatCardModule,
|
||||||
AppRoutingModule
|
AppRoutingModule,
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MatInputModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: HTTP_INTERCEPTORS, useClass: ErrorHandlerInterceptor, multi: true },
|
{ provide: HTTP_INTERCEPTORS, useClass: ErrorHandlerInterceptor, multi: true },
|
||||||
|
@ -15,9 +15,10 @@ export class AuthHandlerInterceptor implements HttpInterceptor {
|
|||||||
constructor(private tokenService: TokenService, private messageService: MessageService) {}
|
constructor(private tokenService: TokenService, private messageService: MessageService) {}
|
||||||
|
|
||||||
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
||||||
if (request.url.includes('api.hv.nober.de')) {
|
const token = localStorage.getItem(TokenService.Id_Token_Key)
|
||||||
|
if (request.url.includes('api.hv.nober.de') && token) {
|
||||||
const clone = request.clone({
|
const clone = request.clone({
|
||||||
setHeaders: { Authorization: `Bearer ${this.tokenService.getToken()}`}
|
setHeaders: { Authorization: `Bearer ${token}`}
|
||||||
})
|
})
|
||||||
return next.handle(clone)
|
return next.handle(clone)
|
||||||
}
|
}
|
||||||
|
0
hv2-ui/src/app/login/login.component.css
Normal file
0
hv2-ui/src/app/login/login.component.css
Normal file
23
hv2-ui/src/app/login/login.component.html
Normal file
23
hv2-ui/src/app/login/login.component.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<mat-card>
|
||||||
|
<mat-card-content>
|
||||||
|
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
||||||
|
<h2>Log In</h2>
|
||||||
|
<mat-error *ngIf="loginInvalid">
|
||||||
|
The username and password were not recognized
|
||||||
|
</mat-error>
|
||||||
|
<mat-form-field class="full-width-input">
|
||||||
|
<input matInput placeholder="Username" formControlName="username" required>
|
||||||
|
<mat-error>
|
||||||
|
Please provide a valid email address
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="full-width-input">
|
||||||
|
<input matInput type="password" placeholder="Password" formControlName="password" required>
|
||||||
|
<mat-error>
|
||||||
|
Please provide a valid password
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<button mat-raised-button color="primary">Login</button>
|
||||||
|
</form>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
25
hv2-ui/src/app/login/login.component.spec.ts
Normal file
25
hv2-ui/src/app/login/login.component.spec.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LoginComponent } from './login.component';
|
||||||
|
|
||||||
|
describe('LoginComponent', () => {
|
||||||
|
let component: LoginComponent;
|
||||||
|
let fixture: ComponentFixture<LoginComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ LoginComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(LoginComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
51
hv2-ui/src/app/login/login.component.ts
Normal file
51
hv2-ui/src/app/login/login.component.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { MessageService } from '../message.service';
|
||||||
|
import { TokenService } from '../token.service';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-login',
|
||||||
|
templateUrl: './login.component.html',
|
||||||
|
styleUrls: ['./login.component.css']
|
||||||
|
})
|
||||||
|
export class LoginComponent implements OnInit {
|
||||||
|
form: FormGroup;
|
||||||
|
public loginInvalid = false;
|
||||||
|
private formSubmitAttempt = false;
|
||||||
|
private returnUrl: string;
|
||||||
|
|
||||||
|
constructor(private fb: FormBuilder,
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
|
private tokenService: TokenService,
|
||||||
|
private messageService: MessageService) {
|
||||||
|
this.returnUrl = this.route.snapshot.queryParams.returnUrl || '/'
|
||||||
|
|
||||||
|
this.form = this.fb.group({
|
||||||
|
username: ['', Validators.required],
|
||||||
|
password: ['', Validators.required]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
async onSubmit(): Promise<void> {
|
||||||
|
this.loginInvalid = false;
|
||||||
|
this.formSubmitAttempt = false;
|
||||||
|
if (this.form.valid) {
|
||||||
|
try {
|
||||||
|
const username = this.form.get('username')?.value;
|
||||||
|
const password = this.form.get('password')?.value;
|
||||||
|
await this.tokenService.login(username, password);
|
||||||
|
} catch (err) {
|
||||||
|
this.loginInvalid = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.formSubmitAttempt = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
0
hv2-ui/src/app/logout/logout.component.css
Normal file
0
hv2-ui/src/app/logout/logout.component.css
Normal file
17
hv2-ui/src/app/logout/logout.component.html
Normal file
17
hv2-ui/src/app/logout/logout.component.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<section class="mat-typography">
|
||||||
|
<mat-card class="defaultCard">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>
|
||||||
|
Logout
|
||||||
|
</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<h2>Good bye</h2>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</section>
|
25
hv2-ui/src/app/logout/logout.component.spec.ts
Normal file
25
hv2-ui/src/app/logout/logout.component.spec.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LogoutComponent } from './logout.component';
|
||||||
|
|
||||||
|
describe('LogoutComponent', () => {
|
||||||
|
let component: LogoutComponent;
|
||||||
|
let fixture: ComponentFixture<LogoutComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ LogoutComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(LogoutComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
19
hv2-ui/src/app/logout/logout.component.ts
Normal file
19
hv2-ui/src/app/logout/logout.component.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { MessageService } from '../message.service';
|
||||||
|
import { TokenService } from '../token.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-logout',
|
||||||
|
templateUrl: './logout.component.html',
|
||||||
|
styleUrls: ['./logout.component.css']
|
||||||
|
})
|
||||||
|
export class LogoutComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor(private messageService: MessageService) { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
localStorage.removeItem(TokenService.Id_Token_Key)
|
||||||
|
this.messageService.add("Token removed from local storage")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,6 +6,8 @@
|
|||||||
<mat-toolbar>Menu</mat-toolbar>
|
<mat-toolbar>Menu</mat-toolbar>
|
||||||
<mat-nav-list>
|
<mat-nav-list>
|
||||||
<a mat-list-item href="/test">Mein Test</a>
|
<a mat-list-item href="/test">Mein Test</a>
|
||||||
|
<a mat-list-item href="/login">Login</a>
|
||||||
|
<a mat-list-item href="/logout">Logout</a>
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
<mat-sidenav-content>
|
<mat-sidenav-content>
|
||||||
|
@ -12,7 +12,7 @@ import { TestOutput } from './testOutput';
|
|||||||
export class TestOutputService {
|
export class TestOutputService {
|
||||||
constructor(private messageService: MessageService, private http: HttpClient) { }
|
constructor(private messageService: MessageService, private http: HttpClient) { }
|
||||||
|
|
||||||
getTestOutput(): Promise<TestOutput> {
|
async getTestOutput(): Promise<TestOutput> {
|
||||||
this.messageService.add(`TestOutputService: fetch test output`);
|
this.messageService.add(`TestOutputService: fetch test output`);
|
||||||
return this.http.get<TestOutput>(`${serviceBaseUrl}/v1/test`).toPromise()
|
return this.http.get<TestOutput>(`${serviceBaseUrl}/v1/test`).toPromise()
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,33 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { MessageService } from './message.service';
|
import { MessageService } from './message.service';
|
||||||
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
|
import { UserCreds } from './userCreds'
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class TokenService {
|
export class TokenService {
|
||||||
|
|
||||||
private token: String;
|
public static Id_Token_Key : string = "id_token";
|
||||||
|
|
||||||
constructor(private messageService: MessageService) {
|
constructor(private http: HttpClient, private messageService: MessageService) {
|
||||||
this.messageService.add("TokenService started, token created")
|
this.messageService.add("TokenService started, token created")
|
||||||
this.token = "abc"
|
|
||||||
|
if (! localStorage.getItem(TokenService.Id_Token_Key)) {
|
||||||
|
localStorage.setItem(TokenService.Id_Token_Key, "abc")
|
||||||
|
this.messageService.add("Token set in local storage")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getToken(): String {
|
|
||||||
this.messageService.add("Providing token to other service")
|
async login(login: string, password: string) {
|
||||||
return this.token
|
this.messageService.add(`TokenService: trying to login and obtain token`);
|
||||||
|
const userCreds : UserCreds = {
|
||||||
|
"application": "hv2",
|
||||||
|
"login": login,
|
||||||
|
"password": password
|
||||||
|
}
|
||||||
|
const token = await this.http.post<String>("https://authservice.hottis.de/token", userCreds).toPromise()
|
||||||
|
this.messageService.add(`Token is ${JSON.stringify(token, undefined, 4)}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
5
hv2-ui/src/app/userCreds.ts
Normal file
5
hv2-ui/src/app/userCreds.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export interface UserCreds {
|
||||||
|
application: string
|
||||||
|
login: string
|
||||||
|
password: string
|
||||||
|
}
|
Reference in New Issue
Block a user