Fixed impersonation not updating the UI correctly. Self is selected and shown by default. Using async pipes & custom pipe.
This commit is contained in:
parent
daa500111c
commit
9338e7e624
@ -1,14 +1,12 @@
|
|||||||
@if (isAdmin()) {
|
@if (isAdmin()) {
|
||||||
<main>
|
<mat-form-field class="mat-small"
|
||||||
<mat-form-field class="mat-small"
|
|
||||||
subscriptSizing="dynamic">
|
subscriptSizing="dynamic">
|
||||||
<mat-label>User to impersonate</mat-label>
|
<mat-label>User to impersonate</mat-label>
|
||||||
<mat-select [formControl]="impersonationControl">
|
<mat-select [formControl]="impersonationControl">
|
||||||
<mat-option>{{getUsername()}}</mat-option>
|
<mat-option [value]="auth.getUserId()">{{getUsername()}}</mat-option>
|
||||||
@for (user of users; track user.id) {
|
@for (user of (users$ | async | excludeById : auth.getUserId()); track user.id) {
|
||||||
<mat-option [value]="user.id">{{ user.name }}</mat-option>
|
<mat-option [value]="user.id">{{ user.name }}</mat-option>
|
||||||
}
|
}
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</main>
|
|
||||||
}
|
}
|
@ -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 { ApiAuthenticationService } from '../../shared/services/api/api-authentication.service';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
import { MatSelectModule } from '@angular/material/select';
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { isPlatformBrowser } from '@angular/common';
|
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import EventService from '../../shared/services/EventService';
|
import EventService from '../../shared/services/EventService';
|
||||||
import { HermesClientService } from '../../hermes-client.service';
|
import { HermesClientService } from '../../hermes-client.service';
|
||||||
import { Router } from '@angular/router';
|
|
||||||
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { User } from '../../shared/models/user';
|
|
||||||
import { UserService } from '../../shared/services/user.service';
|
import { UserService } from '../../shared/services/user.service';
|
||||||
|
import { AsyncPipe } from '@angular/common';
|
||||||
|
import { ExcludeByIdPipe } from '../../shared/pipes/exclude-by-id.pipe';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'impersonation',
|
selector: 'impersonation',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
|
AsyncPipe,
|
||||||
|
ExcludeByIdPipe,
|
||||||
MatCardModule,
|
MatCardModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
@ -24,34 +25,33 @@ import { UserService } from '../../shared/services/user.service';
|
|||||||
styleUrl: './impersonation.component.scss'
|
styleUrl: './impersonation.component.scss'
|
||||||
})
|
})
|
||||||
export class ImpersonationComponent implements OnInit {
|
export class ImpersonationComponent implements OnInit {
|
||||||
private readonly events = inject(EventService);
|
private readonly client = inject(HermesClientService);
|
||||||
private readonly userService = inject(UserService);
|
private readonly userService = inject(UserService);
|
||||||
|
private readonly events = inject(EventService);
|
||||||
|
private readonly http = inject(HttpClient);
|
||||||
|
|
||||||
impersonationControl = new FormControl<string | undefined>(undefined);
|
readonly auth = inject(ApiAuthenticationService);
|
||||||
users: User[];
|
|
||||||
|
|
||||||
constructor(private client: HermesClientService, private auth: ApiAuthenticationService, private router: Router, private http: HttpClient, @Inject(PLATFORM_ID) private platformId: Object) {
|
impersonationControl = new FormControl<string>(this.auth.getUserId());
|
||||||
this.users = [];
|
users$ = this.userService.fetch();
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
if (!isPlatformBrowser(this.platformId)) {
|
if (!this.auth.isAdmin()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.userService.fetch().subscribe(users => {
|
this.users$.subscribe(users => {
|
||||||
this.users = users.filter((d: any) => d.name != this.auth.getUsername());
|
|
||||||
const id = this.auth.getImpersonatedId();
|
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.setValue(id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.impersonationControl.valueChanges.subscribe((impersonationId) => {
|
this.impersonationControl.valueChanges.subscribe((impersonationId) => {
|
||||||
if (!this.auth.isAdmin() || impersonationId == this.auth.getImpersonatedId())
|
if (impersonationId == this.auth.getImpersonatedId())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!impersonationId) {
|
if (impersonationId == this.auth.getUserId()) {
|
||||||
this.http.delete(environment.API_HOST + '/admin/impersonate', {
|
this.http.delete(environment.API_HOST + '/admin/impersonate', {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer ' + localStorage.getItem('jwt')
|
'Authorization': 'Bearer ' + localStorage.getItem('jwt')
|
||||||
@ -73,7 +73,6 @@ export class ImpersonationComponent implements OnInit {
|
|||||||
}).subscribe(async (data: any) => {
|
}).subscribe(async (data: any) => {
|
||||||
this.client.disconnect(true);
|
this.client.disconnect(true);
|
||||||
this.events.emit('impersonation', impersonationId);
|
this.events.emit('impersonation', impersonationId);
|
||||||
await this.router.navigate(['tts-login']);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -6,7 +6,6 @@ import { MatButtonModule } from '@angular/material/button';
|
|||||||
import { AuthModule } from '../../auth/auth.module';
|
import { AuthModule } from '../../auth/auth.module';
|
||||||
import { ApiAuthenticationService } from '../../shared/services/api/api-authentication.service';
|
import { ApiAuthenticationService } from '../../shared/services/api/api-authentication.service';
|
||||||
import { ImpersonationComponent } from '../../auth/impersonation/impersonation.component';
|
import { ImpersonationComponent } from '../../auth/impersonation/impersonation.component';
|
||||||
import { HermesClientService } from '../../hermes-client.service';
|
|
||||||
import EventService from '../../shared/services/EventService';
|
import EventService from '../../shared/services/EventService';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { ThemeComponent } from "../../theme/theme.component";
|
import { ThemeComponent } from "../../theme/theme.component";
|
||||||
@ -32,14 +31,13 @@ import { LoginButtonComponent } from "../../auth/login-button/login-button.compo
|
|||||||
})
|
})
|
||||||
export class Topbar implements OnDestroy {
|
export class Topbar implements OnDestroy {
|
||||||
private readonly auth = inject(ApiAuthenticationService);
|
private readonly auth = inject(ApiAuthenticationService);
|
||||||
private readonly client = inject(HermesClientService);
|
|
||||||
private readonly events = inject(EventService);
|
private readonly events = inject(EventService);
|
||||||
|
|
||||||
private subscriptions: (Subscription | null)[] = [];
|
private subscriptions: (Subscription | null)[] = [];
|
||||||
private _showImpersonation: boolean = false
|
private _showImpersonation: boolean = false
|
||||||
|
|
||||||
constructor() {
|
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 {
|
ngOnDestroy(): void {
|
||||||
|
@ -44,7 +44,6 @@ export class RedemptionListComponent {
|
|||||||
alias: 'twitchRedemptions',
|
alias: 'twitchRedemptions',
|
||||||
transform: toTwitchRedemptionDict,
|
transform: toTwitchRedemptionDict,
|
||||||
});
|
});
|
||||||
//twitchRedemptions = computed<{ [id: string]: string } | null>(() => ({}));
|
|
||||||
actions = input.required<RedeemableAction[]>();
|
actions = input.required<RedeemableAction[]>();
|
||||||
|
|
||||||
|
|
||||||
|
13
src/app/shared/pipes/exclude-by-id.pipe.ts
Normal file
13
src/app/shared/pipes/exclude-by-id.pipe.ts
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -36,6 +36,10 @@ export class ApiAuthenticationService {
|
|||||||
return this.user?.impersonation?.name;
|
return this.user?.impersonation?.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUserId() {
|
||||||
|
return this.user?.id;
|
||||||
|
}
|
||||||
|
|
||||||
getUsername() {
|
getUsername() {
|
||||||
return this.user?.name;
|
return this.user?.name;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { inject, Injectable } from '@angular/core';
|
|||||||
import { HermesClientService } from '../../hermes-client.service';
|
import { HermesClientService } from '../../hermes-client.service';
|
||||||
import EventService from './EventService';
|
import EventService from './EventService';
|
||||||
import { Permission } from '../models/permission';
|
import { Permission } from '../models/permission';
|
||||||
import { map, Observable, of } from 'rxjs';
|
import { filter, map, merge, Observable, of, startWith } from 'rxjs';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -12,6 +12,7 @@ export class PermissionService {
|
|||||||
private readonly events = inject(EventService);
|
private readonly events = inject(EventService);
|
||||||
private data: Permission[] = [];
|
private data: Permission[] = [];
|
||||||
private loaded = false;
|
private loaded = false;
|
||||||
|
changes$: Observable<any>;
|
||||||
create$: Observable<any> | undefined;
|
create$: Observable<any> | undefined;
|
||||||
update$: Observable<any> | undefined;
|
update$: Observable<any> | undefined;
|
||||||
delete$: Observable<any> | undefined;
|
delete$: Observable<any> | undefined;
|
||||||
@ -20,6 +21,12 @@ export class PermissionService {
|
|||||||
this.create$ = this.client.filterByRequestType('create_group_permission');
|
this.create$ = this.client.filterByRequestType('create_group_permission');
|
||||||
this.update$ = this.client.filterByRequestType('update_group_permission');
|
this.update$ = this.client.filterByRequestType('update_group_permission');
|
||||||
this.delete$ = this.client.filterByRequestType('delete_group_permission');
|
this.delete$ = this.client.filterByRequestType('delete_group_permission');
|
||||||
|
this.changes$ = merge<any>(this.create$, this.update$, this.delete$)
|
||||||
|
.pipe(
|
||||||
|
startWith(null),
|
||||||
|
filter(d => !d.error),
|
||||||
|
map(_ => this.data.slice()),
|
||||||
|
);
|
||||||
|
|
||||||
this.create$?.subscribe(d => {
|
this.create$?.subscribe(d => {
|
||||||
if (d.error) {
|
if (d.error) {
|
||||||
|
@ -25,7 +25,7 @@ export default class RedeemableActionService {
|
|||||||
this.changes$ = merge<any>(this.create$, this.update$, this.delete$)
|
this.changes$ = merge<any>(this.create$, this.update$, this.delete$)
|
||||||
.pipe(
|
.pipe(
|
||||||
startWith(null),
|
startWith(null),
|
||||||
map(d => this.data.slice()),
|
map(_ => this.data.slice()),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.create$?.subscribe(d => this.data.push(d.data));
|
this.create$?.subscribe(d => this.data.push(d.data));
|
||||||
|
@ -24,7 +24,7 @@ export default class RedemptionService {
|
|||||||
this.changes$ = merge<any>(this.create$, this.update$, this.delete$)
|
this.changes$ = merge<any>(this.create$, this.update$, this.delete$)
|
||||||
.pipe(
|
.pipe(
|
||||||
startWith(null),
|
startWith(null),
|
||||||
map(d => this.data.slice()),
|
map(_ => this.data.slice()),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.create$?.subscribe(d => this.data.push(d.data));
|
this.create$?.subscribe(d => this.data.push(d.data));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user