diff --git a/src/app/auth/impersonation/impersonation.component.html b/src/app/auth/impersonation/impersonation.component.html index 3afe00c..985aa74 100644 --- a/src/app/auth/impersonation/impersonation.component.html +++ b/src/app/auth/impersonation/impersonation.component.html @@ -1,14 +1,12 @@ @if (isAdmin()) { -
- - User to impersonate - - {{getUsername()}} - @for (user of users; track user.id) { - {{ user.name }} - } - - -
+ + User to impersonate + + {{getUsername()}} + @for (user of (users$ | async | excludeById : auth.getUserId()); track user.id) { + {{ user.name }} + } + + } \ No newline at end of file diff --git a/src/app/auth/impersonation/impersonation.component.ts b/src/app/auth/impersonation/impersonation.component.ts index 256233f..ff23851 100644 --- a/src/app/auth/impersonation/impersonation.component.ts +++ b/src/app/auth/impersonation/impersonation.component.ts @@ -1,21 +1,22 @@ -import { Component, inject, Inject, OnInit, PLATFORM_ID } from '@angular/core'; +import { Component, inject, OnInit } 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'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; -import { User } from '../../shared/models/user'; import { UserService } from '../../shared/services/user.service'; +import { AsyncPipe } from '@angular/common'; +import { ExcludeByIdPipe } from '../../shared/pipes/exclude-by-id.pipe'; @Component({ selector: 'impersonation', standalone: true, imports: [ + AsyncPipe, + ExcludeByIdPipe, MatCardModule, MatSelectModule, ReactiveFormsModule, @@ -24,34 +25,33 @@ import { UserService } from '../../shared/services/user.service'; styleUrl: './impersonation.component.scss' }) export class ImpersonationComponent implements OnInit { - private readonly events = inject(EventService); + private readonly client = inject(HermesClientService); private readonly userService = inject(UserService); + private readonly events = inject(EventService); + private readonly http = inject(HttpClient); - impersonationControl = new FormControl(undefined); - users: User[]; + readonly auth = inject(ApiAuthenticationService); - constructor(private client: HermesClientService, private auth: ApiAuthenticationService, private router: Router, private http: HttpClient, @Inject(PLATFORM_ID) private platformId: Object) { - this.users = []; - } + impersonationControl = new FormControl(this.auth.getUserId()); + users$ = this.userService.fetch(); ngOnInit(): void { - if (!isPlatformBrowser(this.platformId)) { + if (!this.auth.isAdmin()) { return; } - this.userService.fetch().subscribe(users => { - this.users = users.filter((d: any) => d.name != this.auth.getUsername()); + this.users$.subscribe(users => { const id = this.auth.getImpersonatedId(); - if (id && this.users.find(u => u.id == id)) { + if (id && users.find(u => u.id == id)) { this.impersonationControl.setValue(id); } }); this.impersonationControl.valueChanges.subscribe((impersonationId) => { - if (!this.auth.isAdmin() || impersonationId == this.auth.getImpersonatedId()) + if (impersonationId == this.auth.getImpersonatedId()) return; - if (!impersonationId) { + if (impersonationId == this.auth.getUserId()) { this.http.delete(environment.API_HOST + '/admin/impersonate', { headers: { 'Authorization': 'Bearer ' + localStorage.getItem('jwt') @@ -73,7 +73,6 @@ export class ImpersonationComponent implements OnInit { }).subscribe(async (data: any) => { this.client.disconnect(true); this.events.emit('impersonation', impersonationId); - await this.router.navigate(['tts-login']); }); } }); diff --git a/src/app/navigation/topbar/topbar.component.ts b/src/app/navigation/topbar/topbar.component.ts index 6773f66..a7c1794 100644 --- a/src/app/navigation/topbar/topbar.component.ts +++ b/src/app/navigation/topbar/topbar.component.ts @@ -6,7 +6,6 @@ import { MatButtonModule } from '@angular/material/button'; import { AuthModule } from '../../auth/auth.module'; import { ApiAuthenticationService } from '../../shared/services/api/api-authentication.service'; import { ImpersonationComponent } from '../../auth/impersonation/impersonation.component'; -import { HermesClientService } from '../../hermes-client.service'; import EventService from '../../shared/services/EventService'; import { Subscription } from 'rxjs'; import { ThemeComponent } from "../../theme/theme.component"; @@ -32,14 +31,13 @@ import { LoginButtonComponent } from "../../auth/login-button/login-button.compo }) export class Topbar implements OnDestroy { private readonly auth = inject(ApiAuthenticationService); - private readonly client = inject(HermesClientService); private readonly events = inject(EventService); private subscriptions: (Subscription | null)[] = []; private _showImpersonation: boolean = false constructor() { - this.subscriptions.push(this.events.listen('impersonation', () => this.showImpersonation = false)); + this.subscriptions.push(this.events.listen('impersonation', () => { this.auth.update(localStorage.getItem('jwt')); this.showImpersonation = false; })); } ngOnDestroy(): void { diff --git a/src/app/redemptions/redemption-list/redemption-list.component.ts b/src/app/redemptions/redemption-list/redemption-list.component.ts index b47ccff..5b354e9 100644 --- a/src/app/redemptions/redemption-list/redemption-list.component.ts +++ b/src/app/redemptions/redemption-list/redemption-list.component.ts @@ -44,7 +44,6 @@ export class RedemptionListComponent { alias: 'twitchRedemptions', transform: toTwitchRedemptionDict, }); - //twitchRedemptions = computed<{ [id: string]: string } | null>(() => ({})); actions = input.required(); diff --git a/src/app/shared/pipes/exclude-by-id.pipe.ts b/src/app/shared/pipes/exclude-by-id.pipe.ts new file mode 100644 index 0000000..8b7e34d --- /dev/null +++ b/src/app/shared/pipes/exclude-by-id.pipe.ts @@ -0,0 +1,13 @@ +import {Pipe, PipeTransform} from '@angular/core'; + +@Pipe({ + name: 'excludeById', +}) +export class ExcludeByIdPipe implements PipeTransform { + transform(values: any[] | null, id: string): any[] | null { + if (!values) { + return values; + } + return values.filter(value => value.id != id); + } +} \ No newline at end of file diff --git a/src/app/shared/services/api/api-authentication.service.ts b/src/app/shared/services/api/api-authentication.service.ts index 214c45c..f0bbc53 100644 --- a/src/app/shared/services/api/api-authentication.service.ts +++ b/src/app/shared/services/api/api-authentication.service.ts @@ -36,6 +36,10 @@ export class ApiAuthenticationService { return this.user?.impersonation?.name; } + getUserId() { + return this.user?.id; + } + getUsername() { return this.user?.name; } diff --git a/src/app/shared/services/permission.service.ts b/src/app/shared/services/permission.service.ts index 36fd72d..a0ba83a 100644 --- a/src/app/shared/services/permission.service.ts +++ b/src/app/shared/services/permission.service.ts @@ -2,7 +2,7 @@ import { inject, Injectable } from '@angular/core'; import { HermesClientService } from '../../hermes-client.service'; import EventService from './EventService'; import { Permission } from '../models/permission'; -import { map, Observable, of } from 'rxjs'; +import { filter, map, merge, Observable, of, startWith } from 'rxjs'; @Injectable({ providedIn: 'root' @@ -12,6 +12,7 @@ export class PermissionService { private readonly events = inject(EventService); private data: Permission[] = []; private loaded = false; + changes$: Observable; create$: Observable | undefined; update$: Observable | undefined; delete$: Observable | undefined; @@ -20,6 +21,12 @@ export class PermissionService { this.create$ = this.client.filterByRequestType('create_group_permission'); this.update$ = this.client.filterByRequestType('update_group_permission'); this.delete$ = this.client.filterByRequestType('delete_group_permission'); + this.changes$ = merge(this.create$, this.update$, this.delete$) + .pipe( + startWith(null), + filter(d => !d.error), + map(_ => this.data.slice()), + ); this.create$?.subscribe(d => { if (d.error) { diff --git a/src/app/shared/services/redeemable-action.service.ts b/src/app/shared/services/redeemable-action.service.ts index 49579d2..ce67b5f 100644 --- a/src/app/shared/services/redeemable-action.service.ts +++ b/src/app/shared/services/redeemable-action.service.ts @@ -25,7 +25,7 @@ export default class RedeemableActionService { this.changes$ = merge(this.create$, this.update$, this.delete$) .pipe( startWith(null), - map(d => this.data.slice()), + map(_ => this.data.slice()), ); this.create$?.subscribe(d => this.data.push(d.data)); diff --git a/src/app/shared/services/redemption.service.ts b/src/app/shared/services/redemption.service.ts index d941381..c2a7fa9 100644 --- a/src/app/shared/services/redemption.service.ts +++ b/src/app/shared/services/redemption.service.ts @@ -24,7 +24,7 @@ export default class RedemptionService { this.changes$ = merge(this.create$, this.update$, this.delete$) .pipe( startWith(null), - map(d => this.data.slice()), + map(_ => this.data.slice()), ); this.create$?.subscribe(d => this.data.push(d.data));