Created auth module. Created Visitor auth guard for non-logged in users.
This commit is contained in:
16
src/app/auth/auth.module.ts
Normal file
16
src/app/auth/auth.module.ts
Normal file
@ -0,0 +1,16 @@
|
||||
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';
|
||||
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
LoginComponent,
|
||||
TtsLoginComponent,
|
||||
ImpersonationComponent
|
||||
]
|
||||
})
|
||||
export class AuthModule { }
|
19
src/app/auth/impersonation/impersonation.component.html
Normal file
19
src/app/auth/impersonation/impersonation.component.html
Normal file
@ -0,0 +1,19 @@
|
||||
@if (isAdmin()) {
|
||||
<mat-card appearance="outlined">
|
||||
<mat-card-header>
|
||||
<mat-card-title> Impersonation</mat-card-title>
|
||||
<mat-card-subtitle>Impersonate as another user</mat-card-subtitle>
|
||||
</mat-card-header>
|
||||
<mat-card-actions>
|
||||
<mat-form-field>
|
||||
<mat-label>User to impersonate</mat-label>
|
||||
<mat-select (selectionChange)="onChange($event)" [(value)]="impersonated">
|
||||
<mat-option>{{getUsername()}}</mat-option>
|
||||
@for (user of users; track user.id) {
|
||||
<mat-option [value]="user.id">{{ user.name }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
}
|
23
src/app/auth/impersonation/impersonation.component.spec.ts
Normal file
23
src/app/auth/impersonation/impersonation.component.spec.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ImpersonationComponent } from './impersonation.component';
|
||||
|
||||
describe('ImpersonationComponent', () => {
|
||||
let component: ImpersonationComponent;
|
||||
let fixture: ComponentFixture<ImpersonationComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ImpersonationComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ImpersonationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
82
src/app/auth/impersonation/impersonation.component.ts
Normal file
82
src/app/auth/impersonation/impersonation.component.ts
Normal file
@ -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 (id && 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']);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
21
src/app/auth/login/login.component.html
Normal file
21
src/app/auth/login/login.component.html
Normal file
@ -0,0 +1,21 @@
|
||||
<div class="login">
|
||||
<div></div>
|
||||
<mat-card class="outer" appearance="outlined">
|
||||
<mat-card-header>
|
||||
<h1>Login</h1>
|
||||
</mat-card-header>
|
||||
|
||||
<mat-card-content>
|
||||
<p>Log in with your favorite livestream service</p>
|
||||
|
||||
<a>
|
||||
<mat-card appearance="outlined" (click)="login()">
|
||||
<mat-card-content>
|
||||
Twitch
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</a>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<div></div>
|
||||
</div>
|
13
src/app/auth/login/login.component.scss
Normal file
13
src/app/auth/login/login.component.scss
Normal file
@ -0,0 +1,13 @@
|
||||
.login {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr max-content 1fr;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.mat-mdc-card-header {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.mat-mdc-card-content {
|
||||
align-self: center;
|
||||
}
|
23
src/app/auth/login/login.component.spec.ts
Normal file
23
src/app/auth/login/login.component.spec.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoginComponent } from './login.component';
|
||||
|
||||
describe('LoginComponent', () => {
|
||||
let component: LoginComponent;
|
||||
let fixture: ComponentFixture<LoginComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [LoginComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(LoginComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
33
src/app/auth/login/login.component.ts
Normal file
33
src/app/auth/login/login.component.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { Component, OnDestroy, OnInit } 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],
|
||||
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()
|
||||
}
|
||||
|
||||
login() {
|
||||
document.location.replace(environment.API_HOST + '/auth');
|
||||
}
|
||||
}
|
14
src/app/auth/tts-login/tts-login.component.html
Normal file
14
src/app/auth/tts-login/tts-login.component.html
Normal file
@ -0,0 +1,14 @@
|
||||
<h4>TTS Login</h4>
|
||||
<div class="main-div">
|
||||
<mat-card class="main-card">
|
||||
<mat-form-field>
|
||||
<mat-label>API Key</mat-label>
|
||||
<mat-select [(value)]="selected_api_key">
|
||||
@for (key of api_keys; track key.id) {
|
||||
<mat-option [value]="key.id">{{key.label}}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<button mat-raised-button (click)="login()">Log In</button>
|
||||
</mat-card>
|
||||
</div>
|
14
src/app/auth/tts-login/tts-login.component.scss
Normal file
14
src/app/auth/tts-login/tts-login.component.scss
Normal file
@ -0,0 +1,14 @@
|
||||
.main-div {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h4 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.main-card {
|
||||
width: 20%;
|
||||
}
|
23
src/app/auth/tts-login/tts-login.component.spec.ts
Normal file
23
src/app/auth/tts-login/tts-login.component.spec.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TtsLoginComponent } from './tts-login.component';
|
||||
|
||||
describe('TtsLoginComponent', () => {
|
||||
let component: TtsLoginComponent;
|
||||
let fixture: ComponentFixture<TtsLoginComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [TtsLoginComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(TtsLoginComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
70
src/app/auth/tts-login/tts-login.component.ts
Normal file
70
src/app/auth/tts-login/tts-login.component.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
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 { HttpClient } from '@angular/common/http';
|
||||
import { Router } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { HermesClientService } from '../../hermes-client.service';
|
||||
import { MatCard } from '@angular/material/card';
|
||||
|
||||
@Component({
|
||||
selector: 'tts-login',
|
||||
standalone: true,
|
||||
imports: [MatButtonModule, MatCard, MatFormFieldModule, MatSelectModule, MatInputModule, FormsModule],
|
||||
templateUrl: './tts-login.component.html',
|
||||
styleUrl: './tts-login.component.scss'
|
||||
})
|
||||
export class TtsLoginComponent implements OnInit, OnDestroy {
|
||||
api_keys: { id: string, label: string }[];
|
||||
selected_api_key: string|undefined;
|
||||
|
||||
private subscription: Subscription|undefined;
|
||||
|
||||
constructor(private hermes: HermesClientService, private events: EventService, private http: HttpClient, private router: Router) {
|
||||
this.api_keys = [];
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.http.get(environment.API_HOST + '/keys', {
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + localStorage.getItem('jwt')
|
||||
}
|
||||
}).subscribe((data: any) => this.api_keys = data);
|
||||
|
||||
this.subscription = this.events.listen('tts_login_ack', _ => {
|
||||
if (document.location.href.includes('/tts-login')) {
|
||||
this.router.navigate(['/policies'])
|
||||
}
|
||||
});
|
||||
this.events.listen('tts_logoff', _ => {
|
||||
this.selected_api_key = undefined;
|
||||
});
|
||||
this.events.listen('impersonation', _ => {
|
||||
this.selected_api_key = undefined;
|
||||
|
||||
this.http.get(environment.API_HOST + '/keys', {
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + localStorage.getItem('jwt')
|
||||
}
|
||||
}).subscribe((data: any) => this.api_keys = data);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.subscription)
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
|
||||
login() {
|
||||
console.log('api key for login', this.selected_api_key)
|
||||
if (!this.selected_api_key)
|
||||
return;
|
||||
|
||||
this.hermes.login(this.selected_api_key);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user