From bcc747dc3eecd16ed93a9b6b0831715dfa57f1ee Mon Sep 17 00:00:00 2001 From: Sufiyan Shaikh Date: Mon, 22 Aug 2022 15:03:35 +0530 Subject: [PATCH] [UXP-10] klaro cookies permission and test cases --- .../google-recaptcha.service.spec.ts | 12 +++++++- .../google-recaptcha.service.ts | 27 +++++++++++++++--- .../register-email-form.component.html | 14 +++++++--- .../register-email-form.component.ts | 28 +++++++------------ src/app/shared/cookies/klaro-configuration.ts | 9 ++++-- src/assets/i18n/en.json5 | 2 +- 6 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/app/core/google-recaptcha/google-recaptcha.service.spec.ts b/src/app/core/google-recaptcha/google-recaptcha.service.spec.ts index 3698306763..545e3b9873 100644 --- a/src/app/core/google-recaptcha/google-recaptcha.service.spec.ts +++ b/src/app/core/google-recaptcha/google-recaptcha.service.spec.ts @@ -1,6 +1,7 @@ import { GoogleRecaptchaService } from './google-recaptcha.service'; import { of as observableOf } from 'rxjs'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { NativeWindowRef } from '../services/window.service'; describe('GoogleRecaptchaService', () => { let service: GoogleRecaptchaService; @@ -9,6 +10,8 @@ describe('GoogleRecaptchaService', () => { let configurationDataService; let spy: jasmine.Spy; let scriptElementMock: any; + let cookieService; + let window; const innerHTMLTestValue = 'mock-script-inner-html'; const document = { documentElement: { lang: 'en' } } as Document; scriptElementMock = { @@ -17,6 +20,7 @@ describe('GoogleRecaptchaService', () => { }; function init() { + window = new NativeWindowRef(); rendererFactory2 = jasmine.createSpyObj('rendererFactory2', { createRenderer: observableOf('googleRecaptchaToken'), createElement: scriptElementMock @@ -24,7 +28,13 @@ describe('GoogleRecaptchaService', () => { configurationDataService = jasmine.createSpyObj('configurationDataService', { findByPropertyName: createSuccessfulRemoteDataObject$({ values: ['googleRecaptchaToken'] }) }); - service = new GoogleRecaptchaService(document, rendererFactory2, configurationDataService); + cookieService = jasmine.createSpyObj('cookieService', { + get: '{%22token_item%22:true%2C%22impersonation%22:true%2C%22redirect%22:true%2C%22language%22:true%2C%22klaro%22:true%2C%22has_agreed_end_user%22:true%2C%22google-analytics%22:true}', + set: () => { + /* empty */ + } + }); + service = new GoogleRecaptchaService(cookieService, document, window, rendererFactory2, configurationDataService); } beforeEach(() => { diff --git a/src/app/core/google-recaptcha/google-recaptcha.service.ts b/src/app/core/google-recaptcha/google-recaptcha.service.ts index 99311247f6..4f602ef575 100644 --- a/src/app/core/google-recaptcha/google-recaptcha.service.ts +++ b/src/app/core/google-recaptcha/google-recaptcha.service.ts @@ -7,8 +7,11 @@ 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 { CookieService } from '../services/cookie.service'; +import { NativeWindowRef, NativeWindowService } from '../services/window.service'; export const CAPTCHA_COOKIE = '_GRECAPTCHA'; +export const CAPTCHA_NAME = 'google-recaptcha'; /** * A GoogleRecaptchaService used to send action and get a token from REST @@ -35,13 +38,18 @@ export class GoogleRecaptchaService { /** * A Google Recaptcha version */ - captchaVersion$: Observable; + captchaVersion$: Observable = of(''); constructor( + private cookieService: CookieService, @Inject(DOCUMENT) private _document: Document, + @Inject(NativeWindowService) private _window: NativeWindowRef, rendererFactory: RendererFactory2, private configService: ConfigurationDataService, ) { + if (this._window.nativeWindow) { + this._window.nativeWindow.refreshCaptchaScript = this.refreshCaptchaScript; + } this.renderer = rendererFactory.createRenderer(null, null); const registrationVerification$ = this.configService.findByPropertyName('registration.verification.enabled').pipe( take(1), @@ -50,6 +58,14 @@ export class GoogleRecaptchaService { return res.hasSucceeded && res.payload && isNotEmpty(res.payload.values) && res.payload.values[0].toLowerCase() === 'true'; }) ); + registrationVerification$.subscribe(registrationVerification => { + if (registrationVerification) { + this.loadRecaptchaProperties(); + } + }); + } + + loadRecaptchaProperties() { const recaptchaKey$ = this.configService.findByPropertyName('google.recaptcha.key.site').pipe( take(1), getFirstCompletedRemoteData(), @@ -62,13 +78,12 @@ export class GoogleRecaptchaService { take(1), getFirstCompletedRemoteData(), ); - combineLatest(registrationVerification$, recaptchaVersion$, recaptchaMode$, recaptchaKey$).subscribe(([registrationVerification, recaptchaVersion, recaptchaMode, recaptchaKey]) => { - if (registrationVerification) { + 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]); } - 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])) { @@ -137,4 +152,8 @@ export class GoogleRecaptchaService { }); } + refreshCaptchaScript = () => { + this.loadRecaptchaProperties(); + }; + } diff --git a/src/app/register-email-form/register-email-form.component.html b/src/app/register-email-form/register-email-form.component.html index 5e87d2bd42..b10833c097 100644 --- a/src/app/register-email-form/register-email-form.component.html +++ b/src/app/register-email-form/register-email-form.component.html @@ -24,8 +24,8 @@
{{MESSAGE_PREFIX + '.email.hint' |translate}}
-
- +
+
@@ -33,8 +33,14 @@ - + diff --git a/src/app/register-email-form/register-email-form.component.ts b/src/app/register-email-form/register-email-form.component.ts index 79303c8a04..0079ea2da8 100644 --- a/src/app/register-email-form/register-email-form.component.ts +++ b/src/app/register-email-form/register-email-form.component.ts @@ -39,16 +39,6 @@ export class RegisterEmailFormComponent implements OnInit { */ registrationVerification = false; - /** - * captcha version - */ - captchaVersion = 'v2'; - - /** - * captcha mode - */ - captchaMode = 'checkbox'; - recaptchaKey$: Observable; constructor( @@ -74,12 +64,6 @@ export class RegisterEmailFormComponent implements OnInit { this.recaptchaKey$ = this.configService.findByPropertyName('google.recaptcha.key.site').pipe( getFirstSucceededRemoteDataPayload(), ); - this.googleRecaptchaService.captchaVersion$.subscribe(res => { - this.captchaVersion = res; - }); - this.googleRecaptchaService.captchaMode$.subscribe(res => { - this.captchaMode = res; - }); this.configService.findByPropertyName('registration.verification.enabled').pipe( getFirstCompletedRemoteData(), map((res: RemoteData) => { @@ -104,9 +88,17 @@ export class RegisterEmailFormComponent implements OnInit { if (!this.form.invalid) { if (this.registrationVerification) { let token; - if (this.captchaVersion === 'v3') { + let captchaVersion; + let captchaMode; + this.googleRecaptchaService.captchaVersion$.subscribe(res => { + captchaVersion = res; + }); + this.googleRecaptchaService.captchaMode$.subscribe(res => { + captchaMode = res; + }); + if (captchaVersion === 'v3') { token = await this.googleRecaptchaService.getRecaptchaToken('register_email'); - } else if (this.captchaMode === 'checkbox') { + } else if (captchaMode === 'checkbox') { token = await this.googleRecaptchaService.getRecaptchaTokenResponse(); } else { token = tokenV2; diff --git a/src/app/shared/cookies/klaro-configuration.ts b/src/app/shared/cookies/klaro-configuration.ts index 1f780198f4..4075f7f050 100644 --- a/src/app/shared/cookies/klaro-configuration.ts +++ b/src/app/shared/cookies/klaro-configuration.ts @@ -1,7 +1,7 @@ import { TOKENITEM } from '../../core/auth/models/auth-token-info.model'; import { IMPERSONATING_COOKIE, REDIRECT_COOKIE } from '../../core/auth/auth.service'; import { LANG_COOKIE } from '../../core/locale/locale.service'; -import { CAPTCHA_COOKIE } from 'src/app/core/google-recaptcha/google-recaptcha.service'; +import { CAPTCHA_COOKIE, CAPTCHA_NAME } from '../../core/google-recaptcha/google-recaptcha.service'; /** * Cookie for has_agreed_end_user @@ -157,12 +157,15 @@ export const klaroConfiguration: any = { onlyOnce: true, }, { - name: 'google-recaptcha', + name: CAPTCHA_NAME, purposes: ['registration-password-recovery'], - required: true, + required: false, cookies: [ CAPTCHA_COOKIE ], + onAccept: `window.refreshCaptchaScript()`, + onDecline: `window.refreshCaptchaScript()`, + onInit: `window.refreshCaptchaScript()`, onlyOnce: true, } ], diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 7aa884866f..024a3ca54b 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1264,7 +1264,7 @@ "cookies.consent.app.title.google-recaptcha": "Google reCaptcha", - "cookies.consent.app.description.google-recaptcha": "Allows us to track registration and password recovery data", + "cookies.consent.app.description.google-recaptcha": "We use google reCAPTCHA service during registration and password recovery",