mirror of
https://github.com/Codappix/search_core.git
synced 2024-12-23 15:16:09 +01:00
[FEATURE] Add Frontend User access query for secure search on elastic index
This commit is contained in:
parent
404f49aad2
commit
7566bf93d5
11 changed files with 134 additions and 47 deletions
|
@ -63,7 +63,6 @@ class IndexCommandController extends CommandController
|
|||
$this->outputLine('No indexer found for: ' . $value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,5 +27,4 @@ use TYPO3\CMS\Core\TypoScript\TypoScriptService as CoreTypoScriptService;
|
|||
*/
|
||||
class TypoScriptService extends CoreTypoScriptService implements TypoScriptServiceInterface
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -27,5 +27,4 @@ use TYPO3\CMS\Extbase\Service\TypoScriptService as CoreTypoScriptService;
|
|||
*/
|
||||
class TypoScriptService76 extends CoreTypoScriptService implements TypoScriptServiceInterface
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ use Codappix\SearchCore\Domain\Search\QueryFactory;
|
|||
use Elastica\Query;
|
||||
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
|
||||
|
||||
/**
|
||||
* Outer wrapper to elasticsearch.
|
||||
|
|
|
@ -178,7 +178,7 @@ class TcaTableService implements TcaTableServiceInterface
|
|||
true
|
||||
);
|
||||
// Always fallback on public visibility when configured
|
||||
$record[$this->tca['ctrl']['enablecolumns']['fe_group']] = !empty($groups) ? $groups : [0];
|
||||
$record['search_access'] = !empty($groups) ? $groups : [0];
|
||||
}
|
||||
|
||||
if (!isset($record['search_page_typolink'])) {
|
||||
|
|
|
@ -5,7 +5,6 @@ namespace Codappix\SearchCore\Domain\Search;
|
|||
use Codappix\SearchCore\Connection\SearchRequestInterface;
|
||||
use Codappix\SearchCore\Connection\SearchResultInterface;
|
||||
use TYPO3\CMS\Core\SingletonInterface;
|
||||
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
|
||||
|
||||
/**
|
||||
* Service: Cached Search
|
||||
|
@ -13,7 +12,11 @@ use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
|
|||
*/
|
||||
class CachedSearchService implements SingletonInterface
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $results = [];
|
||||
|
||||
/**
|
||||
* @var SearchService
|
||||
*/
|
||||
|
@ -51,5 +54,4 @@ class CachedSearchService implements SingletonInterface
|
|||
}
|
||||
return sha1(serialize($searchRequest));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
6
Classes/Domain/Search/MissingAttributeException.php
Normal file
6
Classes/Domain/Search/MissingAttributeException.php
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
namespace Codappix\SearchCore\Domain\Search;
|
||||
|
||||
class MissingAttributeException extends \InvalidArgumentException
|
||||
{
|
||||
}
|
|
@ -84,7 +84,7 @@ class QueryFactory
|
|||
$this->addSize($searchRequest, $query);
|
||||
$this->addSearch($searchRequest, $query);
|
||||
$this->addBoosts($searchRequest, $query);
|
||||
$this->addFilter($searchRequest, $query);
|
||||
$this->addFilters($searchRequest, $query);
|
||||
$this->addFacets($searchRequest, $query);
|
||||
$this->addFields($searchRequest, $query);
|
||||
$this->addSort($searchRequest, $query);
|
||||
|
@ -249,67 +249,76 @@ class QueryFactory
|
|||
* @param array $query
|
||||
* @return void
|
||||
*/
|
||||
protected function addFilter(SearchRequestInterface $searchRequest, array &$query)
|
||||
protected function addFilters(SearchRequestInterface $searchRequest, array &$query)
|
||||
{
|
||||
if (!$searchRequest->hasFilter()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$filter = [];
|
||||
foreach ($searchRequest->getFilter() as $name => $value) {
|
||||
$filter[] = $this->buildFilter(
|
||||
$this->addFilter(
|
||||
$name,
|
||||
$value,
|
||||
$this->configuration->getIfExists('searching.mapping.filter.' . $name) ?: []
|
||||
$this->configuration->getIfExists('searching.mapping.filter.' . $name) ?: [],
|
||||
$query
|
||||
);
|
||||
}
|
||||
|
||||
ArrayUtility::mergeRecursiveWithOverrule($query, [
|
||||
'query' => [
|
||||
'bool' => [
|
||||
'filter' => $filter,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param $value
|
||||
* @param string $value
|
||||
* @param array $config
|
||||
* @param array $query
|
||||
* @return array
|
||||
*/
|
||||
protected function buildFilter(string $name, $value, array $config): array
|
||||
protected function addFilter(string $name, $value, array $config, array &$query): array
|
||||
{
|
||||
if ($config === []) {
|
||||
return [
|
||||
'term' => [
|
||||
$name => $value,
|
||||
],
|
||||
];
|
||||
}
|
||||
if (!empty($config)) {
|
||||
if ($config['type'] && $config['type'] === 'user') {
|
||||
if (!isset($config['userFunc'])) {
|
||||
throw new MissingAttributeException('No userFunc configured for filter type: user', 1539876182018);
|
||||
}
|
||||
|
||||
$filter = [];
|
||||
$parameters = [
|
||||
'config' => $config,
|
||||
'value' => $value,
|
||||
'query' => &$query,
|
||||
];
|
||||
GeneralUtility::callUserFunction($config['userFunc'], $parameters, $this);
|
||||
} else {
|
||||
$filter = [];
|
||||
if (isset($config['fields'])) {
|
||||
foreach ($config['fields'] as $elasticField => $inputField) {
|
||||
$filter[$elasticField] = $value[$inputField];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config['fields'])) {
|
||||
foreach ($config['fields'] as $elasticField => $inputField) {
|
||||
$filter[$elasticField] = $value[$inputField];
|
||||
if (isset($config['raw'])) {
|
||||
$filter = array_merge($config['raw'], $filter);
|
||||
}
|
||||
|
||||
if ($config['type'] === 'range') {
|
||||
$query['query']['bool']['filter'][] = [
|
||||
'range' => [
|
||||
$config['field'] => $filter
|
||||
]
|
||||
];
|
||||
} else {
|
||||
$query['query']['bool']['filter'][] = [
|
||||
$config['field'] => $filter
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config['raw'])) {
|
||||
$filter = array_merge($config['raw'], $filter);
|
||||
}
|
||||
|
||||
if ($config['type'] === 'range') {
|
||||
return [
|
||||
'range' => [
|
||||
$config['field'] => $filter,
|
||||
],
|
||||
} else {
|
||||
$query['query']['bool']['filter'][] = [
|
||||
'term' => [
|
||||
$name => $value
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
return [$config['field'] => $filter];
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
63
Classes/Hook/Filter/FrontendUserAccessFilter.php
Normal file
63
Classes/Hook/Filter/FrontendUserAccessFilter.php
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace Codappix\SearchCore\Hook\Filter;
|
||||
|
||||
use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
|
||||
|
||||
/**
|
||||
* Filter: FrontendUserAccess
|
||||
* @package Codappix\SearchCore\Hook\Filter
|
||||
*/
|
||||
class FrontendUserAccessFilter
|
||||
{
|
||||
/**
|
||||
* @param array $parameters
|
||||
* @return void
|
||||
*/
|
||||
public function generate($parameters)
|
||||
{
|
||||
$this->appendQueryWithAccessFilter($parameters['query'], $parameters['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $query
|
||||
* @param string $field
|
||||
*/
|
||||
protected function appendQueryWithAccessFilter(array &$query, string $field)
|
||||
{
|
||||
$query['query']['bool']['must'][] = [
|
||||
'terms' => [$field => $this->getUserGroups()]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getUserGroups(): array
|
||||
{
|
||||
$feUser = $this->getFrontendUserAuthentication();
|
||||
if ($feUser !== null) {
|
||||
// If groups is not yet rendered, make sure the group data are fetched
|
||||
if (!isset($feUser->groupData['uid'])) {
|
||||
$feUser->fetchGroupData();
|
||||
}
|
||||
|
||||
$values = $feUser->groupData['uid'];
|
||||
if (!empty($values)) {
|
||||
// Add public content with values
|
||||
return array_merge([0], $values);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback on public content
|
||||
return [0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FrontendUserAuthentication
|
||||
*/
|
||||
protected function getFrontendUserAuthentication()
|
||||
{
|
||||
return $GLOBALS['TSFE']->fe_user ?? null;
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
|
||||
|
||||
call_user_func(function ($extension, $table) {
|
||||
|
||||
$plugin = ExtensionUtility::registerPlugin(
|
||||
'Codappix.' . $extension,
|
||||
'Results',
|
||||
|
@ -21,5 +20,4 @@ call_user_func(function ($extension, $table) {
|
|||
) ?? 'searchcore_form';
|
||||
|
||||
$GLOBALS['TCA'][$table]['types']['list']['subtypes_excludelist'][$plugin] = 'recursive,pages';
|
||||
|
||||
}, 'search_core', 'tt_content');
|
||||
|
|
|
@ -39,6 +39,19 @@ plugin.tx_searchcore {
|
|||
# Default query fields (leave empty for all)
|
||||
query =
|
||||
}
|
||||
|
||||
filter {
|
||||
frontendUserAccess = search_access
|
||||
}
|
||||
|
||||
mapping {
|
||||
filter {
|
||||
frontendUserAccess {
|
||||
type = user
|
||||
userFunc = Codappix\SearchCore\Hook\Filter\FrontendUserAccessFilter->generate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue