2023-11-25 00:55:31 -03:00
|
|
|
<?php
|
|
|
|
namespace Incoviba\Middleware;
|
|
|
|
|
|
|
|
use Psr\Http\Message\ResponseFactoryInterface;
|
|
|
|
use Psr\Http\Message\ResponseInterface;
|
|
|
|
use Psr\Http\Message\ServerRequestInterface;
|
|
|
|
use Psr\Http\Server\RequestHandlerInterface;
|
2024-08-27 14:46:03 -04:00
|
|
|
use Psr\Log\LoggerInterface;
|
2023-11-25 00:55:31 -03:00
|
|
|
use Incoviba\Exception\MissingAuthorizationHeader;
|
2024-03-20 23:07:49 -03:00
|
|
|
use Incoviba\Service;
|
2023-11-25 00:55:31 -03:00
|
|
|
|
|
|
|
class API
|
|
|
|
{
|
2024-07-26 23:57:04 -04:00
|
|
|
public function __construct(protected ResponseFactoryInterface $responseFactory,
|
2024-08-27 14:46:03 -04:00
|
|
|
protected LoggerInterface $logger,
|
|
|
|
protected Service\API $apiService,
|
2024-07-26 23:57:04 -04:00
|
|
|
protected Service\Login $loginService,
|
2025-05-12 16:01:09 -04:00
|
|
|
protected string $key,
|
2024-08-27 14:46:03 -04:00
|
|
|
protected array $permittedPaths,
|
|
|
|
protected array $simplePaths,
|
2025-05-12 16:01:09 -04:00
|
|
|
protected array $externalPaths) {}
|
2023-11-25 00:55:31 -03:00
|
|
|
|
|
|
|
public function __invoke(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
|
|
|
{
|
2025-05-12 16:01:09 -04:00
|
|
|
if ($this->validExternal($request)) {
|
|
|
|
return $handler->handle($request);
|
|
|
|
}
|
2023-11-25 00:55:31 -03:00
|
|
|
try {
|
2024-08-27 14:46:03 -04:00
|
|
|
$key = $this->apiService->getKey($request);
|
2023-11-25 00:55:31 -03:00
|
|
|
} catch (MissingAuthorizationHeader $exception) {
|
|
|
|
return $this->responseFactory->createResponse(401);
|
|
|
|
}
|
2024-07-26 23:57:04 -04:00
|
|
|
if ($this->validateSimpleKey($request, $key)) {
|
|
|
|
return $handler->handle($request);
|
|
|
|
}
|
2024-03-20 23:07:49 -03:00
|
|
|
if ($this->validate($request, $key)) {
|
2023-11-25 00:55:31 -03:00
|
|
|
return $handler->handle($request);
|
|
|
|
}
|
|
|
|
return $this->responseFactory->createResponse(403);
|
|
|
|
}
|
2024-03-20 23:07:49 -03:00
|
|
|
protected function validate(ServerRequestInterface $request, $incoming_key): bool
|
2023-11-25 00:55:31 -03:00
|
|
|
{
|
2024-07-26 23:57:04 -04:00
|
|
|
$selector = null;
|
|
|
|
$token = null;
|
2024-03-20 23:07:49 -03:00
|
|
|
if (str_contains($incoming_key, $this->loginService->getSeparator())) {
|
2024-07-26 23:57:04 -04:00
|
|
|
list($incoming_key, $selector, $token) = explode($this->loginService->getSeparator(), $incoming_key, 3);
|
|
|
|
if (!$this->loginService->isIn($selector, $token)) {
|
2024-03-20 23:07:49 -03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2024-07-26 23:57:04 -04:00
|
|
|
if (!$this->loginService->isIn($selector, $token) and !$this->validPermitted($request)) {
|
2024-03-20 23:07:49 -03:00
|
|
|
return false;
|
|
|
|
}
|
2023-11-25 00:55:31 -03:00
|
|
|
return $incoming_key === md5($this->key);
|
|
|
|
}
|
2024-07-26 23:57:04 -04:00
|
|
|
protected function validateSimpleKey(ServerRequestInterface $request, $incoming_key): bool
|
|
|
|
{
|
|
|
|
return $incoming_key === md5($this->key) and $this->noComplexKeyNeeded($request);
|
|
|
|
}
|
|
|
|
protected function noComplexKeyNeeded(ServerRequestInterface $request): bool
|
|
|
|
{
|
|
|
|
$uri = $request->getUri();
|
2024-08-27 14:46:03 -04:00
|
|
|
return in_array($uri->getPath(), $this->simplePaths);
|
2024-07-26 23:57:04 -04:00
|
|
|
}
|
2024-03-20 23:07:49 -03:00
|
|
|
protected function validPermitted(ServerRequestInterface $request): bool
|
|
|
|
{
|
|
|
|
$uri = $request->getUri();
|
2024-08-27 14:46:03 -04:00
|
|
|
return in_array($uri->getPath(), $this->permittedPaths);
|
2024-03-20 23:07:49 -03:00
|
|
|
}
|
2025-05-12 16:01:09 -04:00
|
|
|
protected function validExternal(ServerRequestInterface $request): bool
|
|
|
|
{
|
|
|
|
$uri = $request->getUri();
|
|
|
|
foreach ($this->externalPaths as $basePath => $paths) {
|
|
|
|
if (!str_starts_with($uri->getPath(), $basePath)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
foreach ($paths as $subPath) {
|
|
|
|
$fullPath = "{$basePath}{$subPath}";
|
|
|
|
if ($uri->getPath() === $fullPath) {
|
|
|
|
return $this->validateExternalKey($request, $basePath, $subPath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
protected function validateExternalKey(ServerRequestInterface $request, $basePath, $subPath): bool
|
|
|
|
{
|
|
|
|
if ($request->hasHeader('x-api-key')) {
|
|
|
|
$key = $request->getHeaderLine('x-api-key');
|
|
|
|
if ($key === $this->externalPaths[$basePath][$subPath]) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($request->hasHeader('Authorization')) {
|
|
|
|
$key = $request->getHeaderLine('Authorization');
|
|
|
|
if (str_starts_with($key, 'Bearer ')) {
|
|
|
|
$key = substr($key, 7);
|
|
|
|
if ($key === $this->externalPaths[$basePath][$subPath]) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2023-11-25 00:55:31 -03:00
|
|
|
}
|