diff --git a/config/config.example.yml b/config/config.example.yml index 3f88b32324..9e1fcc8d1e 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -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 diff --git a/src/app/core/end-user-agreement/abstract-end-user-agreement.guard.ts b/src/app/core/end-user-agreement/abstract-end-user-agreement.guard.ts index b9f134f946..076df8ebc9 100644 --- a/src/app/core/end-user-agreement/abstract-end-user-agreement.guard.ts +++ b/src/app/core/end-user-agreement/abstract-end-user-agreement.guard.ts @@ -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 { + if (!environment.info.enableEndUserAgreement) { + return observableOf(true); + } return this.hasAccepted().pipe( returnEndUserAgreementUrlTreeOnFalse(this.router, state.url) ); diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts index 75b8f6089e..40728ab601 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.spec.ts @@ -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(); + }); + }); + }); }); }); diff --git a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts index 2c04186f34..a79e12cc32 100644 --- a/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts +++ b/src/app/core/end-user-agreement/end-user-agreement-current-user.guard.ts @@ -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 { + if (!environment.info.enableEndUserAgreement) { + return observableOf(true); + } + return this.endUserAgreementService.hasCurrentUserAcceptedAgreement(true); } diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html index 2c1a34ccae..88236d381e 100644 --- a/src/app/footer/footer.component.html +++ b/src/app/footer/footer.component.html @@ -67,11 +67,11 @@ {{ 'footer.link.cookies' | translate}} -
  • +
  • {{ 'footer.link.privacy-policy' | translate}}
  • -
  • +
  • {{ 'footer.link.end-user-agreement' | translate}}
  • diff --git a/src/app/footer/footer.component.ts b/src/app/footer/footer.component.ts index c43a0ae85d..c4195c8eb3 100644 --- a/src/app/footer/footer.component.ts +++ b/src/app/footer/footer.component.ts @@ -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) { } diff --git a/src/app/info/info-routing.module.ts b/src/app/info/info-routing.module.ts index c746bebaaa..4c497461e7 100644 --- a/src/app/info/info-routing.module.ts +++ b/src/app/info/info-routing.module.ts @@ -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 ] }) /** diff --git a/src/app/shared/cookies/browser-klaro.service.ts b/src/app/shared/cookies/browser-klaro.service.ts index 4e6370f179..638d465864 100644 --- a/src/app/shared/cookies/browser-klaro.service.ts +++ b/src/app/shared/cookies/browser-klaro.service.ts @@ -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 = this.getUser$(); @@ -90,7 +95,6 @@ export class BrowserKlaroService extends KlaroService { this.translateConfiguration(); Klaro.setup(this.klaroConfig); }); - } /** diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 7d9a737354..57863b3a69 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -1225,6 +1225,8 @@ "cookies.consent.content-notice.description": "We collect and process your personal information for the following purposes: Authentication, Preferences, Acknowledgement and Statistics.
    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: Authentication, Preferences, Acknowledgement and Statistics.", + "cookies.consent.content-notice.learnMore": "Customize", "cookies.consent.content-modal.description": "Here you can see and customize the information that we collect about you.", diff --git a/src/config/app-config.interface.ts b/src/config/app-config.interface.ts index 649efacb7b..f9d38d9b45 100644 --- a/src/config/app-config.interface.ts +++ b/src/config/app-config.interface.ts @@ -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('APP_CONFIG'); diff --git a/src/config/default-app-config.ts b/src/config/default-app-config.ts index 383b92cf73..11761af49a 100644 --- a/src/config/default-app-config.ts +++ b/src/config/default-app-config.ts @@ -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 + }; } diff --git a/src/config/info-config.interface.ts b/src/config/info-config.interface.ts new file mode 100644 index 0000000000..b1831962b5 --- /dev/null +++ b/src/config/info-config.interface.ts @@ -0,0 +1,6 @@ +import { Config } from './config.interface'; + +export interface InfoConfig extends Config { + enableEndUserAgreement: boolean; + enablePrivacyStatement: boolean; +} diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index 8ad842c33e..4d466bd37b 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -243,5 +243,9 @@ export const environment: BuildConfig = { mediaViewer: { image: true, video: true + }, + info: { + enableEndUserAgreement: true, + enablePrivacyStatement: true, } };