upgrade to newest backend

This commit is contained in:
_Bastler 2021-07-22 18:45:04 +02:00
parent e6742f1cc5
commit 72178dd7c4
39 changed files with 382 additions and 705 deletions

View File

@ -4,7 +4,7 @@ import {Routes, RouterModule} from '@angular/router';
import {AuthGuard, AuthUpdateGuard, AuthenticatedGuard, AnonymousGuard} from './auth/auth.guard'; import {AuthGuard, AuthUpdateGuard, AuthenticatedGuard, AnonymousGuard} from './auth/auth.guard';
import {ImprintComponent, PrivacyPolicyComponent, TermsOfServiceComponent} from './pages/general/general.component'; import {ImprintComponent, PrivacyPolicyComponent, TermsOfServiceComponent} from './pages/general/general.component';
import {FormLoginComponent} from './pages/form-login/form-login.component'; import {FormLoginComponent} from './pages/form-login/form-login.component';
import {FormLoginTotpComponent} from './pages/form-login-totp/form-login-totp.component'; import {FormLogin2FAComponent} from './pages/form-login-2fa/form-login-2fa.component';
import {PasswordComponent} from './pages/password/password.component'; import {PasswordComponent} from './pages/password/password.component';
import {PasswordResetComponent} from './pages/password-reset/password-reset.component'; import {PasswordResetComponent} from './pages/password-reset/password-reset.component';
import {AccountComponent} from './pages/account/account.component'; import {AccountComponent} from './pages/account/account.component';
@ -30,9 +30,9 @@ const routes: Routes = [
{path: 'privacy-policy', component: PrivacyPolicyComponent, canActivate: [AuthUpdateGuard]}, {path: 'privacy-policy', component: PrivacyPolicyComponent, canActivate: [AuthUpdateGuard]},
{path: 'terms-of-service', component: TermsOfServiceComponent, canActivate: [AuthUpdateGuard]}, {path: 'terms-of-service', component: TermsOfServiceComponent, canActivate: [AuthUpdateGuard]},
{path: 'login', component: FormLoginComponent, canActivate: [AnonymousGuard]}, {path: 'login', component: FormLoginComponent, canActivate: [AnonymousGuard]},
{path: 'login/totp', component: FormLoginTotpComponent, canActivate: [AnonymousGuard]}, {path: 'login/2fa', component: FormLogin2FAComponent, canActivate: [AnonymousGuard]},
{path: 'service-login', component: FormLoginComponent, canActivate: [AnonymousGuard]}, {path: 'service-login', component: FormLoginComponent, canActivate: [AnonymousGuard]},
{path: 'service-login/totp', component: FormLoginTotpComponent, canActivate: [AnonymousGuard]}, {path: 'service-login/2fa', component: FormLogin2FAComponent, canActivate: [AnonymousGuard]},
{path: 'password', component: PasswordComponent, canActivate: [AnonymousGuard]}, {path: 'password', component: PasswordComponent, canActivate: [AnonymousGuard]},
{path: 'password-reset', component: PasswordResetComponent, canActivate: [AnonymousGuard]}, {path: 'password-reset', component: PasswordResetComponent, canActivate: [AnonymousGuard]},
{path: 'services', component: ServicesComponent, canActivate: [AuthenticatedGuard]}, {path: 'services', component: ServicesComponent, canActivate: [AuthenticatedGuard]},

View File

@ -18,9 +18,8 @@ import {AccountComponent} from './pages/account/account.component';
import {ServicesComponent} from './pages/services/services.component'; import {ServicesComponent} from './pages/services/services.component';
import {AppComponent} from './app.component'; import {AppComponent} from './app.component';
import {LoginComponent} from './pages/login/login.component'; import {LoginComponent} from './pages/login/login.component';
import {LoginTotpComponent} from './pages/login-totp/login-totp.component';
import {FormLoginComponent} from './pages/form-login/form-login.component'; import {FormLoginComponent} from './pages/form-login/form-login.component';
import {FormLoginTotpComponent} from './pages/form-login-totp/form-login-totp.component'; import {FormLogin2FAComponent} from './pages/form-login-2fa/form-login-2fa.component';
import {TokensComponent} from './pages/tokens/tokens.component'; import {TokensComponent} from './pages/tokens/tokens.component';
import {InvitesComponent} from './pages/invites/invites.component'; import {InvitesComponent} from './pages/invites/invites.component';
import {PermissionsComponent} from './ui/permissions/permissions.component'; import {PermissionsComponent} from './ui/permissions/permissions.component';
@ -73,9 +72,8 @@ export class XhrInterceptor implements HttpInterceptor {
ImprintComponent, PrivacyPolicyComponent, TermsOfServiceComponent, ImprintComponent, PrivacyPolicyComponent, TermsOfServiceComponent,
AccountComponent, AccountComponent,
LoginComponent, LoginComponent,
LoginTotpComponent,
FormLoginComponent, FormLoginComponent,
FormLoginTotpComponent, FormLogin2FAComponent,
TokensComponent, TokensComponent,
InvitesComponent, InvitesComponent,
ServicesComponent, ServicesComponent,

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AccountComponent } from './account.component';
describe('AccountComponent', () => {
let component: AccountComponent;
let fixture: ComponentFixture<AccountComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AccountComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AccountComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AliasesComponent } from './aliases.component';
describe('AliasesComponent', () => {
let component: AliasesComponent;
let fixture: ComponentFixture<AliasesComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AliasesComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AliasesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DomainsComponent } from './domains.component';
describe('DomainsComponent', () => {
let component: DomainsComponent;
let fixture: ComponentFixture<DomainsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ DomainsComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(DomainsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { InfoComponent } from './info.component';
describe('InfoComponent', () => {
let component: InfoComponent;
let fixture: ComponentFixture<InfoComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ InfoComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(InfoComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {ProfileComponent} from './profile.component';
describe('ProfileComponent', () => {
let component: ProfileComponent;
let fixture: ComponentFixture<ProfileComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ProfileComponent]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ProfileComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SecurityComponent } from './security.component';
describe('SecurityComponent', () => {
let component: SecurityComponent;
let fixture: ComponentFixture<SecurityComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SecurityComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(SecurityComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -2,7 +2,7 @@ import {Component, OnInit, ViewChild, Inject} from '@angular/core';
import {FormBuilder, FormGroup, FormControl, Validators, NgForm} from '@angular/forms'; import {FormBuilder, FormGroup, FormControl, Validators, NgForm} from '@angular/forms';
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog'; import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog';
import {AuthService} from './../../../services/auth.service'; import {Auth2FAService} from './../../../services/auth.2fa.service';
import {UserService} from './../../../services/user.service'; import {UserService} from './../../../services/user.service';
import {MatchingValidator} from './../../../utils/matching.validator'; import {MatchingValidator} from './../../../utils/matching.validator';
@ -29,7 +29,7 @@ export class SecurityComponent implements OnInit {
constructor( constructor(
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private userService: UserService, private userService: UserService,
private authService: AuthService, private auth2FAService: Auth2FAService,
public dialog: MatDialog) {} public dialog: MatDialog) {}
ngOnInit(): void { ngOnInit(): void {
@ -52,7 +52,7 @@ export class SecurityComponent implements OnInit {
}) })
this.authService.isTotpEnabled().subscribe(response => { this.auth2FAService.isEnabled('totp').subscribe(response => {
this.totp = true; this.totp = true;
}, error => { }, error => {
this.totp = false; this.totp = false;
@ -99,7 +99,7 @@ export class SecurityComponent implements OnInit {
} }
createTotp() { createTotp() {
this.authService.createTotp().subscribe((result: any) => { this.auth2FAService.create('totp').subscribe((result: any) => {
const dialogRef = this.dialog.open(SecurityTotpDialog, { const dialogRef = this.dialog.open(SecurityTotpDialog, {
closeOnNavigation: false, closeOnNavigation: false,
disableClose: true, disableClose: true,
@ -108,11 +108,11 @@ export class SecurityComponent implements OnInit {
dialogRef.afterClosed().subscribe(result => { dialogRef.afterClosed().subscribe(result => {
if(result) { if(result) {
this.authService.enableTotp(result).subscribe((result: any) => { this.auth2FAService.enable('totp', result).subscribe((result: any) => {
this.totp = true; this.totp = true;
}) })
} else { } else {
this.authService.removeTotp().subscribe((result: any) => { this.auth2FAService.remove('totp').subscribe((result: any) => {
this.totp = false; this.totp = false;
}) })
} }
@ -130,7 +130,7 @@ export class SecurityComponent implements OnInit {
} }
removeTotp() { removeTotp() {
this.authService.removeTotp().subscribe((result: any) => { this.auth2FAService.remove('totp').subscribe((result: any) => {
this.totp = false; this.totp = false;
}) })
} }

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { VoucherComponent } from './voucher.component';
describe('VoucherComponent', () => {
let component: VoucherComponent;
let fixture: ComponentFixture<VoucherComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ VoucherComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(VoucherComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,39 @@
<form action="{{apiUrl}}/auth/login/2fa" method="POST" #form2FA>
<mat-card>
<mat-card-content>
<h2>{{'security.2fa.external' | i18n}}<mat-icon style="font-size: 1em;">open_in_new
</mat-icon>
</h2>
<mat-error *ngIf="loginInvalid">
{{'security.2fa.invalid' | i18n}}
</mat-error>
<input id="provider" name="provider" matInput hidden [value]="selectedProvider.id">
<mat-select [(ngModel)]="selectedProvider" placeholder="{{'security.2fa.provider' | i18n}}"
[ngModelOptions]="{standalone: true}">
<mat-option *ngFor="let provider of providers" [value]="provider">
{{'security.2fa.' + provider.id | i18n}}
</mat-option>
</mat-select>
<a mat-raised-button (click)="request()"
*ngIf="selectedProvider && selectedProvider.request">{{'security.2fa.' + selectedProvider.id +
'.request'
| i18n}}</a>
<mat-form-field>
<input id="code" name="code" matInput placeholder="{{'security.2fa.code' | i18n}}" required
matAutofocus>
<mat-error>
{{'security.2fa.missing' | i18n}}
</mat-error>
</mat-form-field>
<mat-slide-toggle id="keep" name="keep" [checked]="keep">
{{'login.keepSession' | i18n}}
</mat-slide-toggle>
</mat-card-content>
<mat-card-actions>
<button type="submit" mat-raised-button color="primary" (click)="form2FA.submit()"
[disabled]="form2FA.invalid">{{'security.2fa.login' | i18n}}<mat-icon style="font-size: 1em;">
open_in_new
</mat-icon></button>
</mat-card-actions>
</mat-card>
</form>

View File

@ -3,20 +3,25 @@ import {ActivatedRoute, Router} from '@angular/router';
import {environment} from '../../../environments/environment'; import {environment} from '../../../environments/environment';
import {Auth2FAService} from '../../services/auth.2fa.service';
@Component({ @Component({
selector: 'app-form-login-totp', selector: 'app-form-login-2fa',
templateUrl: './form-login-totp.component.html', templateUrl: './form-login-2fa.component.html',
styleUrls: ['./form-login-totp.component.scss'] styleUrls: ['./form-login-2fa.component.scss']
}) })
export class FormLoginTotpComponent implements OnInit { export class FormLogin2FAComponent implements OnInit {
loginInvalid: boolean; loginInvalid: boolean;
keep: boolean = false; keep: boolean = false;
apiUrl = environment.apiUrl; apiUrl = environment.apiUrl;
selectedProvider = {id: "", request: false};
providers = [];
constructor( constructor(
private router: Router, private router: Router,
private route: ActivatedRoute) {} private route: ActivatedRoute,
private auth2FAService: Auth2FAService) {}
async ngOnInit() { async ngOnInit() {
this.route.queryParams.subscribe(params => { this.route.queryParams.subscribe(params => {
@ -29,8 +34,20 @@ export class FormLoginTotpComponent implements OnInit {
this.router.navigate([], {queryParams: {keep: null}, queryParamsHandling: 'merge'}); this.router.navigate([], {queryParams: {keep: null}, queryParamsHandling: 'merge'});
} }
}); });
this.auth2FAService.getEnabled().subscribe((providers: any) => {
this.providers = providers;
if(this.providers[0]) {
this.selectedProvider = this.providers[0];
}
})
} }
request() {
}
} }

View File

@ -1,27 +0,0 @@
<form action="{{apiUrl}}/auth/login/totp" method="POST" #totpForm>
<mat-card>
<mat-card-content>
<h2>{{'security.2fa.totp.external' | i18n}}<mat-icon style="font-size: 1em;">open_in_new
</mat-icon>
</h2>
<mat-error *ngIf="loginInvalid">
{{'security.2fa.totp.invalid' | i18n}}
</mat-error>
<mat-form-field>
<input id="code" name="code" matInput placeholder="{{'security.2fa.totp.code' | i18n}}" required matAutofocus>
<mat-error>
{{'security.2fa.totp.missing' | i18n}}
</mat-error>
</mat-form-field>
<mat-slide-toggle id="keep" name="keep" [checked]="keep" >
{{'login.keepSession' | i18n}}
</mat-slide-toggle>
</mat-card-content>
<mat-card-actions>
<button type="submit" mat-raised-button color="primary" (click)="totpForm.submit()"
[disabled]="totpForm.invalid">{{'security.2fa.totp.login' | i18n}}<mat-icon style="font-size: 1em;">
open_in_new
</mat-icon></button>
</mat-card-actions>
</mat-card>
</form>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormLoginTotpComponent } from './form-login-totp.component';
describe('FormLoginTotpComponent', () => {
let component: FormLoginTotpComponent;
let fixture: ComponentFixture<FormLoginTotpComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FormLoginTotpComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(FormLoginTotpComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormLoginComponent } from './form-login.component';
describe('FormLoginComponent', () => {
let component: FormLoginComponent;
let fixture: ComponentFixture<FormLoginComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FormLoginComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(FormLoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { InvitesComponent } from './invites.component';
describe('InvitesComponent', () => {
let component: InvitesComponent;
let fixture: ComponentFixture<InvitesComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ InvitesComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(InvitesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { JitsiComponent } from './jitsi.component';
describe('JitsiComponent', () => {
let component: JitsiComponent;
let fixture: ComponentFixture<JitsiComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ JitsiComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(JitsiComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginTotpComponent } from './login-totp.component';
describe('LoginTotpComponent', () => {
let component: LoginTotpComponent;
let fixture: ComponentFixture<LoginTotpComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LoginTotpComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(LoginTotpComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,9 +1,9 @@
import { Component, OnInit } from '@angular/core'; import {Component, OnInit} from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import { AuthService } from '../../services/auth.service'; import {Auth2FAService} from '../../services/auth.2fa.service';
import { Router, ActivatedRoute } from '@angular/router'; import {Router, ActivatedRoute} from '@angular/router';
import { environment } from '../../../environments/environment'; import {environment} from '../../../environments/environment';
@Component({ @Component({
selector: 'app-login', selector: 'app-login',
@ -17,7 +17,7 @@ export class LoginTotpComponent implements OnInit {
public apiUrl = environment.apiUrl; public apiUrl = environment.apiUrl;
targetRoute = '/account/info'; targetRoute = '/account/info';
constructor(private formBuilder: FormBuilder, private authService: AuthService, private router: Router, private route: ActivatedRoute) { } constructor(private formBuilder: FormBuilder, private auth2FAService: Auth2FAService, private router: Router, private route: ActivatedRoute) {}
ngOnInit() { ngOnInit() {
@ -27,7 +27,7 @@ export class LoginTotpComponent implements OnInit {
}); });
this.route.queryParams.subscribe(params => { this.route.queryParams.subscribe(params => {
if (params['target']) { if(params['target']) {
this.targetRoute = params['target']; this.targetRoute = params['target'];
} }
}); });
@ -35,14 +35,8 @@ export class LoginTotpComponent implements OnInit {
async loginTotp() { async loginTotp() {
this.loginInvalid = false; this.loginInvalid = false;
if (this.form.valid) { if(this.form.valid) {
this.auth2FAService.login('totp', this.form.get('code').value, this.form.get('keep').value).subscribe((response: any) => {
const totpModel = {
code: this.form.get('code').value,
keep: this.form.get('keep').value
};
this.authService.loginTotp(totpModel).subscribe((response: any) => {
this.router.navigate([this.targetRoute]); this.router.navigate([this.targetRoute]);
}, error => { }, error => {
this.loginInvalid = true; this.loginInvalid = true;

View File

@ -1,25 +0,0 @@
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({
declarations: [ LoginComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NotfoundComponent } from './notfound.component';
describe('NotfoundComponent', () => {
let component: NotfoundComponent;
let fixture: ComponentFixture<NotfoundComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ NotfoundComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(NotfoundComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PasswordResetComponent } from './password-reset.component';
describe('PasswordResetComponent', () => {
let component: PasswordResetComponent;
let fixture: ComponentFixture<PasswordResetComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PasswordResetComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(PasswordResetComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PasswordComponent } from './password.component';
describe('PasswordComponent', () => {
let component: PasswordComponent;
let fixture: ComponentFixture<PasswordComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PasswordComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(PasswordComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RegisterComponent } from './register.component';
describe('RegisterComponent', () => {
let component: RegisterComponent;
let fixture: ComponentFixture<RegisterComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RegisterComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(RegisterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ServicesComponent } from './services.component';
describe('ServicesComponent', () => {
let component: ServicesComponent;
let fixture: ComponentFixture<ServicesComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ServicesComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ServicesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TokensComponent } from './tokens.component';
describe('TokensComponent', () => {
let component: TokensComponent;
let fixture: ComponentFixture<TokensComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TokensComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TokensComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UnavailableComponent } from './unavailable.component';
describe('UnavailableComponent', () => {
let component: UnavailableComponent;
let fixture: ComponentFixture<UnavailableComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ UnavailableComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(UnavailableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -2,7 +2,7 @@
<mat-progress-bar *ngIf="!success && !error" mode="indeterminate"></mat-progress-bar> <mat-progress-bar *ngIf="!success && !error" mode="indeterminate"></mat-progress-bar>
<div *ngIf="success"> <div *ngIf="success">
<h3>{{model.username}}</h3> <h3>{{model.username}} <small *ngIf="isMe">{{'user.isMe' | i18n}}</small></h3>
<app-profilefields [username]="model.username"></app-profilefields> <app-profilefields [username]="model.username"></app-profilefields>
<div *ngIf="model.aliases && model.aliases.length > 0"> <div *ngIf="model.aliases && model.aliases.length > 0">
<h4>{{'user.aliases' | i18n}}</h4> <h4>{{'user.aliases' | i18n}}</h4>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserComponent } from './user.component';
describe('UserComponent', () => {
let component: UserComponent;
let fixture: ComponentFixture<UserComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ UserComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(UserComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -2,6 +2,7 @@ import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import {AuthService} from '../../services/auth.service';
import {ProfileService} from '../../services/profile.service'; import {ProfileService} from '../../services/profile.service';
@Component({ @Component({
@ -14,8 +15,10 @@ export class UserComponent implements OnInit {
model: any; model: any;
error = false; error = false;
success = false; success = false;
isMe = false;
constructor( constructor(
private authService: AuthService,
private profileService: ProfileService, private profileService: ProfileService,
private route: ActivatedRoute) {} private route: ActivatedRoute) {}
@ -27,6 +30,12 @@ export class UserComponent implements OnInit {
}, error => { }, error => {
this.error = error; this.error = error;
}) })
this.authService.auth.subscribe((auth: any) => {
this.isMe = auth && auth.principal && auth.principal.username == this.username;
console.log(this.isMe, auth);
});
} }

View File

@ -0,0 +1,45 @@
import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {environment} from '../../environments/environment';
@Injectable({
providedIn: 'root',
})
export class Auth2FAService {
constructor(private http: HttpClient) {
}
getEnabled() {
return this.http.get(environment.apiUrl + "/auth/2fa");
}
getAvailable() {
return this.http.get(environment.apiUrl + "/auth/2fa/available");
}
isEnabled(provider) {
return this.http.get(environment.apiUrl + "/auth/2fa/" + provider);
}
create(provider) {
return this.http.put(environment.apiUrl + "/auth/2fa/" + provider, {});
}
enable(provider, code) {
return this.http.patch(environment.apiUrl + "/auth/2fa/" + provider, code);
}
remove(provider) {
return this.http.delete(environment.apiUrl + "/auth/2fa/" + provider);
}
login(provider, code, keep) {
return this.http.post(environment.apiUrl + "/auth/login/2fa", {
'provider': provider,
'code': code,
'keep': keep
});
}
}

View File

@ -1,15 +1,15 @@
import { Injectable } from '@angular/core'; import {Injectable} from '@angular/core';
import { BehaviorSubject, of } from 'rxjs'; import {ReplaySubject, of} from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http'; import {HttpClient, HttpHeaders} from '@angular/common/http';
import { environment } from './../../environments/environment'; import {environment} from './../../environments/environment';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
}) })
export class AuthService { export class AuthService {
auth: BehaviorSubject<any> = new BehaviorSubject(undefined); auth: ReplaySubject<any> = new ReplaySubject(undefined);
constructor(private http: HttpClient) { constructor(private http: HttpClient) {
} }
@ -37,31 +37,11 @@ export class AuthService {
passwordRequest(username) { passwordRequest(username) {
const headers = new HttpHeaders().set('Content-Type', 'text/plain; charset=utf-8'); const headers = new HttpHeaders().set('Content-Type', 'text/plain; charset=utf-8');
return this.http.post(environment.apiUrl + "/auth/password/request", username, { headers, responseType: 'text' }); return this.http.post(environment.apiUrl + "/auth/password/request", username, {headers, responseType: 'text'});
} }
passwordReset(model) { passwordReset(model) {
const headers = new HttpHeaders().set('Content-Type', 'text/plain; charset=utf-8'); const headers = new HttpHeaders().set('Content-Type', 'text/plain; charset=utf-8');
return this.http.post(environment.apiUrl + "/auth/password/reset", model); return this.http.post(environment.apiUrl + "/auth/password/reset", model);
} }
isTotpEnabled() {
return this.http.get(environment.apiUrl + "/auth/totp");
}
createTotp() {
return this.http.put(environment.apiUrl + "/auth/totp", {});
}
enableTotp(code) {
return this.http.patch(environment.apiUrl + "/auth/totp", code);
}
removeTotp() {
return this.http.delete(environment.apiUrl + "/auth/totp");
}
loginTotp(totpModel) {
return this.http.post(environment.apiUrl + "/auth/login/totp", totpModel);
}
} }

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PermissionsComponent } from './permissions.component';
describe('PermissionsComponent', () => {
let component: PermissionComponent;
let fixture: ComponentFixture<PermissionComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PermissionsComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(PermissionsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -29,7 +29,7 @@ export class ProfileFieldPgpBlob implements OnInit {
} }
ngOnInit(): void { ngOnInit(): void {
this.authService.getAuth().then((auth: any) => { this.authService.auth.subscribe((auth: any) => {
if(!auth.authenticated) { if(!auth.authenticated) {
return; return;
} }

View File

@ -1,25 +0,0 @@
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {ProfileFieldsComponent} from './profilefields.component';
describe('ProfileFieldsComponent', () => {
let component: ProfileFieldsComponent;
let fixture: ComponentFixture<ProfileFieldsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ProfileFieldsComponent]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ProfileFieldsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { QuotasComponent } from './quotas.component';
describe('QuotasComponent', () => {
let component: QuotasComponent;
let fixture: ComponentFixture<QuotasComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ QuotasComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(QuotasComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -878,6 +878,117 @@
</tbody> </tbody>
</table> </table>
<h4 id="PeerTube">Nutzung des Dienstes PeerTube <small>tube.bstly.de</small></h4>
<h5>Gespeicherte Daten</h5>
<p>Die folgenden Daten werden durch den Dienst PeerTube erfasst:
<p>
<table border="1">
<thead>
<tr>
<th>Bezeichnung</th>
<th>Betroffene Benutzer </th>
<th>Speicherfrist</th>
<th>Verwendungszweck</th>
<th>Weitergabe an Dritte</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<strong>Streaming-Daten / IP-Addresse</strong>
<p>P2P Video Funktionalität (<a href="https://tube.bstly.de/about/peertube#privacy">Details</a>)</p>
</td>
<td>
<p>Alle Nutzer der Plattform mit aktiviertem Verteilsystem (Standard)</p>
</td>
<td>
<p>Bis zum Leeren des Browser Caches</p>
</td>
<td>
<p>Teilen von geschauten Videos über P2P mit anderen.</p>
</td>
<td>
<p>Weitergabe an Dritte! Kann aktiv ausgeschaltet werden.</p>
</td>
</tr>
<tr>
<td>
<strong>Account-Daten</strong>
<p>Benutzername, E-Mail Adresse, Profildaten (freiwillig)</p>
</td>
<td>
<p>Benutzer mit Account</p>
</td>
<td>
<p>bis zur Löschung</p>
</td>
<td>
<p>Erstellen von Kanälen, Videos, Livestreams und Kommentaren.</p>
</td>
<td>
<p>einsehbar für andere Benutzer</p>
<p>öffentlich einsehbar bei Aktivitäten in öffentlichen Kanälen</p>
</td>
</tr>
<tr>
<td>
<strong>Einstellungen/Kanäle</strong>
<p>Eigene, favorisierte Kanäle</p>
</td>
<td>
<p>Benutzer mit Account</p>
</td>
<td>
<p>bis zur Löschung</p>
</td>
<td>
<p>Verwaltung der Kanälen, Nutzung der Plattform</p>
</td>
<td>
<p>Weitergabe individuell vom Nutzer einstellbar</p>
</td>
</tr>
<tr>
<td>
<strong>Videos/Livestreams</strong>
<p>Videos in den Kanälen</p>
</td>
<td>
<p>Benutzer mit Account</p>
</td>
<td>
<p>siehe Einstellungen/Kanäle</p>
</td>
<td>
<p>Hochladen von Videos in Kanäle, Bereitstellen der Videos für andere, Livestreams</p>
</td>
<td>
<p>Abhängig von Sichtbarkeit der entsprechenden Kanäle/Videos/Livestreams, siehe Einstellungen/Kanäle</p>
</td>
</tr>
<tr>
<td>
<strong>Kommentare</strong>
<p>Kommentare zu Videos</p>
</td>
<td>
<p>Benutzer mit Account</p>
</td>
<td>
<p>siehe Einstellungen/ Kanäle</p>
</td>
<td>
<p>Kommunikation über Inhalte</p>
</td>
<td>
<p>Abhängig von Sichtbarkeit der entsprechenden Kanäle/Videos, siehe Einstellungen/Kanäle</p>
</td>
</tr>
</tbody>
</table>
<h4 id="Gitea">Nutzung des Dienstes Gitea <small>git.bstly.de</small></h4> <h4 id="Gitea">Nutzung des Dienstes Gitea <small>git.bstly.de</small></h4>
@ -918,7 +1029,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<strong>Einstellungen/ Repositorien</strong> <strong>Einstellungen/Repositorien</strong>
<p>Eigene, favorisierte Repositorien, Öffentlicher Schlüssel zur Authentifizierung </p> <p>Eigene, favorisierte Repositorien, Öffentlicher Schlüssel zur Authentifizierung </p>
</td> </td>
<td> <td>
@ -943,13 +1054,13 @@
<p>Benutzer mit Account</p> <p>Benutzer mit Account</p>
</td> </td>
<td> <td>
<p>siehe Einstellungen/ Repositorien</p> <p>siehe Einstellungen/Repositorien</p>
</td> </td>
<td> <td>
<p>Speichern von Dateien in Repositorien</p> <p>Speichern von Dateien in Repositorien</p>
</td> </td>
<td> <td>
<p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/ Repositorien</p> <p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/Repositorien</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -961,13 +1072,13 @@
<p>Benutzer mit Account</p> <p>Benutzer mit Account</p>
</td> </td>
<td> <td>
<p>siehe Einstellungen/ Repositorien</p> <p>siehe Einstellungen/Repositorien</p>
</td> </td>
<td> <td>
<p>Nachverfolgung und Wiederherstellung von Änderungen</p> <p>Nachverfolgung und Wiederherstellung von Änderungen</p>
</td> </td>
<td> <td>
<p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/ Repositorien</p> <p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/Repositorien</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -979,13 +1090,13 @@
<p>Benutzer mit Account</p> <p>Benutzer mit Account</p>
</td> </td>
<td> <td>
<p>siehe Einstellungen/ Repositorien</p> <p>siehe Einstellungen/Repositorien</p>
</td> </td>
<td> <td>
<p>Dokumentation, Aufgabenmanagement und Kommunikation über Inhalte</p> <p>Dokumentation, Aufgabenmanagement und Kommunikation über Inhalte</p>
</td> </td>
<td> <td>
<p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/ Repositorien</p> <p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/Repositorien</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -1007,4 +1118,4 @@
target="_blank">netcup GmbH</a> gespeichert. Eine regelmäßige, automatisierte Datensicherung der target="_blank">netcup GmbH</a> gespeichert. Eine regelmäßige, automatisierte Datensicherung der
Bestandsdaten Bestandsdaten
wird durchgeführt. wird durchgeführt.
</p> </p>

View File

@ -880,6 +880,117 @@
</tbody> </tbody>
</table> </table>
<h4 id="PeerTube">Nutzung des Dienstes PeerTube <small>tube.bstly.de</small></h4>
<h5>Gespeicherte Daten</h5>
<p>Die folgenden Daten werden durch den Dienst PeerTube erfasst:
<p>
<table border="1">
<thead>
<tr>
<th>Bezeichnung</th>
<th>Betroffene Benutzer </th>
<th>Speicherfrist</th>
<th>Verwendungszweck</th>
<th>Weitergabe an Dritte</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<strong>Streaming-Daten / IP-Addresse</strong>
<p>P2P Video Funktionalität (<a href="https://tube.bstly.de/about/peertube#privacy">Details</a>)</p>
</td>
<td>
<p>Alle Nutzer der Plattform mit aktiviertem Verteilsystem (Standard)</p>
</td>
<td>
<p>Bis zum Leeren des Browser Caches</p>
</td>
<td>
<p>Teilen von geschauten Videos über P2P mit anderen.</p>
</td>
<td>
<p>Weitergabe an Dritte! Kann aktiv ausgeschaltet werden.</p>
</td>
</tr>
<tr>
<td>
<strong>Account-Daten</strong>
<p>Benutzername, E-Mail Adresse, Profildaten (freiwillig)</p>
</td>
<td>
<p>Benutzer mit Account</p>
</td>
<td>
<p>bis zur Löschung</p>
</td>
<td>
<p>Erstellen von Kanälen, Videos, Livestreams und Kommentaren.</p>
</td>
<td>
<p>einsehbar für andere Benutzer</p>
<p>öffentlich einsehbar bei Aktivitäten in öffentlichen Kanälen</p>
</td>
</tr>
<tr>
<td>
<strong>Einstellungen/Kanäle</strong>
<p>Eigene, favorisierte Kanäle</p>
</td>
<td>
<p>Benutzer mit Account</p>
</td>
<td>
<p>bis zur Löschung</p>
</td>
<td>
<p>Verwaltung der Kanälen, Nutzung der Plattform</p>
</td>
<td>
<p>Weitergabe individuell vom Nutzer einstellbar</p>
</td>
</tr>
<tr>
<td>
<strong>Videos/Livestreams</strong>
<p>Videos in den Kanälen</p>
</td>
<td>
<p>Benutzer mit Account</p>
</td>
<td>
<p>siehe Einstellungen/Kanäle</p>
</td>
<td>
<p>Hochladen von Videos in Kanäle, Bereitstellen der Videos für andere, Livestreams</p>
</td>
<td>
<p>Abhängig von Sichtbarkeit der entsprechenden Kanäle/Videos/Livestreams, siehe Einstellungen/Kanäle</p>
</td>
</tr>
<tr>
<td>
<strong>Kommentare</strong>
<p>Kommentare zu Videos</p>
</td>
<td>
<p>Benutzer mit Account</p>
</td>
<td>
<p>siehe Einstellungen/ Kanäle</p>
</td>
<td>
<p>Kommunikation über Inhalte</p>
</td>
<td>
<p>Abhängig von Sichtbarkeit der entsprechenden Kanäle/Videos, siehe Einstellungen/Kanäle</p>
</td>
</tr>
</tbody>
</table>
<h4 id="Gitea">Nutzung des Dienstes Gitea <small>git.bstly.de</small></h4> <h4 id="Gitea">Nutzung des Dienstes Gitea <small>git.bstly.de</small></h4>
@ -920,7 +1031,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<strong>Einstellungen/ Repositorien</strong> <strong>Einstellungen/Repositorien</strong>
<p>Eigene, favorisierte Repositorien, Öffentlicher Schlüssel zur Authentifizierung </p> <p>Eigene, favorisierte Repositorien, Öffentlicher Schlüssel zur Authentifizierung </p>
</td> </td>
<td> <td>
@ -945,13 +1056,13 @@
<p>Benutzer mit Account</p> <p>Benutzer mit Account</p>
</td> </td>
<td> <td>
<p>siehe Einstellungen/ Repositorien</p> <p>siehe Einstellungen/Repositorien</p>
</td> </td>
<td> <td>
<p>Speichern von Dateien in Repositorien</p> <p>Speichern von Dateien in Repositorien</p>
</td> </td>
<td> <td>
<p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/ Repositorien</p> <p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/Repositorien</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -963,13 +1074,13 @@
<p>Benutzer mit Account</p> <p>Benutzer mit Account</p>
</td> </td>
<td> <td>
<p>siehe Einstellungen/ Repositorien</p> <p>siehe Einstellungen/Repositorien</p>
</td> </td>
<td> <td>
<p>Nachverfolgung und Wiederherstellung von Änderungen</p> <p>Nachverfolgung und Wiederherstellung von Änderungen</p>
</td> </td>
<td> <td>
<p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/ Repositorien</p> <p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/Repositorien</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -981,13 +1092,13 @@
<p>Benutzer mit Account</p> <p>Benutzer mit Account</p>
</td> </td>
<td> <td>
<p>siehe Einstellungen/ Repositorien</p> <p>siehe Einstellungen/Repositorien</p>
</td> </td>
<td> <td>
<p>Dokumentation, Aufgabenmanagement und Kommunikation über Inhalte</p> <p>Dokumentation, Aufgabenmanagement und Kommunikation über Inhalte</p>
</td> </td>
<td> <td>
<p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/ Repositorien</p> <p>Abhängig von Sichtbarkeit der entsprechenden Repositorien, siehe Einstellungen/Repositorien</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -1009,4 +1120,4 @@
target="_blank">netcup GmbH</a> gespeichert. Eine regelmäßige, automatisierte Datensicherung der target="_blank">netcup GmbH</a> gespeichert. Eine regelmäßige, automatisierte Datensicherung der
Bestandsdaten Bestandsdaten
wird durchgeführt. wird durchgeführt.
</p> </p>