Auth Email Rework (#1567)

* Hooked up Send to for Series and volumes and fixed a bug where Email Service errors weren't propagating to the UI layer.

When performing actions on series detail, don't disable the button anymore.

* Added send to action to volumes

* Fixed a bug where .kavitaignore wasn't being applied at library root level

* Added a notification for when a device is being sent a file.

* Added a check in forgot password for users that do not have an email set or aren't confirmed.

* Added a new api for change email and moved change password directly into new Account tab (styling and logic needs testing)

* Save approx scroll position like with jump key, but on normal click of card.

* Implemented the ability to change your email address or set one. This requires a 2 step process using a confirmation token. This needs polishing and css.

* Removed an unused directive from codebase

* Fixed up some typos on publicly

* Updated query for Pending Invites to also check if the user account has not logged in at least once.

* Cleaned up the css for validate email change

* Hooked in an indicator to tell user that a user has an unconfirmed email

* Cleaned up code smells
This commit is contained in:
Joe Milazzo 2022-10-01 08:23:35 -05:00 committed by GitHub
parent 3792ac3421
commit 5f17c2fb73
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 816 additions and 274 deletions

View file

@ -0,0 +1,82 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ToastrService } from 'ngx-toastr';
import { map, Observable, of, shareReplay, Subject, takeUntil } from 'rxjs';
import { User } from 'src/app/_models/user';
import { AccountService } from 'src/app/_services/account.service';
@Component({
selector: 'app-change-password',
templateUrl: './change-password.component.html',
styleUrls: ['./change-password.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChangePasswordComponent implements OnInit, OnDestroy {
passwordChangeForm: FormGroup = new FormGroup({});
user: User | undefined = undefined;
hasChangePasswordAbility: Observable<boolean> = of(false);
observableHandles: Array<any> = [];
passwordsMatch = false;
resetPasswordErrors: string[] = [];
isViewMode: boolean = true;
public get password() { return this.passwordChangeForm.get('password'); }
public get confirmPassword() { return this.passwordChangeForm.get('confirmPassword'); }
private onDestroy = new Subject<void>();
constructor(private accountService: AccountService, private toastr: ToastrService, private readonly cdRef: ChangeDetectorRef) { }
ngOnInit(): void {
this.hasChangePasswordAbility = this.accountService.currentUser$.pipe(takeUntil(this.onDestroy), shareReplay(), map(user => {
return user !== undefined && (this.accountService.hasAdminRole(user) || this.accountService.hasChangePasswordRole(user));
}));
this.cdRef.markForCheck();
this.passwordChangeForm.addControl('password', new FormControl('', [Validators.required]));
this.passwordChangeForm.addControl('confirmPassword', new FormControl('', [Validators.required]));
this.passwordChangeForm.addControl('oldPassword', new FormControl('', [Validators.required]));
this.observableHandles.push(this.passwordChangeForm.valueChanges.subscribe(() => {
const values = this.passwordChangeForm.value;
this.passwordsMatch = values.password === values.confirmPassword;
this.cdRef.markForCheck();
}));
}
ngOnDestroy() {
this.observableHandles.forEach(o => o.unsubscribe());
this.onDestroy.next();
this.onDestroy.complete();
}
resetPasswordForm() {
this.passwordChangeForm.get('password')?.setValue('');
this.passwordChangeForm.get('confirmPassword')?.setValue('');
this.passwordChangeForm.get('oldPassword')?.setValue('');
this.resetPasswordErrors = [];
this.cdRef.markForCheck();
}
savePasswordForm() {
if (this.user === undefined) { return; }
const model = this.passwordChangeForm.value;
this.resetPasswordErrors = [];
this.observableHandles.push(this.accountService.resetPassword(this.user?.username, model.confirmPassword, model.oldPassword).subscribe(() => {
this.toastr.success('Password has been updated');
this.resetPasswordForm();
this.isViewMode = true;
}, err => {
this.resetPasswordErrors = err;
}));
}
toggleViewMode() {
this.isViewMode = !this.isViewMode;
this.resetPasswordForm();
}
}