Merge remote-tracking branch 'atmire/w2p-97298_issue-3281_self-register-issue-7.2' into w2p-97298_issue-3281_self-register-issue-main

# Conflicts:
#	src/app/register-email-form/register-email-form.component.spec.ts
#	src/app/register-email-form/register-email-form.component.ts
This commit is contained in:
Alexandre Vryghem
2023-02-06 15:56:22 +01:00
4 changed files with 51 additions and 27 deletions

View File

@@ -1,8 +1,10 @@
<div class="container"> <div class="container">
<h2>{{MESSAGE_PREFIX + '.header'|translate}}</h2> <h2>{{MESSAGE_PREFIX + '.header'|translate}}</h2>
<p>{{MESSAGE_PREFIX + '.info' | translate}}</p> <p>{{MESSAGE_PREFIX + '.info' | translate}}</p>
<p
*ngIf="validMailDomains.length!= 0 && MESSAGE_PREFIX==='register-page.registration'">{{ MESSAGE_PREFIX + '.info.maildomain' | translate}} {{ validMailDomains.join(", ")}} </p> <p *ngIf="validMailDomains.length != 0 && typeRequest === TYPE_REQUEST_REGISTER">
{{ MESSAGE_PREFIX + '.info.maildomain' | translate}} {{ validMailDomains.join(', ')}}
</p>
<form [class]="'ng-invalid'" [formGroup]="form"> <form [class]="'ng-invalid'" [formGroup]="form">
@@ -20,9 +22,9 @@
</span> </span>
<span *ngIf="email.errors && ((email.errors.pattern && this.typeRequest === TYPE_REQUEST_REGISTER) || email.errors.email)"> <span *ngIf="email.errors && ((email.errors.pattern && this.typeRequest === TYPE_REQUEST_REGISTER) || email.errors.email)">
{{ MESSAGE_PREFIX + '.email.error.not-email-form' | translate }} {{ MESSAGE_PREFIX + '.email.error.not-email-form' | translate }}
</span> <ng-container *ngIf="validMailDomains.length > 0">
<span *ngIf="email.errors && email.errors.pattern && this.typeRequest === TYPE_REQUEST_REGISTER"> {{ MESSAGE_PREFIX + '.email.error.not-valid-domain' | translate: { domains: validMailDomains.join(', ') } }}
{{ MESSAGE_PREFIX + '.email.error.not-valid-domain' | translate: { domains: validMailDomains } }} </ng-container>
</span> </span>
</div> </div>
</div> </div>

View File

