Merge pull request 'feature/views' (#8) from feature/views into main
Reviewed-on: #8feature/comunication-ogagent
commit
2e856947f2
|
@ -30,6 +30,7 @@
|
|||
"symfony/runtime": "6.4.*",
|
||||
"symfony/security-bundle": "6.4.*",
|
||||
"symfony/serializer": "6.4.*",
|
||||
"symfony/translation": "6.4.*",
|
||||
"symfony/twig-bundle": "6.4.*",
|
||||
"symfony/validator": "6.4.*",
|
||||
"symfony/yaml": "6.4.*"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "e953b0066fb773aaf6b3835086280c86",
|
||||
"content-hash": "bf1165324e27bddd1a412f25e438fc4c",
|
||||
"packages": [
|
||||
{
|
||||
"name": "api-platform/core",
|
||||
|
@ -6061,6 +6061,101 @@
|
|||
],
|
||||
"time": "2024-05-31T14:49:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v6.4.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "a002933b13989fc4bd0b58e04bf7eec5210e438a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/a002933b13989fc4bd0b58e04bf7eec5210e438a",
|
||||
"reference": "a002933b13989fc4bd0b58e04bf7eec5210e438a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"symfony/deprecation-contracts": "^2.5|^3",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/translation-contracts": "^2.5|^3.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/config": "<5.4",
|
||||
"symfony/console": "<5.4",
|
||||
"symfony/dependency-injection": "<5.4",
|
||||
"symfony/http-client-contracts": "<2.5",
|
||||
"symfony/http-kernel": "<5.4",
|
||||
"symfony/service-contracts": "<2.5",
|
||||
"symfony/twig-bundle": "<5.4",
|
||||
"symfony/yaml": "<5.4"
|
||||
},
|
||||
"provide": {
|
||||
"symfony/translation-implementation": "2.3|3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"nikic/php-parser": "^4.18|^5.0",
|
||||
"psr/log": "^1|^2|^3",
|
||||
"symfony/config": "^5.4|^6.0|^7.0",
|
||||
"symfony/console": "^5.4|^6.0|^7.0",
|
||||
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
|
||||
"symfony/finder": "^5.4|^6.0|^7.0",
|
||||
"symfony/http-client-contracts": "^2.5|^3.0",
|
||||
"symfony/http-kernel": "^5.4|^6.0|^7.0",
|
||||
"symfony/intl": "^5.4|^6.0|^7.0",
|
||||
"symfony/polyfill-intl-icu": "^1.21",
|
||||
"symfony/routing": "^5.4|^6.0|^7.0",
|
||||
"symfony/service-contracts": "^2.5|^3",
|
||||
"symfony/yaml": "^5.4|^6.0|^7.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"Resources/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Translation\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides tools to internationalize your application",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/translation/tree/v6.4.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-31T14:49:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
"version": "v3.5.0",
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
resources:
|
||||
App\Entity\View:
|
||||
processor: App\State\Processor\ViewProcessor
|
||||
input: App\Dto\Input\ViewInput
|
||||
output: App\Dto\Output\ViewOutput
|
||||
normalizationContext:
|
||||
groups: ['default', 'view:read']
|
||||
denormalizationContext:
|
||||
groups: ['view:write']
|
||||
operations:
|
||||
ApiPlatform\Metadata\GetCollection:
|
||||
provider: App\State\Provider\ViewProvider
|
||||
filters:
|
||||
- 'api_platform.filter.view.order'
|
||||
- 'api_platform.filter.view.search'
|
||||
ApiPlatform\Metadata\Get:
|
||||
provider: App\State\Provider\ViewProvider
|
||||
ApiPlatform\Metadata\Put:
|
||||
provider: App\State\Provider\ViewProvider
|
||||
ApiPlatform\Metadata\Patch:
|
||||
provider: App\State\Provider\ViewProvider
|
||||
ApiPlatform\Metadata\Post: ~
|
||||
ApiPlatform\Metadata\Delete: ~
|
||||
|
||||
properties:
|
||||
App\Entity\View:
|
||||
id:
|
||||
identifier: false
|
||||
uuid:
|
||||
identifier: true
|
|
@ -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:
|
||||
|
|
|
@ -11,7 +11,7 @@ security:
|
|||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||
security: false
|
||||
main:
|
||||
stateless: true
|
||||
stateless: false
|
||||
provider: app_user_provider
|
||||
entry_point: jwt
|
||||
json_login:
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
framework:
|
||||
default_locale: es
|
||||
translator:
|
||||
default_path: '%kernel.project_dir%/translations'
|
||||
fallbacks:
|
||||
- en
|
||||
- es
|
||||
providers:
|
|
@ -21,6 +21,12 @@ services:
|
|||
- { name: api_platform.doctrine.orm.query_extension.collection }
|
||||
- { name: api_platform.doctrine.orm.query_extension.item }
|
||||
|
||||
App\EventListener\LocaleSubscriber:
|
||||
arguments:
|
||||
$defaultLocale: '%kernel.default_locale%'
|
||||
tags:
|
||||
- { name: kernel.event_subscriber }
|
||||
|
||||
App\OpenApi\OpenApiFactory:
|
||||
decorates: 'api_platform.openapi.factory'
|
||||
arguments: [ '@App\OpenApi\OpenApiFactory.inner' ]
|
||||
|
@ -90,3 +96,8 @@ services:
|
|||
bind:
|
||||
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
|
||||
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
|
||||
|
||||
App\State\Provider\ViewProvider:
|
||||
bind:
|
||||
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
|
||||
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20240717094811 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE view (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, favourite TINYINT(1) NOT NULL, filters JSON DEFAULT NULL COMMENT \'(DC2Type:json)\', name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_FEFDAB8ED17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('DROP TABLE view');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20240718064611 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE client ADD position JSON DEFAULT NULL COMMENT \'(DC2Type:json)\'');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE client DROP position');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20240801130155 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE view ADD user_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE view ADD CONSTRAINT FK_FEFDAB8EA76ED395 FOREIGN KEY (user_id) REFERENCES user (id)');
|
||||
$this->addSql('CREATE INDEX IDX_FEFDAB8EA76ED395 ON view (user_id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE view DROP FOREIGN KEY FK_FEFDAB8EA76ED395');
|
||||
$this->addSql('DROP INDEX IDX_FEFDAB8EA76ED395 ON view');
|
||||
$this->addSql('ALTER TABLE view DROP user_id');
|
||||
}
|
||||
}
|
|
@ -62,6 +62,7 @@ class MigrateClientsCommand extends Command
|
|||
$clientEntity->setNetdriver($client['netdriver']);
|
||||
$clientEntity->setMac($client['mac']);
|
||||
$clientEntity->setIp($client['ip']);
|
||||
$clientEntity->setPosition(['x' => 0, 'y' => 0]);
|
||||
}
|
||||
|
||||
$migrationId = $client['ordenadores.grupoid'] === 0 ? $client['ordenadores.idaula'] : $client['ordenadores.grupoid'];
|
||||
|
|
|
@ -14,7 +14,7 @@ use Symfony\Component\Console\Command\Command;
|
|||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[AsCommand(name: 'opengnsys:migrate-hardware-profile', description: 'Migrate hardware and hardware profile data')]
|
||||
#[AsCommand(name: 'opengnsys:migration:hardware-profile', description: 'Migrate hardware and hardware profile data')]
|
||||
class MigrateHardwareAndHardwareProfileCommand extends Command
|
||||
{
|
||||
public function __construct(
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace App\Command\Migration;
|
||||
|
||||
use App\Entity\Client;
|
||||
use App\Entity\HardwareProfile;
|
||||
use App\Entity\OperativeSystem;
|
||||
use App\Entity\OrganizationalUnit;
|
||||
use App\Entity\Partition;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Query\ResultSetMapping;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[AsCommand(name: 'opengnsys:migration:partition', description: 'Migrate os data')]
|
||||
class MigratePartitionClientCommand extends Command
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly ManagerRegistry $doctrine
|
||||
)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
ini_set('memory_limit', '512M');
|
||||
|
||||
/** @var EntityManagerInterface $oldDatabaseEntityManager */
|
||||
$oldDatabaseEntityManager = $this->doctrine->getManager('og_1');
|
||||
|
||||
$clientRepository = $this->entityManager->getRepository(Client::class);
|
||||
$operativeSystemRepository = $this->entityManager->getRepository(OperativeSystem::class);
|
||||
|
||||
/** Obtener las particiones de los clientes de la base de datos antigua **/
|
||||
$rsmPartitions = new ResultSetMapping();
|
||||
$rsmPartitions->addScalarResult('idordenador', 'idordenador');
|
||||
$rsmPartitions->addScalarResult('idnombreso', 'idnombreso');
|
||||
$rsmPartitions->addScalarResult('numdisk', 'numdisk');
|
||||
$rsmPartitions->addScalarResult('numpar', 'numpar');
|
||||
$rsmPartitions->addScalarResult('codpar', 'codpar');
|
||||
$rsmPartitions->addScalarResult('tamano', 'tamano');
|
||||
$rsmPartitions->addScalarResult('uso', 'uso');
|
||||
|
||||
$partitionQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idordenador, idnombreso, numdisk, numpar, codpar, tamano, uso FROM ordenadores_particiones', $rsmPartitions);
|
||||
$partitions = $partitionQuery->getResult();
|
||||
|
||||
/** Particiones **/
|
||||
$output->writeln("PARTICIONES TOTAL: ". count($partitions));
|
||||
foreach ($partitions as $partition){
|
||||
$clientEntity = $clientRepository->findOneBy(['migrationId' => $partition['idordenador']]);
|
||||
if(!$clientEntity){
|
||||
$output->writeln("No se ha encontrado el cliente con id: ". $partition['idordenador']);
|
||||
continue;
|
||||
}
|
||||
|
||||
$operativeSystemEntity = $operativeSystemRepository->findOneBy(['migrationId' => $partition['idnombreso']]);
|
||||
if(!$operativeSystemEntity){
|
||||
$output->writeln("No se ha encontrado el sistema operativo con id: ". $partition['idnombreso']);
|
||||
continue;
|
||||
}
|
||||
|
||||
$partitionEntity = new Partition();
|
||||
$partitionEntity->setDiskNumber($partition['numdisk']);
|
||||
$partitionEntity->setPartitionNumber($partition['numpar']);
|
||||
$partitionEntity->setPartitionCode($partition['codpar']);
|
||||
$partitionEntity->setSize($partition['tamano']);
|
||||
$partitionEntity->setMemoryUsage($partition['uso']);
|
||||
$partitionEntity->setClient($clientEntity);
|
||||
$partitionEntity->setOperativeSystem($operativeSystemEntity);
|
||||
|
||||
$this->entityManager->persist($partitionEntity);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ use Symfony\Component\Console\Command\Command;
|
|||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[AsCommand(name: 'opengnsys:migrate-software-profile', description: 'Migrate software and software profile data')]
|
||||
#[AsCommand(name: 'opengnsys:migration:software-profile', description: 'Migrate software and software profile data')]
|
||||
class MigrateSoftwareAndSoftwareProfileCommand extends Command
|
||||
{
|
||||
public function __construct(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace App\Doctrine;
|
||||
|
||||
use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface;
|
||||
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use App\Entity\User;
|
||||
use App\Entity\View;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
|
||||
final readonly class UserViewExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface
|
||||
{
|
||||
public function __construct(
|
||||
private Security $security,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void
|
||||
{
|
||||
$this->addWhere($queryBuilder, $resourceClass);
|
||||
|
||||
}
|
||||
|
||||
public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, ?Operation $operation = null, array $context = []): void
|
||||
{
|
||||
$this->addWhere($queryBuilder, $resourceClass);
|
||||
}
|
||||
|
||||
private function addWhere(QueryBuilder $queryBuilder, string $resourceClass): void
|
||||
{
|
||||
if (View::class !== $resourceClass ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var User $user */
|
||||
$user = $this->security->getUser();
|
||||
|
||||
$rootAlias = $queryBuilder->getRootAliases()[0];
|
||||
$queryBuilder->andWhere(sprintf('%s.user = :current_user', $rootAlias));
|
||||
$queryBuilder->setParameter('current_user', $user->getId());
|
||||
}
|
||||
}
|
|
@ -12,46 +12,75 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
|
||||
final class ClientInput
|
||||
{
|
||||
#[Assert\NotBlank]
|
||||
#[Assert\NotBlank(message: 'validators.client.name.not_blank')]
|
||||
#[Groups(['client:write'])]
|
||||
#[ApiProperty(description: 'The name of the client', example: "Client 1")]
|
||||
#[ApiProperty(
|
||||
description: 'El nombre del cliente',
|
||||
example: 'Cliente 1',
|
||||
)]
|
||||
public ?string $name = null;
|
||||
|
||||
#[Groups(['client:write'])]
|
||||
#[ApiProperty(description: 'The serial number of the client', example: "123456")]
|
||||
#[ApiProperty(
|
||||
description: 'La descripción del cliente',
|
||||
example: 'Cliente descripcion 1',
|
||||
)]
|
||||
public ?string $serialNumber = null;
|
||||
|
||||
#[Groups(['client:write'])]
|
||||
#[ApiProperty(description: 'The network interface of the client', example: "eth0")]
|
||||
#[ApiProperty(
|
||||
description: 'La interfaz de red del cliente',
|
||||
example: 'eth0'
|
||||
)]
|
||||
public ?string $netiface = null;
|
||||
|
||||
#[Groups(['client:write'])]
|
||||
#[ApiProperty(description: 'The network driver of the client', example: "e1000e")]
|
||||
#[ApiProperty(
|
||||
description: 'El driver de red del cliente',
|
||||
example: 'e1000e'
|
||||
)]
|
||||
public ?string $netDriver = null;
|
||||
|
||||
#[Groups(['client:write'])]
|
||||
#[ApiProperty(description: 'The MAC address of the client', example: "00:11:22:33:44:55")]
|
||||
#[ApiProperty(
|
||||
description: 'La dirección MAC del cliente',
|
||||
example: '00:00:00:00:00:00'
|
||||
)]
|
||||
public ?string $mac = null;
|
||||
|
||||
#[Groups(['client:write'])]
|
||||
#[Assert\Ip]
|
||||
#[ApiProperty(description: 'The IP address of the client', example: "127.0.0.1")]
|
||||
#[Assert\Ip(message: 'validators.ip_address.invalid')]
|
||||
#[ApiProperty(
|
||||
description: 'La dirección IP del cliente',
|
||||
example: '192.168.1.1'
|
||||
)]
|
||||
public ?string $ip = null;
|
||||
|
||||
#[Groups(['client:write'])]
|
||||
public ?string $status = null;
|
||||
|
||||
#[Assert\NotNull]
|
||||
#[Assert\NotNull(message: 'validators.organizational_unit.not_null')]
|
||||
#[Groups(['client:write', 'client:patch'])]
|
||||
#[ApiProperty(description: 'The organizational unit of the client')]
|
||||
#[ApiProperty(
|
||||
description: 'La unidad organizativa del cliente'
|
||||
)]
|
||||
public ?OrganizationalUnitOutput $organizationalUnit = null;
|
||||
|
||||
#[Groups(['client:write'])]
|
||||
#[ApiProperty(
|
||||
description: 'El menú del cliente'
|
||||
)]
|
||||
public ?MenuOutput $menu = null;
|
||||
|
||||
#[Groups(['client:write'])]
|
||||
#[ApiProperty(
|
||||
description: 'El perfil de hardware del cliente'
|
||||
)]
|
||||
public ?HardwareProfileOutput $hardwareProfile = null;
|
||||
|
||||
#[Groups(['client:write'])]
|
||||
#[ApiProperty(
|
||||
description: 'descriptions.client.validation'
|
||||
)]
|
||||
public ?array $position = ['x' => 0, 'y' => 0];
|
||||
|
||||
public function __construct(?Client $client = null)
|
||||
{
|
||||
if (!$client) {
|
||||
|
@ -65,7 +94,7 @@ final class ClientInput
|
|||
$this->netDriver = $client->getNetDriver();
|
||||
$this->mac = $client->getMac();
|
||||
$this->ip = $client->getIp();
|
||||
$this->status = $client->getStatus();
|
||||
$this->position = $client->getPosition();
|
||||
|
||||
if ($client->getMenu()) {
|
||||
$this->menu = new MenuOutput($client->getMenu());
|
||||
|
@ -89,10 +118,10 @@ final class ClientInput
|
|||
$client->setNetDriver($this->netDriver);
|
||||
$client->setMac($this->mac);
|
||||
$client->setIp($this->ip);
|
||||
$client->setStatus($this->status);
|
||||
$client->setMenu($this->menu?->getEntity());
|
||||
$client->setHardwareProfile($this->hardwareProfile?->getEntity());
|
||||
$client->setPosition($this->position);
|
||||
|
||||
return $client;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use ApiPlatform\Metadata\ApiProperty;
|
||||
use App\Entity\View;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
final class ViewInput
|
||||
{
|
||||
#[Assert\NotBlank(message: 'validators.view.name.not_blank')]
|
||||
#[Groups(['view:write'])]
|
||||
#[ApiProperty(description: 'The name of the view', example: "View 1")]
|
||||
public ?string $name = null;
|
||||
|
||||
#[Groups(['view:write'])]
|
||||
#[ApiProperty(description: 'The favourite status of the view', example: true)]
|
||||
public ?bool $favourite = null;
|
||||
|
||||
#[Groups(['view:write'])]
|
||||
#[ApiProperty(description: 'The filters of the view', example: ["filter1" => "value1"])]
|
||||
public ?array $filters = null;
|
||||
|
||||
public function __construct(?View $view = null)
|
||||
{
|
||||
if (!$view) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->name = $view->getName();
|
||||
$this->favourite = $view->isFavourite();
|
||||
$this->filters= $view->getFilters();
|
||||
}
|
||||
|
||||
public function createOrUpdateEntity(?View $view = null): View
|
||||
{
|
||||
if (!$view) {
|
||||
$view = new View();
|
||||
}
|
||||
|
||||
$view->setName($this->name);
|
||||
$view->setFavourite($this->favourite);
|
||||
$view->setFilters($this->filters);
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
}
|
|
@ -48,6 +48,9 @@ final class ClientOutput extends AbstractOutput
|
|||
#[ApiProperty(readableLink: true )]
|
||||
public ?HardwareProfileOutput $hardwareProfile = null;
|
||||
|
||||
#[Groups(['client:read'])]
|
||||
public ?array $position = ['x' => 0, 'y' => 0];
|
||||
|
||||
#[Groups(['client:read'])]
|
||||
public \DateTime $createdAt;
|
||||
|
||||
|
@ -74,8 +77,8 @@ final class ClientOutput extends AbstractOutput
|
|||
)->toArray();
|
||||
|
||||
$this->menu = $client->getMenu() ? new MenuOutput($client->getMenu()) : null;
|
||||
$this->position = $client->getPosition();
|
||||
$this->hardwareProfile = $client->getHardwareProfile() ? new HardwareProfileOutput($client->getHardwareProfile()) : null;
|
||||
|
||||
$this->createdAt = $client->getCreatedAt();
|
||||
$this->createdBy = $client->getCreatedBy();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Output;
|
||||
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use App\Entity\View;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
#[Get(shortName: 'View')]
|
||||
final class ViewOutput extends AbstractOutput
|
||||
{
|
||||
#[Groups(['view:read'])]
|
||||
public string $name;
|
||||
|
||||
#[Groups(['view:read'])]
|
||||
public bool $favorite;
|
||||
|
||||
#[Groups(['view:read'])]
|
||||
public ?array $filters = null;
|
||||
|
||||
public function __construct(View $view)
|
||||
{
|
||||
parent::__construct($view);
|
||||
|
||||
$this->name = $view->getName();
|
||||
$this->favorite = $view->isFavourite();
|
||||
$this->filters = $view->getFilters();
|
||||
}
|
||||
}
|
|
@ -54,6 +54,9 @@ class Client extends AbstractEntity
|
|||
#[ORM\Column(nullable: true)]
|
||||
private ?bool $validation = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?array $position = ['x' => 0, 'y' => 0];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
@ -209,4 +212,16 @@ class Client extends AbstractEntity
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPosition(): ?array
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function setPosition(?array $position): static
|
||||
{
|
||||
$this->position = $position;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\ViewRepository;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: ViewRepository::class)]
|
||||
class View extends \App\Entity\AbstractEntity
|
||||
{
|
||||
use NameableTrait;
|
||||
|
||||
#[ORM\Column]
|
||||
private ?bool $favourite = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, nullable: true)]
|
||||
private ?array $filters = [];
|
||||
|
||||
#[ORM\ManyToOne]
|
||||
private ?User $user = null;
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isFavourite(): ?bool
|
||||
{
|
||||
return $this->favourite;
|
||||
}
|
||||
|
||||
public function setFavourite(bool $favourite): static
|
||||
{
|
||||
$this->favourite = $favourite;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFilters(): ?array
|
||||
{
|
||||
return $this->filters;
|
||||
}
|
||||
|
||||
public function setFilters(?array $filters): static
|
||||
{
|
||||
$this->filters = $filters;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUser(): ?User
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function setUser(?User $user): static
|
||||
{
|
||||
$this->user = $user;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
// src/EventListener/LocaleSubscriber.php
|
||||
namespace App\EventListener;
|
||||
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
class LocaleSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
private string $defaultLocale;
|
||||
private RequestStack $requestStack;
|
||||
|
||||
public function __construct(RequestStack $requestStack, string $defaultLocale = 'es')
|
||||
{
|
||||
$this->defaultLocale = $defaultLocale;
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function onKernelRequest(RequestEvent $event): void
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
$locale = $request->getSession()->get('_locale', $this->defaultLocale);
|
||||
|
||||
if ($request->attributes->get('_locale')) {
|
||||
$locale = $request->attributes->get('_locale');
|
||||
}
|
||||
|
||||
$localeFromHeader = $request->getPreferredLanguage(['en', 'es']);
|
||||
if ($localeFromHeader) {
|
||||
$locale = $localeFromHeader;
|
||||
}
|
||||
|
||||
$request->setLocale($locale);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::REQUEST => [['onKernelRequest', 20]],
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Entity\View;
|
||||
use App\Repository\ViewRepository;
|
||||
use Zenstruck\Foundry\ModelFactory;
|
||||
use Zenstruck\Foundry\Persistence\PersistentProxyObjectFactory;
|
||||
use Zenstruck\Foundry\Persistence\Proxy;
|
||||
use Zenstruck\Foundry\Persistence\ProxyRepositoryDecorator;
|
||||
|
||||
/**
|
||||
* @extends PersistentProxyObjectFactory<View>
|
||||
*/
|
||||
final class ViewFactory extends ModelFactory
|
||||
{
|
||||
/**
|
||||
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services
|
||||
*
|
||||
* @todo inject services if required
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public static function class(): string
|
||||
{
|
||||
return View::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories
|
||||
*
|
||||
* @todo add your default values here
|
||||
*/
|
||||
protected function getDefaults(): array
|
||||
{
|
||||
return [
|
||||
'createdAt' => self::faker()->dateTime(),
|
||||
'favourite' => self::faker()->boolean(),
|
||||
'name' => self::faker()->text(255),
|
||||
'updatedAt' => self::faker()->dateTime()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization
|
||||
*/
|
||||
protected function initialize(): self
|
||||
{
|
||||
return $this
|
||||
// ->afterInstantiate(function(View $view): void {})
|
||||
;
|
||||
}
|
||||
|
||||
protected static function getClass(): string
|
||||
{
|
||||
return View::class;
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
),
|
||||
])
|
||||
));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\View;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<View>
|
||||
*/
|
||||
class ViewRepository extends AbstractRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, View::class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace App\State\Processor;
|
||||
|
||||
use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use ApiPlatform\State\ProcessorInterface;
|
||||
use ApiPlatform\Validator\ValidatorInterface;
|
||||
use App\Dto\Input\ViewInput;
|
||||
use App\Dto\Output\ViewOutput;
|
||||
use App\Repository\ViewRepository;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
readonly class ViewProcessor implements ProcessorInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ViewRepository $viewRepository,
|
||||
private ValidatorInterface $validator,
|
||||
private Security $security
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): ViewOutput|null
|
||||
{
|
||||
switch ($operation){
|
||||
case $operation instanceof Post:
|
||||
case $operation instanceof Put:
|
||||
case $operation instanceof Patch:
|
||||
return $this->processCreateOrUpdate($data, $operation, $uriVariables, $context);
|
||||
case $operation instanceof Delete:
|
||||
return $this->processDelete($data, $operation, $uriVariables, $context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): ViewOutput
|
||||
{
|
||||
if (!($data instanceof ViewInput)) {
|
||||
throw new \Exception(sprintf('data is not instance of %s', ViewInput::class));
|
||||
}
|
||||
|
||||
$entity = null;
|
||||
if (isset($uriVariables['uuid'])) {
|
||||
$entity = $this->viewRepository->findOneByUuid($uriVariables['uuid']);
|
||||
}
|
||||
|
||||
$view = $data->createOrUpdateEntity($entity);
|
||||
$view->setUser($this->security->getUser());
|
||||
$this->validator->validate($view);
|
||||
$this->viewRepository->save($view);
|
||||
|
||||
return new ViewOutput($view);
|
||||
}
|
||||
|
||||
private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null
|
||||
{
|
||||
$user = $this->viewRepository->findOneByUuid($uriVariables['uuid']);
|
||||
$this->viewRepository->delete($user);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace App\State\Provider;
|
||||
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use ApiPlatform\State\Pagination\TraversablePaginator;
|
||||
use ApiPlatform\State\ProviderInterface;
|
||||
use App\Dto\Input\ViewInput;
|
||||
use App\Dto\Output\ViewOutput;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
readonly class ViewProvider implements ProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ProviderInterface $collectionProvider,
|
||||
private ProviderInterface $itemProvider
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||
{
|
||||
switch ($operation){
|
||||
case $operation instanceof GetCollection:
|
||||
return $this->provideCollection($operation, $uriVariables, $context);
|
||||
case $operation instanceof Patch:
|
||||
case $operation instanceof Put:
|
||||
return $this->provideInput($operation, $uriVariables, $context);
|
||||
case $operation instanceof Get:
|
||||
return $this->provideItem($operation, $uriVariables, $context);
|
||||
}
|
||||
}
|
||||
|
||||
private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object
|
||||
{
|
||||
$paginator = $this->collectionProvider->provide($operation, $uriVariables, $context);
|
||||
|
||||
$items = new \ArrayObject();
|
||||
foreach ($paginator->getIterator() as $item){
|
||||
$items[] = new ViewOutput($item);
|
||||
}
|
||||
|
||||
return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems());
|
||||
}
|
||||
|
||||
public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||
{
|
||||
$item = $this->itemProvider->provide($operation, $uriVariables, $context);
|
||||
|
||||
if (!$item) {
|
||||
throw new NotFoundHttpException('View not found');
|
||||
}
|
||||
|
||||
return new ViewOutput($item);
|
||||
}
|
||||
|
||||
public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||
{
|
||||
if (isset($uriVariables['uuid'])) {
|
||||
$item = $this->itemProvider->provide($operation, $uriVariables, $context);
|
||||
|
||||
return $item !== null ? new ViewInput($item) : null;
|
||||
}
|
||||
|
||||
return new ViewInput();
|
||||
}
|
||||
}
|
13
symfony.lock
13
symfony.lock
|
@ -219,6 +219,19 @@
|
|||
"config/routes/security.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/translation": {
|
||||
"version": "6.4",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.3",
|
||||
"ref": "e28e27f53663cc34f0be2837aba18e3a1bef8e7b"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/translation.yaml",
|
||||
"translations/.gitignore"
|
||||
]
|
||||
},
|
||||
"symfony/twig-bundle": {
|
||||
"version": "6.4",
|
||||
"recipe": {
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
namespace Functional;
|
||||
|
||||
|
||||
use App\Entity\HardwareProfile;
|
||||
use App\Entity\OrganizationalUnit;
|
||||
use App\Entity\View;
|
||||
use App\Factory\HardwareProfileFactory;
|
||||
use App\Factory\OrganizationalUnitFactory;
|
||||
use App\Factory\UserFactory;
|
||||
use App\Factory\ViewFactory;
|
||||
use App\Model\OrganizationalUnitTypes;
|
||||
use App\Model\UserGroupPermissions;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
class ViewTest extends AbstractTest
|
||||
{
|
||||
CONST string USER_ADMIN = 'ogadmin';
|
||||
CONST string VIEW_CREATE = 'test-view-create';
|
||||
CONST string VIEW_UPDATE = 'test-view-update';
|
||||
CONST string VIEW_DELETE = 'test-view-delete';
|
||||
|
||||
/**
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws DecodingExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
*/
|
||||
public function testGetCollectionViews(): void
|
||||
{
|
||||
$user = UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
|
||||
|
||||
ViewFactory::createMany(10, ['user' => $user]);
|
||||
|
||||
$this->createClientWithCredentials()->request('GET', '/views');
|
||||
$this->assertResponseStatusCodeSame(Response::HTTP_OK);
|
||||
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
|
||||
$this->assertJsonContains([
|
||||
'@context' => '/contexts/View',
|
||||
'@id' => '/views',
|
||||
'@type' => 'hydra:Collection',
|
||||
'hydra:totalItems' => 10,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws DecodingExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
*/
|
||||
public function testCreateView(): void
|
||||
{
|
||||
$user = UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
|
||||
|
||||
ViewFactory::createOne(['name' => self::VIEW_CREATE, 'favourite' => true, 'user' => $user]);
|
||||
$viewIri = $this->findIriBy(View::class, ['name' => self::VIEW_CREATE]);
|
||||
|
||||
$this->createClientWithCredentials()->request('POST', '/views',['json' => [
|
||||
'name' => self::VIEW_CREATE,
|
||||
'favourite' => true
|
||||
]]);
|
||||
|
||||
$this->assertResponseStatusCodeSame(201);
|
||||
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
|
||||
$this->assertJsonContains([
|
||||
'@context' => '/contexts/ViewOutput',
|
||||
'@type' => 'View',
|
||||
'name' => self::VIEW_CREATE
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws DecodingExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
*/
|
||||
public function testUpdateView(): void
|
||||
{
|
||||
$user = UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
|
||||
|
||||
ViewFactory::createOne(['name' => self::VIEW_CREATE, 'favourite' => true, 'user' => $user]);
|
||||
$viewIri = $this->findIriBy(View::class, ['name' => self::VIEW_CREATE]);
|
||||
|
||||
$this->createClientWithCredentials()->request('PUT', $viewIri, ['json' => [
|
||||
'name' => self::VIEW_UPDATE,
|
||||
'favourite' => false
|
||||
]]);
|
||||
|
||||
$this->assertResponseIsSuccessful();
|
||||
$this->assertJsonContains([
|
||||
'@id' => $viewIri,
|
||||
'name' => self::VIEW_UPDATE,
|
||||
'favorite' => false
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws DecodingExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function testDeleteView(): void
|
||||
{
|
||||
$user = UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
|
||||
|
||||
ViewFactory::createOne(['name' => self::VIEW_DELETE, 'favourite' => true, 'user' => $user]);
|
||||
$viewIri = $this->findIriBy(View::class, ['name' => self::VIEW_DELETE]);
|
||||
|
||||
$this->createClientWithCredentials()->request('DELETE', $viewIri);
|
||||
$this->assertResponseStatusCodeSame(204);
|
||||
$this->assertNull(
|
||||
static::getContainer()->get('doctrine')->getRepository(View::class)->findOneBy(['name' => self::VIEW_DELETE])
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
# messages.en.yaml
|
||||
validators:
|
||||
client:
|
||||
ip_address:
|
||||
invalid: 'The IP address "{{ value }}" is not valid.'
|
||||
name:
|
||||
not_blank: 'The name should not be blank.'
|
||||
organizational_unit:
|
||||
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.'
|
|
@ -0,0 +1,39 @@
|
|||
# messages.es.yaml
|
||||
validators:
|
||||
client:
|
||||
ip_address:
|
||||
invalid: 'La dirección IP "{{ value }}" no es válida.'
|
||||
name:
|
||||
not_blank: 'El nombre no debería estar vacío.'
|
||||
organizational_unit:
|
||||
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.'
|
Loading…
Reference in New Issue