Merge pull request #4768 from Icinga/fix/object-name-wildcard-filter

Change FilterMatch to FilterEqual class for single object filter on object name.
This commit is contained in:
Johannes Meyer 2022-05-12 16:39:31 +02:00 committed by GitHub
commit 0a41c52002
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 257 additions and 35 deletions

View File

@ -6,6 +6,8 @@ namespace Icinga\Data\Db;
use DateTime;
use DateTimeZone;
use Exception;
use Icinga\Data\Filter\FilterMatch;
use Icinga\Data\Filter\FilterMatchNot;
use Icinga\Data\Inspectable;
use Icinga\Data\Inspection;
use PDO;
@ -552,13 +554,13 @@ class DbConnection implements Selectable, Extensible, Updatable, Reducible, Insp
throw new ProgrammingError(
'Unable to render array expressions with operators other than equal or not equal'
);
} elseif ($sign === '=' && strpos($value, '*') !== false) {
} elseif ($filter instanceof FilterMatch && strpos($value, '*') !== false) {
if ($value === '*') {
return $column . ' IS NOT NULL';
}
return $column . ' LIKE ' . $this->dbAdapter->quote(preg_replace('~\*~', '%', $value));
} elseif ($sign === '!=' && strpos($value, '*') !== false) {
} elseif ($filter instanceof FilterMatchNot && strpos($value, '*') !== false) {
if ($value === '*') {
return $column . ' IS NULL';
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Controllers;
use Icinga\Data\Filter\FilterEqual;
use Icinga\Module\Monitoring\Backend;
use Icinga\Module\Monitoring\Controller;
use Icinga\Security\SecurityException;
@ -63,7 +64,7 @@ class ShowController extends Controller
'contact_notify_host_downtime',
));
$this->applyRestriction('monitoring/filter/objects', $query);
$query->where('contact_name', $contactName);
$query->whereEx(new FilterEqual('contact_name', '=', $contactName));
$contact = $query->getQuery()->fetchRow();
if ($contact) {

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -144,4 +145,14 @@ class CommentQuery extends IdoQuery
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -165,4 +166,14 @@ class CommentdeletionhistoryQuery extends IdoQuery
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -165,4 +166,14 @@ class CommenthistoryQuery extends IdoQuery
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -106,6 +107,16 @@ class ContactQuery extends IdoQuery
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
public function transformToUnion()
{
$this->contactQuery = $this->db->select();

View File

@ -4,6 +4,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Application\Config;
use Icinga\Data\Filter\FilterExpression;
class CustomvarQuery extends IdoQuery
{
@ -40,6 +41,20 @@ class CustomvarQuery extends IdoQuery
return $this;
}
public function whereEx(FilterExpression $ex)
{
$types = ['host' => 1, 'service' => 2, 'contact' => 10];
if ($ex->getColumn() === 'object_type') {
$ex = clone $ex;
$ex->setColumn('object_type_id');
$ex->setExpression($types[$ex->getExpression()]);
}
parent::whereEx($ex);
return $this;
}
protected function joinBaseTables()
{
if (version_compare($this->getIdoVersion(), '1.12.0', '<')) {

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -149,4 +150,14 @@ class DowntimeQuery extends IdoQuery
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -165,4 +166,14 @@ class DowntimeendhistoryQuery extends IdoQuery
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -165,4 +166,14 @@ class DowntimestarthistoryQuery extends IdoQuery
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -120,4 +121,14 @@ class EventhistoryQuery extends IdoQuery
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -165,4 +166,14 @@ class FlappingstarthistoryQuery extends IdoQuery
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -4,6 +4,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Filter\FilterExpression;
/**
* Query for host group summaries
@ -80,4 +81,11 @@ class HoststatussummaryQuery extends IdoQuery
$this->subSelect->where($condition, $value);
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->subSelect->whereEx($ex);
return $this;
}
}

View File

@ -783,6 +783,30 @@ abstract class IdoQuery extends DbQuery
return parent::where($col, $value);
}
/**
* Add a filter expression, with as less validation as possible
*
* @param FilterExpression $ex
*
* @internal If you use this outside the monitoring module, it's your fault if something breaks
* @return $this
*/
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
$col = $this->getMappedField($ex->getColumn());
if ($col === null) {
throw new IcingaException(
'No such field: %s',
$ex->getColumn()
);
}
parent::addFilter((clone $ex)->setColumn($col));
return $this;
}
/**
* Return true if an field contains an explicit timestamp
*

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -130,4 +131,14 @@ class NotificationQuery extends IdoQuery
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -128,4 +129,14 @@ class NotificationhistoryQuery extends IdoQuery
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -4,6 +4,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Filter\FilterExpression;
/**
* Query for service status summary
@ -93,4 +94,11 @@ class ServicestatussummaryQuery extends IdoQuery
$this->subSelect->where($condition, $value);
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->subSelect->whereEx($ex);
return $this;
}
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -165,4 +166,14 @@ class StatehistoryQuery extends IdoQuery
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Data\Filter\FilterExpression;
use Zend_Db_Expr;
use Zend_Db_Select;
use Icinga\Data\Filter\Filter;
@ -229,4 +230,14 @@ We have to find a better solution here.
}
return $this;
}
public function whereEx(FilterExpression $ex)
{
$this->requireColumn($ex->getColumn());
foreach ($this->subQueries as $sub) {
$sub->whereEx($ex);
}
return $this;
}
}

View File

@ -3,11 +3,11 @@
namespace Icinga\Module\Monitoring\DataView;
use Icinga\Data\Filter\FilterExpression;
use IteratorAggregate;
use Icinga\Application\Hook;
use Icinga\Data\ConnectionInterface;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Filter\FilterMatch;
use Icinga\Data\FilterColumns;
use Icinga\Data\PivotTable;
use Icinga\Data\QueryInterface;
@ -94,6 +94,20 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite
return $this;
}
/**
* Add a filter expression, with as less validation as possible
*
* @param FilterExpression $ex
*
* @internal If you use this outside the monitoring module, it's your fault if something breaks
* @return $this
*/
public function whereEx(FilterExpression $ex)
{
$this->query->whereEx($ex);
return $this;
}
public function dump()
{
if (! $this->isSorted) {
@ -442,7 +456,7 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite
*/
public function validateFilterColumns(Filter $filter)
{
if ($filter instanceof FilterMatch) {
if ($filter instanceof FilterExpression) {
if (! $this->isValidFilterTarget($filter->getColumn())) {
throw new QueryException(
mt('monitoring', 'The filter column "%s" is not allowed here.'),

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Object;
use Icinga\Data\Filter\FilterEqual;
use InvalidArgumentException;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
@ -142,7 +143,7 @@ class Host extends MonitoredObject
'instance_name'
);
return $this->backend->select()->from('hoststatus', $columns)
->where('host_name', $this->host);
->whereEx(new FilterEqual('host_name', '=', $this->host));
}
/**

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Object;
use Icinga\Data\Filter\FilterEqual;
use stdClass;
use InvalidArgumentException;
use Icinga\Authentication\Auth;
@ -334,14 +335,14 @@ abstract class MonitoredObject implements Filterable
));
if ($this->type === self::TYPE_SERVICE) {
$commentsView
->where('service_host_name', $this->host_name)
->where('service_description', $this->service_description);
->whereEx(new FilterEqual('service_host_name', '=', $this->host_name))
->whereEx(new FilterEqual('service_description', '=', $this->service_description));
} else {
$commentsView->where('host_name', $this->host_name);
$commentsView->whereEx(new FilterEqual('host_name', '=', $this->host_name));
}
$commentsView
->where('comment_type', array('ack', 'comment'))
->where('object_type', $this->type);
->whereEx(new FilterEqual('comment_type', '=', ['ack', 'comment']))
->whereEx(new FilterEqual('object_type', '=', $this->type));
$comments = $commentsView->fetchAll();
@ -385,10 +386,10 @@ abstract class MonitoredObject implements Filterable
));
if ($this->type === self::TYPE_SERVICE) {
$contactsGroups
->where('service_host_name', $this->host_name)
->where('service_description', $this->service_description);
->whereEx(new FilterEqual('service_host_name', '=', $this->host_name))
->whereEx(new FilterEqual('service_description', '=', $this->service_description));
} else {
$contactsGroups->where('host_name', $this->host_name);
$contactsGroups->whereEx(new FilterEqual('host_name', '=', $this->host_name));
}
$this->contactgroups = $contactsGroups;
return $this;
@ -409,10 +410,10 @@ abstract class MonitoredObject implements Filterable
));
if ($this->type === self::TYPE_SERVICE) {
$contacts
->where('service_host_name', $this->host_name)
->where('service_description', $this->service_description);
->whereEx(new FilterEqual('service_host_name', '=', $this->host_name))
->whereEx(new FilterEqual('service_description', '=', $this->service_description));
} else {
$contacts->where('host_name', $this->host_name);
$contacts->whereEx(new FilterEqual('host_name', '=', $this->host_name));
}
$this->contacts = $contacts;
return $this;
@ -534,8 +535,8 @@ abstract class MonitoredObject implements Filterable
'varvalue',
'is_json'
))
->where('object_type', static::TYPE_HOST)
->where('host_name', $this->host_name);
->whereEx(new FilterEqual('object_type', '=', static::TYPE_HOST))
->whereEx(new FilterEqual('host_name', '=', $this->host_name));
$this->hostVariables = [];
$this->customvarsWithOriginalNames = [];
@ -572,9 +573,9 @@ abstract class MonitoredObject implements Filterable
'varvalue',
'is_json'
))
->where('object_type', static::TYPE_SERVICE)
->where('host_name', $this->host_name)
->where('service_description', $this->service_description);
->whereEx(new FilterEqual('object_type', '=', static::TYPE_SERVICE))
->whereEx(new FilterEqual('host_name', '=', $this->host_name))
->whereEx(new FilterEqual('service_description', '=', $this->service_description));
$this->serviceVariables = [];
$this->customvarsWithOriginalNames = [];
@ -614,16 +615,16 @@ abstract class MonitoredObject implements Filterable
'scheduled_start' => 'downtime_scheduled_start',
'start' => 'downtime_start'
))
->where('object_type', $this->type)
->whereEx(new FilterEqual('object_type', '=', $this->type))
->order('downtime_is_in_effect', 'DESC')
->order('downtime_scheduled_start', 'ASC');
if ($this->type === self::TYPE_SERVICE) {
$downtimes
->where('service_host_name', $this->host_name)
->where('service_description', $this->service_description);
->whereEx(new FilterEqual('service_host_name', '=', $this->host_name))
->whereEx(new FilterEqual('service_description', '=', $this->service_description));
} else {
$downtimes
->where('host_name', $this->host_name);
->whereEx(new FilterEqual('host_name', '=', $this->host_name));
}
$this->downtimes = $downtimes->getQuery()->fetchAll();
return $this;
@ -653,11 +654,13 @@ abstract class MonitoredObject implements Filterable
'type'
)
)
->where('object_type', $this->type)
->where('host_name', $this->host_name);
->whereEx(new FilterEqual('object_type', '=', $this->type))
->whereEx(new FilterEqual('host_name', '=', $this->host_name));
if ($this->type === self::TYPE_SERVICE) {
$eventHistory->where('service_description', $this->service_description);
$eventHistory->whereEx(
new FilterEqual('service_description', '=', $this->service_description)
);
}
$this->eventhistory = $eventHistory;
@ -673,7 +676,7 @@ abstract class MonitoredObject implements Filterable
{
$this->hostgroups = $this->backend->select()
->from('hostgroup', array('hostgroup_name', 'hostgroup_alias'))
->where('host_name', $this->host_name)
->whereEx(new FilterEqual('host_name', '=', $this->host_name))
->applyFilter($this->getFilter())
->fetchPairs();
return $this;
@ -688,10 +691,12 @@ abstract class MonitoredObject implements Filterable
{
$query = $this->backend->select()
->from('servicegroup', array('servicegroup_name', 'servicegroup_alias'))
->where('host_name', $this->host_name);
->whereEx(new FilterEqual('host_name', '=', $this->host_name));
if ($this->type === self::TYPE_SERVICE) {
$query->where('service_description', $this->service_description);
$query->whereEx(
new FilterEqual('service_description', '=', $this->service_description)
);
}
$this->servicegroups = $query->applyFilter($this->getFilter())->fetchPairs();
@ -719,7 +724,7 @@ abstract class MonitoredObject implements Filterable
'services_unknown_handled',
'services_pending',
))
->where('service_host_name', $this->host_name)
->whereEx(new FilterEqual('service_host_name', '=', $this->host_name))
->applyFilter($this->getFilter())
->fetchRow();
return $this;

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Monitoring\Object;
use Icinga\Data\Filter\FilterEqual;
use InvalidArgumentException;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
@ -171,8 +172,8 @@ class Service extends MonitoredObject
'service_state',
'service_state_type'
))
->where('host_name', $this->host->getName())
->where('service_description', $this->service);
->whereEx(new FilterEqual('host_name', '=', $this->host->getName()))
->whereEx(new FilterEqual('service_description', '=', $this->service));
}
/**