183 lines
6.2 KiB
PHP
183 lines
6.2 KiB
PHP
<?php
|
|
|
|
namespace KupShop\GraphQLBundle\Controller;
|
|
|
|
use GraphQL\Executor\ExecutionResult;
|
|
use GraphQL\GraphQL;
|
|
use KupShop\AdminBundle\Util\LegacyAdminCredentials;
|
|
use KupShop\GraphQLBundle\Util\SchemaFactory;
|
|
use KupShop\KupShopBundle\Context\PosContext;
|
|
use KupShop\KupShopBundle\Routing\AdminRoute;
|
|
use KupShop\KupShopBundle\Util\Logging\SentryLogger;
|
|
use KupShop\KupShopBundle\Util\RequestUtil;
|
|
use Psr\Log\LoggerInterface;
|
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
use TheCodingMachine\GraphQLite\Context\Context;
|
|
|
|
class AdminController
|
|
{
|
|
public function __construct(
|
|
private SchemaFactory $schemaFactory,
|
|
private SentryLogger $sentryLogger,
|
|
private LoggerInterface $logger,
|
|
public PosContext $posContext,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* @AdminRoute("/graphql{slash}", requirements={"slash": "\/$"}, defaults={"slash": "/"})
|
|
*/
|
|
public function graphQLAdmin(Request $request, LegacyAdminCredentials $legacyAdminCredentials): Response
|
|
{
|
|
if (!findModule(\Modules::GRAPHQL, \Modules::SUB_GRAPHQL_ADMIN)) {
|
|
throw new NotFoundHttpException();
|
|
}
|
|
|
|
increaseMaxExecutionTime(120);
|
|
increaseMemoryLimit(512);
|
|
|
|
// CORS check - return 200
|
|
if ($request->isMethod('OPTIONS')) {
|
|
return $this->getAPIResponse([]);
|
|
}
|
|
|
|
$token = $request->headers->get('X-Access-Token');
|
|
|
|
if (!$legacyAdminCredentials->isLogged() && (!$token || !$legacyAdminCredentials->loginByHash($token))) {
|
|
$this->log('Unauthorized access', [
|
|
'token' => $token,
|
|
'uri' => $request->getUri(),
|
|
'headers' => $request->headers->all(),
|
|
]);
|
|
|
|
return $this->getAPIResponse(['errors' => ['message' => 'Unauthorized access']], 401);
|
|
}
|
|
|
|
$legacyAdminCredentials->setAdminGlobalVars();
|
|
|
|
$admin = LegacyAdminCredentials::getAdminById($legacyAdminCredentials->getAdminID());
|
|
|
|
if (!findRight('API')) {
|
|
return $this->getAPIResponse(['errors' => ['message' => 'Used access token does not have access to the API']], 403);
|
|
}
|
|
|
|
$schema = $this->schemaFactory->createAdminSchema();
|
|
|
|
$input = json_decode($request->getContent(), true);
|
|
|
|
if (($query = ($input['query'] ?? null)) === null) {
|
|
return $this->getAPIResponse(['errors' => ['message' => 'Invalid request! Missing "query" param']], 400);
|
|
}
|
|
|
|
$variableValues = $input['variables'] ?? null;
|
|
|
|
$result = GraphQL::executeQuery($schema, $query, null, new Context(), $variableValues);
|
|
$output = $result->toArray();
|
|
|
|
$this->captureGraphQLRequest($input, $admin);
|
|
$this->captureGraphQLErrors($result);
|
|
|
|
return $this->getAPIResponse($output);
|
|
}
|
|
|
|
private function captureGraphQLRequest(array $input, ?array $admin = null): void
|
|
{
|
|
$this->log('API Request', [
|
|
'input' => $input,
|
|
'admin' => ['id' => $admin['id'], 'email' => $admin['email'], 'login' => $admin['login'], 'name' => $admin['name'] ?? ''],
|
|
]);
|
|
}
|
|
|
|
private function captureGraphQLErrors(ExecutionResult $result): void
|
|
{
|
|
foreach ($result->errors ?? [] as $error) {
|
|
// pokud je chyba client safe, tak ji neloguju do sentry
|
|
if ($error->isClientSafe()) {
|
|
continue;
|
|
}
|
|
|
|
if (isLocalDevelopment()) {
|
|
throw $error;
|
|
}
|
|
|
|
$this->sentryLogger->captureException($error);
|
|
}
|
|
}
|
|
|
|
private function log(string $message, array $data): void
|
|
{
|
|
if (isLocalDevelopment()) {
|
|
return;
|
|
}
|
|
|
|
$this->logger->notice("[GraphQL] {$message}", $data);
|
|
}
|
|
|
|
private function getAPIResponse(array $data, int $code = 200): JsonResponse
|
|
{
|
|
return new JsonResponse(
|
|
$data,
|
|
$code,
|
|
[
|
|
'Content-Type' => 'application/json',
|
|
'Access-Control-Allow-Origin' => '*',
|
|
'Access-Control-Allow-Headers' => '*',
|
|
]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @AdminRoute("/pos/graphql{slash}", requirements={"slash": "\/$"}, defaults={"slash": "/"})
|
|
*/
|
|
public function graphQLPos(Request $request, LegacyAdminCredentials $legacyAdminCredentials, RequestUtil $requestUtil): Response
|
|
{
|
|
if (!findModule(\Modules::NEW_POS)) {
|
|
throw new NotFoundHttpException();
|
|
}
|
|
|
|
// Checks if the request has a pos ID in the header and activates context
|
|
if ($idPos = PosContext::getIdFromRequest($request)) {
|
|
$this->posContext->activate($idPos);
|
|
}
|
|
|
|
// Checks the API versions, and if they differ, returns 426 Upgrade Required.
|
|
if ($this->posContext->getApiVersion() !== PosContext::getVersionFromRequest($request)) {
|
|
return $this->getAPIResponse([], 426);
|
|
}
|
|
|
|
// CORS check - return 200
|
|
if ($request->isMethod('OPTIONS')) {
|
|
return $this->getAPIResponse([]);
|
|
}
|
|
|
|
$token = $request->headers->get('X-Access-Token');
|
|
if (!$legacyAdminCredentials->isLogged() && (!$token || !$legacyAdminCredentials->loginByHash($token))) {
|
|
return $this->getAPIResponse(['errors' => ['message' => 'Unauthorized access']], 401);
|
|
}
|
|
|
|
$legacyAdminCredentials->setAdminGlobalVars();
|
|
|
|
if (!findRight('POS_API')) {
|
|
return $this->getAPIResponse(['errors' => ['message' => 'User does not have access']], 403);
|
|
}
|
|
|
|
$schema = $this->schemaFactory->createPosSchema();
|
|
$input = json_decode($request->getContent(), true);
|
|
if (!$input) {
|
|
return $this->getAPIResponse(['errors' => ['message' => 'Unprocessable Entity - empty input']], 422);
|
|
}
|
|
|
|
if (preg_match('/^\s*(query|mutation)\s*(\w+)/i', $input['query'], $matches)) {
|
|
$requestUtil->addTransactionInfo($request, ['query' => $matches[2]]);
|
|
}
|
|
|
|
$result = GraphQL::executeQuery($schema, $input['query'], null, new Context(), $input['variables'] ?? null);
|
|
$output = $result->toArray();
|
|
|
|
return $this->getAPIResponse($output);
|
|
}
|
|
}
|