mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
72635: Cookie preferences first committ
This commit is contained in:
@@ -97,6 +97,7 @@
|
||||
"json5": "^2.1.0",
|
||||
"jsonschema": "1.2.2",
|
||||
"jwt-decode": "^2.2.0",
|
||||
"klaro": "^0.5.34",
|
||||
"moment": "^2.22.1",
|
||||
"morgan": "^1.9.1",
|
||||
"ng-mocks": "^8.1.0",
|
||||
|
@@ -5,7 +5,7 @@ import {
|
||||
Component,
|
||||
HostListener,
|
||||
Inject,
|
||||
OnInit,
|
||||
OnInit, Optional,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { NavigationCancel, NavigationEnd, NavigationStart, Router } from '@angular/router';
|
||||
@@ -31,8 +31,7 @@ import { Angulartics2DSpace } from './statistics/angulartics/dspace-provider';
|
||||
import { environment } from '../environments/environment';
|
||||
import { models } from './core/core.module';
|
||||
import { LocaleService } from './core/locale/locale.service';
|
||||
|
||||
export const LANG_COOKIE = 'language_cookie';
|
||||
import { CookiesService } from './shared/cookies/cookies.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-app',
|
||||
@@ -69,7 +68,8 @@ export class AppComponent implements OnInit, AfterViewInit {
|
||||
private cssService: CSSVariableService,
|
||||
private menuService: MenuService,
|
||||
private windowService: HostWindowService,
|
||||
private localeService: LocaleService
|
||||
private localeService: LocaleService,
|
||||
@Optional() private cookiesService: CookiesService
|
||||
) {
|
||||
/* Use models object so all decorators are actually called */
|
||||
this.models = models;
|
||||
@@ -91,6 +91,8 @@ export class AppComponent implements OnInit, AfterViewInit {
|
||||
console.info(environment);
|
||||
}
|
||||
this.storeCSSVariables();
|
||||
|
||||
this.cookiesService.initialize();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
12
src/app/shared/cookies/cookies.service.spec.ts
Normal file
12
src/app/shared/cookies/cookies.service.spec.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CookiesService } from './cookies.service';
|
||||
|
||||
describe('CookiesService', () => {
|
||||
beforeEach(() => TestBed.configureTestingModule({}));
|
||||
|
||||
it('should be created', () => {
|
||||
const service: CookiesService = TestBed.get(CookiesService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
192
src/app/shared/cookies/cookies.service.ts
Normal file
192
src/app/shared/cookies/cookies.service.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import * as Klaro from 'klaro'
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
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 { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
export const HAS_AGREED_END_USER = 'hasAgreedEndUser';
|
||||
export const KLARO = 'klaro';
|
||||
|
||||
const cookieNameMessagePrefix = 'cookies.consent.app.title.';
|
||||
const cookieDescriptionMessagePrefix = 'cookies.consent.app.description.';
|
||||
const cookiePurposeMessagePrefix = 'cookies.consent.purpose.';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
|
||||
export class CookiesService {
|
||||
|
||||
message$: BehaviorSubject<string> = new BehaviorSubject<string>('');
|
||||
|
||||
klaroConfig = {
|
||||
/*
|
||||
Setting 'hideLearnMore' to 'true' will hide the "learn more / customize" link in
|
||||
the consent notice. We strongly advise against using this under most
|
||||
circumstances, as it keeps the user from customizing his/her consent choices.
|
||||
*/
|
||||
hideLearnMore: false,
|
||||
|
||||
/*
|
||||
Setting 'acceptAll' to 'true' will show an "accept all" button in the notice and
|
||||
modal, which will enable all third-party apps if the user clicks on it. If set
|
||||
to 'false', there will be an "accept" button that will only enable the apps that
|
||||
are enabled in the consent modal.
|
||||
*/
|
||||
acceptAll: true,
|
||||
|
||||
/*
|
||||
You can also set a custom expiration time for the Klaro cookie. By default, it
|
||||
will expire after 30 days. Only relevant if 'storageMethod' is set to 'cookie'.
|
||||
*/
|
||||
cookieExpiresAfterDays: 365,
|
||||
|
||||
htmlText: true,
|
||||
|
||||
/*
|
||||
You can overwrite existing translations and add translations for your app
|
||||
descriptions and purposes. See `src/translations/` for a full list of
|
||||
translations that can be overwritten:
|
||||
https://github.com/KIProtect/klaro/tree/master/src/translations
|
||||
*/
|
||||
translations: {
|
||||
en: {
|
||||
consentNotice: {
|
||||
description: 'We collect and process your personal information for the following purposes: {purposes}.<br>To learn more, please read our {privacyPolicy}'
|
||||
},
|
||||
purposes: {}
|
||||
}
|
||||
},
|
||||
apps: [
|
||||
{
|
||||
name: 'token_item',
|
||||
purposes: ['authentication'],
|
||||
required: true,
|
||||
cookies: [
|
||||
TOKENITEM
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'impersonation',
|
||||
purposes: ['authentication'],
|
||||
required: true,
|
||||
cookies: [
|
||||
IMPERSONATING_COOKIE
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'redirect',
|
||||
purposes: ['authentication'],
|
||||
required: true,
|
||||
cookies: [
|
||||
REDIRECT_COOKIE
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'language',
|
||||
purposes: ['preferences'],
|
||||
required: true,
|
||||
cookies: [
|
||||
LANG_COOKIE
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'klaro',
|
||||
purposes: ['acknowledgement'],
|
||||
required: true,
|
||||
cookies: [
|
||||
KLARO
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'has_agreed_end_user',
|
||||
purposes: ['acknowledgement'],
|
||||
required: true,
|
||||
cookies: [
|
||||
HAS_AGREED_END_USER
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'google-analytics',
|
||||
purposes: ['statistics'],
|
||||
required: false,
|
||||
cookies: [
|
||||
// /*
|
||||
// you an either only provide a cookie name or regular expression (regex) or a list
|
||||
// consisting of a name or regex, a path and a cookie domain. Providing a path and
|
||||
// domain is necessary if you have apps that set cookies for a path that is not
|
||||
// "/", or a domain that is not the current domain. If you do not set these values
|
||||
// properly, the cookie can't be deleted by Klaro, as there is no way to access the
|
||||
// path or domain of a cookie in JS. Notice that it is not possible to delete
|
||||
// cookies that were set on a third-party domain, or cookies that have the HTTPOnly
|
||||
// attribute: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#new-
|
||||
// cookie_domain
|
||||
// */
|
||||
//
|
||||
// /*
|
||||
// This rule will match cookies that contain the string '_pk_' and that are set on
|
||||
// the path '/' and the domain 'klaro.kiprotect.com'
|
||||
// */
|
||||
[/^_ga.?$/],
|
||||
[/^_gid$/],
|
||||
//
|
||||
// /*
|
||||
// Same as above, only for the 'localhost' domain
|
||||
// */
|
||||
// [/^_pk_.*$/, '/', 'localhost'],
|
||||
//
|
||||
// /*
|
||||
// This rule will match all cookies named 'piwik_ignore' that are set on the path
|
||||
// '/' on the current domain
|
||||
// */
|
||||
// 'piwik_ignore',
|
||||
],
|
||||
|
||||
/*
|
||||
You can define an optional callback function that will be called each time the
|
||||
consent state for the given app changes. The consent value will be passed as the
|
||||
first parameter to the function (true=consented). The `app` config will be
|
||||
passed as the second parameter.
|
||||
*/
|
||||
callback: (consent, app) => {
|
||||
this.message$.next('User consent for app ' + app.name + ': consent=' + consent);
|
||||
},
|
||||
/*
|
||||
If 'onlyOnce' is set to 'true', the app will only be executed once regardless
|
||||
how often the user toggles it on and off. This is relevant e.g. for tracking
|
||||
scripts that would generate new page view events every time Klaro disables and
|
||||
re-enables them due to a consent change by the user.
|
||||
*/
|
||||
onlyOnce: true,
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
constructor(private translateService: TranslateService) {
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.klaroConfig.apps.forEach((app) => {
|
||||
this.klaroConfig.translations.en[app.name] = { title: this.getTitleTranslation(app.name), description: this.getDescriptionTranslation(app.name) };
|
||||
app.purposes.forEach((purpose) => {
|
||||
this.klaroConfig.translations.en.purposes[purpose] = this.getPurposeTranslation(purpose);
|
||||
})
|
||||
});
|
||||
|
||||
Klaro.show(this.klaroConfig);
|
||||
}
|
||||
|
||||
private getTitleTranslation(title: string) {
|
||||
return this.translateService.instant(cookieNameMessagePrefix + title);
|
||||
}
|
||||
|
||||
private getDescriptionTranslation(description: string) {
|
||||
return this.translateService.instant(cookieDescriptionMessagePrefix + description);
|
||||
}
|
||||
|
||||
private getPurposeTranslation(purpose: string) {
|
||||
return this.translateService.instant(cookiePurposeMessagePrefix + purpose);
|
||||
}
|
||||
}
|
@@ -937,6 +937,41 @@
|
||||
|
||||
|
||||
|
||||
"cookies.consent.app.title.token_item": "User Token",
|
||||
|
||||
"cookies.consent.app.description.token_item": "User login identification",
|
||||
|
||||
|
||||
|
||||
"cookies.consent.app.title.impersonation": "Impersonation",
|
||||
|
||||
"cookies.consent.app.description.impersonation": "Switching users",
|
||||
|
||||
|
||||
|
||||
"cookies.consent.app.title.klaro": "Klaro",
|
||||
|
||||
"cookies.consent.app.description.klaro": "Cookie consent preferences",
|
||||
|
||||
|
||||
|
||||
|
||||
"cookies.consent.app.title.has_agreed_end_user": "Has agreed end user",
|
||||
|
||||
"cookies.consent.app.description.has_agreed_end_user": "",
|
||||
|
||||
|
||||
|
||||
"cookies.consent.purpose.authentication": "Authentication",
|
||||
|
||||
"cookies.consent.purpose.statistics": "Statistics",
|
||||
|
||||
"cookies.consent.purpose.preferences": "Preferences",
|
||||
|
||||
"cookies.consent.purpose.acknowledgement": "Acknowledgement",
|
||||
|
||||
|
||||
|
||||
"curation-task.task.checklinks.label": "Check Links in Metadata",
|
||||
|
||||
"curation-task.task.noop.label": "NOOP",
|
||||
|
@@ -23,6 +23,7 @@ import { SubmissionService } from '../../app/submission/submission.service';
|
||||
import { StatisticsModule } from '../../app/statistics/statistics.module';
|
||||
import { HardRedirectService } from '../../app/core/services/hard-redirect.service';
|
||||
import { BrowserHardRedirectService } from '../../app/core/services/browser-hard-redirect.service';
|
||||
import { CookiesService } from '../../app/shared/cookies/cookies.service';
|
||||
|
||||
export const REQ_KEY = makeStateKey<string>('req');
|
||||
|
||||
@@ -83,6 +84,10 @@ export function locationProvider(): Location {
|
||||
provide: CookieService,
|
||||
useClass: ClientCookieService
|
||||
},
|
||||
{
|
||||
provide: CookiesService,
|
||||
useClass: CookiesService
|
||||
},
|
||||
{
|
||||
provide: SubmissionService,
|
||||
useClass: SubmissionService
|
||||
|
@@ -6165,6 +6165,11 @@ kind-of@^6.0.0, kind-of@^6.0.2:
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
|
||||
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
|
||||
|
||||
klaro@^0.5.34:
|
||||
version "0.5.34"
|
||||
resolved "https://registry.yarnpkg.com/klaro/-/klaro-0.5.34.tgz#0b524be96a1bb177fe88ff2603e1be75f494fc98"
|
||||
integrity sha512-M6KHqlBWpMyYoxOK1icoJMeYsaPT7YhzJIAQ3wdxZWGgBc0sV7xQsf0PsgMUVnuTD0AeC58QegCGEv0qYeq4gw==
|
||||
|
||||
last-call-webpack-plugin@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555"
|
||||
|
Reference in New Issue
Block a user