Fixed minor issues with login & logout. Cleaned up the UI.

This commit is contained in:
Tom 2025-01-09 18:11:44 +00:00
parent d595c3500e
commit 2692294b4b
8 changed files with 128 additions and 86 deletions

View File

@ -1,67 +1,72 @@
import { CommonModule, isPlatformBrowser } from '@angular/common'; import { isPlatformBrowser } from '@angular/common';
import { Component, OnInit, Inject, PLATFORM_ID, NgZone, OnDestroy } from '@angular/core'; import { Component, OnInit, Inject, PLATFORM_ID, NgZone, OnDestroy } from '@angular/core';
import { Router, RouterOutlet } from '@angular/router'; import { Router, RouterOutlet } from '@angular/router';
import { FormsModule } from '@angular/forms'
import { HermesClientService } from './hermes-client.service'; import { HermesClientService } from './hermes-client.service';
import { AuthUserGuard } from './shared/auth/auth.user.guard' import { AuthUserGuard } from './shared/auth/auth.user.guard'
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { NavigationComponent } from "./navigation/navigation.component"; import { NavigationComponent } from "./navigation/navigation.component";
import EventService from './shared/services/EventService'; import EventService from './shared/services/EventService';
import { ApiAuthenticationService } from './shared/services/api/api-authentication.service'; import { ApiAuthenticationService } from './shared/services/api/api-authentication.service';
import { PoliciesModule } from './policies/policies.module';
import { TtsFiltersModule } from './tts-filters/tts-filters.module';
import { AuthModule } from './auth/auth.module'; import { AuthModule } from './auth/auth.module';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
standalone: true, standalone: true,
imports: [RouterOutlet, CommonModule, FormsModule, PoliciesModule, TtsFiltersModule, AuthModule, NavigationComponent], imports: [RouterOutlet, AuthModule, NavigationComponent],
providers: [AuthUserGuard], providers: [AuthUserGuard],
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrl: './app.component.scss' styleUrl: './app.component.scss'
}) })
export class AppComponent implements OnInit, OnDestroy { export class AppComponent implements OnInit, OnDestroy {
private isBrowser: boolean; private isBrowser: boolean;
private ngZone: NgZone; private ngZone: NgZone;
private subscriptions: Subscription[]; private subscriptions: Subscription[];
constructor(private auth: ApiAuthenticationService, private client: HermesClientService, private events: EventService, private router: Router, ngZone: NgZone, @Inject(PLATFORM_ID) private platformId: Object) { constructor(private auth: ApiAuthenticationService, private client: HermesClientService, private events: EventService, private router: Router, ngZone: NgZone, @Inject(PLATFORM_ID) private platformId: Object) {
this.ngZone = ngZone; this.ngZone = ngZone;
this.isBrowser = isPlatformBrowser(this.platformId); this.isBrowser = isPlatformBrowser(this.platformId);
this.subscriptions = []; this.subscriptions = [];
}
ngOnInit(): void {
if (!this.isBrowser)
return;
this.auth.update();
this.addSubscription(this.events.listen('logoff', async (message) => {
localStorage.removeItem('jwt');
if (!document.location.href.includes('/login')) {
if (message)
await this.router.navigate(['login'], {
queryParams: { message: message }
});
else
await this.router.navigate(['login']);
}
}));
this.addSubscription(this.events.listen('login', async (_) => {
if (['/login', '/auth'].some(partial => document.location.href.includes(partial))) {
await this.router.navigate(['tts-login']);
}
}));
const connection = this.client.connect();
if (connection) {
this.addSubscription(connection);
} }
this.ngZone.runOutsideAngular(() => setInterval(() => this.client.heartbeat(), 15000));
}
ngOnInit(): void { ngOnDestroy() {
if (!this.isBrowser) for (let s of this.subscriptions) {
return; s.unsubscribe();
this.auth.update();
this.addSubscription(this.events.listen('logoff', (message) => {
localStorage.removeItem('jwt');
if (!document.location.href.includes('/login')) {
this.router.navigate(['/login?warning=' + message]);
}
}));
this.addSubscription(this.events.listen('login', (_) => {
if (document.location.href.includes('/login')) {
this.router.navigate(['/tts-login']);
}
}));
this.client.connect();
this.ngZone.runOutsideAngular(() => setInterval(() => this.client.heartbeat(), 15000));
} }
}
ngOnDestroy() { private addSubscription(s: Subscription) {
for (let s of this.subscriptions) { this.subscriptions.push(s);
s.unsubscribe(); }
}
}
private addSubscription(s: Subscription) {
this.subscriptions.push(s);
}
} }

View File

@ -59,10 +59,10 @@ export class ImpersonationComponent implements OnInit {
body: { body: {
impersonation: e.value impersonation: e.value
} }
}).subscribe((data: any) => { }).subscribe(async (data: any) => {
this.hermes.disconnect(); this.hermes.disconnect();
this.events.emit('impersonation', e.value); this.events.emit('impersonation', e.value);
this.router.navigate(['/tts-login']); await this.router.navigate(['tts-login']);
}); });
} else { } else {
this.http.put(environment.API_HOST + '/admin/impersonate', { this.http.put(environment.API_HOST + '/admin/impersonate', {
@ -71,10 +71,10 @@ export class ImpersonationComponent implements OnInit {
headers: { headers: {
'Authorization': 'Bearer ' + localStorage.getItem('jwt') 'Authorization': 'Bearer ' + localStorage.getItem('jwt')
} }
}).subscribe((data: any) => { }).subscribe(async (data: any) => {
this.hermes.disconnect(); this.hermes.disconnect();
this.events.emit('impersonation', e.value); this.events.emit('impersonation', e.value);
this.router.navigate(['/tts-login']); await this.router.navigate(['tts-login']);
}); });
} }
} }

