Skip to content

Commit

Permalink
- Refactored initialization of tracking setup (TrackingService.init()…
Browse files Browse the repository at this point in the history
…) to trigger after license verification

- Replaced inline license-based tracking conditions with TrackingService for consistent management of cookies and scripts
- Invoked TrackingService.init() directly in LoginCtrl to ensure tracking settings are removed immediately when no user
- Updated CookiePolicyModalController and cookie-consent.directive to streamline consent handling
- Updated CookieConsent model to include a toJSON() method
- Moved GoogleAnalyticsCookieService script management logic into TrackingService
  • Loading branch information
teodossidossev committed Nov 4, 2024
1 parent 2759ca2 commit 869ad06
Show file tree
Hide file tree
Showing 14 changed files with 431 additions and 295 deletions.
18 changes: 2 additions & 16 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import 'angular/core/interceptors/authentication.interceptor';
import 'angular/core/directives/rdfresourcesearch/rdf-resource-search.directive';
import 'angular/core/directives/languageselector/language-selector.directive';
import 'angular/core/directives/copy-to-clipboard/copy-to-clipboard.directive';
import 'angular/core/directives/cookie-policy/cookie-consent.directive';
import 'angular/core/directives/angulartooltips/angular-tooltips.js';
import 'angular/core/directives/uppercased.directive';
import 'angular/core/directives/operations-statuses-monitor/operations-statuses-monitor.directive';
Expand Down Expand Up @@ -40,14 +39,11 @@ const modules = [
'graphdb.framework.core.directives.rdfresourcesearch.rdfresourcesearch',
'graphdb.framework.core.directives.languageselector.languageselector',
'graphdb.framework.core.directives.copytoclipboard.copytoclipboard',
'graphdb.framework.core.directives.cookie-consent',
'graphdb.framework.core.directives.angular-tooltips',
'graphdb.framework.core.directives.uppercased',
'graphdb.framework.core.directives.prop-indeterminate',
'graphdb.framework.core.directives.page-info-tooltip',
'graphdb.framework.guides.services',
'graphdb.framework.core.services.licenseService',
'graphdb.framework.core.services.installationCookieService',
'graphdb.framework.core.directives.operationsstatusesmonitor',
'graphdb.framework.core.directives.autocomplete',
'ngCustomElement'
Expand Down Expand Up @@ -201,8 +197,8 @@ const moduleDefinition = function (productInfo, translations) {
workbench.constant('productInfo', productInfo);

// we need to inject $jwtAuth here in order to init the service before everything else
workbench.run(['$rootScope', '$route', 'toastr', '$sce', '$translate', 'ThemeService', 'WorkbenchSettingsStorageService', 'LSKeys', 'GuidesService', '$licenseService', 'InstallationCookieService',
function ($rootScope, $route, toastr, $sce, $translate, ThemeService, WorkbenchSettingsStorageService, LSKeys, GuidesService, $licenseService, InstallationCookieService) {
workbench.run(['$rootScope', '$route', 'toastr', '$sce', '$translate', 'ThemeService', 'WorkbenchSettingsStorageService', 'LSKeys', 'GuidesService',
function ($rootScope, $route, toastr, $sce, $translate, ThemeService, WorkbenchSettingsStorageService, LSKeys, GuidesService) {
$rootScope.$on('$routeChangeSuccess', function () {
updateTitleAndHelpInfo();

Expand Down Expand Up @@ -231,16 +227,6 @@ const moduleDefinition = function (productInfo, translations) {
ThemeService.applyDarkThemeMode();

GuidesService.init();

// Checks license status and adds tracking code and cookies when free/evaluation license
$licenseService.checkLicenseStatus().then(() => {
if ($licenseService.isTrackingAllowed()) {
const installationId = $licenseService.license().installationId || '';
InstallationCookieService.setIfAbsent(installationId);
} else {
InstallationCookieService.remove();
}
});
}]);

workbench.filter('titlecase', function () {
Expand Down
16 changes: 10 additions & 6 deletions src/js/angular/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import 'ng-file-upload/dist/ng-file-upload-shim.min';
import 'angular/core/services/jwt-auth.service';
import 'angular/core/services/repositories.service';
import 'angular/core/services/license.service';
import 'angular/core/services/installation-cookie.service';
import 'angular/core/services/tracking/tracking.service';
import {UserRole} from 'angular/utils/user-utils';
import 'angular/utils/local-storage-adapter';
import 'angular/utils/workbench-settings-storage-service';
Expand All @@ -32,7 +32,7 @@ angular
'graphdb.framework.core.services.jwtauth',
'graphdb.framework.core.services.repositories',
'graphdb.framework.core.services.licenseService',
'graphdb.framework.core.services.installationCookieService',
'graphdb.framework.core.services.trackingService',
'graphdb.framework.core.services.theme-service',
'ngCookies',
'ngFileUpload',
Expand Down Expand Up @@ -128,11 +128,11 @@ function homeCtrl($scope, $rootScope, $http, $repositories, $jwtAuth, $licenseSe

mainCtrl.$inject = ['$scope', '$menuItems', '$jwtAuth', '$http', 'toastr', '$location', '$repositories', '$licenseService', '$rootScope',
'productInfo', '$timeout', 'ModalService', '$interval', '$filter', 'LicenseRestService', 'RepositoriesRestService',
'MonitoringRestService', 'SparqlRestService', '$sce', 'LocalStorageAdapter', 'LSKeys', '$translate', 'UriUtils', '$q', 'GuidesService', '$route', '$window', 'AuthTokenService'];
'MonitoringRestService', 'SparqlRestService', '$sce', 'LocalStorageAdapter', 'LSKeys', '$translate', 'UriUtils', '$q', 'GuidesService', '$route', '$window', 'AuthTokenService', 'TrackingService'];

function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repositories, $licenseService, $rootScope,
productInfo, $timeout, ModalService, $interval, $filter, LicenseRestService, RepositoriesRestService,
MonitoringRestService, SparqlRestService, $sce, LocalStorageAdapter, LSKeys, $translate, UriUtils, $q, GuidesService, $route, $window, AuthTokenService) {
MonitoringRestService, SparqlRestService, $sce, LocalStorageAdapter, LSKeys, $translate, UriUtils, $q, GuidesService, $route, $window, AuthTokenService, TrackingService) {
$scope.descr = $translate.instant('main.gdb.description');
$scope.documentation = '';
$scope.menu = $menuItems;
Expand Down Expand Up @@ -212,7 +212,7 @@ function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repos
}, 400);
if (previous) {
// Recheck license status on navigation within the workbench (security is already inited)
$licenseService.checkLicenseStatus();
$licenseService.checkLicenseStatus().then(() => TrackingService.init());
}
});

Expand Down Expand Up @@ -854,10 +854,14 @@ function mainCtrl($scope, $menuItems, $jwtAuth, $http, toastr, $location, $repos
// There are many places where setTimeout is used, see $jwtAuth#authenticate and $jwtAuth#setAuthHeaders.
setTimeout(() => $scope.getSavedQueries(), 500);
});
$licenseService.checkLicenseStatus();
$licenseService.checkLicenseStatus().then(() => TrackingService.init());
}
});

$scope.isTrackingAllowed = function () {
return TrackingService.isTrackingAllowed();
};

$scope.getProductType = function () {
return $licenseService.productType();
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {CookieConsent} from "../../../models/cookie-policy/cookie-consent";
import {CookiePolicyModalController} from "./cookie-policy-modal-controller";

const modules = [];
Expand All @@ -7,13 +6,18 @@ angular
.module('graphdb.framework.core.directives.cookie-consent', modules)
.directive('cookieConsent', cookieConsent);

cookieConsent.$inject = ['$jwtAuth', '$uibModal', '$licenseService', '$translate', 'toastr'];
cookieConsent.$inject = ['$jwtAuth', '$uibModal', '$licenseService', '$translate', 'toastr', 'TrackingService'];

function cookieConsent($jwtAuth, $uibModal, $licenseService, $translate, toastr) {
function cookieConsent($jwtAuth, $uibModal, $licenseService, $translate, toastr, TrackingService) {
return {
restrict: 'E',
templateUrl: 'js/angular/core/templates/cookie-policy/cookie-consent.html',
link: ($scope) => {
// =========================
// Private variables
// =========================
let cookieConsent = undefined;

// =========================
// Public variables
// =========================
Expand All @@ -23,21 +27,16 @@ function cookieConsent($jwtAuth, $uibModal, $licenseService, $translate, toastr)
// Public functions
// =========================
$scope.acceptConsent = () => {
$jwtAuth.getPrincipal()
.then((data) => {
const appSettings = data.appSettings;
const username = data.username;
appSettings.COOKIE_CONSENT = CookieConsent.fromJSON(appSettings.COOKIE_CONSENT).getConsent();
appSettings.COOKIE_CONSENT.policyAccepted = true;
return $jwtAuth.updateUserData({appSettings, username});
})
.finally(() => $scope.showCookieConsent = false);
TrackingService.updateCookieConsent(cookieConsent.setPolicyAccepted(true))
.then(() => $scope.showCookieConsent = false);
};

$scope.showCookiePolicy = () => {
$uibModal.open({
templateUrl: 'js/angular/core/templates/cookie-policy/cookie-policy.html',
controller: CookiePolicyModalController,
backdrop: 'static',
keyboard: false,
windowClass: 'cookie-policy-modal'
});
};
Expand All @@ -46,29 +45,10 @@ function cookieConsent($jwtAuth, $uibModal, $licenseService, $translate, toastr)
// Private functions
// =========================
const init = () => {
$licenseService.checkLicenseStatus()
.then(() => {
if ($licenseService.isTrackingAllowed()) {
return checkUserConsentStatus();
}
})
.catch((error) => {
const msg = getError(error.data, error.status);
toastr.error(msg, $translate.instant('common.error'));
});
};

const checkUserConsentStatus = () => {
return $jwtAuth.getPrincipal()
.then((data) => {
if (!data) {
return;
}
const appSettings = data.appSettings;
appSettings.COOKIE_CONSENT = CookieConsent.fromJSON(appSettings.COOKIE_CONSENT).getConsent();
if (!appSettings.COOKIE_CONSENT.policyAccepted) {
$scope.showCookieConsent = true;
}
TrackingService.getCookieConsent()
.then((consent) => {
cookieConsent = consent;
$scope.showCookieConsent = !consent.getPolicyAccepted();
})
.catch((error) => {
const msg = getError(error.data, error.status);
Expand All @@ -78,7 +58,7 @@ function cookieConsent($jwtAuth, $uibModal, $licenseService, $translate, toastr)

const securityInit = (event, securityEnabled, userLoggedIn) => {
if (userLoggedIn) {
checkUserConsentStatus();
init();
} else {
$scope.showCookieConsent = false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,63 +1,65 @@
import {ConsentTypes, CookieConsent} from "../../../models/cookie-policy/cookie-consent";
import {ConsentTypes} from "../../../models/cookie-policy/cookie-consent";

CookiePolicyModalController.$inject = ['$scope', '$jwtAuth', '$translate', 'toastr'];
CookiePolicyModalController.$inject = ['$scope', '$translate', 'toastr', 'TrackingService'];

/**
* Controller for managing cookie consent settings in a modal.
* Handles toggling and saving user consent preferences for different cookie types.
*
* @param {Object} $scope - AngularJS scope for managing modal variables and functions.
* @param {Object} $jwtAuth - Service for handling user authentication and data.
* @param {Object} $translate - Service for translating messages.
* @param {Object} $translate - Service for translating messages within the modal.
* @param {Object} toastr - Service for displaying toast notifications.
* @param {Object} TrackingService - Service responsible for tracking and managing consent data.
*/
export function CookiePolicyModalController($scope, $jwtAuth, $translate, toastr) {
export function CookiePolicyModalController($scope, $translate, toastr, TrackingService) {
let callCount = 0;
// =========================
// Public variables
// =========================
$scope.appSettings = undefined;
$scope.username = undefined;
$scope.cookieConsent = undefined;
$scope.ConsentTypes = ConsentTypes;

// =========================
// Private variables
// =========================
let username = undefined;

// =========================
// Public functions
// =========================
$scope.toggleConsent = (type) => {
if (type === ConsentTypes.STATISTIC) {
$scope.appSettings.COOKIE_CONSENT.statistic = !$scope.appSettings.COOKIE_CONSENT.statistic;
$scope.cookieConsent.setStatisticConsent(!$scope.cookieConsent.getStatisticConsent());
} else if (type === ConsentTypes.THIRD_PARTY) {
$scope.appSettings.COOKIE_CONSENT.thirdParty = !$scope.appSettings.COOKIE_CONSENT.thirdParty;
callCount++;
$scope.cookieConsent.setThirdPartyConsent(!$scope.cookieConsent.getThirdPartyConsent());

}
$scope.saveConsent();
};

$scope.saveConsent = () => {
$jwtAuth.updateUserData({appSettings: $scope.appSettings, username})
.catch((error) => {
const msg = getError(error.data, error.status);
toastr.error(msg, $translate.instant('common.error'));
});
TrackingService.updateCookieConsent($scope.cookieConsent);
};

/**
* Closes the modal and passes a result to indicate if the page should be reloaded.
* - The page reloads only if the user has
* (1) toggled third-party consent multiple times (`didAbusedThirdPartyToggle`),
* (2) left third-party consent as enabled (`hasThirdPartyConsent`), and
* (3) previously accepted the overall policy (`hasPolicyAccepted`)
* - This reload is necessary in cases where multiple third-party consent changes
* lead to duplicate and redundant tracking data being loaded.
*/
$scope.close = () => {
$scope.$close($scope.appSettings);
const didAbusedThirdPartyToggle = callCount > 1;
const hasThirdPartyConsent = $scope.cookieConsent.getThirdPartyConsent();
const hasPolicyAccepted = $scope.cookieConsent.getPolicyAccepted();

$scope.$close(didAbusedThirdPartyToggle && hasThirdPartyConsent && hasPolicyAccepted);
};

// =========================
// Private functions
// =========================
const init = () => {
$jwtAuth.getPrincipal()
.then((data) => {
$scope.appSettings = data.appSettings;
username = data.username;
$scope.appSettings.COOKIE_CONSENT = CookieConsent.fromJSON($scope.appSettings.COOKIE_CONSENT).getConsent();
})
TrackingService.getCookieConsent()
.then((cookieConsent) => $scope.cookieConsent = cookieConsent)
.catch((error) => {
const msg = getError(error.data, error.status);
toastr.error(msg, $translate.instant('common.error'));
Expand Down
Loading

0 comments on commit 869ad06

Please sign in to comment.