Merge pull request #1715 from atmire/w2p-92701_issue-1506-gdpr-privacy-config

Option to disable gdpr / privacy statements
This commit is contained in:
Tim Donohue
2022-08-09 09:40:59 -05:00
committed by GitHub
13 changed files with 112 additions and 30 deletions

View File

@@ -248,3 +248,10 @@ bundle:
mediaViewer:
image: 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

View File

@@ -1,6 +1,7 @@
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 { environment } from '../../../environments/environment';
/**
* 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
*/
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> {
if (!environment.info.enableEndUserAgreement) {
return observableOf(true);
}
return this.hasAccepted().pipe(
returnEndUserAgreementUrlTreeOnFalse(this.router, state.url)
);

View File

@@ -2,6 +2,7 @@ import { EndUserAgreementCurrentUserGuard } from './end-user-agreement-current-u
import { EndUserAgreementService } from './end-user-agreement.service';
import { Router, UrlTree } from '@angular/router';
import { of as observableOf } from 'rxjs';
import { environment } from '../../../environments/environment.test';
describe('EndUserAgreementGuard', () => {
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();
});
});
});
});
});

View File

@@ -1,8 +1,9 @@
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 { EndUserAgreementService } from './end-user-agreement.service';
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
@@ -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
*/
hasAccepted(): Observable<boolean> {
if (!environment.info.enableEndUserAgreement) {
return observableOf(true);
}
return this.endUserAgreementService.hasCurrentUserAcceptedAgreement(true);
}

View File

@@ -67,11 +67,11 @@
<a class="text-white" href="javascript:void(0);"
(click)="showCookieSettings()">{{ 'footer.link.cookies' | translate}}</a>
</li>
<li>
<li *ngIf="showPrivacyPolicy">
<a class="text-white"
routerLink="info/privacy">{{ 'footer.link.privacy-policy' | translate}}</a>
</li>
<li>
<li *ngIf="showEndUserAgreement">
<a class="text-white"
routerLink="info/end-user-agreement">{{ 'footer.link.end-user-agreement' | translate}}</a>
</li>

View File

@@ -1,6 +1,7 @@
import { Component, Optional } from '@angular/core';
import { hasValue } from '../shared/empty.util';
import { KlaroService } from '../shared/cookies/klaro.service';
import { environment } from '../../environments/environment';
@Component({
selector: 'ds-footer',
@@ -14,6 +15,8 @@ export class FooterComponent {
* A boolean representing if to show or not the top footer container
*/
showTopFooter = false;
showPrivacyPolicy = environment.info.enablePrivacyStatement;
showEndUserAgreement = environment.info.enableEndUserAgreement;
constructor(@Optional() private cookies: KlaroService) {
}

View File

@@ -6,35 +6,47 @@ import { ThemedEndUserAgreementComponent } from './end-user-agreement/themed-end
import { ThemedPrivacyComponent } from './privacy/themed-privacy.component';
import { ThemedFeedbackComponent } from './feedback/themed-feedback.component';
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({
imports: [
RouterModule.forChild([
{
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]
}
])
...imports
]
})
/**

View File

@@ -63,6 +63,11 @@ export class BrowserKlaroService extends KlaroService {
* - Add and translate klaro configuration messages
*/
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);
const user$: Observable<EPerson> = this.getUser$();
@@ -90,7 +95,6 @@ export class BrowserKlaroService extends KlaroService {
this.translateConfiguration();
Klaro.setup(this.klaroConfig);
});
}
/**

View File

@@ -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.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-modal.description": "Here you can see and customize the information that we collect about you.",

View File

@@ -16,6 +16,7 @@ import { MediaViewerConfig } from './media-viewer-config.interface';
import { BrowseByConfig } from './browse-by-config.interface';
import { BundleConfig } from './bundle-config.interface';
import { ActuatorsConfig } from './actuators.config';
import { InfoConfig } from './info-config.interface';
interface AppConfig extends Config {
ui: UIServerConfig;
@@ -36,6 +37,7 @@ interface AppConfig extends Config {
mediaViewer: MediaViewerConfig;
bundle: BundleConfig;
actuators: ActuatorsConfig
info: InfoConfig;
}
const APP_CONFIG = new InjectionToken<AppConfig>('APP_CONFIG');

View File

@@ -16,6 +16,7 @@ import { ThemeConfig } from './theme.model';
import { UIServerConfig } from './ui-server-config.interface';
import { BundleConfig } from './bundle-config.interface';
import { ActuatorsConfig } from './actuators.config';
import { InfoConfig } from './info-config.interface';
export class DefaultAppConfig implements AppConfig {
production = false;
@@ -324,4 +325,16 @@ export class DefaultAppConfig implements AppConfig {
image: 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
};
}

View File

@@ -0,0 +1,6 @@
import { Config } from './config.interface';
export interface InfoConfig extends Config {
enableEndUserAgreement: boolean;
enablePrivacyStatement: boolean;
}

View File

@@ -243,5 +243,9 @@ export const environment: BuildConfig = {
mediaViewer: {
image: true,
video: true
},
info: {
enableEndUserAgreement: true,
enablePrivacyStatement: true,
}
};