diff --git a/library/Icingadb/Authentication/ObjectAuthorization.php b/library/Icingadb/Authentication/ObjectAuthorization.php index 27f8dd3c..e2b14cf5 100644 --- a/library/Icingadb/Authentication/ObjectAuthorization.php +++ b/library/Icingadb/Authentication/ObjectAuthorization.php @@ -23,6 +23,13 @@ class ObjectAuthorization /** @var array */ protected static $knownGrants = []; + /** + * Caches already applied filters to an object + * + * @var array + */ + protected static $matchedFilters = []; + /** * Check whether the permission is granted on the object * @@ -88,6 +95,43 @@ class ObjectAuthorization return $self->checkGrants($permission, self::$knownGrants[$type][$uniqueId]); } + /** + * Check whether the given filter matches on the given object + * + * @param string $queryString + * @param Model $object + * + * @return bool + */ + public static function matchesOn(string $queryString, Model $object): bool + { + $self = new static(); + + $uniqueId = $object->{$object->getKeyName()}; + if (! isset(self::$matchedFilters[$queryString][$uniqueId])) { + $restriction = 'icingadb/filter/services'; + if ($object instanceof Host) { + $restriction = 'icingadb/filter/hosts'; + } + + $filter = $self->parseRestriction($queryString, $restriction); + + $query = $object::on($self->getDb()); + $query + ->filter($filter) + ->filter(Filter::equal($object->getKeyName(), $uniqueId)) + ->getSelectBase() + ->columns([new Expression('1')]); + + $result = $query->execute()->hasResult(); + self::$matchedFilters[$queryString][$uniqueId] = $result; + + return $result; + } + + return self::$matchedFilters[$queryString][$uniqueId]; + } + /** * Load all the user's roles that grant access to at least one object matching the filter * diff --git a/library/Icingadb/Common/Auth.php b/library/Icingadb/Common/Auth.php index be590c60..1e66dfe2 100644 --- a/library/Icingadb/Common/Auth.php +++ b/library/Icingadb/Common/Auth.php @@ -85,6 +85,19 @@ trait Auth return ObjectAuthorization::grantsOnType($permission, $type, $filter, $cache); } + /** + * Check whether the filter matches the given object + * + * @param string $queryString + * @param Model $object + * + * @return bool + */ + public function isMatchedOn(string $queryString, Model $object): bool + { + return ObjectAuthorization::matchesOn($queryString, $object); + } + /** * Apply Icinga DB Web's restrictions depending on what is queried * @@ -211,7 +224,7 @@ trait Auth $where = $queryClone->getSelectBase()->getWhere(); $values = []; - $rendered = $this->getDb()->getQueryBuilder()->buildCondition($where, $values); + $rendered = $query->getDb()->getQueryBuilder()->buildCondition($where, $values); $columns[$flatvaluePath] = new Expression( "CASE WHEN (" . $rendered . ") THEN (%s) ELSE '***' END", [$flatvalue],