refs #518. New endpoint 'search'

pull/8/head
Manuel Aranda Rosales 2024-07-18 12:43:57 +02:00
parent 7ba4deaafa
commit b6ade24314
12 changed files with 168 additions and 28 deletions

View File

@ -1,6 +1,6 @@
api_platform:
title: 'OgCore API'
description: 'API Documentation for OgCore'
title: 'OgCore Api'
description: 'Api Documentation for OgCore'
version: 1.0.0
path_segment_name_generator: 'api_platform.path_segment_name_generator.dash'
formats:

View File

@ -0,0 +1,37 @@
<?php
namespace App\Controller\Api;
use App\Entity\Client;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class SearchController extends AbstractController
{
#[Route('/search', methods: ['GET'])]
public function index(Request $request, EntityManagerInterface $entityManager): Response
{
$filters = $request->query->get('filters');
if ($filters) {
$filters = json_decode($filters, true);
}
$repository = $entityManager->getRepository(Client::class);
$queryBuilder = $repository->createQueryBuilder('e');
if (!empty($filters)) {
foreach ($filters as $field => $value) {
$queryBuilder->andWhere("e.$field = :$field")
->setParameter($field, $value);
}
}
$results = $queryBuilder->getQuery()->getResult();
return new JsonResponse($results);
}
}

View File

@ -15,63 +15,63 @@ final class ClientInput
#[Assert\NotBlank(message: 'validators.client.name.not_blank')]
#[Groups(['client:write'])]
#[ApiProperty(
description: 'descriptions.client.name',
example: "examples.client.name",
description: 'El nombre del cliente',
example: 'Cliente 1',
)]
public ?string $name = null;
#[Groups(['client:write'])]
#[ApiProperty(
description: 'descriptions.client.serial_number',
example: "examples.client.serial_number"
description: 'La descripción del cliente',
example: 'Cliente descripcion 1',
)]
public ?string $serialNumber = null;
#[Groups(['client:write'])]
#[ApiProperty(
description: 'descriptions.client.network_interface',
example: "examples.client.network_interface"
description: 'La interfaz de red del cliente',
example: 'eth0'
)]
public ?string $netiface = null;
#[Groups(['client:write'])]
#[ApiProperty(
description: 'descriptions.client.network_driver',
example: "examples.client.network_driver"
description: 'El driver de red del cliente',
example: 'e1000e'
)]
public ?string $netDriver = null;
#[Groups(['client:write'])]
#[ApiProperty(
description: 'descriptions.client.mac_address',
example: "examples.client.mac_address"
description: 'La dirección MAC del cliente',
example: '00:00:00:00:00:00'
)]
public ?string $mac = null;
#[Groups(['client:write'])]
#[Assert\Ip(message: 'validators.ip_address.invalid')]
#[ApiProperty(
description: 'descriptions.client.ip_address',
example: "examples.client.ip_address"
description: 'La dirección IP del cliente',
example: '192.168.1.1'
)]
public ?string $ip = null;
#[Assert\NotNull(message: 'validators.organizational_unit.not_null')]
#[Groups(['client:write', 'client:patch'])]
#[ApiProperty(
description: 'descriptions.client.organizational_unit'
description: 'La unidad organizativa del cliente'
)]
public ?OrganizationalUnitOutput $organizationalUnit = null;
#[Groups(['client:write'])]
#[ApiProperty(
description: 'descriptions.client.menu'
description: 'El menú del cliente'
)]
public ?MenuOutput $menu = null;
#[Groups(['client:write'])]
#[ApiProperty(
description: 'descriptions.client.hardware_profile'
description: 'El perfil de hardware del cliente'
)]
public ?HardwareProfileOutput $hardwareProfile = null;

View File