View File

@ -1,21 +1,19 @@
<div class="login"> <div class="login">
<div></div> <mat-card class="outer" appearance="outlined">
<mat-card class="outer" appearance="outlined"> <mat-card-header>
<mat-card-header> <h1 class="title">Login</h1>
<h1>Login</h1> </mat-card-header>
</mat-card-header>
<mat-card-content> <mat-card-content class="services">
<p>Log in with your favorite livestream service</p> <p>Log in with your favorite livestream service</p>
<a> <a>
<mat-card appearance="outlined" (click)="login()"> <mat-card appearance="outlined" class="twitch" (click)="login()">
<mat-card-content> <mat-card-content>
Twitch Twitch
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
</a> </a>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
<div></div>
</div> </div>

View File

@ -1,13 +1,35 @@
.login { .login {
display: grid; height: 100vh;
grid-template-columns: 1fr max-content 1fr; display: flex;
place-items: center; flex-direction: column;
align-items: center;
justify-content: center;
} }
.mat-mdc-card-header { .mat-mdc-card-header {
align-self: center; display: grid;
grid-template-columns: 1fr;
}
.title {
text-align: center;
margin: 0;
} }
.mat-mdc-card-content { .mat-mdc-card-content {
align-self: center; align-self: center;
}
a {
cursor: pointer;
}
.services p {
margin-bottom: 2em;
}
.twitch {
background-color: #a970ff;
color: black;
font-weight: 500;
} }

View File

@ -36,12 +36,12 @@ export class TtsLoginComponent implements OnInit, OnDestroy {
} }
}).subscribe((data: any) => this.api_keys = data); }).subscribe((data: any) => this.api_keys = data);
this.subscription = this.events.listen('tts_login_ack', _ => { this.subscription = this.events.listen('tts_login_ack', async _ => {
this.router.navigate(['/policies']) await this.router.navigate(['policies'])
}); });
this.events.listen('tts_logoff', _ => { this.events.listen('tts_logoff', async _ => {
this.selected_api_key = undefined; this.selected_api_key = undefined;
this.router.navigate(['/tts-login']) await this.router.navigate(['tts-login'])
}); });
this.events.listen('impersonation', _ => { this.events.listen('impersonation', _ => {
this.selected_api_key = undefined; this.selected_api_key = undefined;

View File

@ -32,7 +32,7 @@ export class PolicyComponent implements OnInit, OnDestroy {
return; return;
if (!this.client.logged_in) { if (!this.client.logged_in) {
this.router.navigate(["/tts-login"]); this.router.navigate(["tts-login"]);
return; return;
} }
} }

View File

@ -58,7 +58,7 @@ export class FiltersComponent implements OnInit, OnDestroy {
return; return;
if (!this.client.logged_in) { if (!this.client.logged_in) {
this.router.navigate(["/tts-login"]); this.router.navigate(["tts-login"]);
return; return;
} }
} }

View File

@ -19,28 +19,45 @@ export class TwitchAuthCallbackComponent implements OnInit {
this.isBrowser = isPlatformBrowser(this.platformId) this.isBrowser = isPlatformBrowser(this.platformId)
} }
ngOnInit(): void { async ngOnInit(): Promise<any> {
if (!this.isBrowser) { if (!this.isBrowser) {
return; return;
} }
if (this.auth.isAuthenticated()) {
await this.router.navigate(['tts-login']);
return;
}
const code = this.route.snapshot.queryParamMap.get('code'); const code = this.route.snapshot.queryParamMap.get('code');
const scope = this.route.snapshot.queryParamMap.get('scope'); const scope = this.route.snapshot.queryParamMap.get('scope');
const state = this.route.snapshot.queryParamMap.get('state'); const state = this.route.snapshot.queryParamMap.get('state');
if (!code || !scope || !state) if (!code || !scope || !state) {
await this.router.navigate(['login'], {
queryParams: {
error: 'callback_issue'
}
});
return; return;
}
this.http.post(environment.API_HOST + '/auth/twitch/callback', { code, scope, state }) this.http.post(environment.API_HOST + '/auth/twitch/callback', { code, scope, state })
.subscribe((data: any) => { .subscribe(async (response: any) => {
if (!data?.authenticated) { if (!response?.authenticated) {
this.router.navigate(['/login?error=callback_error']); await this.router.navigate(['login'], {
queryParams: {
error: 'callback_issue'
}
});
return; return;
} }
localStorage.setItem('jwt', data.token); localStorage.setItem('jwt', response.token);
this.auth.update(); this.auth.update();
this.router.navigate(['/tts-login']);
console.log('logged in. so nav to tts login.');
await this.router.navigate(['tts-login']);
}); });
} }
} }