[UXP-10] Code refactoring

This commit is contained in:
Davide Negretti
2022-09-07 18:02:23 +02:00
parent b72b37a647
commit b6d6091c87
4 changed files with 115 additions and 103 deletions

View File

@@ -15,7 +15,8 @@ import {
ActivationEnd,
NavigationCancel,
NavigationEnd,
NavigationStart, ResolveEnd,
NavigationStart,
ResolveEnd,
Router,
} from '@angular/router';
@@ -48,8 +49,7 @@ import { BASE_THEME_NAME } from './shared/theme-support/theme.constants';
import { BreadcrumbsService } from './breadcrumbs/breadcrumbs.service';
import { IdleModalComponent } from './shared/idle-modal/idle-modal.component';
import { getDefaultThemeConfig } from '../config/config.util';
import { AppConfig, APP_CONFIG } from '../config/app-config.interface';
import { GoogleRecaptchaService } from './core/google-recaptcha/google-recaptcha.service';
import { APP_CONFIG, AppConfig } from '../config/app-config.interface';
@Component({
selector: 'ds-app',
@@ -110,7 +110,6 @@ export class AppComponent implements OnInit, AfterViewInit {
private modalConfig: NgbModalConfig,
@Optional() private cookiesService: KlaroService,
@Optional() private googleAnalyticsService: GoogleAnalyticsService,
@Optional() private googleRecaptchaService: GoogleRecaptchaService,
) {
if (!isEqual(environment, this.appConfig)) {

View File

@@ -5,8 +5,8 @@ import { isNotEmpty } from '../../shared/empty.util';
import { DOCUMENT } from '@angular/common';
import { ConfigurationDataService } from '../data/configuration-data.service';
import { RemoteData } from '../data/remote-data';
import { map, take } from 'rxjs/operators';
import { combineLatest, Observable, of } from 'rxjs';
import { map, switchMap, take } from 'rxjs/operators';
import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';
import { CookieService } from '../services/cookie.service';
import { NativeWindowRef, NativeWindowService } from '../services/window.service';
@@ -20,25 +20,33 @@ export const CAPTCHA_NAME = 'google-recaptcha';
export class GoogleRecaptchaService {
private renderer: Renderer2;
/**
* A Google Recaptcha site key
*/
captchaSiteKeyStr: string;
/**
* A Google Recaptcha site key
*/
captchaSiteKey$: Observable<string>;
/**
* A Google Recaptcha mode
*/
captchaMode$: Observable<string> = of('invisible');
/**
* A Google Recaptcha version
*/
captchaVersion$: Observable<string> = of('');
private captchaVersionSubject$ = new BehaviorSubject<string>(null);
/**
* The Google Recaptcha Key
*/
private captchaKeySubject$ = new BehaviorSubject<string>(null);
/**
* The Google Recaptcha mode
*/
private captchaModeSubject$ = new BehaviorSubject<string>(null);
captchaKey(): Observable<string> {
return this.captchaKeySubject$.asObservable();
}
captchaMode(): Observable<string> {
return this.captchaModeSubject$.asObservable();
}
captchaVersion(): Observable<string> {
return this.captchaVersionSubject$.asObservable();
}
constructor(
private cookieService: CookieService,
@@ -66,38 +74,48 @@ export class GoogleRecaptchaService {
}
loadRecaptchaProperties() {
const recaptchaKey$ = this.configService.findByPropertyName('google.recaptcha.key.site').pipe(
take(1),
const recaptchaKeyRD$ = this.configService.findByPropertyName('google.recaptcha.key.site').pipe(
getFirstCompletedRemoteData(),
);
const recaptchaVersion$ = this.configService.findByPropertyName('google.recaptcha.version').pipe(
take(1),
const recaptchaVersionRD$ = this.configService.findByPropertyName('google.recaptcha.version').pipe(
getFirstCompletedRemoteData(),
);
const recaptchaMode$ = this.configService.findByPropertyName('google.recaptcha.mode').pipe(
take(1),
const recaptchaModeRD$ = this.configService.findByPropertyName('google.recaptcha.mode').pipe(
getFirstCompletedRemoteData(),
);
combineLatest(recaptchaVersion$, recaptchaMode$, recaptchaKey$).subscribe(([recaptchaVersion, recaptchaMode, recaptchaKey]) => {
if (this.cookieService.get('klaro-anonymous') && this.cookieService.get('klaro-anonymous')[CAPTCHA_NAME]) {
if (recaptchaKey.hasSucceeded && isNotEmpty(recaptchaKey?.payload?.values[0])) {
this.captchaSiteKeyStr = recaptchaKey?.payload?.values[0];
this.captchaSiteKey$ = of(recaptchaKey?.payload?.values[0]);
combineLatest([recaptchaVersionRD$, recaptchaModeRD$, recaptchaKeyRD$]).subscribe(([recaptchaVersionRD, recaptchaModeRD, recaptchaKeyRD]) => {
if (
this.cookieService.get('klaro-anonymous') && this.cookieService.get('klaro-anonymous')[CAPTCHA_NAME] &&
recaptchaKeyRD.hasSucceeded && recaptchaVersionRD.hasSucceeded &&
isNotEmpty(recaptchaVersionRD.payload?.values) && isNotEmpty(recaptchaKeyRD.payload?.values)
) {
const key = recaptchaKeyRD.payload?.values[0];
const version = recaptchaVersionRD.payload?.values[0];
this.captchaKeySubject$.next(key);
this.captchaVersionSubject$.next(version);
let captchaUrl;
switch (version) {
case 'v3':
if (recaptchaKeyRD.hasSucceeded && isNotEmpty(recaptchaKeyRD.payload?.values)) {
captchaUrl = this.buildCaptchaUrl(key);
this.captchaModeSubject$.next('invisible');
}
if (recaptchaVersion.hasSucceeded && isNotEmpty(recaptchaVersion?.payload?.values[0]) && recaptchaVersion?.payload?.values[0] === 'v3') {
this.captchaVersion$ = of('v3');
if (recaptchaKey.hasSucceeded && isNotEmpty(recaptchaKey?.payload?.values[0])) {
this.loadScript(this.buildCaptchaUrl(recaptchaKey?.payload?.values[0]));
break;
case 'v2':
if (recaptchaModeRD.hasSucceeded && isNotEmpty(recaptchaModeRD.payload?.values)) {
captchaUrl = 'https://www.google.com/recaptcha/api.js';
this.captchaModeSubject$.next(recaptchaModeRD.payload?.values[0]);
}
} else {
this.captchaVersion$ = of('v2');
const captchaUrl = 'https://www.google.com/recaptcha/api.js';
if (recaptchaMode.hasSucceeded && isNotEmpty(recaptchaMode?.payload?.values[0])) {
this.captchaMode$ = of(recaptchaMode?.payload?.values[0]);
break;
default:
// TODO handle error
}
if (captchaUrl) {
this.loadScript(captchaUrl);
}
}
}
});
}
@@ -105,23 +123,21 @@ export class GoogleRecaptchaService {
* Returns an observable of string
* @param action action is the process type in which used to protect multiple spam REST calls
*/
public async getRecaptchaToken (action) {
return await grecaptcha.execute(this.captchaSiteKeyStr, {action: action});
public getRecaptchaToken(action) {
return this.captchaKey().pipe(
switchMap((key) => grecaptcha.execute(key, {action: action}))
);
}
/**
* Returns an observable of string
*/
public async executeRecaptcha () {
return await grecaptcha.execute();
public executeRecaptcha() {
return of(grecaptcha.execute());
}
/**
* Returns an observable of string
* @param action action is the process type in which used to protect multiple spam REST calls
*/
public async getRecaptchaTokenResponse () {
return await grecaptcha.getResponse();
public getRecaptchaTokenResponse () {
return grecaptcha.getResponse();
}
/**

View File

@@ -24,8 +24,8 @@
<div class="col-12">
{{MESSAGE_PREFIX + '.email.hint' |translate}}
</div>
<div class="col-12" *ngIf="(googleRecaptchaService.captchaVersion$ | async) === 'v2'">
<ds-google-recaptcha [captchaMode]="(googleRecaptchaService.captchaMode$ | async)" (executeRecaptcha)="register($event)"></ds-google-recaptcha>
<div class="col-12" *ngIf="(googleRecaptchaService.captchaVersion() | async) === 'v2'">
<ds-google-recaptcha [captchaMode]="(googleRecaptchaService.captchaMode() | async)" (executeRecaptcha)="register($event)"></ds-google-recaptcha>
</div>
</div>
@@ -33,12 +33,12 @@
</div>
</form>
<button *ngIf="(googleRecaptchaService.captchaVersion$ | async) === 'v2' && (googleRecaptchaService.captchaMode$ | async) === 'invisible'"
<button *ngIf="(googleRecaptchaService.captchaVersion() | async) === 'v2' && (googleRecaptchaService.captchaMode() | async) === 'invisible'"
class="btn btn-primary"
[disabled]="form.invalid"
(click)="executeRecaptcha()">
{{ MESSAGE_PREFIX + '.submit' | translate }}</button>
<button *ngIf="!((googleRecaptchaService.captchaVersion$ | async) === 'v2' && (googleRecaptchaService.captchaMode$ | async) === 'invisible')"
<button *ngIf="!((googleRecaptchaService.captchaVersion() | async) === 'v2' && (googleRecaptchaService.captchaMode() | async) === 'invisible')"
class="btn btn-primary"
[disabled]="form.invalid"
(click)="register()">

View File

@@ -7,12 +7,12 @@ import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'
import { Registration } from '../core/shared/registration.model';
import { RemoteData } from '../core/data/remote-data';
import { ConfigurationDataService } from '../core/data/configuration-data.service';
import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../core/shared/operators';
import { getFirstSucceededRemoteDataPayload } from '../core/shared/operators';
import { ConfigurationProperty } from '../core/shared/configuration-property.model';
import { isNotEmpty } from '../shared/empty.util';
import { combineLatest, Observable, of, switchMap } from 'rxjs';
import { map } from 'rxjs/operators';
import { GoogleRecaptchaService } from '../core/google-recaptcha/google-recaptcha.service';
import { Observable } from 'rxjs';
@Component({
selector: 'ds-register-email-form',
@@ -39,7 +39,14 @@ export class RegisterEmailFormComponent implements OnInit {
*/
registrationVerification = false;
recaptchaKey$: Observable<any>;
captchaVersion(): Observable<string> {
return this.googleRecaptchaService.captchaVersion();
}
captchaMode(): Observable<string> {
return this.googleRecaptchaService.captchaMode();
}
constructor(
private epersonRegistrationService: EpersonRegistrationService,
@@ -61,14 +68,9 @@ export class RegisterEmailFormComponent implements OnInit {
],
})
});
this.recaptchaKey$ = this.configService.findByPropertyName('google.recaptcha.key.site').pipe(
getFirstSucceededRemoteDataPayload(),
);
this.configService.findByPropertyName('registration.verification.enabled').pipe(
getFirstCompletedRemoteData(),
map((res: RemoteData<ConfigurationProperty>) => {
return res.hasSucceeded && res.payload && isNotEmpty(res.payload.values) && res.payload.values[0].toLowerCase() === 'true';
})
getFirstSucceededRemoteDataPayload(),
map((res: ConfigurationProperty) => res?.values[0].toLowerCase() === 'true')
).subscribe((res: boolean) => {
this.registrationVerification = res;
});
@@ -77,38 +79,36 @@ export class RegisterEmailFormComponent implements OnInit {
/**
* execute the captcha function for v2 invisible
*/
async executeRecaptcha() {
await this.googleRecaptchaService.executeRecaptcha();
executeRecaptcha() {
console.log('executeRecaptcha');
this.googleRecaptchaService.executeRecaptcha();
}
/**
* Register an email address
*/
async register(tokenV2 = null) {
register(tokenV2 = null) {
if (!this.form.invalid) {
if (this.registrationVerification) {
let token;
let captchaVersion;
let captchaMode;
this.googleRecaptchaService.captchaVersion$.subscribe(res => {
captchaVersion = res;
});
this.googleRecaptchaService.captchaMode$.subscribe(res => {
captchaMode = res;
});
combineLatest([this.captchaVersion(), this.captchaMode()]).pipe(
switchMap(([captchaVersion, captchaMode]) => {
if (captchaVersion === 'v3') {
token = await this.googleRecaptchaService.getRecaptchaToken('register_email');
return this.googleRecaptchaService.getRecaptchaToken('register_email');
} else if (captchaMode === 'checkbox') {
token = await this.googleRecaptchaService.getRecaptchaTokenResponse();
return this.googleRecaptchaService.getRecaptchaTokenResponse();
} else {
token = tokenV2;
return of(tokenV2);
}
}),
).subscribe((token) => {
if (isNotEmpty(token)) {
this.registration(token);
} else {
this.notificationService.error(this.translateService.get(`${this.MESSAGE_PREFIX}.error.head`),
this.translateService.get(`${this.MESSAGE_PREFIX}.error.recaptcha`));
}
}
);
} else {
this.registration();
}
@@ -119,12 +119,9 @@ export class RegisterEmailFormComponent implements OnInit {
* Registration of an email address
*/
registration(captchaToken = null) {
let registerEmail$;
if (captchaToken) {
registerEmail$ = this.epersonRegistrationService.registerEmail(this.email.value, captchaToken);
} else {
registerEmail$ = this.epersonRegistrationService.registerEmail(this.email.value);
}
let registerEmail$ = captchaToken ?
this.epersonRegistrationService.registerEmail(this.email.value, captchaToken) :
this.epersonRegistrationService.registerEmail(this.email.value);
registerEmail$.subscribe((response: RemoteData<Registration>) => {
if (response.hasSucceeded) {
this.notificationService.success(this.translateService.get(`${this.MESSAGE_PREFIX}.success.head`),