From 44aaf3150f93e66e3d750e83ce1d5773ad7bed94 Mon Sep 17 00:00:00 2001 From: Tobias Gross-Vogt Date: Wed, 3 Apr 2024 10:12:14 +0200 Subject: [PATCH] remove LDAPApi and use people API instead: filter by local data attribute almaId --- composer.json | 1 - composer.lock | 502 +----------------- src/DependencyInjection/Configuration.php | 22 +- .../DbpRelaySublibraryExtension.php | 4 - src/Resources/config/services.yaml | 11 - src/Service/AlmaApi.php | 99 ++-- src/Service/HealthCheck.php | 7 +- src/Service/LDAPApi.php | 135 ----- tests/AlmaApiTest.php | 8 +- tests/Kernel.php | 6 - 10 files changed, 50 insertions(+), 745 deletions(-) delete mode 100644 src/Service/LDAPApi.php diff --git a/composer.json b/composer.json index 8f00949..a838d4a 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,6 @@ "api-platform/core": "^2.7.11", "dbp/relay-base-person-bundle": "^0.2.26", "dbp/relay-core-bundle": "^0.1.148", - "directorytree/ldaprecord": "^2.20", "doctrine/collections": "^1.6", "doctrine/common": "^3.1", "guzzlehttp/guzzle": "^7.0", diff --git a/composer.lock b/composer.lock index 823dadd..1abda68 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "128b58dc7274ee6958a0a0ed45ad9a6a", + "content-hash": "4add12593d94ce2f6324b24aea83e10c", "packages": [ { "name": "api-platform/core", @@ -169,75 +169,6 @@ }, "time": "2024-03-19T07:17:43+00:00" }, - { - "name": "carbonphp/carbon-doctrine-types", - "version": "3.2.0", - "source": { - "type": "git", - "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", - "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/18ba5ddfec8976260ead6e866180bd5d2f71aa1d", - "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "conflict": { - "doctrine/dbal": "<4.0.0 || >=5.0.0" - }, - "require-dev": { - "doctrine/dbal": "^4.0.0", - "nesbot/carbon": "^2.71.0 || ^3.0.0", - "phpunit/phpunit": "^10.3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "KyleKatarn", - "email": "kylekatarnls@gmail.com" - } - ], - "description": "Types to use Carbon in Doctrine", - "keywords": [ - "carbon", - "date", - "datetime", - "doctrine", - "time" - ], - "support": { - "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", - "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" - }, - "funding": [ - { - "url": "https://github.com/kylekatarnls", - "type": "github" - }, - { - "url": "https://opencollective.com/Carbon", - "type": "open_collective" - }, - { - "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", - "type": "tidelift" - } - ], - "time": "2024-02-09T16:56:22+00:00" - }, { "name": "dbp/relay-base-person-bundle", "version": "v0.2.26", @@ -388,80 +319,6 @@ }, "time": "2024-03-28T12:00:03+00:00" }, - { - "name": "directorytree/ldaprecord", - "version": "v2.20.5", - "source": { - "type": "git", - "url": "https://github.com/DirectoryTree/LdapRecord.git", - "reference": "5bd0a5a9d257cf1049ae83055dbba4c3479ddf16" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/5bd0a5a9d257cf1049ae83055dbba4c3479ddf16", - "reference": "5bd0a5a9d257cf1049ae83055dbba4c3479ddf16", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-ldap": "*", - "illuminate/contracts": "^5.0|^6.0|^7.0|^8.0|^9.0|^10.0", - "nesbot/carbon": "^1.0|^2.0", - "php": ">=7.3", - "psr/log": "^1.0|^2.0|^3.0", - "psr/simple-cache": "^1.0|^2.0", - "symfony/polyfill-php80": "^1.25", - "tightenco/collect": "^5.6|^6.0|^7.0|^8.0|^9.0" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^9.0", - "spatie/ray": "^1.24" - }, - "type": "library", - "autoload": { - "psr-4": { - "LdapRecord\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Steve Bauman", - "email": "steven_bauman@outlook.com", - "role": "Developer" - } - ], - "description": "A fully-featured LDAP ORM.", - "homepage": "https://www.ldaprecord.com", - "keywords": [ - "active directory", - "ad", - "adLDAP", - "adldap2", - "directory", - "ldap", - "ldaprecord", - "orm", - "windows" - ], - "support": { - "docs": "https://ldaprecord.com", - "email": "steven_bauman@outlook.com", - "issues": "https://github.com/DirectoryTree/LdapRecord/issues", - "source": "https://github.com/DirectoryTree/LdapRecord" - }, - "funding": [ - { - "url": "https://github.com/stevebauman", - "type": "github" - } - ], - "time": "2023-10-11T16:34:34+00:00" - }, { "name": "doctrine/annotations", "version": "2.0.1", @@ -1489,54 +1346,6 @@ ], "time": "2023-12-03T20:05:35+00:00" }, - { - "name": "illuminate/contracts", - "version": "v10.47.0", - "source": { - "type": "git", - "url": "https://github.com/illuminate/contracts.git", - "reference": "8d7152c4a1f5d9cf7da3e8b71f23e4556f6138ac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/illuminate/contracts/zipball/8d7152c4a1f5d9cf7da3e8b71f23e4556f6138ac", - "reference": "8d7152c4a1f5d9cf7da3e8b71f23e4556f6138ac", - "shasum": "" - }, - "require": { - "php": "^8.1", - "psr/container": "^1.1.1|^2.0.1", - "psr/simple-cache": "^1.0|^2.0|^3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "10.x-dev" - } - }, - "autoload": { - "psr-4": { - "Illuminate\\Contracts\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "The Illuminate Contracts package.", - "homepage": "https://laravel.com", - "support": { - "issues": "https://github.com/laravel/framework/issues", - "source": "https://github.com/laravel/framework" - }, - "time": "2024-01-15T18:52:32+00:00" - }, { "name": "kevinrob/guzzle-cache-middleware", "version": "v5.1.0", @@ -1960,113 +1769,6 @@ }, "time": "2023-11-30T16:41:19+00:00" }, - { - "name": "nesbot/carbon", - "version": "2.72.3", - "source": { - "type": "git", - "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/0c6fd108360c562f6e4fd1dedb8233b423e91c83", - "reference": "0c6fd108360c562f6e4fd1dedb8233b423e91c83", - "shasum": "" - }, - "require": { - "carbonphp/carbon-doctrine-types": "*", - "ext-json": "*", - "php": "^7.1.8 || ^8.0", - "psr/clock": "^1.0", - "symfony/polyfill-mbstring": "^1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" - }, - "provide": { - "psr/clock-implementation": "1.0" - }, - "require-dev": { - "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0", - "doctrine/orm": "^2.7 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.0", - "kylekatarnls/multi-tester": "^2.0", - "ondrejmirtes/better-reflection": "*", - "phpmd/phpmd": "^2.9", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.99 || ^1.7.14", - "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", - "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", - "squizlabs/php_codesniffer": "^3.4" - }, - "bin": [ - "bin/carbon" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-3.x": "3.x-dev", - "dev-master": "2.x-dev" - }, - "laravel": { - "providers": [ - "Carbon\\Laravel\\ServiceProvider" - ] - }, - "phpstan": { - "includes": [ - "extension.neon" - ] - } - }, - "autoload": { - "psr-4": { - "Carbon\\": "src/Carbon/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Brian Nesbitt", - "email": "brian@nesbot.com", - "homepage": "https://markido.com" - }, - { - "name": "kylekatarnls", - "homepage": "https://github.com/kylekatarnls" - } - ], - "description": "An API extension for DateTime that supports 281 different languages.", - "homepage": "https://carbon.nesbot.com", - "keywords": [ - "date", - "datetime", - "time" - ], - "support": { - "docs": "https://carbon.nesbot.com/docs", - "issues": "https://github.com/briannesbitt/Carbon/issues", - "source": "https://github.com/briannesbitt/Carbon" - }, - "funding": [ - { - "url": "https://github.com/sponsors/kylekatarnls", - "type": "github" - }, - { - "url": "https://opencollective.com/Carbon#sponsor", - "type": "opencollective" - }, - { - "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", - "type": "tidelift" - } - ], - "time": "2024-01-25T10:35:09+00:00" - }, { "name": "phpdocumentor/reflection-common", "version": "2.2.0", @@ -2748,57 +2450,6 @@ }, "time": "2021-07-14T16:46:02+00:00" }, - { - "name": "psr/simple-cache", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/8707bf3cea6f710bf6ef05491234e3ab06f6432a", - "reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\SimpleCache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interfaces for simple caching", - "keywords": [ - "cache", - "caching", - "psr", - "psr-16", - "simple-cache" - ], - "support": { - "source": "https://github.com/php-fig/simple-cache/tree/2.0.0" - }, - "time": "2021-10-29T13:22:09+00:00" - }, { "name": "ralouphie/getallheaders", "version": "3.0.3", @@ -6352,101 +6003,6 @@ ], "time": "2024-02-01T13:16:41+00:00" }, - { - "name": "symfony/translation", - "version": "v6.4.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/translation.git", - "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/bce6a5a78e94566641b2594d17e48b0da3184a8e", - "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.5|^3.0" - }, - "conflict": { - "symfony/config": "<5.4", - "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", - "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<5.4", - "symfony/service-contracts": "<2.5", - "symfony/twig-bundle": "<5.4", - "symfony/yaml": "<5.4" - }, - "provide": { - "symfony/translation-implementation": "2.3|3.0" - }, - "require-dev": { - "nikic/php-parser": "^4.18|^5.0", - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/http-client-contracts": "^2.5|^3.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/intl": "^5.4|^6.0|^7.0", - "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^5.4|^6.0|^7.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^5.4|^6.0|^7.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools to internationalize your application", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.4" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-02-20T13:16:58+00:00" - }, { "name": "symfony/translation-contracts", "version": "v3.4.1", @@ -7203,60 +6759,6 @@ ], "time": "2024-01-23T14:51:35+00:00" }, - { - "name": "tightenco/collect", - "version": "v9.52.7", - "source": { - "type": "git", - "url": "https://github.com/tighten/collect.git", - "reference": "b15143cd11fe01a700fcc449df61adc64452fa6d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/tighten/collect/zipball/b15143cd11fe01a700fcc449df61adc64452fa6d", - "reference": "b15143cd11fe01a700fcc449df61adc64452fa6d", - "shasum": "" - }, - "require": { - "php": "^8.0", - "symfony/var-dumper": "^3.4 || ^4.0 || ^5.0 || ^6.0" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "nesbot/carbon": "^2.23.0", - "phpunit/phpunit": "^8.3" - }, - "type": "library", - "autoload": { - "files": [ - "src/Collect/Support/helpers.php", - "src/Collect/Support/alias.php" - ], - "psr-4": { - "Tightenco\\Collect\\": "src/Collect" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylorotwell@gmail.com" - } - ], - "description": "Collect - Illuminate Collections as a separate package.", - "keywords": [ - "collection", - "laravel" - ], - "support": { - "issues": "https://github.com/tighten/collect/issues", - "source": "https://github.com/tighten/collect/tree/v9.52.7" - }, - "time": "2023-04-14T21:51:36+00:00" - }, { "name": "twig/twig", "version": "v3.8.0", @@ -11004,5 +10506,5 @@ "platform-overrides": { "php": "8.1" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.2.0" } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 0a37d72..e5c223d 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -12,6 +12,9 @@ class Configuration implements ConfigurationInterface { + public const LDAP_CONNECTION_ATTRIBUTE = 'connection'; + public const LDAP_ALMA_USER_ID_ATTRIBUTE_ATTRIBUTE = 'alma_user_id_attribute'; + public const ROLE_LIBRARY_MANAGER = 'ROLE_LIBRARY_MANAGER'; public const SUBLIBRARY_IDS = 'SUBLIBRARY_IDS'; public const ALMA_LIBRARY_IDS = 'ALMA_LIBRARY_IDS'; @@ -32,25 +35,6 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ; - $ldapBuilder = new TreeBuilder('ldap'); - $ldapNode = $ldapBuilder->getRootNode() - ->children() - ->scalarNode('host')->end() - ->scalarNode('base_dn')->end() - ->scalarNode('username')->end() - ->scalarNode('password')->end() - ->scalarNode('encryption')->end() - ->end(); - - $attributesBuilder = new TreeBuilder('attributes'); - $attributesNode = $attributesBuilder->getRootNode() - ->children() - ->scalarNode('identifier')->end() - ->scalarNode('alma_user_id')->end() - ->end(); - $ldapNode->append($attributesNode); - - $rootNode->append($ldapNode); $rootNode->append($this->getAuthorizationNode()); return $treeBuilder; diff --git a/src/DependencyInjection/DbpRelaySublibraryExtension.php b/src/DependencyInjection/DbpRelaySublibraryExtension.php index f692f90..45c317f 100644 --- a/src/DependencyInjection/DbpRelaySublibraryExtension.php +++ b/src/DependencyInjection/DbpRelaySublibraryExtension.php @@ -7,7 +7,6 @@ use Dbp\Relay\CoreBundle\Extension\ExtensionTrait; use Dbp\Relay\SublibraryBundle\Authorization\AuthorizationService; use Dbp\Relay\SublibraryBundle\Service\AlmaApi; -use Dbp\Relay\SublibraryBundle\Service\LDAPApi; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; @@ -48,9 +47,6 @@ public function loadInternal(array $mergedConfig, ContainerBuilder $container): ); $loader->load('services.yaml'); - $definition = $container->getDefinition(LDAPApi::class); - $definition->addMethodCall('setConfig', [$mergedConfig['ldap'] ?? []]); - $definition = $container->getDefinition(AlmaApi::class); $definition->addMethodCall('setConfig', [$mergedConfig]); diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml index 034d04f..1376539 100644 --- a/src/Resources/config/services.yaml +++ b/src/Resources/config/services.yaml @@ -5,12 +5,6 @@ services: calls: - setCache: [ '@dbp.relay.sublibrary.cache.alma_analytics' ] - Dbp\Relay\SublibraryBundle\Service\LDAPApi: - autowire: true - autoconfigure: true - calls: - - setLDAPCache: [ '@dbp.relay.sublibrary.cache.ldap', 360 ] - Dbp\Relay\SublibraryBundle\ApiPlatform\: resource: '../../ApiPlatform' autowire: true @@ -39,8 +33,3 @@ services: parent: cache.app tags: - { name: 'cache.pool', default_lifetime: 60 } - - dbp.relay.sublibrary.cache.ldap: - parent: cache.app - tags: - - { name: 'cache.pool', default_lifetime: 360 } diff --git a/src/Service/AlmaApi.php b/src/Service/AlmaApi.php index 1b9a501..ebd5fd8 100644 --- a/src/Service/AlmaApi.php +++ b/src/Service/AlmaApi.php @@ -7,12 +7,12 @@ namespace Dbp\Relay\SublibraryBundle\Service; -use DateTime; use Dbp\Relay\BasePersonBundle\API\PersonProviderInterface; use Dbp\Relay\BasePersonBundle\Entity\Person; use Dbp\Relay\CoreBundle\Exception\ApiError; use Dbp\Relay\CoreBundle\Helpers\GuzzleTools; use Dbp\Relay\CoreBundle\Rest\Options; +use Dbp\Relay\CoreBundle\Rest\Query\Filter\FilterTreeBuilder; use Dbp\Relay\SublibraryBundle\API\SublibraryProviderInterface; use Dbp\Relay\SublibraryBundle\ApiPlatform\Book; use Dbp\Relay\SublibraryBundle\ApiPlatform\BookLoan; @@ -45,10 +45,9 @@ use Psr\Http\Message\ResponseInterface; use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareTrait; -use SimpleXMLElement; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Exception\AccessDeniedException; -use Symfony\Component\Security\Core\Security; class AlmaApi implements LoggerAwareInterface { @@ -58,51 +57,35 @@ class AlmaApi implements LoggerAwareInterface private const ALMA_ID_ATTRIBUTE = 'almaId'; private const TUG_FUNCTIONS_ATTRIBUTE = 'tugFunctions'; - /** @var PersonProviderInterface */ - private $personProvider; - - /** @var Security */ - private $security; - - /** @var SublibraryProviderInterface */ - private $libraryProvider; - - private $clientHandler; - private $apiKey; - private $analyticsApiKey; - private $apiUrl; - private $readonly; - private $urls; - private $analyticsUpdatesHash = ''; - private $ldapApi; - - private $cachePool; - // 30h caching for Analytics, they will expire when there is a new Analytics Update private const ANALYTICS_CACHE_TTL = 108000; // 1h caching for the Analytics Updates private const ANALYTICS_UPDATES_CACHE_TTL = 3600; - /** @var AuthorizationService */ - private $authorizationService; + private PersonProviderInterface $personProvider; + private Security $security; + private SublibraryProviderInterface $libraryProvider; + private ?CacheItemPoolInterface $cachePool = null; + private AuthorizationService $authorizationService; + + private ?object $clientHandler = null; + private string $apiKey = ''; + private string $analyticsApiKey = ''; + private string $apiUrl = ''; + private bool $readonly = false; + private AlmaUrlApi $almaUrlApi; + private string $analyticsUpdatesHash = ''; public function __construct(PersonProviderInterface $personProvider, SublibraryProviderInterface $libraryProvider, - Security $security, LDAPApi $ldapApi, AuthorizationService $authorizationService) + Security $security, AuthorizationService $authorizationService) { $this->security = $security; $this->personProvider = $personProvider; - $this->clientHandler = null; - $this->urls = new AlmaUrlApi(); + $this->almaUrlApi = new AlmaUrlApi(); $this->libraryProvider = $libraryProvider; - $this->ldapApi = $ldapApi; $this->authorizationService = $authorizationService; - - $this->apiKey = ''; - $this->analyticsApiKey = ''; - $this->apiUrl = ''; - $this->readonly = false; } public function setConfig(array $config) @@ -332,7 +315,7 @@ private function getBookOfferJsonData(string $identifier, bool $assoc = true) ]; try { - $url = $this->urls->getBookOfferUrl($identifier); + $url = $this->almaUrlApi->getBookOfferUrl($identifier); } catch (InvalidIdentifierException $e) { throw new ItemNotLoadedException(Tools::filterErrorMessage($e->getMessage())); } @@ -370,7 +353,7 @@ private function getBookOffersJsonData(string $barcode): ?array ], ]; - $url = $this->urls->getBarcodeBookOfferUrl($barcode); + $url = $this->almaUrlApi->getBarcodeBookOfferUrl($barcode); try { $response = $client->request('GET', $url, $options); @@ -409,7 +392,7 @@ public function getBookJsonData(string $identifier): ?array try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $response = $client->request('GET', $this->urls->getBookUrl($identifier), $options); + $response = $client->request('GET', $this->almaUrlApi->getBookUrl($identifier), $options); $dataArray = $this->decodeResponse($response); @@ -453,7 +436,7 @@ public function getBookLoanJsonData(string $identifier, bool $assoc = true) try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $response = $client->request('GET', $this->urls->getBookLoanUrl($identifier), $options); + $response = $client->request('GET', $this->almaUrlApi->getBookLoanUrl($identifier), $options); $dataArray = $this->decodeResponse($response, $assoc); @@ -498,14 +481,16 @@ public function bookLoanFromJsonItem(array $item): BookLoan $bookLoan->setLoanStatus($item['loan_status']); - $userId = $item['user_id']; - try { - $personId = $this->ldapApi->getPersonIdByAlmaUserId($userId); - $person = $this->getPerson($personId, false); - $bookLoan->setBorrower($person); - } catch (ItemNotFoundException $e) { - // this happens if no person was found in LDAP by AlmaUserId, must be handled in the frontend + $options = []; + // filter: get person(s) whose Alma user ID matches the ID of the loan + $filter = FilterTreeBuilder::create()->equals('localData.almaId', $item['user_id'])->createFilter(); + $persons = $this->personProvider->getPersons(1, 1, Options::setFilter($options, $filter)); + if (count($persons) > 0) { + $bookLoan->setBorrower($persons[0]); + } + } catch (\Exception $e) { + // must be handled in the frontend // catching the exception has the advantage that we can return the book even if no person was found } @@ -715,7 +700,7 @@ public function updateBookOffer(BookOffer $bookOffer, $library = '') try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $response = $client->request('PUT', $this->urls->getBookOfferUrl($identifier), $options); + $response = $client->request('PUT', $this->almaUrlApi->getBookOfferUrl($identifier), $options); $data = $this->decodeResponse($response); $bookOffer = $this->bookOfferFromJsonItem($data); @@ -792,7 +777,7 @@ public function createBookLoan(BookOffer &$bookOffer, array $bodyData) $identifier = $bookOffer->getIdentifier(); // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $response = $client->request('POST', $this->urls->getBookLoanPostUrl($identifier, $userId), $options); + $response = $client->request('POST', $this->almaUrlApi->getBookLoanPostUrl($identifier, $userId), $options); $data = $this->decodeResponse($response); $bookLoan = $this->bookLoanFromJsonItem($data); @@ -981,7 +966,7 @@ public function returnBookOffer(BookOffer &$bookOffer) try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $client->request('POST', $this->urls->getReturnBookOfferUrl($identifier, $libraryCode), $options); + $client->request('POST', $this->almaUrlApi->getReturnBookOfferUrl($identifier, $libraryCode), $options); $this->log("Book offer <{$identifier}> ({$bookOffer->getName()}) was returned", ['library' => $libraryCode]); } catch (InvalidIdentifierException $e) { @@ -1039,7 +1024,7 @@ public function updateBookLoan(BookLoan $bookLoan) try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $response = $client->request('PUT', $this->urls->getBookLoanUrl($identifier), $options); + $response = $client->request('PUT', $this->almaUrlApi->getBookLoanUrl($identifier), $options); $data = $this->decodeResponse($response); $bookLoan = $this->bookLoanFromJsonItem($data); @@ -1103,7 +1088,7 @@ public function locationIdentifiersByBookOffer(BookOffer $bookOffer): array try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $response = $client->request('GET', $this->urls->getBookOfferLocationsIdentifierUrl($bookOffer), $options); + $response = $client->request('GET', $this->almaUrlApi->getBookOfferLocationsIdentifierUrl($bookOffer), $options); $dataArray = $this->decodeResponse($response); $results = array_map(function ($item) { @@ -1145,7 +1130,7 @@ public function getBookLoansJsonDataByBookOffer(BookOffer $bookOffer): ?array try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $response = $client->request('GET', $this->urls->getBookOfferLoansUrl($identifier), $options); + $response = $client->request('GET', $this->almaUrlApi->getBookOfferLoansUrl($identifier), $options); $dataArray = $this->decodeResponse($response); return $dataArray['item_loan'] ?? []; @@ -1192,7 +1177,7 @@ public function getBookLoansJsonDataByPerson(Person $person): ?array // do as many requests as necessary to get all loans by the user do { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $response = $client->request('GET', $this->urls->getLoansByUserIdUrl($userId, $limit, $offset), $options); + $response = $client->request('GET', $this->almaUrlApi->getLoansByUserIdUrl($userId, $limit, $offset), $options); $dataArray = $this->decodeResponse($response); $totalCount = (int) ($dataArray['total_record_count'] ?? 0); $resultList = array_merge($resultList, $dataArray['item_loan'] ?? []); @@ -1266,7 +1251,7 @@ public function getBookOffersAnalyticsXMLByOrganization(Sublibrary $sublibrary, try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $url = $this->urls->getBookOfferAnalyticsUrl($sublibrary, $resumptionToken); + $url = $this->almaUrlApi->getBookOfferAnalyticsUrl($sublibrary, $resumptionToken); $response = $client->request('GET', $url, $options); $dataArray = $this->decodeResponse($response); @@ -1313,7 +1298,7 @@ public function getBookLoanAnalyticsXMLByOrganization(Sublibrary $library, $resu try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $url = $this->urls->getBookLoanAnalyticsUrl($library, $resumptionToken); + $url = $this->almaUrlApi->getBookLoanAnalyticsUrl($library, $resumptionToken); $response = $client->request('GET', $url, $options); $dataArray = $this->decodeResponse($response); @@ -1362,7 +1347,7 @@ public function getBookOrdersAnalyticsXMLByOrganization(Sublibrary $library, $re try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $url = $this->urls->getBookOrderAnalyticsUrl($library, $resumptionToken); + $url = $this->almaUrlApi->getBookOrderAnalyticsUrl($library, $resumptionToken); $response = $client->request('GET', $url, $options); $dataArray = $this->decodeResponse($response); @@ -1402,7 +1387,7 @@ public function getBudgetMonetaryAmountAnalyticsXML(): ?\SimpleXMLElement try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $url = $this->urls->getBudgetMonetaryAmountAnalyticsUrl(); + $url = $this->almaUrlApi->getBudgetMonetaryAmountAnalyticsUrl(); $response = $client->request('GET', $url, $options); $dataArray = $this->decodeResponse($response); @@ -1517,7 +1502,7 @@ public function getAnalyticsUpdatesAnalyticsXML(): ?\SimpleXMLElement try { // http://docs.guzzlephp.org/en/stable/quickstart.html?highlight=get#making-a-request - $url = $this->urls->getAnalyticsUpdatesAnalyticsUrl(); + $url = $this->almaUrlApi->getAnalyticsUpdatesAnalyticsUrl(); $response = $client->request('GET', $url, $options); $dataArray = $this->decodeResponse($response); diff --git a/src/Service/HealthCheck.php b/src/Service/HealthCheck.php index f8ecca0..bc5fef5 100644 --- a/src/Service/HealthCheck.php +++ b/src/Service/HealthCheck.php @@ -10,13 +10,11 @@ class HealthCheck implements CheckInterface { - private $api; - private $ldap; + private AlmaApi $api; - public function __construct(AlmaApi $api, LDAPApi $ldap) + public function __construct(AlmaApi $api) { $this->api = $api; - $this->ldap = $ldap; } public function getName(): string @@ -44,7 +42,6 @@ public function check(CheckOptions $options): array $results = []; $results[] = $this->checkMethod('Check if we can connect to the Alma "bibs" API', [$this->api, 'checkConnection']); $results[] = $this->checkMethod('Check if we can connect to the Alma "analytics" API', [$this->api, 'checkConnectionAnalytics']); - $results[] = $this->checkMethod('Check if we can connect to the LDAP server', [$this->ldap, 'checkConnection']); return $results; } diff --git a/src/Service/LDAPApi.php b/src/Service/LDAPApi.php deleted file mode 100644 index b9a86de..0000000 --- a/src/Service/LDAPApi.php +++ /dev/null @@ -1,135 +0,0 @@ -cacheTTL = 0; - $this->logger = new NullLogger(); - } - - public function setConfig(array $config) - { - $this->identifierAttributeName = $config['attributes']['identifier'] ?? 'cn'; - $this->almaUserIdAttributeName = $config['attributes']['alma_user_id'] ?? 'CO-ALMA-PATRON-ID'; - - $this->providerConfig = [ - 'hosts' => [$config['host'] ?? ''], - 'base_dn' => $config['base_dn'] ?? '', - 'username' => $config['username'] ?? '', - 'password' => $config['password'] ?? '', - ]; - - $encryption = $config['encryption'] ?? ''; - assert(in_array($encryption, ['start_tls', 'simple_tls'], true)); - $this->providerConfig['use_tls'] = ($encryption === 'start_tls'); - $this->providerConfig['use_ssl'] = ($encryption === 'simple_tls'); - $this->providerConfig['port'] = ($encryption === 'start_tls') ? 389 : 636; - } - - public function checkConnection() - { - $connection = $this->getConnection(); - $builder = $this->getCachedBuilder($connection); - $builder->first(); - } - - public function setLDAPCache(?CacheItemPoolInterface $cachePool, int $ttl) - { - $this->cachePool = $cachePool; - $this->cacheTTL = $ttl; - } - - private function getConnection(): Connection - { - Container::getInstance()->manager()->setLogger($this->logger); - $connection = new Connection($this->providerConfig); - if ($this->cachePool !== null) { - $connection->setCache(new Psr16Cache($this->cachePool)); - } - $connection->connect(); - - return $connection; - } - - private function getCachedBuilder(Connection $connection): Builder - { - $until = (new \DateTimeImmutable())->add(new \DateInterval('PT'.$this->cacheTTL.'S')); - - return $connection->query()->cache($until); - } - - private function getPersonUserItemByAlmaUserId(string $almaUserId): ?Model - { - try { - // if we already have fetched the user by alma user id in this request we will use the cached version - if (array_key_exists($almaUserId, self::$USERS_BY_ALMA_USER_ID)) { - $user = self::$USERS_BY_ALMA_USER_ID[$almaUserId]; - } else { - $connection = $this->getConnection(); - $builder = $this->getCachedBuilder($connection); - - /** @var Entry $user */ - $user = $builder->model(new Entry())->where('objectClass', '=', 'person') - ->whereEquals($this->almaUserIdAttributeName, $almaUserId) - ->first(); - - self::$USERS_BY_ALMA_USER_ID[$almaUserId] = $user; - } - - if ($user === null) { - throw new NotFoundHttpException(sprintf("Person with alma user id '%s' could not be found!", $almaUserId)); - } - - return $user; - } catch (BindException $e) { - // There was an issue binding / connecting to the server. - throw new ApiError(Response::HTTP_BAD_GATEWAY, sprintf("Person with alma user id '%s' could not be loaded! Message: %s", $almaUserId, CoreTools::filterErrorMessage($e->getMessage()))); - } - } - - public function getPersonIdByAlmaUserId(string $almaUserId): string - { - $user = $this->getPersonUserItemByAlmaUserId($almaUserId); - - return $user->getFirstAttribute($this->identifierAttributeName); - } -} diff --git a/tests/AlmaApiTest.php b/tests/AlmaApiTest.php index 4fa80de..568d79e 100644 --- a/tests/AlmaApiTest.php +++ b/tests/AlmaApiTest.php @@ -13,7 +13,6 @@ use Dbp\Relay\SublibraryBundle\Helpers\ItemNotLoadedException; use Dbp\Relay\SublibraryBundle\Service\AlmaApi; use Dbp\Relay\SublibraryBundle\Service\DummySublibraryProvider; -use Dbp\Relay\SublibraryBundle\Service\LDAPApi; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; @@ -21,7 +20,7 @@ use GuzzleHttp\Psr7\Response; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; -use Symfony\Component\Security\Core\Security; +use Symfony\Bundle\SecurityBundle\Security; class AlmaApiTest extends WebTestCase { @@ -43,16 +42,11 @@ protected function setUp(): void $personProvider = new DummyPersonProvider(); $personProvider->setCurrentPerson($person); $libraryProvider = new DummySublibraryProvider(); - $ldapApi = new LDAPApi(); - $ldapApi->setConfig([ - 'encryption' => 'simple_tls', - ]); $this->api = new AlmaApi( $personProvider, $libraryProvider, new Security($client->getContainer()), - $ldapApi, new AuthorizationService() ); $this->api->setApiKey('secret'); diff --git a/tests/Kernel.php b/tests/Kernel.php index 2ce28c2..91379bd 100644 --- a/tests/Kernel.php +++ b/tests/Kernel.php @@ -48,12 +48,6 @@ protected function configureContainer(ContainerConfigurator $container) 'secret' => '', ]); - $container->extension('dbp_relay_sublibrary', [ - 'ldap' => [ - 'encryption' => 'simple_tls', - ], - ]); - $container->extension('api_platform', [ 'metadata_backward_compatibility_layer' => false, ]);