Account Email Support (#1000)
* Moved the Server Settings out into a button on nav header * Refactored Mange Users page to the new design (skeleton). Implemented skeleton code for Invite User. * Hashed out more of the code, but need to move all the email code to a Kavita controlled API server due to password credentials. * Cleaned up some warnings * When no user exists for an api key in Plugin controller, throw 401. * Hooked in the ability to check if the Kavita instance can be accessed externally so we can determine if the user can invite or not. * Hooked up some logic if the user's server isn't accessible, then default to old flow * Basic flow is working for confirm email. Needs validation, error handling, etc. * Refactored Password validation to account service * Cleaned up the code in confirm-email to work much better. * Refactored the login page to have a container functionality, so we can reuse the styles on multiple pages (registration pages). Hooked up the code for confirm email. * Messy code, but making progress. Refactored Register to be used only for first time user registration. Added a new register component to handle first time flow only. * Invite works much better, still needs a bit of work for non-accessible server setup. Started work on underlying manage users page to meet new design. * Changed (you) to a star to indicate who you're logged in as. * Inviting a user is now working and tested fully. * Removed the register member component as we now have invite and confirm components. * Editing a user is now working. Username change and Role/Library access from within one screen. Email changing is on hold. * Cleaned up code for edit user and disabled email field for now. * Cleaned up the code to indicate changing a user's email is not possible. * Implemented a migration for existing accounts so they can validate their emails and still login. * Change url for email server * Implemented the ability to resend an email confirmation code (or regenerate for non accessible servers). Fixed an overflow on the confirm dialog. * Took care of some code cleanup * Removed 3 db calls from cover refresh and some misc cleanup * Fixed a broken test
This commit is contained in:
parent
6e6b72a5b5
commit
efb527035d
109 changed files with 2041 additions and 407 deletions
|
|
@ -0,0 +1,58 @@
|
|||
<!--
|
||||
<div class="text-danger" *ngIf="errors.length > 0">
|
||||
<p>Errors:</p>
|
||||
<ul>
|
||||
<li *ngFor="let error of errors">{{error}}</li>
|
||||
</ul>
|
||||
</div> -->
|
||||
<app-splash-container>
|
||||
<ng-container title><h2>Register</h2></ng-container>
|
||||
<ng-container body>
|
||||
<p>Complete the form to complete your registration</p>
|
||||
<form [formGroup]="registerForm" (ngSubmit)="submit()">
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input id="username" class="form-control" formControlName="username" type="text">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="registerForm.dirty || registerForm.touched">
|
||||
<div *ngIf="registerForm.get('username')?.errors?.required">
|
||||
This field is required
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" style="width:100%">
|
||||
<label for="email">Email</label>
|
||||
<input class="form-control" type="email" id="email" formControlName="email" required>
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="registerForm.dirty || registerForm.touched">
|
||||
<div *ngIf="registerForm.get('email')?.errors?.required">
|
||||
This field is required
|
||||
</div>
|
||||
<div *ngIf="registerForm.get('email')?.errors?.email">
|
||||
This must be a valid email address
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="passwordTooltip" role="button" tabindex="0"></i>
|
||||
<ng-template #passwordTooltip>
|
||||
Password must be between 6 and 32 characters in length
|
||||
</ng-template>
|
||||
<span class="sr-only" id="password-help"><ng-container [ngTemplateOutlet]="passwordTooltip"></ng-container></span>
|
||||
<input id="password" class="form-control" maxlength="32" minlength="6" formControlName="password" type="password" aria-describedby="password-help">
|
||||
<div id="inviteForm-validations" class="invalid-feedback" *ngIf="registerForm.dirty || registerForm.touched">
|
||||
<div *ngIf="registerForm.get('password')?.errors?.required">
|
||||
This field is required
|
||||
</div>
|
||||
<div *ngIf="registerForm.get('password')?.errors?.minlength || registerForm.get('password')?.errors?.maxLength">
|
||||
Password must be between 6 and 32 characters in length
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="float-right">
|
||||
<button class="btn btn-secondary alt" type="submit">Register</button>
|
||||
</div>
|
||||
</form>
|
||||
</ng-container>
|
||||
</app-splash-container>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
input {
|
||||
background-color: #fff !important;
|
||||
color: black;
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { AccountService } from 'src/app/_services/account.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-confirm-email',
|
||||
templateUrl: './confirm-email.component.html',
|
||||
styleUrls: ['./confirm-email.component.scss']
|
||||
})
|
||||
export class ConfirmEmailComponent implements OnInit {
|
||||
|
||||
|
||||
/**
|
||||
* Email token used for validating
|
||||
*/
|
||||
token: string = '';
|
||||
|
||||
registerForm: FormGroup = new FormGroup({
|
||||
email: new FormControl('', [Validators.required, Validators.email]),
|
||||
username: new FormControl('', [Validators.required]),
|
||||
password: new FormControl('', [Validators.required, Validators.maxLength(32), Validators.minLength(6)]),
|
||||
});
|
||||
|
||||
/**
|
||||
* Validation errors from API
|
||||
*/
|
||||
errors: Array<string> = [];
|
||||
|
||||
|
||||
constructor(private route: ActivatedRoute, private router: Router, private accountService: AccountService, private toastr: ToastrService) {
|
||||
|
||||
const token = this.route.snapshot.queryParamMap.get('token');
|
||||
const email = this.route.snapshot.queryParamMap.get('email');
|
||||
if (token == undefined || token === '' || token === null) {
|
||||
// This is not a valid url, redirect to login
|
||||
this.toastr.error('Invalid confirmation email');
|
||||
this.router.navigateByUrl('login');
|
||||
return;
|
||||
}
|
||||
this.token = token;
|
||||
this.registerForm.get('email')?.setValue(email || '');
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
submit() {
|
||||
let model = this.registerForm.getRawValue();
|
||||
model.token = this.token;
|
||||
this.accountService.confirmEmail(model).subscribe((user) => {
|
||||
this.toastr.success('Account registration complete');
|
||||
this.router.navigateByUrl('login');
|
||||
}, err => {
|
||||
this.errors = err;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue