FilterByNameRestriction: test and unify behavior

fixes #1392
This commit is contained in:
Thomas Gelf 2018-02-20 13:29:33 +01:00
parent 47c7c1b5f2
commit a515e02953
4 changed files with 108 additions and 58 deletions

View File

@ -39,7 +39,7 @@ class FilterByNameRestriction extends ObjectRestriction
return true;
}
return $this->prepareFilter()->matches([
return $this->getFilter()->matches([
(object) ['object_name' => $object->getObjectName()]
]);
}
@ -47,7 +47,11 @@ class FilterByNameRestriction extends ObjectRestriction
public function getFilter()
{
if ($this->filter === null) {
$this->filter = $this->prepareFilter();
$this->filter = MatchingFilter::forUser(
$this->auth->getUser(),
$this->name,
'object_name'
);
}
return $this->filter;
@ -57,26 +61,4 @@ class FilterByNameRestriction extends ObjectRestriction
{
FilterRenderer::applyToQuery($this->getFilter(), $query);
}
protected function prepareFilter()
{
$filter = Filter::matchAll();
foreach ($this->auth->getRestrictions($this->name) as $restriction) {
$filter->addFilter(Filter::expression('object_name', '=', $restriction));
}
return $filter;
}
protected function preparePrefixedFilter($prefix)
{
$filter = Filter::matchAll();
foreach ($this->auth->getRestrictions($this->name) as $restriction) {
$filter->addFilter(
Filter::expression("$prefix.object_name", '=', $restriction)
);
}
return $filter;
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace Icinga\Module\Director\Restriction;
use Icinga\Data\Filter\Filter;
use Icinga\User;
class MatchingFilter
{
public static function forPatterns(array $restrictions, $columnName)
{
$filters = [];
foreach ($restrictions as $restriction) {
foreach (preg_split('/\|/', $restriction) as $pattern) {
$filters[] = Filter::expression(
$columnName,
'=',
$pattern
);
}
}
if (count($filters) === 1) {
return $filters[0];
} else {
return Filter::matchAny($filters);
}
}
public static function forUser(
User $user,
$restrictionName,
$columnName
) {
return static::forPatterns(
$user->getRestrictions($restrictionName),
$columnName
);
}
}

View File

@ -2,60 +2,32 @@
namespace Icinga\Module\Director\Web\Form\Validate;
use Icinga\Data\Filter\FilterMatch;
use Icinga\Data\Filter\FilterOr;
use Icinga\Module\Director\Restriction\MatchingFilter;
use Zend_Validate_Abstract;
class NamePattern extends Zend_Validate_Abstract
{
const INVALID = 'intInvalid';
private $pattern;
private $filter;
public function __construct($pattern)
{
if (is_array($pattern) && count($pattern) === 1) {
$this->pattern = current($pattern);
} else {
$this->pattern = $pattern;
if (! is_array($pattern)) {
$pattern = [$pattern];
}
if (is_array($this->pattern)) {
$msg = implode(' | ', $this->pattern);
} else {
$msg = $this->pattern;
}
$this->filter = MatchingFilter::forPatterns($pattern, 'value');
$this->_messageTemplates[self::INVALID] = sprintf(
'Does not match %s',
$msg
(string) $this->filter
);
}
protected function matches($value)
{
if ($this->filter === null) {
if (is_array($this->pattern)) {
$this->filter = new FilterOr();
foreach ($this->pattern as $pattern) {
$filter = new FilterMatch('prop', '=', $pattern);
$filter->setCaseSensitive(false);
$this->filter->addFilter($filter);
}
} else {
$this->filter = new FilterMatch('prop', '=', $this->pattern);
$this->filter->setCaseSensitive(false);
}
}
return $this->filter->matches($value);
}
public function isValid($value)
{
if ($this->matches((object) ['prop' => $value])) {
if ($this->filter->matches((object) ['value' => $value])) {
return true;
} else {
$this->_error(self::INVALID, $value);

View File

@ -0,0 +1,56 @@
<?php
namespace Tests\Icinga\Module\Director\Restriction;
use Icinga\Module\Director\Restriction\MatchingFilter;
use Icinga\Module\Director\Test\BaseTestCase;
use Icinga\User;
class MatchingFilterTest extends BaseTestCase
{
public function testUserWithNoRestrictionHasNoFilter()
{
$user = new User('dummy');
$this->assertEquals(
'',
(string) MatchingFilter::forUser($user, 'some/name', 'prop')
);
}
public function testSimpleRestrictionRendersCorrectly()
{
$this->assertEquals(
'prop = a*',
(string) MatchingFilter::forPatterns(['a*'], 'prop')
);
}
public function testMultipleRestrictionsAreCombinedWithOr()
{
$this->assertEquals(
'prop = a* | prop = *b',
(string) MatchingFilter::forPatterns(['a*', '*b'], 'prop')
);
}
public function testUserWithMultipleRestrictionsWorksFine()
{
$user = new User('dummy');
$user->setRestrictions([
'some/name' => ['a*', '*b'],
'some/thing' => ['else']
]);
$this->assertEquals(
'prop = a* | prop = *b',
(string) MatchingFilter::forUser($user, 'some/name', 'prop')
);
}
public function testSingleRestrictionAllowsForPipes()
{
$this->assertEquals(
'prop = a* | prop = *b',
(string) MatchingFilter::forPatterns(['a*|*b'], 'prop')
);
}
}