Skip to content
Snippets Groups Projects
Commit 4efaeaaf authored by Tobias Gross-Vogt's avatar Tobias Gross-Vogt
Browse files

proxydata directory and functionality

parent d7cb138c
No related branches found
No related tags found
No related merge requests found
Pipeline #202464 passed
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\Authorization;
/**
* @deprecated use AbstractAuthorizationService instead
*/
abstract class AuthorizationService extends AbstractAuthorizationService
{
}
......@@ -80,7 +80,7 @@ class ApiConnection
/**
* @throws ConnectionException
*/
public function get(string $uri, array $options): ResponseInterface
public function get(string $uri, array $query): ResponseInterface
{
$requestOptions = [
Connection::REQUEST_OPTION_HEADERS => [
......@@ -88,7 +88,21 @@ class ApiConnection
],
];
return $this->getApiConnection()->get($uri, $options, $requestOptions);
return $this->getConnection()->get($uri, $query, $requestOptions);
}
/**
* @throws ConnectionException
*/
public function postJSON(string $uri, array $parameters): ResponseInterface
{
$requestOptions = [
Connection::REQUEST_OPTION_HEADERS => [
'Authorization' => 'Bearer '.$this->getAccessToken(),
],
];
return $this->getConnection()->postJSON($uri, $parameters, $requestOptions);
}
/**
......@@ -123,7 +137,7 @@ class ApiConnection
return $this->accessToken;
}
private function getApiConnection(): Connection
private function getConnection(): Connection
{
if ($this->connection === null) {
$connection = new Connection($this->config[self::API_URL_CONFIG_PARAMETER]);
......
......@@ -11,6 +11,7 @@ class ConnectionException extends \RuntimeException
{
public const REQUEST_EXCEPTION = 1;
public const JSON_EXCEPTION = 2;
public const INVALID_DATA_EXCEPTION = 3;
/** @var RequestInterface|null */
private $request;
......
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\ProxyApi;
use Exception;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
abstract class AbstractProxyDataEventSubscriber implements EventSubscriberInterface
{
protected const NAMESPACE = '';
public static function getSubscribedEvents(): array
{
return [
ProxyApi::PROXY_DATA_EVENT_NAME.static::NAMESPACE => 'onProxyDataEvent',
];
}
/**
* @throws BadRequestException
*/
public function onProxyDataEvent(ProxyDataEvent $event): void
{
$event->setHandled();
$proxyData = $event->getProxyData();
$functionName = $proxyData->getFunctionName();
$arguments = $proxyData->getArguments();
$returnValue = null;
if ($this->isFunctionDefined($functionName) === false) {
throw new BadRequestException(sprintf('unknown function "%s" under namespace "%s"', $functionName, static::NAMESPACE));
} elseif ($this->areAllRequiredArgumentsDefined($functionName, $arguments) === false) {
throw new BadRequestException(sprintf('incomplete argument list for function "%s" under namespace "%s"', $functionName, static::NAMESPACE));
}
try {
$returnValue = $this->callFunction($functionName, $arguments);
} catch (Exception $exception) {
$proxyData->setErrorsFromException($exception);
}
$proxyData->setData($returnValue);
}
abstract protected function isFunctionDefined(string $functionName): bool;
abstract protected function areAllRequiredArgumentsDefined(string $functionName, array $arguments): bool;
abstract protected function callFunction(string $functionName, array $arguments);
}
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\ProxyApi;
use Dbp\Relay\CoreBundle\Helpers\Tools;
use Dbp\Relay\CoreBundle\Http\ApiConnection as BaseApiConnection;
use Dbp\Relay\CoreBundle\Http\ConnectionException as BaseConnectionException;
class ApiConnection extends BaseApiConnection
{
private const NAMESPACE_PARAMETER_NAME = 'namespace';
private const FUNCTION_NAME_PARAMETER_NAME = 'functionName';
private const ARGUMENTS_PARAMETER_NAME = 'arguments';
private const PROXY_DATA_URI = 'proxy/proxydata';
/**
* @throws ConnectionException
*/
public function callFunction(string $namespace, string $functionName, array $arguments = [])
{
$parameters = [
self::NAMESPACE_PARAMETER_NAME => $namespace,
self::FUNCTION_NAME_PARAMETER_NAME => $functionName,
self::ARGUMENTS_PARAMETER_NAME => $arguments,
];
$responseBody = (string) $this->postJSON(self::PROXY_DATA_URI, $parameters)->getBody();
try {
$proxyData = Tools::decodeJSON($responseBody, true);
} catch (\JsonException $exception) {
throw new ConnectionException('failed to JSON decode API response: '.$exception->getMessage(), BaseConnectionException::JSON_EXCEPTION);
}
try {
$errors = $proxyData[ProxyApi::PROXY_DATA_ERRORS_KEY];
$returnValue = $proxyData[ProxyApi::PROXY_DATA_RETURN_VALUE_KEY];
} catch (\Exception $exception) {
throw new ConnectionException('API returned invalid ProxyData object', BaseConnectionException::INVALID_DATA_EXCEPTION);
}
if (!empty($errors)) {
$topLevelError = $errors[0];
throw new ConnectionException(sprintf('call to API function "%s" under namespace "%s" resulted in an error: %s (code: %s)', $functionName, $namespace, $topLevelError['message'] ?? 'message not available', $topLevelError['code'] ?? 'code not available'), ConnectionException::API_ERROR);
}
return $returnValue;
}
}
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\ProxyApi;
class ConnectionException extends \Dbp\Relay\CoreBundle\Http\ConnectionException
{
public const API_ERROR = 101;
}
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\ProxyApi;
class ProxyApi
{
public const PROXY_DATA_EVENT_NAME = '';
public const PROXY_DATA_RETURN_VALUE_KEY = 'data';
public const PROXY_DATA_ERRORS_KEY = 'errors';
}
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\ProxyApi;
use Symfony\Contracts\EventDispatcher\Event;
class ProxyDataEvent extends Event
{
public const NAME = 'dbp.relay.proxy_bundle.proxy_data';
/** @var ProxyDataInterface */
private $proxyData;
/** @var bool */
private $wasHandled;
public function __construct(ProxyDataInterface $proxyData)
{
$this->proxyData = $proxyData;
$this->wasHandled = false;
}
public function getProxyData(): ProxyDataInterface
{
return $this->proxyData;
}
/**
* Indicate, that the event was handled, e.g. there was an event subscriber for the requested proxy data namespace.
*/
public function setHandled(): void
{
$this->wasHandled = true;
}
/**
* True, if the event was handled, e.g. there was an event subscriber for the requested proxy data namespace, false otherwise.
*/
public function wasHandled(): bool
{
return $this->wasHandled;
}
}
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\ProxyApi;
use Dbp\Relay\CoreBundle\Authorization\AuthorizationDataProviderProvider;
use Dbp\Relay\CoreBundle\Helpers\Tools;
use Exception;
class ProxyDataEventSubscriber extends AbstractProxyDataEventSubscriber
{
protected const NAMESPACE = 'core';
public const GET_AVAILABLE_ATTRIBUTES_FUNCTION_NAME = 'getAvailableAttributes';
public const GET_USER_ATTRIBUTES_FUNCTION_NAME = 'getUserAttributes';
public const USER_ID_PARAMETER_NAME = 'userId';
/**
* @var AuthorizationDataProviderProvider
*/
private $provider;
public function __construct(AuthorizationDataProviderProvider $provider)
{
$this->provider = $provider;
}
protected function isFunctionDefined(string $functionName): bool
{
return
$functionName === self::GET_AVAILABLE_ATTRIBUTES_FUNCTION_NAME ||
$functionName === self::GET_USER_ATTRIBUTES_FUNCTION_NAME;
}
protected function areAllRequiredArgumentsDefined(string $functionName, array $arguments): bool
{
return
$functionName !== self::GET_USER_ATTRIBUTES_FUNCTION_NAME ||
!Tools::isNullOrEmpty($arguments[self::USER_ID_PARAMETER_NAME] ?? null);
}
/**
* @throws Exception
*/
protected function callFunction(string $functionName, array $arguments): ?array
{
$returnValue = null;
switch ($functionName) {
case self::GET_AVAILABLE_ATTRIBUTES_FUNCTION_NAME:
$returnValue = $this->getAvailableAttributes();
break;
case self::GET_USER_ATTRIBUTES_FUNCTION_NAME:
$returnValue = $this->getUserAttributes($arguments[self::USER_ID_PARAMETER_NAME]);
break;
}
return $returnValue;
}
private function getAvailableAttributes(): array
{
$availableAttributes = [];
foreach ($this->provider->getAuthorizationDataProviders() as $provider) {
$availableAttributes = array_merge($availableAttributes, $provider->getAvailableAttributes());
}
return $availableAttributes;
}
private function getUserAttributes(string $userId): array
{
$userAttributes = [];
foreach ($this->provider->getAuthorizationDataProviders() as $provider) {
$userAttributes = array_merge($userAttributes, $provider->getUserAttributes($userId));
}
return $userAttributes;
}
}
<?php
declare(strict_types=1);
namespace Dbp\Relay\CoreBundle\ProxyApi;
interface ProxyDataInterface
{
public function getArguments(): array;
public function getFunctionName(): ?string;
public function setData($data);
public function setErrorsFromException(\Exception $exception): void;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment