From 2bde8b850a566c47bc0499f8613d2899399d1479 Mon Sep 17 00:00:00 2001 From: Tom Date: Thu, 31 Oct 2024 05:33:11 +0000 Subject: [PATCH] Added impersonation. More data available via auth service about the user. Added admin auth guard. --- src/app/app.component.html | 2 +- src/app/app.component.ts | 4 +- src/app/app.routes.ts | 6 +- src/app/hermes-client.service.ts | 5 +- .../impersonation.component.html | 19 +++++ .../impersonation.component.scss | 0 .../impersonation.component.spec.ts | 23 ++++++ .../impersonation/impersonation.component.ts | 82 +++++++++++++++++++ src/app/navigation/navigation.component.html | 7 +- src/app/navigation/navigation.component.ts | 12 ++- .../policy-table/policy-table.component.ts | 1 - .../{auth.guard.ts => auth.admin.guard.ts} | 10 +-- src/app/shared/auth/auth.user.guard.ts | 15 ++++ .../api/api-authentication.service.ts | 53 +++++++----- src/app/tts-login/tts-login.component.html | 4 +- src/app/tts-login/tts-login.component.ts | 22 ++++- 16 files changed, 218 insertions(+), 47 deletions(-) create mode 100644 src/app/impersonation/impersonation.component.html create mode 100644 src/app/impersonation/impersonation.component.scss create mode 100644 src/app/impersonation/impersonation.component.spec.ts create mode 100644 src/app/impersonation/impersonation.component.ts rename src/app/shared/auth/{auth.guard.ts => auth.admin.guard.ts} (69%) create mode 100644 src/app/shared/auth/auth.user.guard.ts diff --git a/src/app/app.component.html b/src/app/app.component.html index bf4f620..c906b11 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,4 +1,4 @@
- +
\ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 20620ad..8b8851a 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -3,7 +3,7 @@ import { Component, OnInit, Inject, PLATFORM_ID, NgZone, OnDestroy } from '@angu import { Router, RouterOutlet } from '@angular/router'; import { FormsModule } from '@angular/forms' import { HermesClientService } from './hermes-client.service'; -import { AuthGuard } from './shared/auth/auth.guard' +import { AuthUserGuard } from './shared/auth/auth.user.guard' import { Subscription } from 'rxjs'; import { PolicyComponent } from "./policy/policy.component"; import { NavigationComponent } from "./navigation/navigation.component"; @@ -14,7 +14,7 @@ import { ApiAuthenticationService } from './shared/services/api/api-authenticati selector: 'app-root', standalone: true, imports: [RouterOutlet, CommonModule, FormsModule, PolicyComponent, NavigationComponent], - providers: [AuthGuard], + providers: [AuthUserGuard], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 585ecc8..b1373a8 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,6 +1,6 @@ import { Routes } from '@angular/router'; import { PolicyComponent } from './policy/policy.component'; -import { AuthGuard } from './shared/auth/auth.guard'; +import { AuthUserGuard } from './shared/auth/auth.user.guard'; import { LoginComponent } from './login/login.component'; import { TtsLoginComponent } from './tts-login/tts-login.component'; import { TwitchAuthCallbackComponent } from './twitch-auth-callback/twitch-auth-callback.component'; @@ -9,7 +9,7 @@ export const routes: Routes = [ { path: 'policies', component: PolicyComponent, - canActivate: [AuthGuard], + canActivate: [AuthUserGuard], }, { path: 'login', @@ -18,7 +18,7 @@ export const routes: Routes = [ { path: 'tts-login', component: TtsLoginComponent, - canActivate: [AuthGuard], + canActivate: [AuthUserGuard], }, { path: 'auth', diff --git a/src/app/hermes-client.service.ts b/src/app/hermes-client.service.ts index eef3710..6eb10fa 100644 --- a/src/app/hermes-client.service.ts +++ b/src/app/hermes-client.service.ts @@ -42,8 +42,9 @@ export class HermesClientService { if (!this.connected) return; - this.socket.close(); this.connected = false; + this.logged_in = false; + this.socket.close(); this.events.emit('tts_logoff', null); } @@ -58,6 +59,8 @@ export class HermesClientService { } public login(api_key: string) { + if (!this.connected) + this.connect(); if (this.logged_in) return; diff --git a/src/app/impersonation/impersonation.component.html b/src/app/impersonation/impersonation.component.html new file mode 100644 index 0000000..070a2a1 --- /dev/null +++ b/src/app/impersonation/impersonation.component.html @@ -0,0 +1,19 @@ +@if (isAdmin()) { + + + Impersonation + Impersonate as another user + + + + User to impersonate + + {{getUsername()}} + @for (user of users; track user) { + {{ user.name }} + } + + + + +} \ No newline at end of file diff --git a/src/app/impersonation/impersonation.component.scss b/src/app/impersonation/impersonation.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/impersonation/impersonation.component.spec.ts b/src/app/impersonation/impersonation.component.spec.ts new file mode 100644 index 0000000..3eda4a3 --- /dev/null +++ b/src/app/impersonation/impersonation.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ImpersonationComponent } from './impersonation.component'; + +describe('ImpersonationComponent', () => { + let component: ImpersonationComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ImpersonationComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ImpersonationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/impersonation/impersonation.component.ts b/src/app/impersonation/impersonation.component.ts new file mode 100644 index 0000000..1ee6107 --- /dev/null +++ b/src/app/impersonation/impersonation.component.ts @@ -0,0 +1,82 @@ +import { Component, Inject, OnInit, PLATFORM_ID } from '@angular/core'; +import { ApiAuthenticationService } from '../shared/services/api/api-authentication.service'; +import { MatCardModule } from '@angular/material/card'; +import { MatSelectModule } from '@angular/material/select'; +import { HttpClient } from '@angular/common/http'; +import { isPlatformBrowser } from '@angular/common'; +import { environment } from '../../environments/environment'; +import EventService from '../shared/services/EventService'; +import { HermesClientService } from '../hermes-client.service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'impersonation', + standalone: true, + imports: [MatCardModule, MatSelectModule], + templateUrl: './impersonation.component.html', + styleUrl: './impersonation.component.scss' +}) +export class ImpersonationComponent implements OnInit { + impersonated: string | undefined; + users: { id: string, name: string }[]; + + constructor(private hermes: HermesClientService, private auth: ApiAuthenticationService, private router: Router, private events: EventService, private http: HttpClient, @Inject(PLATFORM_ID) private platformId: Object) { + this.users = [] + } + + ngOnInit(): void { + if (!isPlatformBrowser(this.platformId)) { + return; + } + + this.http.get(environment.API_HOST + '/admin/users', { + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('jwt') + } + }).subscribe((data: any) => { + this.users = data.filter((d: any) => d.name != this.auth.getUsername()); + const id = this.auth.getImpersonatedId(); + if (this.users.find(u => u.id == id)) { + this.impersonated = id; + } + }); + } + + public isAdmin() { + return this.auth.isAdmin(); + } + + public getUsername() { + return this.auth.getUsername(); + } + + public onChange(e: any) { + console.log('impersonate befre', e.value); + if (!e.value) { + this.http.delete(environment.API_HOST + '/admin/impersonate', { + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('jwt') + }, + body: { + impersonation: e.value + } + }).subscribe((data: any) => { + this.hermes.disconnect(); + this.events.emit('impersonation', e.value); + this.router.navigate(['/tts-login']); + }); + } else { + this.http.put(environment.API_HOST + '/admin/impersonate', { + impersonation: e.value + }, { + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('jwt') + } + }).subscribe((data: any) => { + this.hermes.disconnect(); + this.events.emit('impersonation', e.value); + this.router.navigate(['/tts-login']); + }); + } + } +} diff --git a/src/app/navigation/navigation.component.html b/src/app/navigation/navigation.component.html index beadf50..9f59bf9 100644 --- a/src/app/navigation/navigation.component.html +++ b/src/app/navigation/navigation.component.html @@ -1,10 +1,11 @@