mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge pull request #1715 from atmire/w2p-92701_issue-1506-gdpr-privacy-config
Option to disable gdpr / privacy statements
This commit is contained in:
@@ -248,3 +248,10 @@ bundle:
|
|||||||
mediaViewer:
|
mediaViewer:
|
||||||
image: false
|
image: false
|
||||||
video: false
|
video: false
|
||||||
|
|
||||||
|
# Whether the end user agreement is required before users use the repository.
|
||||||
|
# If enabled, the user will be required to accept the agreement before they can use the repository.
|
||||||
|
# And whether the privacy statement should exist or not.
|
||||||
|
info:
|
||||||
|
enableEndUserAgreement: true
|
||||||
|
enablePrivacyStatement: true
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
|
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, of as observableOf } from 'rxjs';
|
||||||
import { returnEndUserAgreementUrlTreeOnFalse } from '../shared/authorized.operators';
|
import { returnEndUserAgreementUrlTreeOnFalse } from '../shared/authorized.operators';
|
||||||
|
import { environment } from '../../../environments/environment';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract guard for redirecting users to the user agreement page if a certain condition is met
|
* An abstract guard for redirecting users to the user agreement page if a certain condition is met
|
||||||
@@ -18,6 +19,9 @@ export abstract class AbstractEndUserAgreementGuard implements CanActivate {
|
|||||||
* when they're finished accepting the agreement
|
* when they're finished accepting the agreement
|
||||||
*/
|
*/
|
||||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> {
|
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> {
|
||||||
|
if (!environment.info.enableEndUserAgreement) {
|
||||||
|
return observableOf(true);
|
||||||
|
}
|
||||||
return this.hasAccepted().pipe(
|
return this.hasAccepted().pipe(
|
||||||
returnEndUserAgreementUrlTreeOnFalse(this.router, state.url)
|
returnEndUserAgreementUrlTreeOnFalse(this.router, state.url)
|
||||||
);
|
);
|
||||||
|
@@ -2,6 +2,7 @@ import { EndUserAgreementCurrentUserGuard } from './end-user-agreement-current-u
|
|||||||
import { EndUserAgreementService } from './end-user-agreement.service';
|
import { EndUserAgreementService } from './end-user-agreement.service';
|
||||||
import { Router, UrlTree } from '@angular/router';
|
import { Router, UrlTree } from '@angular/router';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { environment } from '../../../environments/environment.test';
|
||||||
|
|
||||||
describe('EndUserAgreementGuard', () => {
|
describe('EndUserAgreementGuard', () => {
|
||||||
let guard: EndUserAgreementCurrentUserGuard;
|
let guard: EndUserAgreementCurrentUserGuard;
|
||||||
@@ -44,5 +45,24 @@ describe('EndUserAgreementGuard', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when the end user agreement is disabled', () => {
|
||||||
|
it('should return true', (done) => {
|
||||||
|
environment.info.enableEndUserAgreement = false;
|
||||||
|
guard.canActivate(undefined, Object.assign({ url: 'redirect' })).subscribe((result) => {
|
||||||
|
console.log(result);
|
||||||
|
expect(result).toEqual(true);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not resolve to the end user agreement page', (done) => {
|
||||||
|
environment.info.enableEndUserAgreement = false;
|
||||||
|
guard.canActivate(undefined, Object.assign({ url: 'redirect' })).subscribe((result) => {
|
||||||
|
expect(router.navigateByUrl).not.toHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, of as observableOf } from 'rxjs';
|
||||||
import { AbstractEndUserAgreementGuard } from './abstract-end-user-agreement.guard';
|
import { AbstractEndUserAgreementGuard } from './abstract-end-user-agreement.guard';
|
||||||
import { EndUserAgreementService } from './end-user-agreement.service';
|
import { EndUserAgreementService } from './end-user-agreement.service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
import { environment } from '../../../environments/environment';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A guard redirecting logged in users to the end agreement page when they haven't accepted the latest user agreement
|
* A guard redirecting logged in users to the end agreement page when they haven't accepted the latest user agreement
|
||||||
@@ -19,6 +20,10 @@ export class EndUserAgreementCurrentUserGuard extends AbstractEndUserAgreementGu
|
|||||||
* True when the currently logged in user has accepted the agreements or when the user is not currently authenticated
|
* True when the currently logged in user has accepted the agreements or when the user is not currently authenticated
|
||||||
*/
|
*/
|
||||||
hasAccepted(): Observable<boolean> {
|
hasAccepted(): Observable<boolean> {
|
||||||
|
if (!environment.info.enableEndUserAgreement) {
|
||||||
|
return observableOf(true);
|
||||||
|
}
|
||||||
|
|
||||||
return this.endUserAgreementService.hasCurrentUserAcceptedAgreement(true);
|
return this.endUserAgreementService.hasCurrentUserAcceptedAgreement(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -67,11 +67,11 @@
|
|||||||
<a class="text-white" href="javascript:void(0);"
|
<a class="text-white" href="javascript:void(0);"
|
||||||
(click)="showCookieSettings()">{{ 'footer.link.cookies' | translate}}</a>
|
(click)="showCookieSettings()">{{ 'footer.link.cookies' | translate}}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li *ngIf="showPrivacyPolicy">
|
||||||
<a class="text-white"
|
<a class="text-white"
|
||||||
routerLink="info/privacy">{{ 'footer.link.privacy-policy' | translate}}</a>
|
routerLink="info/privacy">{{ 'footer.link.privacy-policy' | translate}}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li *ngIf="showEndUserAgreement">
|
||||||
<a class="text-white"
|
<a class="text-white"
|
||||||
routerLink="info/end-user-agreement">{{ 'footer.link.end-user-agreement' | translate}}</a>
|
routerLink="info/end-user-agreement">{{ 'footer.link.end-user-agreement' | translate}}</a>
|
||||||
</li>
|
</li>
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { Component, Optional } from '@angular/core';
|
import { Component, Optional } from '@angular/core';
|
||||||
import { hasValue } from '../shared/empty.util';
|
import { hasValue } from '../shared/empty.util';
|
||||||
import { KlaroService } from '../shared/cookies/klaro.service';
|
import { KlaroService } from '../shared/cookies/klaro.service';
|
||||||
|
import { environment } from '../../environments/environment';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-footer',
|
selector: 'ds-footer',
|
||||||
@@ -14,6 +15,8 @@ export class FooterComponent {
|
|||||||
* A boolean representing if to show or not the top footer container
|
* A boolean representing if to show or not the top footer container
|
||||||
*/
|
*/
|
||||||
showTopFooter = false;
|
showTopFooter = false;
|
||||||
|
showPrivacyPolicy = environment.info.enablePrivacyStatement;
|
||||||
|
showEndUserAgreement = environment.info.enableEndUserAgreement;
|
||||||
|
|
||||||
constructor(@Optional() private cookies: KlaroService) {
|
constructor(@Optional() private cookies: KlaroService) {
|
||||||
}
|
}
|
||||||
|
@@ -6,35 +6,47 @@ import { ThemedEndUserAgreementComponent } from './end-user-agreement/themed-end
|
|||||||
import { ThemedPrivacyComponent } from './privacy/themed-privacy.component';
|
import { ThemedPrivacyComponent } from './privacy/themed-privacy.component';
|
||||||
import { ThemedFeedbackComponent } from './feedback/themed-feedback.component';
|
import { ThemedFeedbackComponent } from './feedback/themed-feedback.component';
|
||||||
import { FeedbackGuard } from '../core/feedback/feedback.guard';
|
import { FeedbackGuard } from '../core/feedback/feedback.guard';
|
||||||
|
import { environment } from '../../environments/environment';
|
||||||
|
|
||||||
|
|
||||||
|
const imports = [
|
||||||
|
RouterModule.forChild([
|
||||||
|
{
|
||||||
|
path: FEEDBACK_PATH,
|
||||||
|
component: ThemedFeedbackComponent,
|
||||||
|
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
||||||
|
data: { title: 'info.feedback.title', breadcrumbKey: 'info.feedback' },
|
||||||
|
canActivate: [FeedbackGuard]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
];
|
||||||
|
|
||||||
|
if (environment.info.enableEndUserAgreement) {
|
||||||
|
imports.push(
|
||||||
|
RouterModule.forChild([
|
||||||
|
{
|
||||||
|
path: END_USER_AGREEMENT_PATH,
|
||||||
|
component: ThemedEndUserAgreementComponent,
|
||||||
|
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
||||||
|
data: { title: 'info.end-user-agreement.title', breadcrumbKey: 'info.end-user-agreement' }
|
||||||
|
}
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
if (environment.info.enablePrivacyStatement) {
|
||||||
|
imports.push(
|
||||||
|
RouterModule.forChild([
|
||||||
|
{
|
||||||
|
path: PRIVACY_PATH,
|
||||||
|
component: ThemedPrivacyComponent,
|
||||||
|
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
||||||
|
data: { title: 'info.privacy.title', breadcrumbKey: 'info.privacy' }
|
||||||
|
}
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule.forChild([
|
...imports
|
||||||
{
|
|
||||||
path: END_USER_AGREEMENT_PATH,
|
|
||||||
component: ThemedEndUserAgreementComponent,
|
|
||||||
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
|
||||||
data: { title: 'info.end-user-agreement.title', breadcrumbKey: 'info.end-user-agreement' }
|
|
||||||
}
|
|
||||||
]),
|
|
||||||
RouterModule.forChild([
|
|
||||||
{
|
|
||||||
path: PRIVACY_PATH,
|
|
||||||
component: ThemedPrivacyComponent,
|
|
||||||
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
|
||||||
data: { title: 'info.privacy.title', breadcrumbKey: 'info.privacy' }
|
|
||||||
}
|
|
||||||
]),
|
|
||||||
RouterModule.forChild([
|
|
||||||
{
|
|
||||||
path: FEEDBACK_PATH,
|
|
||||||
component: ThemedFeedbackComponent,
|
|
||||||
resolve: { breadcrumb: I18nBreadcrumbResolver },
|
|
||||||
data: { title: 'info.feedback.title', breadcrumbKey: 'info.feedback' },
|
|
||||||
canActivate: [FeedbackGuard]
|
|
||||||
}
|
|
||||||
])
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
|
@@ -63,6 +63,11 @@ export class BrowserKlaroService extends KlaroService {
|
|||||||
* - Add and translate klaro configuration messages
|
* - Add and translate klaro configuration messages
|
||||||
*/
|
*/
|
||||||
initialize() {
|
initialize() {
|
||||||
|
if (!environment.info.enablePrivacyStatement) {
|
||||||
|
delete this.klaroConfig.privacyPolicy;
|
||||||
|
this.klaroConfig.translations.en.consentNotice.description = 'cookies.consent.content-notice.description.no-privacy';
|
||||||
|
}
|
||||||
|
|
||||||
this.translateService.setDefaultLang(environment.defaultLanguage);
|
this.translateService.setDefaultLang(environment.defaultLanguage);
|
||||||
|
|
||||||
const user$: Observable<EPerson> = this.getUser$();
|
const user$: Observable<EPerson> = this.getUser$();
|
||||||
@@ -90,7 +95,6 @@ export class BrowserKlaroService extends KlaroService {
|
|||||||
this.translateConfiguration();
|
this.translateConfiguration();
|
||||||
Klaro.setup(this.klaroConfig);
|
Klaro.setup(this.klaroConfig);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1225,6 +1225,8 @@
|
|||||||
|
|
||||||
"cookies.consent.content-notice.description": "We collect and process your personal information for the following purposes: <strong>Authentication, Preferences, Acknowledgement and Statistics</strong>. <br/> To learn more, please read our {privacyPolicy}.",
|
"cookies.consent.content-notice.description": "We collect and process your personal information for the following purposes: <strong>Authentication, Preferences, Acknowledgement and Statistics</strong>. <br/> To learn more, please read our {privacyPolicy}.",
|
||||||
|
|
||||||
|
"cookies.consent.content-notice.description.no-privacy": "We collect and process your personal information for the following purposes: <strong>Authentication, Preferences, Acknowledgement and Statistics</strong>.",
|
||||||
|
|
||||||
"cookies.consent.content-notice.learnMore": "Customize",
|
"cookies.consent.content-notice.learnMore": "Customize",
|
||||||
|
|
||||||
"cookies.consent.content-modal.description": "Here you can see and customize the information that we collect about you.",
|
"cookies.consent.content-modal.description": "Here you can see and customize the information that we collect about you.",
|
||||||
|
@@ -16,6 +16,7 @@ import { MediaViewerConfig } from './media-viewer-config.interface';
|
|||||||
import { BrowseByConfig } from './browse-by-config.interface';
|
import { BrowseByConfig } from './browse-by-config.interface';
|
||||||
import { BundleConfig } from './bundle-config.interface';
|
import { BundleConfig } from './bundle-config.interface';
|
||||||
import { ActuatorsConfig } from './actuators.config';
|
import { ActuatorsConfig } from './actuators.config';
|
||||||
|
import { InfoConfig } from './info-config.interface';
|
||||||
|
|
||||||
interface AppConfig extends Config {
|
interface AppConfig extends Config {
|
||||||
ui: UIServerConfig;
|
ui: UIServerConfig;
|
||||||
@@ -36,6 +37,7 @@ interface AppConfig extends Config {
|
|||||||
mediaViewer: MediaViewerConfig;
|
mediaViewer: MediaViewerConfig;
|
||||||
bundle: BundleConfig;
|
bundle: BundleConfig;
|
||||||
actuators: ActuatorsConfig
|
actuators: ActuatorsConfig
|
||||||
|
info: InfoConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
const APP_CONFIG = new InjectionToken<AppConfig>('APP_CONFIG');
|
const APP_CONFIG = new InjectionToken<AppConfig>('APP_CONFIG');
|
||||||
|
@@ -16,6 +16,7 @@ import { ThemeConfig } from './theme.model';
|
|||||||
import { UIServerConfig } from './ui-server-config.interface';
|
import { UIServerConfig } from './ui-server-config.interface';
|
||||||
import { BundleConfig } from './bundle-config.interface';
|
import { BundleConfig } from './bundle-config.interface';
|
||||||
import { ActuatorsConfig } from './actuators.config';
|
import { ActuatorsConfig } from './actuators.config';
|
||||||
|
import { InfoConfig } from './info-config.interface';
|
||||||
|
|
||||||
export class DefaultAppConfig implements AppConfig {
|
export class DefaultAppConfig implements AppConfig {
|
||||||
production = false;
|
production = false;
|
||||||
@@ -324,4 +325,16 @@ export class DefaultAppConfig implements AppConfig {
|
|||||||
image: false,
|
image: false,
|
||||||
video: false
|
video: false
|
||||||
};
|
};
|
||||||
|
// Whether the end-user-agreement and privacy policy feature should be enabled or not.
|
||||||
|
// Disabling the end user agreement feature will result in:
|
||||||
|
// - Users no longer being forced to accept the end-user-agreement before they can access the repository
|
||||||
|
// - A 404 page if you manually try to navigate to the end-user-agreement page at info/end-user-agreement
|
||||||
|
// - All end-user-agreement related links and pages will be removed from the UI (e.g. in the footer)
|
||||||
|
// Disabling the privacy policy feature will result in:
|
||||||
|
// - A 404 page if you manually try to navigate to the privacy policy page at info/privacy
|
||||||
|
// - All mentions of the privacy policy being removed from the UI (e.g. in the footer)
|
||||||
|
info: InfoConfig = {
|
||||||
|
enableEndUserAgreement: true,
|
||||||
|
enablePrivacyStatement: true
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
6
src/config/info-config.interface.ts
Normal file
6
src/config/info-config.interface.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { Config } from './config.interface';
|
||||||
|
|
||||||
|
export interface InfoConfig extends Config {
|
||||||
|
enableEndUserAgreement: boolean;
|
||||||
|
enablePrivacyStatement: boolean;
|
||||||
|
}
|
@@ -243,5 +243,9 @@ export const environment: BuildConfig = {
|
|||||||
mediaViewer: {
|
mediaViewer: {
|
||||||
image: true,
|
image: true,
|
||||||
video: true
|
video: true
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
enableEndUserAgreement: true,
|
||||||
|
enablePrivacyStatement: true,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user