Add email re-validation handling with UI feedback and backend validation to prevent duplicate email verification attempts
This commit is contained in:
parent
d1da1296bb
commit
42b11eecf1
|
|
@ -33,6 +33,14 @@ public class MailController implements MailApi {
|
||||||
@RateLimit(limit = 5, timeValue = 1, timeUnit = TimeUnit.HOURS, key = "mailSubmit")
|
@RateLimit(limit = 5, timeValue = 1, timeUnit = TimeUnit.HOURS, key = "mailSubmit")
|
||||||
public ResponseEntity<MailResponseDto> submitEmailForVerification(SubmitEmailDto submitEmailDto) {
|
public ResponseEntity<MailResponseDto> submitEmailForVerification(SubmitEmailDto submitEmailDto) {
|
||||||
UUID uuid = AuthenticatedUuid.getAuthenticatedUserUuid();
|
UUID uuid = AuthenticatedUuid.getAuthenticatedUserUuid();
|
||||||
|
boolean emailAlreadyVerified = mailVerificationService.listAll(uuid).stream()
|
||||||
|
.filter(EmailVerification::verified)
|
||||||
|
.map(EmailVerification::email)
|
||||||
|
.anyMatch(mail -> mail.equalsIgnoreCase(submitEmailDto.getEmail()));
|
||||||
|
if (emailAlreadyVerified) {
|
||||||
|
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Email already verified for user");
|
||||||
|
}
|
||||||
|
|
||||||
EmailVerification saved = mailVerificationService.submitEmail(uuid, submitEmailDto.getEmail());
|
EmailVerification saved = mailVerificationService.submitEmail(uuid, submitEmailDto.getEmail());
|
||||||
MailResponseDto response = new MailResponseDto()
|
MailResponseDto response = new MailResponseDto()
|
||||||
.email(saved.email())
|
.email(saved.email())
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,14 @@
|
||||||
</mat-error>
|
</mat-error>
|
||||||
}
|
}
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
@if (emailIsValid()) {
|
||||||
|
<div class="valid-email">
|
||||||
|
<ng-container matSuffix>
|
||||||
|
<mat-icon>check</mat-icon>
|
||||||
|
<span>Your have already validated your email, and can continue to the next page!</span>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<button mat-raised-button (click)="validateMailOrNextPage()" [disabled]="form.controls.email.invalid">
|
<button mat-raised-button (click)="validateMailOrNextPage()" [disabled]="form.controls.email.invalid">
|
||||||
Next
|
Next
|
||||||
|
|
|
||||||
|
|
@ -89,3 +89,23 @@ main {
|
||||||
max-width: 75ch;
|
max-width: 75ch;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.valid-email {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #4CAF50;
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: rgba(76, 175, 80, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.valid-email mat-icon {
|
||||||
|
color: #4CAF50;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.valid-email span {
|
||||||
|
color: #4CAF50;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ export class AppealComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
protected verifiedEmails = computed(() => this.emails()
|
protected verifiedEmails = computed(() => this.emails()
|
||||||
.filter(email => email.verified)
|
.filter(email => email.verified)
|
||||||
.map(email => email.email.toLowerCase()));
|
.map(email => email.email.toLowerCase()));
|
||||||
protected validatedMail = signal<boolean>(false);
|
protected emailIsValid = signal<boolean>(false);
|
||||||
protected dialog = inject(MatDialog);
|
protected dialog = inject(MatDialog);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
@ -73,10 +73,13 @@ export class AppealComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
this.emails.set(emails);
|
this.emails.set(emails);
|
||||||
});
|
});
|
||||||
this.form.valueChanges.subscribe(() => {
|
this.form.valueChanges.subscribe(() => {
|
||||||
if (this.form.getRawValue().email.toLowerCase() in this.verifiedEmails()) {
|
if (this.verifiedEmails().includes(this.form.getRawValue().email.toLowerCase())) {
|
||||||
this.validatedMail.set(true);
|
this.emailIsValid.set(true);
|
||||||
|
} else {
|
||||||
|
this.emailIsValid.set(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
|
@ -225,7 +228,7 @@ export class AppealComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected validateMailOrNextPage() {
|
protected validateMailOrNextPage() {
|
||||||
if (this.validatedMail()) {
|
if (this.emailIsValid()) {
|
||||||
this.nextPage();
|
this.nextPage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -234,7 +237,7 @@ export class AppealComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
});
|
});
|
||||||
dialogRef.afterClosed().subscribe(result => {
|
dialogRef.afterClosed().subscribe(result => {
|
||||||
if (result === true) {
|
if (result === true) {
|
||||||
this.validatedMail.set(true);
|
this.emailIsValid.set(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user