Skip to content

Commit

Permalink
[!!!][TASK] Allow to disable siteHash chech by setting query.allowedS…
Browse files Browse the repository at this point in the history
…ites to *

This PR changes the behaviour of query.allowedSites the previos setting * behaviour was changed:

* Before: * was the same as __all, which means all sites in the system
* After: __all is still handled as __all sites in the system, but * now means every site (same as no check at all)

Migration: When you are using * for query.allowedSites change the setting to __all.

During the implementation the following things have been done

* Move SiteHash related logic from Util* to SiteHashService* and make them non static (See: http://wiki.c2.com/?AbuseOfUtilityClasses)
* Mark SiteHash related method in Util deprecated and announce removal
* Added Tests for Query and SiteHashService modifications
* When variants should be used accross multiple instances the variantId needs to be unique by system (not by site!). By now the variantId only contains (type/uid), to have a unique variantId accros multiple systems, a
system hash was added.

Impact:

* If you use * for query.allowedSites please use __all now unless you want to disable the siteHash check
* If you use variants, it is recommended to reindex your pages, since the hash was changed.

Fixes: #862
  • Loading branch information
timohund committed Jan 30, 2017
1 parent b9fc318 commit ab09be1
Show file tree
Hide file tree
Showing 18 changed files with 683 additions and 73 deletions.
129 changes: 129 additions & 0 deletions Classes/Domain/Site/SiteHashService.php
@@ -0,0 +1,129 @@
<?php

namespace ApacheSolrForTypo3\Solr\Domain\Site;

/***************************************************************
* Copyright notice
*
* (c) 2016 Timo Hund <timo.hund@dkd.de>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

use ApacheSolrForTypo3\Solr\Site;

/**
* SiteHashService
*
* Responsible to provide sitehash related service methods.
*
* @author Timo Hund <timo.hund@dkd.de>
*/
class SiteHashService
{

/**
* Resolves magic keywords in allowed sites configuration.
* Supported keywords:
* __solr_current_site - The domain of the site the query has been started from
* __current_site - Same as __solr_current_site
* __all - Adds all domains as allowed sites
* * - Means all sites are allowed, same as no siteHash
*
* @param integer $pageId A page ID that is then resolved to the site it belongs to
* @param string $allowedSitesConfiguration TypoScript setting for allowed sites
* @return string List of allowed sites/domains, magic keywords resolved
*/
public function getAllowedSitesForPageIdAndAllowedSitesConfiguration($pageId, $allowedSitesConfiguration)
{
if ($allowedSitesConfiguration == '__all') {
return $this->getDomainListOfAllSites();
} elseif ($allowedSitesConfiguration == '*') {
return '*';
} else {
return $this->getDomainByPageIdAndReplaceMarkers($pageId, $allowedSitesConfiguration);
}
}

/**
* Gets the site hash for a domain
*
* @param string $domain Domain to calculate the site hash for.
* @return string site hash for $domain
*/
public function getSiteHashForDomain($domain)
{
static $siteHashes = [];
if (isset($siteHashes[$domain])) {
return $siteHashes[$domain];
}

$siteHashes[$domain] = sha1($domain . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] . 'tx_solr');
return $siteHashes[$domain];
}


/**
* Returns a comma separated list of all domains from all sites.
*
* @return string
*/
protected function getDomainListOfAllSites()
{
$sites = $this->getAvailableSites();
$domains = [];
foreach ($sites as $site) {
$domains[] = $site->getDomain();
}

$allowedSites = implode(',', $domains);
return $allowedSites;
}

/**
* Retrieves the domain of the site that belongs to the passed pageId and replaces ther markers __solr_current_site
* and __current_site.
*
* @param $pageId
* @param $allowedSitesConfiguration
* @return mixed
*/
protected function getDomainByPageIdAndReplaceMarkers($pageId, $allowedSitesConfiguration)
{
$domainOfPage = $this->getSiteByPageId($pageId)->getDomain();
$allowedSites = str_replace(['__solr_current_site', '__current_site'], $domainOfPage, $allowedSitesConfiguration);
return $allowedSites;
}

/**
* @return Site[]
*/
protected function getAvailableSites()
{
return Site::getAvailableSites();
}

/**
* @param $pageId
* @return Site
*/
protected function getSiteByPageId($pageId)
{
return Site::getSiteByPageId($pageId);
}
}
95 changes: 95 additions & 0 deletions Classes/Domain/Variants/IdBuilder.php
@@ -0,0 +1,95 @@
<?php

namespace ApacheSolrForTypo3\Solr\Domain\Variants;

/***************************************************************
* Copyright notice
*
* (c) 2010-2017 Timo Hund <timo.hund@dkd.de
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* The variantId can be used to group documents by a variantId. This variantId is by default unique per system,
* and has the following syntax:
*
* <SystemHash>/type/uid
*
* A file from one system will get the same variantId, which could be useful for de-duplication.
* @author Timo Hund <timo.hund@dkd.de>
*/
class IdBuilder
{

/**
* This method is used to build a variantId.
*
* By default the variantId is used
* @param string $type
* @param integer $uid
* @return string
*/
public function buildFromTypeAndUid($type, $uid)
{
$systemHash = $this->getSystemHash();
$variantId = $systemHash . '/' . $type . '/' . $uid;

$variantId = $this->applyHook($variantId, $systemHash, $type, $uid);
return $variantId;
}

/**
* Applies configured postProcessing hooks to build a custom variantId.
*
* @param string $variantId
* @param string $systemHash
* @param string $type
* @param integer $uid
* @return string
*/
protected function applyHook($variantId, $systemHash, $type, $uid)
{
if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['modifyVariantId'])) {
return $variantId;
}

foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['modifyVariantId'] as $classReference) {
$variantIdModifier = GeneralUtility::getUserObj($classReference);
if ($variantIdModifier instanceof IdModifier) {
$variantId = $variantIdModifier->modifyVariantId($variantId, $systemHash, $type, $uid);
}
}

return $variantId;
}

/**
* Returns a system unique hash.
*
* @return string
*/
protected function getSystemHash()
{
$siteName = isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']) ? $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'] : 'none';
$systemKey = 'tx_solr' . $siteName;
return GeneralUtility::hmac($systemKey);
}
}
45 changes: 45 additions & 0 deletions Classes/Domain/Variants/IdModifier.php
@@ -0,0 +1,45 @@
<?php

namespace ApacheSolrForTypo3\Solr\Domain\Variants;

/***************************************************************
* Copyright notice
*
* (c) 2010-2017 Timo Hund <timo.hund@dkd.de
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/


/**
* An implementation of this class can be used to modify the variantId.
*
* @author Timo Hund <timo.hund@dkd.de>
*/
interface IdModifier
{

/**
* @param string $variantId
* @param string $systemHash
* @param string $type
* @param integer $uid
* @return string
*/
public function modifyVariantId($variantId, $systemHash, $type, $uid);
}
5 changes: 4 additions & 1 deletion Classes/Eid/SiteHash.php
Expand Up @@ -32,6 +32,7 @@
*/

use ApacheSolrForTypo3\Solr\Domain\Site\SiteHashService;
use ApacheSolrForTypo3\Solr\Util;
use TYPO3\CMS\Core\Utility\HttpUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
Expand All @@ -40,7 +41,9 @@
$returnData = '';

if (!empty($domain)) {
$siteHash = Util::getSiteHashForDomain($domain);
/** @var $siteHashService SiteHashService */
$siteHashService = GeneralUtility::makeInstance(SiteHashService::class);
$siteHash = $siteHashService->getSiteHashForDomain($domain);
$returnData = json_encode(['sitehash' => $siteHash]);
} else {
header(HttpUtility::HTTP_STATUS_400);
Expand Down
7 changes: 3 additions & 4 deletions Classes/Eid/Suggest.php
Expand Up @@ -23,6 +23,7 @@
***************************************************************/

use ApacheSolrForTypo3\Solr\ConnectionManager;
use ApacheSolrForTypo3\Solr\Domain\Site\SiteHashService;
use ApacheSolrForTypo3\Solr\Search;
use ApacheSolrForTypo3\Solr\SuggestQuery;
use ApacheSolrForTypo3\Solr\Util;
Expand Down Expand Up @@ -69,10 +70,8 @@
$q = GeneralUtility::_GET('q');
}
$allowedSitesConfig = $solrConfiguration->getObjectByPathOrDefault('plugin.tx_solr.search.query.', []);
$allowedSites = Util::resolveSiteHashAllowedSites(
$pageId,
$allowedSitesConfig['allowedSites']
);
$siteService = GeneralUtility::makeInstance(SiteHashService::class);
$allowedSites = $siteService->getAllowedSitesForPageIdAndAllowedSitesConfiguration($pageId, $allowedSitesConfig['allowedSites']);

$suggestQuery = GeneralUtility::makeInstance(SuggestQuery::class, $q);
$suggestQuery->setUserAccessGroups(explode(',', $GLOBALS['TSFE']->gr_list));
Expand Down
13 changes: 11 additions & 2 deletions Classes/IndexQueue/Indexer.php
Expand Up @@ -27,6 +27,7 @@
use Apache_Solr_Document;
use Apache_Solr_Response;
use ApacheSolrForTypo3\Solr\ConnectionManager;
use ApacheSolrForTypo3\Solr\Domain\Variants\IdBuilder;
use ApacheSolrForTypo3\Solr\FieldProcessor\Service;
use ApacheSolrForTypo3\Solr\NoSolrConnectionFoundException;
use ApacheSolrForTypo3\Solr\Site;
Expand Down Expand Up @@ -76,6 +77,11 @@ class Indexer extends AbstractIndexer
*/
protected $loggingEnabled = false;

/**
* @var IdBuilder
*/
protected $variantIdBuilder;

/**
* Cache of the sys_language_overlay information
*
Expand All @@ -87,11 +93,13 @@ class Indexer extends AbstractIndexer
* Constructor
*
* @param array $options array of indexer options
* @param IdBuilder $idBuilder
*/
public function __construct(array $options = [])
public function __construct(array $options = [], IdBuilder $idBuilder = null)
{
$this->options = $options;
$this->connectionManager = GeneralUtility::makeInstance(ConnectionManager::class);
$this->variantIdBuilder = is_null($idBuilder) ? GeneralUtility::makeInstance(IdBuilder::class) : $idBuilder;
}

/**
Expand Down Expand Up @@ -337,7 +345,8 @@ protected function getBaseDocument(Item $item, array $itemRecord)
$document->setField('pid', $itemRecord['pid']);

// variantId
$document->setField('variantId', $item->getType() . '/' . $itemRecord['uid']);
$variantId = $this->variantIdBuilder->buildFromTypeAndUid($item->getType(), $itemRecord['uid']);
$document->setField('variantId', $variantId);

// created, changed
if (!empty($GLOBALS['TCA'][$item->getType()]['ctrl']['crdate'])) {
Expand Down

0 comments on commit ab09be1

Please sign in to comment.