mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-14 13:33:03 +00:00
[UXP-10] klaro cookies permission and test cases
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { GoogleRecaptchaService } from './google-recaptcha.service';
|
import { GoogleRecaptchaService } from './google-recaptcha.service';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||||
|
import { NativeWindowRef } from '../services/window.service';
|
||||||
|
|
||||||
describe('GoogleRecaptchaService', () => {
|
describe('GoogleRecaptchaService', () => {
|
||||||
let service: GoogleRecaptchaService;
|
let service: GoogleRecaptchaService;
|
||||||
@@ -9,6 +10,8 @@ describe('GoogleRecaptchaService', () => {
|
|||||||
let configurationDataService;
|
let configurationDataService;
|
||||||
let spy: jasmine.Spy;
|
let spy: jasmine.Spy;
|
||||||
let scriptElementMock: any;
|
let scriptElementMock: any;
|
||||||
|
let cookieService;
|
||||||
|
let window;
|
||||||
const innerHTMLTestValue = 'mock-script-inner-html';
|
const innerHTMLTestValue = 'mock-script-inner-html';
|
||||||
const document = { documentElement: { lang: 'en' } } as Document;
|
const document = { documentElement: { lang: 'en' } } as Document;
|
||||||
scriptElementMock = {
|
scriptElementMock = {
|
||||||
@@ -17,6 +20,7 @@ describe('GoogleRecaptchaService', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
window = new NativeWindowRef();
|
||||||
rendererFactory2 = jasmine.createSpyObj('rendererFactory2', {
|
rendererFactory2 = jasmine.createSpyObj('rendererFactory2', {
|
||||||
createRenderer: observableOf('googleRecaptchaToken'),
|
createRenderer: observableOf('googleRecaptchaToken'),
|
||||||
createElement: scriptElementMock
|
createElement: scriptElementMock
|
||||||
@@ -24,7 +28,13 @@ describe('GoogleRecaptchaService', () => {
|
|||||||
configurationDataService = jasmine.createSpyObj('configurationDataService', {
|
configurationDataService = jasmine.createSpyObj('configurationDataService', {
|
||||||
findByPropertyName: createSuccessfulRemoteDataObject$({ values: ['googleRecaptchaToken'] })
|
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(() => {
|
beforeEach(() => {
|
||||||
|
@@ -7,8 +7,11 @@ import { ConfigurationDataService } from '../data/configuration-data.service';
|
|||||||
import { RemoteData } from '../data/remote-data';
|
import { RemoteData } from '../data/remote-data';
|
||||||
import { map, take } from 'rxjs/operators';
|
import { map, take } from 'rxjs/operators';
|
||||||
import { combineLatest, Observable, of } from 'rxjs';
|
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_COOKIE = '_GRECAPTCHA';
|
||||||
|
export const CAPTCHA_NAME = 'google-recaptcha';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A GoogleRecaptchaService used to send action and get a token from REST
|
* A GoogleRecaptchaService used to send action and get a token from REST
|
||||||
@@ -35,13 +38,18 @@ export class GoogleRecaptchaService {
|
|||||||
/**
|
/**
|
||||||
* A Google Recaptcha version
|
* A Google Recaptcha version
|
||||||
*/
|
*/
|
||||||
captchaVersion$: Observable<string>;
|
captchaVersion$: Observable<string> = of('');
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private cookieService: CookieService,
|
||||||
@Inject(DOCUMENT) private _document: Document,
|
@Inject(DOCUMENT) private _document: Document,
|
||||||
|
@Inject(NativeWindowService) private _window: NativeWindowRef,
|
||||||
rendererFactory: RendererFactory2,
|
rendererFactory: RendererFactory2,
|
||||||
private configService: ConfigurationDataService,
|
private configService: ConfigurationDataService,
|
||||||
) {
|
) {
|
||||||
|
if (this._window.nativeWindow) {
|
||||||
|
this._window.nativeWindow.refreshCaptchaScript = this.refreshCaptchaScript;
|
||||||
|
}
|
||||||
this.renderer = rendererFactory.createRenderer(null, null);
|
this.renderer = rendererFactory.createRenderer(null, null);
|
||||||
const registrationVerification$ = this.configService.findByPropertyName('registration.verification.enabled').pipe(
|
const registrationVerification$ = this.configService.findByPropertyName('registration.verification.enabled').pipe(
|
||||||
take(1),
|
take(1),
|
||||||
@@ -50,6 +58,14 @@ export class GoogleRecaptchaService {
|
|||||||
return res.hasSucceeded && res.payload && isNotEmpty(res.payload.values) && res.payload.values[0].toLowerCase() === 'true';
|
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(
|
const recaptchaKey$ = this.configService.findByPropertyName('google.recaptcha.key.site').pipe(
|
||||||
take(1),
|
take(1),
|
||||||
getFirstCompletedRemoteData(),
|
getFirstCompletedRemoteData(),
|
||||||
@@ -62,13 +78,12 @@ export class GoogleRecaptchaService {
|
|||||||
take(1),
|
take(1),
|
||||||
getFirstCompletedRemoteData(),
|
getFirstCompletedRemoteData(),
|
||||||
);
|
);
|
||||||
combineLatest(registrationVerification$, recaptchaVersion$, recaptchaMode$, recaptchaKey$).subscribe(([registrationVerification, recaptchaVersion, recaptchaMode, recaptchaKey]) => {
|
combineLatest(recaptchaVersion$, recaptchaMode$, recaptchaKey$).subscribe(([recaptchaVersion, recaptchaMode, recaptchaKey]) => {
|
||||||
if (registrationVerification) {
|
if (this.cookieService.get('klaro-anonymous') && this.cookieService.get('klaro-anonymous')[CAPTCHA_NAME]) {
|
||||||
if (recaptchaKey.hasSucceeded && isNotEmpty(recaptchaKey?.payload?.values[0])) {
|
if (recaptchaKey.hasSucceeded && isNotEmpty(recaptchaKey?.payload?.values[0])) {
|
||||||
this.captchaSiteKeyStr = recaptchaKey?.payload?.values[0];
|
this.captchaSiteKeyStr = recaptchaKey?.payload?.values[0];
|
||||||
this.captchaSiteKey$ = of(recaptchaKey?.payload?.values[0]);
|
this.captchaSiteKey$ = of(recaptchaKey?.payload?.values[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recaptchaVersion.hasSucceeded && isNotEmpty(recaptchaVersion?.payload?.values[0]) && recaptchaVersion?.payload?.values[0] === 'v3') {
|
if (recaptchaVersion.hasSucceeded && isNotEmpty(recaptchaVersion?.payload?.values[0]) && recaptchaVersion?.payload?.values[0] === 'v3') {
|
||||||
this.captchaVersion$ = of('v3');
|
this.captchaVersion$ = of('v3');
|
||||||
if (recaptchaKey.hasSucceeded && isNotEmpty(recaptchaKey?.payload?.values[0])) {
|
if (recaptchaKey.hasSucceeded && isNotEmpty(recaptchaKey?.payload?.values[0])) {
|
||||||
@@ -137,4 +152,8 @@ export class GoogleRecaptchaService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshCaptchaScript = () => {
|
||||||
|
this.loadRecaptchaProperties();
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -24,8 +24,8 @@
|
|||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
{{MESSAGE_PREFIX + '.email.hint' |translate}}
|
{{MESSAGE_PREFIX + '.email.hint' |translate}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12" *ngIf="captchaVersion === 'v2'">
|
<div class="col-12" *ngIf="(googleRecaptchaService.captchaVersion$ | async) === 'v2'">
|
||||||
<ds-google-recaptcha [captchaMode]="captchaMode" (executeRecaptcha)="register($event)"></ds-google-recaptcha>
|
<ds-google-recaptcha [captchaMode]="(googleRecaptchaService.captchaMode$ | async)" (executeRecaptcha)="register($event)"></ds-google-recaptcha>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -33,8 +33,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<button class="btn btn-primary"
|
<button *ngIf="(googleRecaptchaService.captchaVersion$ | async) === 'v2' && (googleRecaptchaService.captchaMode$ | async) === 'invisible'"
|
||||||
|
class="btn btn-primary"
|
||||||
[disabled]="form.invalid"
|
[disabled]="form.invalid"
|
||||||
(click)="(captchaVersion === 'v2' && captchaMode === 'invisible') ? executeRecaptcha() : register()">
|
(click)="executeRecaptcha()">
|
||||||
|
{{MESSAGE_PREFIX + '.submit'| translate}}</button>
|
||||||
|
<button *ngIf="!((googleRecaptchaService.captchaVersion$ | async) === 'v2' && (googleRecaptchaService.captchaMode$ | async) === 'invisible')"
|
||||||
|
class="btn btn-primary"
|
||||||
|
[disabled]="form.invalid"
|
||||||
|
(click)="register()">
|
||||||
{{MESSAGE_PREFIX + '.submit'| translate}}</button>
|
{{MESSAGE_PREFIX + '.submit'| translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -39,16 +39,6 @@ export class RegisterEmailFormComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
registrationVerification = false;
|
registrationVerification = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* captcha version
|
|
||||||
*/
|
|
||||||
captchaVersion = 'v2';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* captcha mode
|
|
||||||
*/
|
|
||||||
captchaMode = 'checkbox';
|
|
||||||
|
|
||||||
recaptchaKey$: Observable<any>;
|
recaptchaKey$: Observable<any>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -74,12 +64,6 @@ export class RegisterEmailFormComponent implements OnInit {
|
|||||||
this.recaptchaKey$ = this.configService.findByPropertyName('google.recaptcha.key.site').pipe(
|
this.recaptchaKey$ = this.configService.findByPropertyName('google.recaptcha.key.site').pipe(
|
||||||
getFirstSucceededRemoteDataPayload(),
|
getFirstSucceededRemoteDataPayload(),
|
||||||
);
|
);
|
||||||
this.googleRecaptchaService.captchaVersion$.subscribe(res => {
|
|
||||||
this.captchaVersion = res;
|
|
||||||
});
|
|
||||||
this.googleRecaptchaService.captchaMode$.subscribe(res => {
|
|
||||||
this.captchaMode = res;
|
|
||||||
});
|
|
||||||
this.configService.findByPropertyName('registration.verification.enabled').pipe(
|
this.configService.findByPropertyName('registration.verification.enabled').pipe(
|
||||||
getFirstCompletedRemoteData(),
|
getFirstCompletedRemoteData(),
|
||||||
map((res: RemoteData<ConfigurationProperty>) => {
|
map((res: RemoteData<ConfigurationProperty>) => {
|
||||||
@@ -104,9 +88,17 @@ export class RegisterEmailFormComponent implements OnInit {
|
|||||||
if (!this.form.invalid) {
|
if (!this.form.invalid) {
|
||||||
if (this.registrationVerification) {
|
if (this.registrationVerification) {
|
||||||
let token;
|
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');
|
token = await this.googleRecaptchaService.getRecaptchaToken('register_email');
|
||||||
} else if (this.captchaMode === 'checkbox') {
|
} else if (captchaMode === 'checkbox') {
|
||||||
token = await this.googleRecaptchaService.getRecaptchaTokenResponse();
|
token = await this.googleRecaptchaService.getRecaptchaTokenResponse();
|
||||||
} else {
|
} else {
|
||||||
token = tokenV2;
|
token = tokenV2;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { TOKENITEM } from '../../core/auth/models/auth-token-info.model';
|
import { TOKENITEM } from '../../core/auth/models/auth-token-info.model';
|
||||||
import { IMPERSONATING_COOKIE, REDIRECT_COOKIE } from '../../core/auth/auth.service';
|
import { IMPERSONATING_COOKIE, REDIRECT_COOKIE } from '../../core/auth/auth.service';
|
||||||
import { LANG_COOKIE } from '../../core/locale/locale.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
|
* Cookie for has_agreed_end_user
|
||||||
@@ -157,12 +157,15 @@ export const klaroConfiguration: any = {
|
|||||||
onlyOnce: true,
|
onlyOnce: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'google-recaptcha',
|
name: CAPTCHA_NAME,
|
||||||
purposes: ['registration-password-recovery'],
|
purposes: ['registration-password-recovery'],
|
||||||
required: true,
|
required: false,
|
||||||
cookies: [
|
cookies: [
|
||||||
CAPTCHA_COOKIE
|
CAPTCHA_COOKIE
|
||||||
],
|
],
|
||||||
|
onAccept: `window.refreshCaptchaScript()`,
|
||||||
|
onDecline: `window.refreshCaptchaScript()`,
|
||||||
|
onInit: `window.refreshCaptchaScript()`,
|
||||||
onlyOnce: true,
|
onlyOnce: true,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@@ -1264,7 +1264,7 @@
|
|||||||
|
|
||||||
"cookies.consent.app.title.google-recaptcha": "Google reCaptcha",
|
"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",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user