From 7d3cd72db5c23839c750f79cc78ff7bdd3effb4f Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Tue, 15 Oct 2024 14:36:10 +0200 Subject: [PATCH 1/6] [!!!][FEATURE] Enrich fingerprint hash with IP address Tracking purely based on device fingerprinting lead to some issues, namely mobile browsers working more towards sandboxing requests so that device hashes end up being the same across the same line of devices. This makes individual tracking unreliable and in the case of Lux leads to some leads that contain several different people in them. This change enriches the fingerprint with the users IP address and hashes it again, leading to a more unique identification value. Negative impact of this change: * (BREAKING) Previously identified users can't be identified anymore, as the calculated fingerprint value has changed. * Compared to before, we now create _more_ unique users than before, as IP addresses (usually) change on the regular for home connections or when switching wi-fi/cellular networks. Related: https://projekte.in2code.de/issues/67221 --- Classes/Domain/Model/Fingerprint.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Classes/Domain/Model/Fingerprint.php b/Classes/Domain/Model/Fingerprint.php index e99f4a00..e09d57f9 100644 --- a/Classes/Domain/Model/Fingerprint.php +++ b/Classes/Domain/Model/Fingerprint.php @@ -7,6 +7,7 @@ use In2code\Lux\Exception\FingerprintMustNotBeEmptyException; use In2code\Lux\Utility\BackendUtility; use In2code\Lux\Utility\EnvironmentUtility; +use In2code\Lux\Utility\IpUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use WhichBrowser\Parser; @@ -52,7 +53,7 @@ public function setValue(string $value): self if (strlen($value) === 33) { $this->setType(self::TYPE_STORAGE); } - $this->value = $value; + $this->value = hash('sha256', $value . IpUtility::getIpAddress()); return $this; } From 884e832005aae50eb105c6d952193bb65d795723 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Tue, 15 Oct 2024 14:36:42 +0200 Subject: [PATCH 2/6] [TASK] Add tests for Fingerprint model class Related: https://projekte.in2code.de/issues/67221 --- Tests/Unit/Domain/Model/FingerprintTest.php | 77 +++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 Tests/Unit/Domain/Model/FingerprintTest.php diff --git a/Tests/Unit/Domain/Model/FingerprintTest.php b/Tests/Unit/Domain/Model/FingerprintTest.php new file mode 100644 index 00000000..29bc596e --- /dev/null +++ b/Tests/Unit/Domain/Model/FingerprintTest.php @@ -0,0 +1,77 @@ +setValue(random_bytes(32)); + self::assertEquals($fingerprint->getType(), Fingerprint::TYPE_FINGERPRINT); + + $fingerprint->setValue(random_bytes(33)); + self::assertEquals($fingerprint->getType(), Fingerprint::TYPE_STORAGE); + } + + /** + * @return void + * @covers ::setValue + */ + public function testAssertSameHashesWithSameIps(): void + { + $fingerprint = new Fingerprint(); + $identifier = bin2hex(random_bytes(16)); + + $fingerprint->setValue($identifier); + $value1 = $fingerprint->getValue(); + + $fingerprint->setValue($identifier); + $value2 = $fingerprint->getValue(); + + self::assertEquals($value1, $value2); + } + + /** + * @return void + * @covers ::setValue + */ + public function testAssertDifferentHashesWithDifferentIps(): void + { + $fingerprint = new Fingerprint(); + $identifier = bin2hex(random_bytes(16)); + + GeneralUtility::setIndpEnv('REMOTE_ADDR', '192.168.178.1'); + $fingerprint->setValue($identifier); + + $value1 = $fingerprint->getValue(); + + GeneralUtility::setIndpEnv('REMOTE_ADDR', '192.168.178.16'); + $fingerprint->setValue($identifier); + + $value2 = $fingerprint->getValue(); + + self::assertNotEquals($value1, $value2); + } +} From 50e33ab802f29980116fd6168282ebb656ab1125 Mon Sep 17 00:00:00 2001 From: Andreas Nedbal Date: Tue, 15 Oct 2024 15:35:57 +0200 Subject: [PATCH 3/6] [TASK] Don't hash local storage fingerprints Local storage fingerprint values are already deterministic, they don't require the extra uniqueness factor. Related: https://projekte.in2code.de/issues/67221 --- Classes/Domain/Model/Fingerprint.php | 4 +++- Tests/Unit/Domain/Model/FingerprintTest.php | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Classes/Domain/Model/Fingerprint.php b/Classes/Domain/Model/Fingerprint.php index e09d57f9..d7b8946f 100644 --- a/Classes/Domain/Model/Fingerprint.php +++ b/Classes/Domain/Model/Fingerprint.php @@ -52,8 +52,10 @@ public function setValue(string $value): self } if (strlen($value) === 33) { $this->setType(self::TYPE_STORAGE); + $this->value = $value; + } else { + $this->value = hash('sha256', $value . IpUtility::getIpAddress()); } - $this->value = hash('sha256', $value . IpUtility::getIpAddress()); return $this; } diff --git a/Tests/Unit/Domain/Model/FingerprintTest.php b/Tests/Unit/Domain/Model/FingerprintTest.php index 29bc596e..339123c0 100644 --- a/Tests/Unit/Domain/Model/FingerprintTest.php +++ b/Tests/Unit/Domain/Model/FingerprintTest.php @@ -60,7 +60,7 @@ public function testAssertSameHashesWithSameIps(): void public function testAssertDifferentHashesWithDifferentIps(): void { $fingerprint = new Fingerprint(); - $identifier = bin2hex(random_bytes(16)); + $identifier = random_bytes(32); GeneralUtility::setIndpEnv('REMOTE_ADDR', '192.168.178.1'); $fingerprint->setValue($identifier); @@ -74,4 +74,19 @@ public function testAssertDifferentHashesWithDifferentIps(): void self::assertNotEquals($value1, $value2); } + + /** + * @return void + * @covers ::setValue + */ + public function testAssertNoHashingForStorageType(): void + { + $fingerprint = new Fingerprint(); + $identifier = random_bytes(33); + + $fingerprint->setValue($identifier); + $value = $fingerprint->getValue(); + + self::assertEquals($identifier, $value); + } } From 71fe132b85ef73400b860dca87b5d852fa095c49 Mon Sep 17 00:00:00 2001 From: Alexander Kellner Date: Wed, 23 Oct 2024 14:21:47 +0200 Subject: [PATCH 4/6] [FEATURE] Add sorting possibility in lead list As a follow up of a pull request from Andi, we discussed a similar and smarter way Resolves: https://github.com/in2code-de/lux/pull/61 --- Classes/Controller/AbstractController.php | 8 ++++ Classes/Domain/Model/Transfer/FilterDto.php | 43 +++++++++++++++++++ .../Domain/Repository/VisitorRepository.php | 6 +-- Configuration/Backend/Modules.php | 2 + .../Private/Partials/Filter/Lead/List.html | 2 + .../Private/Partials/Filter/TableSorting.html | 28 ++++++++++++ Resources/Private/Templates/Lead/List.html | 4 ++ ext_tables.php | 6 ++- 8 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 Resources/Private/Partials/Filter/TableSorting.html diff --git a/Classes/Controller/AbstractController.php b/Classes/Controller/AbstractController.php index cdc04885..f84aaddd 100644 --- a/Classes/Controller/AbstractController.php +++ b/Classes/Controller/AbstractController.php @@ -168,6 +168,14 @@ public function resetFilterAction(string $redirectAction): ResponseInterface return $this->redirect($redirectAction); } + public function tableSortingAction(string $sortingField, string $sortingDirection, string $redirectAction): ResponseInterface + { + $filter = BackendUtility::getFilterArrayFromSession($redirectAction, $this->getControllerName()); + $filter['sortingField'] = $sortingField; + $filter['sortingDirection'] = $sortingDirection; + return $this->redirect($redirectAction, null, null, ['filter' => $filter]); + } + /** * @return string like "Analysis" or "Lead" */ diff --git a/Classes/Domain/Model/Transfer/FilterDto.php b/Classes/Domain/Model/Transfer/FilterDto.php index 7298f1a6..677814d4 100644 --- a/Classes/Domain/Model/Transfer/FilterDto.php +++ b/Classes/Domain/Model/Transfer/FilterDto.php @@ -14,6 +14,7 @@ use In2code\Lux\Utility\StringUtility; use Throwable; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Persistence\QueryInterface; /** * Class FilterDto is a filter class that helps to filter visitors by given parameters. Per default, get visitors @@ -38,6 +39,8 @@ class FilterDto protected string $searchterm = ''; protected string $href = ''; protected string $pid = ''; + protected string $sortingField = ''; + protected string $sortingDirection = QueryInterface::ORDER_DESCENDING; /** * Must be a string like "2021-01-01T15:03:01.012345Z" (date format "c") @@ -923,6 +926,46 @@ protected function getYearIntervals(): array return $interval; } + public function getSortingField(): string + { + return StringUtility::cleanString($this->sortingField); + } + + public function isSortingFieldSet(): bool + { + return $this->getSortingField() !== ''; + } + + public function setSortingField(string $sortingField): self + { + $this->sortingField = $sortingField; + return $this; + } + + public function getSortingDirection(): string + { + return StringUtility::cleanString($this->sortingDirection); + } + + public function setSortingDirection(string $sortingDirection): self + { + $this->sortingDirection = $sortingDirection; + return $this; + } + + public function getOrderings(): array + { + $orderings = [ + 'identified' => QueryInterface::ORDER_DESCENDING, + 'scoring' => QueryInterface::ORDER_DESCENDING, + 'tstamp' => QueryInterface::ORDER_DESCENDING, + ]; + if ($this->isSortingFieldSet()) { + $orderings = [$this->getSortingField() => $this->getSortingDirection()]; + } + return $orderings; + } + /** * Get all sites on which the current editor has reading access * diff --git a/Classes/Domain/Repository/VisitorRepository.php b/Classes/Domain/Repository/VisitorRepository.php index d54bd6a0..6599f167 100644 --- a/Classes/Domain/Repository/VisitorRepository.php +++ b/Classes/Domain/Repository/VisitorRepository.php @@ -83,11 +83,7 @@ public function findAllWithIdentifiedFirst(FilterDto $filter): array $logicalAnd = $this->extendLogicalAndWithFilterConstraints($filter, $query, []); $logicalAnd = $this->extendLogicalAndWithFilterConstraintsForSite($filter, $query, $logicalAnd, 'pagevisits'); $query->matching($query->logicalAnd(...$logicalAnd)); - $query->setOrderings([ - 'identified' => QueryInterface::ORDER_DESCENDING, - 'scoring' => QueryInterface::ORDER_DESCENDING, - 'tstamp' => QueryInterface::ORDER_DESCENDING, - ]); + $query->setOrderings($filter->getOrderings()); $query->setLimit($filter->getLimit()); return $query->execute()->toArray(); } diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php index ce5f7708..5f657246 100644 --- a/Configuration/Backend/Modules.php +++ b/Configuration/Backend/Modules.php @@ -37,6 +37,7 @@ 'remove', 'deactivate', 'resetFilter', + 'tableSorting', 'companies', 'companiesDisabled', 'company', @@ -65,6 +66,7 @@ 'remove', 'deactivate', 'resetFilter', + 'tableSorting', 'companies', 'companiesDisabled', 'company', diff --git a/Resources/Private/Partials/Filter/Lead/List.html b/Resources/Private/Partials/Filter/Lead/List.html index 98b7385b..62a34438 100644 --- a/Resources/Private/Partials/Filter/Lead/List.html +++ b/Resources/Private/Partials/Filter/Lead/List.html @@ -139,6 +139,8 @@
Scoring
+ + diff --git a/Resources/Private/Partials/Filter/TableSorting.html b/Resources/Private/Partials/Filter/TableSorting.html new file mode 100644 index 00000000..5081364f --- /dev/null +++ b/Resources/Private/Partials/Filter/TableSorting.html @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Templates/Lead/List.html b/Resources/Private/Templates/Lead/List.html index 424a53e0..c3ba8848 100644 --- a/Resources/Private/Templates/Lead/List.html +++ b/Resources/Private/Templates/Lead/List.html @@ -55,6 +55,7 @@ Scoring + @@ -65,11 +66,13 @@ Email + Company + @@ -87,6 +90,7 @@ (PID{filter.pid}) + diff --git a/ext_tables.php b/ext_tables.php index 0701cbcb..0080d0c2 100644 --- a/ext_tables.php +++ b/ext_tables.php @@ -75,7 +75,8 @@ function () { 'dashboard,content,news,linkListener,search,deleteLinkListener,detailPage' . ',detailNews,detailSearch,detailDownload,detailLinkListener,resetFilter,utm', \In2code\Lux\Controller\LeadController::class => 'dashboard,list,detail,downloadCsv,remove,' . - 'deactivate,resetFilter,companies,companiesDisabled,company,downloadCsvCompanies,removeCompany', + 'deactivate,resetFilter,tableSorting,companies,companiesDisabled,company,downloadCsvCompanies,' . + 'removeCompany', \In2code\Lux\Controller\GeneralController::class => 'information' ], [ @@ -92,7 +93,8 @@ function () { '', [ \In2code\Lux\Controller\LeadController::class => 'dashboard,list,detail,downloadCsv,remove,' . - 'deactivate,resetFilter,companies,companiesDisabled,company,downloadCsvCompanies,removeCompany', + 'deactivate,resetFilter,tableSorting,companies,companiesDisabled,company,downloadCsvCompanies,' . + 'removeCompany', \In2code\Lux\Controller\AnalysisController::class => 'dashboard,content,linkClicks,detailPage,detailDownload,resetFilter', \In2code\Lux\Controller\GeneralController::class => 'information' From f8aa86fd05600b5922b81b4cd03284fe9d34558d Mon Sep 17 00:00:00 2001 From: Alexander Kellner Date: Fri, 25 Oct 2024 09:03:59 +0200 Subject: [PATCH 5/6] [TASK] Release preparations --- .../Privacy/FingerprintsAndLocalStorage.md | 69 +++++++++++++++++++ Documentation/Privacy/Index.md | 1 + Documentation/Privacy/OptInAndOptOut.md | 2 + Documentation/Technical/Changelog/Index.md | 2 + Documentation/Technical/Installation/Index.md | 22 +++--- ext_emconf.php | 2 +- 6 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 Documentation/Privacy/FingerprintsAndLocalStorage.md diff --git a/Documentation/Privacy/FingerprintsAndLocalStorage.md b/Documentation/Privacy/FingerprintsAndLocalStorage.md new file mode 100644 index 00000000..00232061 --- /dev/null +++ b/Documentation/Privacy/FingerprintsAndLocalStorage.md @@ -0,0 +1,69 @@ +![LUX](/Documentation/Images/logo_claim.svg#gh-light-mode-only "LUX") +![LUX](/Documentation/Images/logo_claim_white.svg#gh-dark-mode-only "LUX") + +## Introduction + +Whenever a lead visits your website, we want to track which pages have been seen or which document were downloaded. +This makes it necessary to recognize the lead when leaving page a and entering page b or when the lead comes again on +another day. +To fulfill this requirement, there a basically two different possible technics available with LUX. + +### Fingerprint (recommended for B2B) + +Per default LUX runs in fingerprint mode and try to automatically recognize a visitor by its hardware combined with +his IP-address. Those values are hashed to one string (sha256) and cannot be reverted or splitted into its originally +parts. + +Values are: + +* userAgent +* webdriver +* language +* colorDepth +* deviceMemory +* hardwareConcurrency +* screenResolution and availableScreenResolution +* timezone and timezoneOffset +* sessionStorage and localStorage +* indexedDB and openDatabase +* addBehavior +* cpuClass +* platform +* plugins +* canvas +* webgl and webglVendorRenderer +* hasLiedLanguages and hasLiedResolution and hasLiedOs and hasLiedBrowser +* touchSupport +* fonts +* audio +* IP-address + +**Upside:** Fingerprint is calculated automatically and does not need to be stored anywhere on the device +(cookie or local storage). A tracking between different domains and page branches is possible +within the same TYPO3 instance. + +**Downside:** To calculate a fingerprint every page request needs 200-400ms on top (asynchronous). +Beside that multiple visitors with same hard- and software +are recognized as only one visitor, if they are using the same IP-address. +This is especially true for iPhones of the same version and generation. + +### LocalStorage (recommended for B2C) + +**Upside:** If you have a lot of mobile visitors on your website (e.g. if you own a b2c shop for a younger target +group), you may want to differ between your visitors. So you could go for LocalStorage. This is comparable to a cookie. +A random string will be saved on the visitor's device, which can be done very quickly. +You can also differ between multiple mobile visitors - even with same hardware and IP-address. + +**Downside:** You have to ask your visitor if you are allowed to store a random string the local storage of the device, +to identify your visitor. To meet GDPR rules, we would suggest you to set up a cookie banner. +In addition, a visitor of domain A is not automatically merged if he also visits domain B on the same TYPO3 instance +(every domain has its own local storage area. Of course if the user is identified on both domains, the profile will be +merged to only one). + +This can be turned on via TypoScript constants: + +``` +plugin.tx_lux.settings.identificationMethod = 2 +``` + +**Note:** Maybe you want to disable the "autoenable" functionality. See [OptIn and OptOut](OptInAndOptOut.md) diff --git a/Documentation/Privacy/Index.md b/Documentation/Privacy/Index.md index cf5d0b29..27460e8e 100644 --- a/Documentation/Privacy/Index.md +++ b/Documentation/Privacy/Index.md @@ -14,6 +14,7 @@ rules of GDPR (General Data Protection Regulation) / DSGVO (Datenschutzgrundvero * [Example privacy page content](PrivacyPage.md) * [All related to the visitor ip address](IpAddresses.md) +* [Fingerprints vs. local storage (cookie)](FingerprintsAndLocalStorage.md) * [All information about optin and optout](OptInAndOptOut.md) * [Privacy related commands](Commands.md) * [Do not track header in browser](DoNotTrack.md) diff --git a/Documentation/Privacy/OptInAndOptOut.md b/Documentation/Privacy/OptInAndOptOut.md index 40a13c00..ae55e218 100644 --- a/Documentation/Privacy/OptInAndOptOut.md +++ b/Documentation/Privacy/OptInAndOptOut.md @@ -90,3 +90,5 @@ will respect this setting of course! **Note:** While Firefox turns on the DNT by default for anonymous tabs, Chrome and Internet Explorer never turn this setting on by default. + +**Note:** Maybe you want to switch from fingerprint to local storage mode. See [OptIn and OptOut](FingerprintsAndLocalStorage.md) diff --git a/Documentation/Technical/Changelog/Index.md b/Documentation/Technical/Changelog/Index.md index f3cd4b4b..7fd14432 100644 --- a/Documentation/Technical/Changelog/Index.md +++ b/Documentation/Technical/Changelog/Index.md @@ -9,6 +9,7 @@ | Version | Date | State | TYPO3 | Description | |------------|------------|----------|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 37.0.0 !!! | 2024-10-25 | Feature | `11.5 + 12.4` | Use IP-address in fingerprint hash to get a more unique hash, add sorting for lead list | | 36.5.1 | 2024-10-17 | Bugfix | `11.5 + 12.4` | Prevent sql exception in MySQL (not MariaDB) when filtering for a category in lead list | | 36.5.0 | 2024-10-01 | Bugfix | `11.5 + 12.4` | Prevent exceptions when configuration is missing, fix typo in configuration, add mail provider to disallowed mail provider list | | 36.4.0 | 2024-09-16 | Feature | `11.5 + 12.4` | Add a Modern.js file to add frontend JS with a basic bot detection (this file is not yet added per default in TypoScript and only for testing reasons available at the moment) | @@ -302,6 +303,7 @@ Double check if you have cleared all caches after installing a new LUX version t | Version | Situation | Upgrade instructions | |--------------------------------|---------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| From former versions to 37.0.0 | IP-address will be used for creating fingerprint hashes | There is nothing to do for your, just a note that old fingerprints may not be recognized any more because we added IP-address to the fingerprint hash to be more unique now | | From former versions to 36.5.0 | Typo in extension configuration | Changed option from `enbaleExceptionLogging` to `enableExceptionLogging` if you turned on exception logging, you have to update your configuration | | From former versions to 35.0.0 | Multiclient usage on some records need some time to work | Nothing to do for you - just a note: Some records have to be extended with site information, but this can only be done with new records - not with existing (affected tables: Logs, Search, Fingerprint and some boxes on Lead Dashboard). To ensure that privacy is guaranteed, you need to remove all existing LUX data in a multiclient environment. | | From former versions to 35.0.0 | Define storage pid for editors (linklistener, shortener, utmgenerator) | Records of different tables (tx_lux_domain_model_linklistener, tx_luxenterprise_domain_model_shortener, tx_luxenterprise_domain_model_utmgenerator_uri) can be stored on different pids depending on the backend user - see [Editors configuration](../Editors/Index.md) for details. | diff --git a/Documentation/Technical/Installation/Index.md b/Documentation/Technical/Installation/Index.md index 34d7bc04..13ca11b3 100644 --- a/Documentation/Technical/Installation/Index.md +++ b/Documentation/Technical/Installation/Index.md @@ -161,29 +161,31 @@ localstorage mode. While a fingerprint can be calculated by hardware details aut similar to a cookie. We would also don't use `autoenable` if you want to go for local storage and ask your visitors for an opt-in. -###### Fingerprint for b2b +###### Fingerprint (recommended for B2B) **Upside:** Fingerprint is calculated automatically and does not need to be stored anywhere on the device (cookie or local storage). A tracking between different domains and page branches is possible within the same TYPO3 instance. -**Downside:** To calculate a fingerprint 200-400ms is needed. Beside that multiple visitors with same hard- and software -are recognized as only one visitor. This is especially true for iPhones of the same version and generation. +**Downside:** To calculate a fingerprint every page request needs 200-400ms on top (asynchronous). +Beside that multiple visitors with same hard- and software +are recognized as only one visitor, if they are using the same IP-address. +This is especially true for iPhones of the same version and generation. -###### LocalStorage for b2c +###### LocalStorage (recommended for B2C) -**Upside:** If you have a lot of iPhone visitors on your website (e.g. if you own a b2c shop for a younger target -group), you may want to differ between your visitors. So you could go for LocalStorage. -A random string is generated where fast and saved on the visitors device. You can also differ between multiple iPhone -visitors. +**Upside:** If you have a lot of mobile visitors on your website (e.g. if you own a b2c shop for a younger target +group), you may want to differ between your visitors. So you could go for LocalStorage. This is comparable to a cookie. +A random string will be saved on the visitor's device, which can be done very quickly. +You can also differ between multiple mobile visitors - even with same hardware and IP-address. **Downside:** You have to ask your visitor if you are allowed to store a random string the local storage of the device, to identify your visitor. To meet GDPR rules, we would suggest you to set up a cookie banner. -In addition a visitor of domain A is not automatically merged if he also visits domain B on the same TYPO3 instance +In addition, a visitor of domain A is not automatically merged if he also visits domain B on the same TYPO3 instance (every domain has its own local storage area. Of course if the user is identified on both domains, the profile will be merged to only one). -#### +#### TypoScript If you want to see in detail what kind of TypoScript will be included and how to overwrite some parts, look at [the Lux folder](../../../Configuration/TypoScript/Lux) diff --git a/ext_emconf.php b/ext_emconf.php index 530042b6..1ad1d623 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -4,7 +4,7 @@ 'description' => 'Living User Experience - LUX - the Marketing Automation tool for TYPO3. Turn your visitors to leads. Identification and profiling of your visitors within your TYPO3 website.', 'category' => 'plugin', - 'version' => '36.5.1', + 'version' => '37.0.0', 'author' => 'Alex Kellner', 'author_email' => 'alexander.kellner@in2code.de', 'author_company' => 'in2code.de', From 80ab446d60edfabdd5025be88dede39f5e576403 Mon Sep 17 00:00:00 2001 From: Alexander Kellner Date: Fri, 25 Oct 2024 09:24:33 +0200 Subject: [PATCH 6/6] [TASK] Small code cleanup to clarify which identificator length represents what type --- Classes/Domain/Factory/VisitorFactory.php | 4 ++-- Classes/Domain/Model/Fingerprint.php | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Classes/Domain/Factory/VisitorFactory.php b/Classes/Domain/Factory/VisitorFactory.php index 05de3bc1..9b6f76df 100644 --- a/Classes/Domain/Factory/VisitorFactory.php +++ b/Classes/Domain/Factory/VisitorFactory.php @@ -190,11 +190,11 @@ protected function getIpAddress(): string protected function checkIdentificator(string $identificator): void { - $length = [0, 32, 33]; + $length = [0, Fingerprint::IDENTIFICATOR_LENGTH_FINGERPRINT, Fingerprint::IDENTIFICATOR_LENGTH_STORAGE]; if (in_array(strlen($identificator), $length) === false) { throw new IdentificatorFormatException('Identificator is in wrong format: ' . $identificator, 1680203759); } - if (preg_replace('/[a-z0-9]{32,33}/', '', $identificator) !== '') { + if (preg_replace('/[a-z0-9]{' . Fingerprint::IDENTIFICATOR_LENGTH_FINGERPRINT . ',' . Fingerprint::IDENTIFICATOR_LENGTH_STORAGE . '}/', '', $identificator) !== '') { throw new IdentificatorFormatException('Identificator is in wrong format: ' . $identificator, 1680204272); } } diff --git a/Classes/Domain/Model/Fingerprint.php b/Classes/Domain/Model/Fingerprint.php index d7b8946f..2d17cef4 100644 --- a/Classes/Domain/Model/Fingerprint.php +++ b/Classes/Domain/Model/Fingerprint.php @@ -17,6 +17,9 @@ class Fingerprint extends AbstractModel public const TYPE_FINGERPRINT = 0; public const TYPE_COOKIE = 1; public const TYPE_STORAGE = 2; + public const IDENTIFICATOR_LENGTH_FINGERPRINT = 32; + public const IDENTIFICATOR_LENGTH_STORAGE = 33; + public const IDENTIFICATOR_LENGTH_FINGERPRINTWITHIPHASH = 64; protected string $value = ''; protected string $domain = ''; @@ -50,7 +53,7 @@ public function setValue(string $value): self if ($value === '') { throw new FingerprintMustNotBeEmptyException('Value is empty', 1585901797); } - if (strlen($value) === 33) { + if (strlen($value) === self::IDENTIFICATOR_LENGTH_STORAGE) { $this->setType(self::TYPE_STORAGE); $this->value = $value; } else {