Added top bar on all pages. Simplified TTS login component. Fixed some issues. Removed redirects for now.
This commit is contained in:
@ -1,6 +1,5 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { LoginComponent } from './login/login.component';
|
||||
import { TtsLoginComponent } from './tts-login/tts-login.component';
|
||||
import { ImpersonationComponent } from './impersonation/impersonation.component';
|
||||
import { UserCardComponent } from './user-card/user-card.component';
|
||||
|
||||
@ -8,7 +7,6 @@ import { UserCardComponent } from './user-card/user-card.component';
|
||||
declarations: [],
|
||||
imports: [
|
||||
LoginComponent,
|
||||
TtsLoginComponent,
|
||||
ImpersonationComponent,
|
||||
UserCardComponent,
|
||||
]
|
||||
|
@ -1,9 +1,9 @@
|
||||
@if (isAdmin()) {
|
||||
<main>
|
||||
<mat-form-field>
|
||||
<mat-form-field class="mat-small"
|
||||
subscriptSizing="dynamic">
|
||||
<mat-label>User to impersonate</mat-label>
|
||||
<mat-select (selectionChange)="onChange($event)"
|
||||
[(value)]="impersonated">
|
||||
<mat-select [formControl]="impersonationControl">
|
||||
<mat-option>{{getUsername()}}</mat-option>
|
||||
@for (user of users; track user.id) {
|
||||
<mat-option [value]="user.id">{{ user.name }}</mat-option>
|
||||
|
@ -2,5 +2,4 @@ main {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 1em;
|
||||
}
|
@ -8,56 +8,76 @@ import { environment } from '../../../environments/environment';
|
||||
import EventService from '../../shared/services/EventService';
|
||||
import { HermesClientService } from '../../hermes-client.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { timeout, first } from 'rxjs';
|
||||
import ApiKey from '../../shared/models/api-key';
|
||||
import { ApiKeyService } from '../../shared/services/api/api-key.service';
|
||||
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||
import { User } from '../../shared/models/user';
|
||||
import { UserService } from '../../shared/services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'impersonation',
|
||||
standalone: true,
|
||||
imports: [MatCardModule, MatSelectModule],
|
||||
imports: [
|
||||
MatCardModule,
|
||||
MatSelectModule,
|
||||
ReactiveFormsModule,
|
||||
],
|
||||
templateUrl: './impersonation.component.html',
|
||||
styleUrl: './impersonation.component.scss'
|
||||
})
|
||||
export class ImpersonationComponent implements OnInit {
|
||||
private readonly keyService = inject(ApiKeyService);
|
||||
private readonly events = inject(EventService);
|
||||
private readonly userService = inject(UserService);
|
||||
|
||||
impersonated: string | undefined;
|
||||
users: { id: string, name: string }[];
|
||||
impersonationControl = new FormControl<string | undefined>(undefined);
|
||||
users: User[];
|
||||
|
||||
constructor(private client: HermesClientService, private auth: ApiAuthenticationService, private router: Router, private events: EventService, private http: HttpClient, @Inject(PLATFORM_ID) private platformId: Object) {
|
||||
this.users = []
|
||||
constructor(private client: HermesClientService, private auth: ApiAuthenticationService, private router: Router, private http: HttpClient, @Inject(PLATFORM_ID) private platformId: Object) {
|
||||
this.users = [];
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (!isPlatformBrowser(this.platformId) || !this.auth.isAdmin()) {
|
||||
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());
|
||||
this.userService.fetch().subscribe(users => {
|
||||
this.users = users.filter((d: any) => d.name != this.auth.getUsername());
|
||||
const id = this.auth.getImpersonatedId();
|
||||
if (id && this.users.find(u => u.id == id)) {
|
||||
this.impersonated = id;
|
||||
this.impersonationControl.setValue(id);
|
||||
}
|
||||
});
|
||||
|
||||
this.events.listen('impersonation', (userId) => {
|
||||
const url = this.router.url;
|
||||
this.client.first(d => d.op == 2 && !d.d.another_client)
|
||||
.subscribe(async _ =>
|
||||
await setTimeout(async () =>
|
||||
await this.router.navigate([url.substring(1)]), 500));
|
||||
this.keyService.fetch()
|
||||
.pipe(timeout(3000), first())
|
||||
.subscribe(async (d: ApiKey[]) => {
|
||||
if (d.length > 0)
|
||||
this.client.login(d[0].id);
|
||||
this.impersonationControl.valueChanges.subscribe((impersonationId) => {
|
||||
if (!this.auth.isAdmin() || impersonationId == this.auth.getImpersonatedId())
|
||||
return;
|
||||
|
||||
if (!impersonationId) {
|
||||
this.http.delete(environment.API_HOST + '/admin/impersonate', {
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + localStorage.getItem('jwt')
|
||||
},
|
||||
body: {
|
||||
impersonation: impersonationId
|
||||
}
|
||||
}).subscribe(async (data: any) => {
|
||||
this.impersonationControl.setValue(undefined);
|
||||
this.client.disconnect(true);
|
||||
this.events.emit('impersonation', undefined);
|
||||
});
|
||||
} else {
|
||||
this.http.put(environment.API_HOST + '/admin/impersonate', {
|
||||
impersonation: impersonationId
|
||||
}, {
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + localStorage.getItem('jwt')
|
||||
}
|
||||
}).subscribe(async (data: any) => {
|
||||
this.impersonationControl.setValue(impersonationId);
|
||||
this.client.disconnect(true);
|
||||
this.events.emit('impersonation', impersonationId);
|
||||
await this.router.navigate(['tts-login']);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -68,35 +88,4 @@ export class ImpersonationComponent implements OnInit {
|
||||
public getUsername() {
|
||||
return this.auth.getUsername();
|
||||
}
|
||||
|
||||
public onChange(e: any) {
|
||||
if (!this.auth.isAdmin())
|
||||
return;
|
||||
|
||||
if (!e.value) {
|
||||
this.http.delete(environment.API_HOST + '/admin/impersonate', {
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + localStorage.getItem('jwt')
|
||||
},
|
||||
body: {
|
||||
impersonation: e.value
|
||||
}
|
||||
}).subscribe(async (data: any) => {
|
||||
this.client.disconnect();
|
||||
this.events.emit('impersonation', e.value);
|
||||
});
|
||||
} else {
|
||||
this.http.put(environment.API_HOST + '/admin/impersonate', {
|
||||
impersonation: e.value
|
||||
}, {
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + localStorage.getItem('jwt')
|
||||
}
|
||||
}).subscribe(async (data: any) => {
|
||||
this.client.disconnect();
|
||||
this.events.emit('impersonation', e.value);
|
||||
await this.router.navigate(['tts-login']);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +1,15 @@
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { Router, RouterModule } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { environment } from '../../../environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'login',
|
||||
standalone: true,
|
||||
imports: [MatCardModule, RouterModule],
|
||||
imports: [MatCardModule],
|
||||
templateUrl: './login.component.html',
|
||||
styleUrl: './login.component.scss'
|
||||
})
|
||||
export class LoginComponent implements OnInit, OnDestroy {
|
||||
subscription: Subscription | null;
|
||||
|
||||
constructor(private router: Router) {
|
||||
this.subscription = null;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.subscription)
|
||||
this.subscription.unsubscribe()
|
||||
}
|
||||
|
||||
export class LoginComponent {
|
||||
login() {
|
||||
document.location.replace(environment.API_HOST + '/auth');
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
<mat-card-content class="content">
|
||||
<mat-form-field>
|
||||
<mat-label>API Key</mat-label>
|
||||
<mat-select [(value)]="selected_api_key">
|
||||
<mat-select [formControl]="keyControl">
|
||||
@for (key of api_keys; track key.id) {
|
||||
<mat-option [value]="key.id">{{key.label}}</mat-option>
|
||||
}
|
||||
|
@ -1,58 +1,41 @@
|
||||
import { Component, inject, OnDestroy, OnInit } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import EventService from '../../shared/services/EventService';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { first, Subscription, timeout } from 'rxjs';
|
||||
import { HermesClientService } from '../../hermes-client.service';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { ApiKeyService } from '../../shared/services/api/api-key.service';
|
||||
|
||||
@Component({
|
||||
selector: 'tts-login',
|
||||
standalone: true,
|
||||
imports: [MatButtonModule, MatCardModule, MatFormFieldModule, MatSelectModule, MatInputModule, FormsModule],
|
||||
imports: [
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatFormFieldModule,
|
||||
MatSelectModule,
|
||||
ReactiveFormsModule,
|
||||
],
|
||||
templateUrl: './tts-login.component.html',
|
||||
styleUrl: './tts-login.component.scss'
|
||||
})
|
||||
export class TtsLoginComponent implements OnInit, OnDestroy {
|
||||
export class TtsLoginComponent implements OnInit {
|
||||
private readonly client = inject(HermesClientService);
|
||||
private readonly keyService = inject(ApiKeyService);
|
||||
private readonly events = inject(EventService);
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
|
||||
keyControl = new FormControl<string | null>('');
|
||||
api_keys: { id: string, label: string }[] = [];
|
||||
selected_api_key: string | undefined;
|
||||
|
||||
private subscriptions: Subscription[] = [];
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
this.route.data.subscribe(d => this.api_keys = d['keys']);
|
||||
|
||||
this.subscriptions.push(this.events.listen('tts_logoff', async _ => {
|
||||
this.selected_api_key = undefined;
|
||||
}));
|
||||
this.subscriptions.push(this.events.listen('impersonation', _ => {
|
||||
this.selected_api_key = undefined;
|
||||
|
||||
this.keyService.fetch()
|
||||
.pipe(timeout(3000), first())
|
||||
.subscribe(d => this.api_keys = d);
|
||||
}));
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.subscriptions.forEach(s => s.unsubscribe());
|
||||
}
|
||||
|
||||
login(): void {
|
||||
if (!this.selected_api_key)
|
||||
if (!this.keyControl.value)
|
||||
return;
|
||||
|
||||
this.client.login(this.selected_api_key);
|
||||
this.client.login(this.keyControl.value);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user