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: api_platform:
title: 'OgCore API' title: 'OgCore Api'
description: 'API Documentation for OgCore' description: 'Api Documentation for OgCore'
version: 1.0.0 version: 1.0.0
path_segment_name_generator: 'api_platform.path_segment_name_generator.dash' path_segment_name_generator: 'api_platform.path_segment_name_generator.dash'
formats: 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')] #[Assert\NotBlank(message: 'validators.client.name.not_blank')]
#[Groups(['client:write'])] #[Groups(['client:write'])]
#[ApiProperty( #[ApiProperty(
description: 'descriptions.client.name', description: 'El nombre del cliente',
example: "examples.client.name", example: 'Cliente 1',
)] )]
public ?string $name = null; public ?string $name = null;
#[Groups(['client:write'])] #[Groups(['client:write'])]
#[ApiProperty( #[ApiProperty(
description: 'descriptions.client.serial_number', description: 'La descripción del cliente',
example: "examples.client.serial_number" example: 'Cliente descripcion 1',
)] )]
public ?string $serialNumber = null; public ?string $serialNumber = null;
#[Groups(['client:write'])] #[Groups(['client:write'])]
#[ApiProperty( #[ApiProperty(
description: 'descriptions.client.network_interface', description: 'La interfaz de red del cliente',
example: "examples.client.network_interface" example: 'eth0'
)] )]
public ?string $netiface = null; public ?string $netiface = null;
#[Groups(['client:write'])] #[Groups(['client:write'])]
#[ApiProperty( #[ApiProperty(
description: 'descriptions.client.network_driver', description: 'El driver de red del cliente',
example: "examples.client.network_driver" example: 'e1000e'
)] )]
public ?string $netDriver = null; public ?string $netDriver = null;
#[Groups(['client:write'])] #[Groups(['client:write'])]
#[ApiProperty( #[ApiProperty(
description: 'descriptions.client.mac_address', description: 'La dirección MAC del cliente',
example: "examples.client.mac_address" example: '00:00:00:00:00:00'
)] )]
public ?string $mac = null; public ?string $mac = null;
#[Groups(['client:write'])] #[Groups(['client:write'])]
#[Assert\Ip(message: 'validators.ip_address.invalid')] #[Assert\Ip(message: 'validators.ip_address.invalid')]
#[ApiProperty( #[ApiProperty(
description: 'descriptions.client.ip_address', description: 'La dirección IP del cliente',
example: "examples.client.ip_address" example: '192.168.1.1'
)] )]
public ?string $ip = null; public ?string $ip = null;
#[Assert\NotNull(message: 'validators.organizational_unit.not_null')] #[Assert\NotNull(message: 'validators.organizational_unit.not_null')]
#[Groups(['client:write', 'client:patch'])] #[Groups(['client:write', 'client:patch'])]
#[ApiProperty( #[ApiProperty(
description: 'descriptions.client.organizational_unit' description: 'La unidad organizativa del cliente'
)] )]
public ?OrganizationalUnitOutput $organizationalUnit = null; public ?OrganizationalUnitOutput $organizationalUnit = null;
#[Groups(['client:write'])] #[Groups(['client:write'])]
#[ApiProperty( #[ApiProperty(
description: 'descriptions.client.menu' description: 'El menú del cliente'
)] )]
public ?MenuOutput $menu = null; public ?MenuOutput $menu = null;
#[Groups(['client:write'])] #[Groups(['client:write'])]
#[ApiProperty( #[ApiProperty(
description: 'descriptions.client.hardware_profile' description: 'El perfil de hardware del cliente'
)] )]
public ?HardwareProfileOutput $hardwareProfile = null; public ?HardwareProfileOutput $hardwareProfile = null;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,6 +19,8 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface
$openApi = $this->decorated->__invoke($context); $openApi = $this->decorated->__invoke($context);
$this->addRefreshToken($openApi); $this->addRefreshToken($openApi);
$this->addSearchEndpoint($openApi);
return $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

@ -11,3 +11,29 @@ validators:
view: view:
name: name:
not_blank: 'The name should not be blank.' 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

@ -11,3 +11,29 @@ validators:
view: view:
name: name:
not_blank: 'El nombre no debería estar vacío.' 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.'