diff --git a/lib/Adapter.php b/lib/Adapter.php index dada7c7a38de90049a5c1f030738078e540f58dc..a8c628588eaac673a19d8db7031511a8482c8d73 100644 --- a/lib/Adapter.php +++ b/lib/Adapter.php @@ -265,21 +265,25 @@ abstract class Adapter abstract public function isUserInVo($user, $voShortName); /** - * @param int $entityId entityId - * @param array $userGroups of groups where user belongs to + * @param string $spEntityId entityId + * @param array $userGroups of groups where user belongs to * @param string $entityIdAttr entity id attribute * * @return array of resource capabilities */ - abstract public function getResourceCapabilities($entityId, $userGroups, $entityIdAttr); + abstract public function getResourceCapabilities( + string $spEntityId, + array $userGroups, + string $entityIdAttr + ): array; /** - * @param int $entityId entityId + * @param string $spEntityId entityId * @param string $entityIdAttr entity id attribute * * @return array of facility capabilities */ - abstract public function getFacilityCapabilities($entityId, $entityIdAttr); + abstract public function getFacilityCapabilities(string $spEntityId, string $entityIdAttr): array; /** * @param HasId[] $entities diff --git a/lib/AdapterLdap.php b/lib/AdapterLdap.php index 486c60a49000e5011c3a21625b19679a54068eab..b78b193ef6c8035bbd690ea14cf42a165f1e02d0 100644 --- a/lib/AdapterLdap.php +++ b/lib/AdapterLdap.php @@ -56,6 +56,8 @@ class AdapterLdap extends Adapter public const TYPE = 'type'; + private const DEBUG_PREFIX = 'perun:AdapterLdap - '; + protected $connector; private $ldapBase; @@ -563,67 +565,121 @@ class AdapterLdap extends Adapter return $this->getMemberStatusByUserAndVo($user, $vo) === Member::VALID; } - public function getResourceCapabilities($entityId, $userGroups, $entityIdAttr = 'perunFacilityAttr_entityID') + public function getResourceCapabilities(string $spEntityId, array $userGroups, string $entityIdAttr): array { - $facility = $this->getFacilityByEntityId($entityId, $entityIdAttr); - - if ($facility === null) { + if (empty($spEntityId)) { + Logger::warning( + self::DEBUG_PREFIX . 'getResourceCapabilities - empty spEntityId provided, returning empty list of resource capabilities.' + ); + return []; + } elseif (empty($userGroups)) { + Logger::warning( + self::DEBUG_PREFIX . 'getResourceCapabilities - empty userGroups provided, returning empty list of resource capabilities.' + ); + return []; + } + $facility = $this->getFacilityByEntityId($spEntityId, $entityIdAttr); + if ($facility === null || $facility->getId() === null) { + Logger::warning( + self::DEBUG_PREFIX . sprintf( + 'getResourceCapabilities - no facility (or facility with null ID) found four EntityID \'%s\', returning empty list of resource capabilities.', + $spEntityId + ) + ); return []; } - - $facilityId = $facility->getId(); $resources = $this->connector->searchForEntities( $this->ldapBase, - '(&(objectClass=perunResource)(perunFacilityDn=perunFacilityId=' . $facilityId . ',' + '(&(objectClass=perunResource)(perunFacilityDn=perunFacilityId=' . $facility->getId() . ',' . $this->ldapBase . '))', [self::CAPABILITIES, self::ASSIGNED_GROUP_ID] ); + if (empty($resources)) { + Logger::debug( + self::DEBUG_PREFIX . sprintf( + 'getResourceCapabilities - no resources found for SP with EntityID \'%s\', returning empty list of resource capabilities.', + $spEntityId + ) + ); + return []; + } $userGroupsIds = []; foreach ($userGroups as $userGroup) { - array_push($userGroupsIds, $userGroup->getId()); + if ($userGroup === null || $userGroup->getId() === null) { + Logger::debug( + self::DEBUG_PREFIX . 'getResourceCapabilities - skipping user group due to null group or null group ID.' + ); + continue; + } + $userGroupsIds[] = $userGroup->getId(); } - $resourceCapabilities = []; + $capabilities = []; foreach ($resources as $resource) { - if ( - !array_key_exists(self::ASSIGNED_GROUP_ID, $resource) || - !array_key_exists(self::CAPABILITIES, $resource) - ) { + if (($resource[self::ASSIGNED_GROUP_ID] ?? null) === null) { + Logger::debug( + self::DEBUG_PREFIX . 'getResourceCapabilities - skipping resource due to null resource or null assigned group ID.' + ); + continue; + } elseif (empty($resource[self::CAPABILITIES])) { + Logger::debug( + self::DEBUG_PREFIX . 'getResourceCapabilities - skipping resource due to empty capabilities.' + ); continue; } + foreach ($resource[self::ASSIGNED_GROUP_ID] as $groupId) { if (in_array($groupId, $userGroupsIds, true)) { - foreach ($resource[self::CAPABILITIES] as $resourceCapability) { - array_push($resourceCapabilities, $resourceCapability); - } + $capabilities = array_merge($capabilities, $resources[self::CAPABILITIES]); break; } } } - return $resourceCapabilities; + return array_values(array_unique($capabilities)); } - public function getFacilityCapabilities($entityId, $entityIdAttr = 'perunFacilityAttr_entityID') + public function getFacilityCapabilities(string $spEntityId, string $entityIdAttr): array { - if (empty($entityId)) { + if (empty($spEntityId)) { + Logger::warning( + self::DEBUG_PREFIX . 'getFacilityCapabilities - empty spEntityId provided, returning empty list of facility capabilities.' + ); return []; } + $attrName = AttributeUtils::getLdapAttrName($entityIdAttr); + if (empty($attrName)) { + $attrName = 'entityID'; + Logger::warning( + self::DEBUG_PREFIX . + sprintf( + 'getFacilityCapabilities - no LDAP mapping found for attribute \'%s\', using \'%s\'as fallback value', + $entityIdAttr, + $attrName + ) + ); + } $facilityCapabilities = $this->connector->searchForEntity( $this->ldapBase, - '(&(objectClass=perunFacility)(' . $attrName . '=' . $entityId . '))', + '(&(objectClass=perunFacility)(' . $attrName . '=' . $spEntityId . '))', [self::CAPABILITIES] ); - if (empty($facilityCapabilities)) { + if (empty($facilityCapabilities[self::CAPABILITIES])) { + Logger::debug( + self::DEBUG_PREFIX . 'getFacilityCapabilities - empty or missing value of facility capabilities attribute detected, returning empty list of facility capabilities.' + ); return []; } + if (!is_array($facilityCapabilities[self::CAPABILITIES])) { + $facilityCapabilities[self::CAPABILITIES] = [$facilityCapabilities[self::CAPABILITIES]]; + } - return $facilityCapabilities['capabilities']; + return array_values(array_unique($facilityCapabilities[self::CAPABILITIES])); } private function mapUser($user) diff --git a/lib/AdapterRpc.php b/lib/AdapterRpc.php index 7e9132d57d69db2315c46dc04aea49b2b7c8fa00..5b56259e71c7ebc5f2c00e7a1cb3fde0dc1489cb 100644 --- a/lib/AdapterRpc.php +++ b/lib/AdapterRpc.php @@ -42,6 +42,8 @@ class AdapterRpc extends Adapter public const TYPE_MAP = 'java.util.LinkedHashMap'; + private const DEBUG_PREFIX = 'perun:AdapterRpc - '; + protected $connector; private $rpcUrl; @@ -649,69 +651,134 @@ class AdapterRpc extends Adapter return $member->getStatus(); } - public function getResourceCapabilities($entityId, $userGroups, $entityIdAttr = 'perunFacilityAttr_entityID') + public function getResourceCapabilities(string $spEntityId, array $userGroups, string $entityIdAttr): array { - $facility = $this->getFacilityByEntityId($entityId, $entityIdAttr); + if (empty($spEntityId)) { + Logger::warning( + self::DEBUG_PREFIX . 'getResourceCapabilities - empty spEntityId provided, returning empty list of resource capabilities.' + ); + return []; + } elseif (empty($userGroups)) { + Logger::warning( + self::DEBUG_PREFIX . 'getResourceCapabilities - empty userGroups provided, returning empty list of resource capabilities.' + ); + return []; + } - if ($facility === null) { + $facility = $this->getFacilityByEntityId($spEntityId, $entityIdAttr); + if ($facility === null || $facility->getId() === null) { + Logger::warning( + self::DEBUG_PREFIX . sprintf( + 'getResourceCapabilities - no facility (or facility with null ID) found four EntityID \'%s\', returning empty list of resource capabilities.', + $spEntityId + ) + ); return []; } - $resources = $this->connector->get('facilitiesManager', 'getAssignedResources', [ - 'facility' => $facility->getId(), - ]); + $resources = $this->getAssignedResources($facility->getId()); + if (empty($resources)) { + Logger::debug( + self::DEBUG_PREFIX . sprintf( + 'getResourceCapabilities - no resources found for SP with EntityID \'%s\', returning empty list of resource capabilities.', + $spEntityId + ) + ); + return []; + } $userGroupsIds = []; foreach ($userGroups as $userGroup) { - array_push($userGroupsIds, $userGroup->getId()); + if ($userGroup === null || $userGroup->getId() === null) { + Logger::debug( + self::DEBUG_PREFIX . 'getResourceCapabilities - skipping user group due to null group or null group ID.' + ); + continue; + } + $userGroupsIds[] = $userGroup->getId(); } $capabilities = []; foreach ($resources as $resource) { - $resourceGroups = $this->connector->get('resourcesManager', 'getAssignedGroups', [ + if ($resource === null || $resource->getId() === null) { + Logger::debug( + self::DEBUG_PREFIX . 'getResourceCapabilities - skipping resource due to null resource or null resource ID.' + ); + continue; + } + $resourceCapabilities = $this->connector->get('attributesManager', 'getAttribute', [ 'resource' => $resource['id'], + 'attributeName' => 'urn:perun:resource:attribute-def:def:capabilities', ]); - $resourceCapabilities = $this->connector->get('attributesManager', 'getAttribute', [ + if (empty($resourceCapabilities['value'])) { + Logger::debug( + self::DEBUG_PREFIX . 'getResourceCapabilities - skipping resource due to empty capabilities.' + ); + continue; + } + $resourceCapabilities = $resourceCapabilities['value']; + + $resourceGroups = $this->connector->get('resourcesManager', 'getAssignedGroups', [ 'resource' => $resource['id'], - 'attributeName' => 'urn:perun:resource:attribute-def:def:capabilities', - ])['value']; + ]); - if ($resourceCapabilities === null) { + if (empty($resourceGroups)) { continue; } foreach ($resourceGroups as $resourceGroup) { + if (($resourceGroup['id'] ?? null) === null) { + Logger::debug( + self::DEBUG_PREFIX . 'getResourceCapabilities - skipping resource group due to missing group ID.' + ); + continue; + } if (in_array($resourceGroup['id'], $userGroupsIds, true)) { - foreach ($resourceCapabilities as $capability) { - array_push($capabilities, $capability); - } + $capabilities = array_merge($capabilities, $resourceCapabilities); break; } } } - return $capabilities; + return array_values(array_unique($capabilities)); } - public function getFacilityCapabilities($entityId, $entityIdAttr = 'perunFacilityAttr_entityID') + public function getFacilityCapabilities(string $spEntityId, string $entityIdAttr): array { - $facility = $this->getFacilityByEntityId($entityId, $entityIdAttr); + if (empty($spEntityId)) { + Logger::warning( + self::DEBUG_PREFIX . 'getFacilityCapabilities - empty spEntityId provided, returning empty list of facility capabilities.' + ); + return []; + } + $facility = $this->getFacilityByEntityId($spEntityId, $entityIdAttr); if ($facility === null) { + Logger::warning( + self::DEBUG_PREFIX . sprintf( + 'getFacilityCapabilities - no facility found four EntityID \'%s\', returning empty list of facility capabilities.', + $spEntityId + ) + ); return []; } $facilityCapabilities = $this->connector->get('attributesManager', 'getAttribute', [ 'facility' => $facility->getId(), 'attributeName' => 'urn:perun:facility:attribute-def:def:capabilities', - ])['value']; + ]); - if (empty($facilityCapabilities)) { - $facilityCapabilities = []; + if (empty($facilityCapabilities['value'])) { + Logger::debug( + self::DEBUG_PREFIX . 'getFacilityCapabilities - empty or missing value of facility capabilities attribute detected, returning empty list of facility capabilities.' + ); + return []; } - - return $facilityCapabilities; + if (!is_array($facilityCapabilities['value'])) { + $facilityCapabilities['value'] = [$facilityCapabilities['value']]; + } + return array_values(array_unique($facilityCapabilities['value'])); } public function getAttributesDefinition() @@ -749,4 +816,15 @@ class AdapterRpc extends Adapter return $attributes; } + + private function getAssignedResources(int $facilityId): array + { + $perunResources = $this->connector->get('facilitiesManager', 'getAssignedResources', [ + 'facility' => $facilityId, + ]); + + return empty($perunResources) ? [] : array_map(function ($resource) { + return new Resource($resource['id'], $resource['voId'], $resource['facilityId'], $resource['name']); + }, array_filter($perunResources)); + } }