@@ -12,7 +12,10 @@ import { EpersonRegistrationService } from '../core/data/eperson-registration.se
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { RouterStub } from '../shared/testing/router.stub'; import { RouterStub } from '../shared/testing/router.stub';
import { NotificationsServiceStub } from '../shared/testing/notifications-service.stub'; import { NotificationsServiceStub } from '../shared/testing/notifications-service.stub';
import { RegisterEmailFormComponent } from './register-email-form.component'; import {
RegisterEmailFormComponent,
TYPE_REQUEST_FORGOT
} from './register-email-form.component';
import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils';
import { ConfigurationDataService } from '../core/data/configuration-data.service'; import { ConfigurationDataService } from '../core/data/configuration-data.service';
import { GoogleRecaptchaService } from '../core/google-recaptcha/google-recaptcha.service'; import { GoogleRecaptchaService } from '../core/google-recaptcha/google-recaptcha.service';
@@ -53,6 +56,8 @@ describe('RegisterEmailFormComponent', () => {
registerEmail: createSuccessfulRemoteDataObject$({}) registerEmail: createSuccessfulRemoteDataObject$({})
}); });
jasmine.getEnv().allowRespy(true);
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), ReactiveFormsModule], imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), ReactiveFormsModule],
declarations: [RegisterEmailFormComponent], declarations: [RegisterEmailFormComponent],
@@ -82,6 +87,15 @@ describe('RegisterEmailFormComponent', () => {
const elem = fixture.debugElement.queryAll(By.css('input#email'))[0].nativeElement; const elem = fixture.debugElement.queryAll(By.css('input#email'))[0].nativeElement;
expect(elem).toBeDefined(); expect(elem).toBeDefined();
}); });
it('should not retrieve the validDomains for TYPE_REQUEST_FORGOT', () => {
spyOn(configurationDataService, 'findByPropertyName');
comp.typeRequest = TYPE_REQUEST_FORGOT;
comp.ngOnInit();
expect(configurationDataService.findByPropertyName).not.toHaveBeenCalledWith('authentication-password.domain.valid');
});
}); });
describe('email validation', () => { describe('email validation', () => {
it('should be invalid when no email is present', () => { it('should be invalid when no email is present', () => {

View File

@@ -1,4 +1,4 @@
import {ChangeDetectorRef, Component, Input, OnInit, Optional} from '@angular/core'; import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit, Optional } from '@angular/core';
import {EpersonRegistrationService} from '../core/data/eperson-registration.service'; import {EpersonRegistrationService} from '../core/data/eperson-registration.service';
import {NotificationsService} from '../shared/notifications/notifications.service'; import {NotificationsService} from '../shared/notifications/notifications.service';
import {TranslateService} from '@ngx-translate/core'; import {TranslateService} from '@ngx-translate/core';
@@ -7,7 +7,7 @@ import { FormBuilder, FormControl, FormGroup, Validators, ValidatorFn } from '@a
import {Registration} from '../core/shared/registration.model'; import {Registration} from '../core/shared/registration.model';
import {RemoteData} from '../core/data/remote-data'; import {RemoteData} from '../core/data/remote-data';
import {ConfigurationDataService} from '../core/data/configuration-data.service'; import {ConfigurationDataService} from '../core/data/configuration-data.service';
import {getAllCompletedRemoteData, getFirstSucceededRemoteDataPayload} from '../core/shared/operators'; import { getAllSucceededRemoteDataPayload, getFirstSucceededRemoteDataPayload } from '../core/shared/operators';
import {ConfigurationProperty} from '../core/shared/configuration-property.model'; import {ConfigurationProperty} from '../core/shared/configuration-property.model';
import {isNotEmpty} from '../shared/empty.util'; import {isNotEmpty} from '../shared/empty.util';
import {BehaviorSubject, combineLatest, Observable, of, switchMap} from 'rxjs'; import {BehaviorSubject, combineLatest, Observable, of, switchMap} from 'rxjs';
@@ -16,6 +16,7 @@ import {CAPTCHA_NAME, GoogleRecaptchaService} from '../core/google-recaptcha/goo
import {AlertType} from '../shared/alert/aletr-type'; import {AlertType} from '../shared/alert/aletr-type';
import {KlaroService} from '../shared/cookies/klaro.service'; import {KlaroService} from '../shared/cookies/klaro.service';
import {CookieService} from '../core/services/cookie.service'; import {CookieService} from '../core/services/cookie.service';
import { Subscription } from 'rxjs';
export const TYPE_REQUEST_FORGOT = 'forgot'; export const TYPE_REQUEST_FORGOT = 'forgot';
export const TYPE_REQUEST_REGISTER = 'register'; export const TYPE_REQUEST_REGISTER = 'register';
@@ -27,7 +28,7 @@ export const TYPE_REQUEST_REGISTER = 'register';
/** /**
* Component responsible to render an email registration form. * Component responsible to render an email registration form.
*/ */
export class RegisterEmailFormComponent implements OnInit { export class RegisterEmailFormComponent implements OnDestroy, OnInit {
/** /**
* The form containing the mail address * The form containing the mail address
@@ -63,6 +64,8 @@ export class RegisterEmailFormComponent implements OnInit {
validMailDomains: string[]; validMailDomains: string[];
TYPE_REQUEST_REGISTER = TYPE_REQUEST_REGISTER; TYPE_REQUEST_REGISTER = TYPE_REQUEST_REGISTER;
subscriptions: Subscription[] = [];
captchaVersion(): Observable<string> { captchaVersion(): Observable<string> {
return this.googleRecaptchaService.captchaVersion(); return this.googleRecaptchaService.captchaVersion();
} }
@@ -86,6 +89,10 @@ export class RegisterEmailFormComponent implements OnInit {
) { ) {
} }
ngOnDestroy(): void {
this.subscriptions.forEach((sub: Subscription) => sub.unsubscribe());
}
ngOnInit(): void { ngOnInit(): void {
const validators: ValidatorFn[] = [ const validators: ValidatorFn[] = [
Validators.required, Validators.required,
@@ -100,13 +107,13 @@ export class RegisterEmailFormComponent implements OnInit {
}) })
}); });
this.validMailDomains = []; this.validMailDomains = [];
this.configService.findByPropertyName('authentication-password.domain.valid') if (this.typeRequest === TYPE_REQUEST_REGISTER) {
.pipe(getAllCompletedRemoteData()) this.subscriptions.push(this.configService.findByPropertyName('authentication-password.domain.valid')
.subscribe((remoteData: RemoteData<ConfigurationProperty>) => { .pipe(getAllSucceededRemoteDataPayload())
if (remoteData.payload) { .subscribe((remoteData: ConfigurationProperty) => {
for (const remoteValue of remoteData.payload.values) { this.validMailDomains = remoteData.values;
this.validMailDomains.push(remoteValue); for (const remoteValue of remoteData.values) {
if (this.validMailDomains.length !== 0 && this.typeRequest === TYPE_REQUEST_REGISTER) { if (this.validMailDomains.length !== 0) {
this.form.get('email').setValidators([ this.form.get('email').setValidators([
...validators, ...validators,
Validators.pattern(this.validMailDomains.map((domain: string) => '(^.*' + domain.replace(new RegExp('\\.', 'g'), '\\.') + '$)').join('|')), Validators.pattern(this.validMailDomains.map((domain: string) => '(^.*' + domain.replace(new RegExp('\\.', 'g'), '\\.') + '$)').join('|')),
@@ -114,19 +121,20 @@ export class RegisterEmailFormComponent implements OnInit {
this.form.updateValueAndValidity(); this.form.updateValueAndValidity();
} }
} }
} this.changeDetectorRef.detectChanges();
}); }));
this.configService.findByPropertyName('registration.verification.enabled').pipe( }
this.subscriptions.push(this.configService.findByPropertyName('registration.verification.enabled').pipe(
getFirstSucceededRemoteDataPayload(), getFirstSucceededRemoteDataPayload(),
map((res: ConfigurationProperty) => res?.values[0].toLowerCase() === 'true') map((res: ConfigurationProperty) => res?.values[0].toLowerCase() === 'true')
).subscribe((res: boolean) => { ).subscribe((res: boolean) => {
this.registrationVerification = res; this.registrationVerification = res;
}); }));
this.disableUntilCheckedFcn().subscribe((res) => { this.subscriptions.push(this.disableUntilCheckedFcn().subscribe((res) => {
this.disableUntilChecked = res; this.disableUntilChecked = res;
this.changeDetectorRef.detectChanges(); this.changeDetectorRef.detectChanges();
}); }));
} }
/** /**
@@ -142,7 +150,7 @@ export class RegisterEmailFormComponent implements OnInit {
register(tokenV2?) { register(tokenV2?) {
if (!this.form.invalid) { if (!this.form.invalid) {
if (this.registrationVerification) { if (this.registrationVerification) {
combineLatest([this.captchaVersion(), this.captchaMode()]).pipe( this.subscriptions.push(combineLatest([this.captchaVersion(), this.captchaMode()]).pipe(
switchMap(([captchaVersion, captchaMode]) => { switchMap(([captchaVersion, captchaMode]) => {
if (captchaVersion === 'v3') { if (captchaVersion === 'v3') {
return this.googleRecaptchaService.getRecaptchaToken('register_email'); return this.googleRecaptchaService.getRecaptchaToken('register_email');
@@ -164,7 +172,7 @@ export class RegisterEmailFormComponent implements OnInit {
this.showNotification('error'); this.showNotification('error');
} }
} }
); ));
} else { } else {
this.registration(); this.registration();
} }
@@ -178,7 +186,7 @@ export class RegisterEmailFormComponent implements OnInit {
let registerEmail$ = captchaToken ? let registerEmail$ = captchaToken ?
this.epersonRegistrationService.registerEmail(this.email.value, captchaToken, this.typeRequest) : this.epersonRegistrationService.registerEmail(this.email.value, captchaToken, this.typeRequest) :
this.epersonRegistrationService.registerEmail(this.email.value, null, this.typeRequest); this.epersonRegistrationService.registerEmail(this.email.value, null, this.typeRequest);
registerEmail$.subscribe((response: RemoteData<Registration>) => { this.subscriptions.push(registerEmail$.subscribe((response: RemoteData<Registration>) => {
if (response.hasSucceeded) { if (response.hasSucceeded) {
this.notificationService.success(this.translateService.get(`${this.MESSAGE_PREFIX}.success.head`), this.notificationService.success(this.translateService.get(`${this.MESSAGE_PREFIX}.success.head`),
this.translateService.get(`${this.MESSAGE_PREFIX}.success.content`, {email: this.email.value})); this.translateService.get(`${this.MESSAGE_PREFIX}.success.content`, {email: this.email.value}));
@@ -189,7 +197,7 @@ export class RegisterEmailFormComponent implements OnInit {
this.notificationService.error(this.translateService.get(`${this.MESSAGE_PREFIX}.error.head`), this.notificationService.error(this.translateService.get(`${this.MESSAGE_PREFIX}.error.head`),
this.translateService.get(`${this.MESSAGE_PREFIX}.error.content`, {email: this.email.value})); this.translateService.get(`${this.MESSAGE_PREFIX}.error.content`, {email: this.email.value}));
} }
}); }));
} }
/** /**

View File

@@ -3267,7 +3267,7 @@
"register-page.registration.email.error.required": "Please fill in an email address", "register-page.registration.email.error.required": "Please fill in an email address",
"register-page.registration.email.error.not-email-form": "Please fill in a valid email address. ", "register-page.registration.email.error.not-email-form": "Please fill in a valid email address.",
"register-page.registration.email.error.not-valid-domain": "Use email with allowed domains: {{ domains }}", "register-page.registration.email.error.not-valid-domain": "Use email with allowed domains: {{ domains }}",