@ -10,7 +10,7 @@ use Symfony\Component\Validator\Constraints as Assert;
final class HardwareInput
{
#[Assert\NotBlank]
#[Assert\NotBlank(message: 'validators.hardware.name.not_blank')]
#[Groups(['hardware:write'])]
#[ApiProperty(description: 'The name of the hardware', example: "Hardware 1")]
public ?string $name = null;
@ -19,7 +19,7 @@ final class HardwareInput
#[ApiProperty(description: 'The description of the hardware', example: "Hardware 1 description")]
public ?string $description = null;
#[Assert\NotNull]
#[Assert\NotNull(message: 'validators.hardware.type.not_null')]
#[Groups(['hardware:write'])]
#[ApiProperty(description: 'The type of the hardware', example: "Server")]
public ?HardwareTypeOutput $type = null;

View File

@ -8,7 +8,7 @@ use Symfony\Component\Validator\Constraints as Assert;
class HardwareTypeInput
{
#[Assert\NotBlank]
#[Assert\NotBlank(message: 'validators.hardware_type.name.not_blank')]
#[Groups(['hardware-type:write'])]
public ?string $name = null;

View File

@ -11,7 +11,7 @@ use Symfony\Component\Validator\Constraints as Assert;
final class ImageInput
{
#[Assert\NotBlank]
#[Assert\NotBlank(message: 'validators.image.name.not_blank')]
#[Groups(['image:write'])]
#[ApiProperty(description: 'The name of the image', example: "Image 1")]
public ?string $name = null;

View File

@ -18,11 +18,11 @@ class NetworkSettingsInput
#[Groups(['organizational-unit:write'])]
public ?string $proxy = null;
#[Assert\Ip()]
#[Assert\Ip(message: 'validators.network_settings.ip_address.invalid')]
#[Groups(['organizational-unit:write'])]
public ?string $dns = null;
#[Assert\Ip()]
#[Assert\Ip(message: 'validators.network_settings.ip_address.invalid')]
#[Groups(['organizational-unit:write'])]
public ?string $netmask = null;
@ -36,15 +36,15 @@ class NetworkSettingsInput
#[Groups(['organizational-unit:write'])]
public ?string $p2pMode = null;
#[Assert\GreaterThan(0)]
#[Assert\GreaterThan(0, message: 'validators.network_settings.p2p_time.invalid')]
#[Groups(['organizational-unit:write'])]
public ?int $p2pTime = null;
#[Assert\Ip()]
#[Assert\Ip(message: 'validators.network_settings.ip_address.invalid')]
#[Groups(['organizational-unit:write'])]
public ?string $mcastIp = null;
#[Assert\GreaterThan(0)]
#[Assert\GreaterThan(0, message: 'validators.network_settings.mcast_speed.invalid')]
#[Groups(['organizational-write:write'])]
public ?int $mcastSpeed = null;

View File

@ -8,7 +8,7 @@ use Symfony\Component\Validator\Constraints as Assert;
class OperativeSystemInput
{
#[Assert\NotBlank]
#[Assert\NotBlank(message: 'validators.operative_system.name.not_blank')]
#[Groups(['operative-system:write'])]
public ?string $name = null;

View File

@ -16,7 +16,7 @@ use Symfony\Component\Validator\Constraints as Assert;
#[OrganizationalUnitParent]
class OrganizationalUnitInput
{
#[Assert\NotBlank]
#[Assert\NotBlank(message: 'validators.organizational_unit.name.not_blank')]
#[Groups(['organizational-unit:write'])]
public ?string $name = null;

View File

@ -19,6 +19,8 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface
$openApi = $this->decorated->__invoke($context);
$this->addRefreshToken($openApi);
$this->addSearchEndpoint($openApi);
return $openApi;
}
@ -75,4 +77,53 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface
)
));
}
private function addSearchEndpoint(OpenApi $openApi): void
{
$openApi
->getPaths()
->addPath('/search', (new Model\PathItem())->withGet(
(new Model\Operation('getSearch'))
->withTags(['Search'])
->withResponses([
Response::HTTP_OK => [
'description' => 'Search results',
'content' => [
'application/json' => [
'schema' => [
'type' => 'object',
'properties' => [
'results' => [
'type' => 'array',
'items' => [
'type' => 'object',
'properties' => [
'id' => [
'type' => 'integer',
'example' => 1,
],
'name' => [
'type' => 'string',
'example' => 'Item name',
],
],
],
],
],
],
],
],
],
])
->withSummary('Search for items')
->withParameters([
new Model\Parameter(
'query',
'query',
'Search query parameter',
true,
false,
),
])
));
}
}

View File

@ -9,5 +9,31 @@ validators:
not_null: 'The organizational unit should not be null.'
view:
name:
not_blank: 'The name should not be blank.'
hardware:
name:
not_blank: 'The name should not be blank.'
type:
not_null: 'The type should not be null.'
hardware_type:
name:
not_blank: 'The name should not be blank.'
image:
name:
not_blank: 'The name should not be blank.'
network_settings:
ip_address:
invalid: 'The IP address "{{ value }}" is not valid.'
p2p_time:
invalid: 'The P2P time "{{ value }}" is not valid.'
mcast_speed:
invalid: 'The MCAST speed "{{ value }}" is not valid.'
operative_system:
name:
not_blank: 'The name should not be blank.'

View File

@ -9,5 +9,31 @@ validators:
not_null: 'La unidad organizativa no debería estar vacía.'
view:
name:
not_blank: 'El nombre no debería estar vacío.'
hardware:
name:
not_blank: 'El nombre no debería estar vacío.'
type:
not_null: 'El tipo no debería estar vacío.'
hardware_type:
name:
not_blank: 'El nombre no debería estar vacío.'
image:
name:
not_blank: 'El nombre no debería estar vacío.'
network_settings:
ip_address:
invalid: 'La dirección IP "{{ value }}" no es válida.'
p2p_time:
invalid: 'El tiempo P2P "{{ value }}" no es válido.'
mcast_speed:
invalid: 'La velocidad MCAST "{{ value }}" no es válida.'
operative_system:
name:
not_blank: 'El nombre no debería estar vacío.'