refs #425. NetworkSettings validation

pull/7/head
Manuel Aranda Rosales 2024-06-18 16:16:42 +02:00
parent 00b37723f6
commit f746f435e4
22 changed files with 153 additions and 164 deletions

View File

@ -1,18 +0,0 @@
resources:
App\Entity\NetworkSettings:
output: App\Dto\Output\NetworkSettingsOutput
operations:
ApiPlatform\Metadata\GetCollection:
provider: App\State\Provider\MenuProvider
filters:
- 'api_platform.filter.menu.order'
- 'api_platform.filter.menu.search'
ApiPlatform\Metadata\Get:
provider: App\State\Provider\MenuProvider
properties:
App\Entity\NetworkSettings:
id:
identifier: false
uuid:
identifier: true

View File

@ -7,7 +7,8 @@ resources:
groups: ['default', 'organizational-unit:read']
denormalization_context:
groups: ['organizational-unit:write']
validation_context:
groups: ['organizational-unit:write']
operations:
ApiPlatform\Metadata\GetCollection:
provider: App\State\Provider\OrganizationalUnitProvider

View File

@ -65,11 +65,6 @@ services:
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
App\State\Provider\NetworkSettingsProvider:
bind:
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
App\State\Provider\OperativeSystemProvider:
bind:
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'

View File

@ -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 Version20240618113629 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 UNIQUE INDEX UNIQ_IDENTIFIER_NAME ON organizational_unit (name)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP INDEX UNIQ_IDENTIFIER_NAME ON organizational_unit');
}
}

View File

@ -5,50 +5,58 @@ namespace App\Dto\Input;
use App\Entity\HardwareProfile;
use App\Entity\Menu;
use App\Entity\NetworkSettings;
use App\Validator\Constraints\OrganizationalUnitMulticastMode;
use App\Validator\Constraints\OrganizationalUnitMulticastPort;
use App\Validator\Constraints\OrganizationalUnitP2PMode;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
class NetworkSettingsInput
{
#[Groups(['organizational-write:read'])]
#[Groups(['organizational-unit:write'])]
public ?string $proxy = null;
#[Groups(['organizational-write:read'])]
#[Groups(['organizational-unit:write'])]
public ?string $dns = null;
#[Groups(['organizational-write:read'])]
#[Groups(['organizational-unit:write'])]
public ?string $netmask = null;
#[Groups(['organizational-write:read'])]
#[Groups(['organizational-unit:write'])]
public ?string $router = null;
#[Groups(['organizational-write:read'])]
#[Groups(['organizational-unit:write'])]
public ?string $ntp = null;
#[Groups(['organizational-write:read'])]
#[OrganizationalUnitP2PMode]
#[Groups(['organizational-unit:write'])]
public ?string $p2pMode = null;
#[Groups(['organizational-write:read'])]
#[Groups(['organizational-unit:write'])]
public ?int $p2pTime = null;
#[Groups(['organizational-write:read'])]
#[Assert\Ip()]
#[Groups(['organizational-unit:write'])]
public ?string $mcastIp = null;
#[Groups(['organizational-write:read'])]
#[Groups(['organizational-write:write'])]
public ?int $mcastSpeed = null;
#[Groups(['organizational-write:read'])]
#[OrganizationalUnitMulticastPort]
#[Groups(['organizational-unit:write'])]
public ?int $mcastPort = null;
#[Groups(['organizational-write:read'])]
#[OrganizationalUnitMulticastMode]
#[Groups(['organizational-unit:write'])]
public ?string $mcastMode = null;
#[Groups(['organizational-write:read'])]
#[Groups(['organizational-unit:write'])]
public ?Menu $menu = null;
#[Groups(['organizational-write:read'])]
#[Groups(['organizational-unit:write'])]
public ?HardwareProfile $hardwareProfile = null;
#[Groups(['organizational-write:read'])]
#[Groups(['organizational-unit:write'])]
public ?bool $validation = null;
public function __construct(?NetworkSettings $networkSettings = null)

View File

@ -2,8 +2,13 @@
namespace App\Dto\Input;
use ApiPlatform\Metadata\ApiProperty;
use App\Dto\Output\OrganizationalUnitOutput;
use App\Entity\OrganizationalUnit;
use App\Validator\Constraints\OrganizationalUnitMulticastMode;
use App\Validator\Constraints\OrganizationalUnitMulticastPort;
use App\Validator\Constraints\OrganizationalUnitP2PMode;
use App\Validator\Constraints\OrganizationalUnitType;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
@ -23,9 +28,11 @@ class OrganizationalUnitInput
public ?string $comments = null;
#[Groups(['organizational-unit:write'])]
#[OrganizationalUnitType]
public ?string $type = null;
#[Groups(['organizational-unit:write'])]
#[Assert\Valid()]
public ?NetworkSettingsInput $networkSettings = null;
public function __construct(?OrganizationalUnit $organizationalUnit = null)

View File

@ -7,9 +7,12 @@ use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Tree\Entity\Repository\MaterializedPathRepository;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
#[Gedmo\Tree(type: 'materializedPath')]
#[ORM\Entity(repositoryClass: MaterializedPathRepository::class)]
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_NAME', fields: ['name', 'parent_id'])]
#[UniqueEntity(fields: ['name', 'parent'], message: 'This organizational unit already exists.')]
class OrganizationalUnit extends AbstractEntity
{
use NameableTrait;

View File

@ -2,10 +2,10 @@
namespace App\Model;
final class OrganizationalUnitClassroomMulticastModes
final class OrganizationalUnitMulticastModes
{
public const string HALF_DUPLEX = 'half_duplex';
public const string FULL_DUPLEX = 'full_duplex';
public const string HALF_DUPLEX = 'half-duplex';
public const string FULL_DUPLEX = 'full-duplex';
private const array MCAST_MODES = [
self::HALF_DUPLEX => 'Half Duplex',

View File

@ -2,11 +2,11 @@
namespace App\Model;
final class OrganizationalUnitClassroomP2pModes
final class OrganizationalUnitP2PModes
{
public const string P2P_MODE_LEECHER = 'p2p_mode_leecher';
public const string P2P_MODE_PEER = 'p2p_mode_peer';
public const string P2P_MODE_SEEDER = 'p2p_mode_seeder';
public const string P2P_MODE_LEECHER = 'p2p-mode-leecher';
public const string P2P_MODE_PEER = 'p2p-mode-peer';
public const string P2P_MODE_SEEDER = 'p2p-mode-seeder';
private const array P2P_MODE_NAMES = [
self::P2P_MODE_LEECHER => 'El cliente no comparte mientras descarga la imagen',

View File

@ -4,12 +4,12 @@ namespace App\Model;
final class OrganizationalUnitTypes
{
public const ORGANIZATIONAL_UNIT = 'ORGANIZATIONAL_UNIT';
public const CLASSROOMS_GROUP = 'CLASSROOMS_GROUP';
public const CLASSROOM = 'CLASSROOM';
public const CLIENTS_GROUP = 'CLIENTS_GROUP';
public const string ORGANIZATIONAL_UNIT = 'organizational-unit';
public const string CLASSROOMS_GROUP = 'classrooms-group';
public const string CLASSROOM = 'classroom';
public const string CLIENTS_GROUP = 'clients-group';
private const ORGANIZATIONAL_UNIT_TYPES = [
private const array ORGANIZATIONAL_UNIT_TYPES = [
self::ORGANIZATIONAL_UNIT => 'Unidad Organizativa',
self::CLASSROOMS_GROUP => 'Grupo de aulas',
self::CLASSROOM => 'Aula',

View File

@ -4,14 +4,13 @@ namespace App\Model;
final class UserGroupPermissions
{
public const ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN';
public const ROLE_ORGANIZATIONAL_UNIT_ADMIN = 'ROLE_ORGANIZATIONAL_UNIT_ADMIN';
public const ROLE_ORGANIZATIONAL_UNIT_OPERATOR = 'ROLE_ORGANIZATIONAL_UNIT_OPERATOR';
public const ROLE_ORGANIZATIONAL_UNIT_MINIMAL = 'ROLE_ORGANIZATIONAL_UNIT_MINIMAL';
public const string ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN';
public const string ROLE_ORGANIZATIONAL_UNIT_ADMIN = 'ROLE_ORGANIZATIONAL_UNIT_ADMIN';
public const string ROLE_ORGANIZATIONAL_UNIT_OPERATOR = 'ROLE_ORGANIZATIONAL_UNIT_OPERATOR';
public const string ROLE_ORGANIZATIONAL_UNIT_MINIMAL = 'ROLE_ORGANIZATIONAL_UNIT_MINIMAL';
public const string ROLE_USER = 'ROLE_USER';
public const ROLE_USER = 'ROLE_USER';
private const ROLE_NAMES = [
private const array ROLE_NAMES = [
self::ROLE_SUPER_ADMIN => 'Super Admin',
self::ROLE_ORGANIZATIONAL_UNIT_ADMIN => 'Admin de aulas',
self::ROLE_ORGANIZATIONAL_UNIT_OPERATOR => 'Operador de aulas',

View File

@ -9,35 +9,10 @@ use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<NetworkSettings>
*/
class NetworkSettingsRepository extends ServiceEntityRepository
class NetworkSettingsRepository extends AbstractRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, NetworkSettings::class);
}
// /**
// * @return NetworkSettings[] Returns an array of NetworkSettings objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('n')
// ->andWhere('n.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('n.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?NetworkSettings
// {
// return $this->createQueryBuilder('n')
// ->andWhere('n.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View File

@ -58,8 +58,8 @@ class OrganizationalUnitProcessor implements ProcessorInterface
$entity = $this->organizationalUnitRepository->findOneByUuid($uriVariables['uuid']);
}
$organizationalUnit = $data->createOrUpdateEntity($entity, $this->entityManager);
$this->validator->validate($organizationalUnit);
$organizationalUnit = $data->createOrUpdateEntity($entity);
$this->validator->validate($organizationalUnit, ['groups' => ['organizational-unit:write']]);
$this->organizationalUnitRepository->save($organizationalUnit);
return new OrganizationalUnitOutput($organizationalUnit);

View File

@ -1,61 +0,0 @@
<?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\ClientInput;
use App\Dto\Input\HardwareInput;
use App\Dto\Output\ClientOutput;
use App\Dto\Output\HardwareOutput;
use App\Dto\Output\NetworkSettingsOutput;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class NetworkSettingsProvider implements ProviderInterface
{
public function __construct(
private readonly ProviderInterface $collectionProvider,
private readonly 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 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 NetworkSettingsOutput($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('Hardware not found');
}
return new NetworkSettingsOutput($item);
}
}

View File

@ -2,12 +2,12 @@
namespace App\Validator\Constraints;
use App\Model\OrganizationalUnitClassroomMulticastModes;
use App\Model\OrganizationalUnitMulticastModes;
use App\Model\UserGroupPermissions;
use Symfony\Component\Validator\Constraint;
#[\Attribute]
class OrganizationalUnitClassroomMulticastMode extends Constraint
class OrganizationalUnitMulticastMode extends Constraint
{
private array $modes;
public string $message;
@ -16,7 +16,7 @@ class OrganizationalUnitClassroomMulticastMode extends Constraint
{
parent::__construct($options, $groups, $payload);
$this->modes = OrganizationalUnitClassroomMulticastModes::getMcastModes();
$this->modes = OrganizationalUnitMulticastModes::getMcastModes();
$this->message = sprintf(
'The multicast mode is not valid. Please use one of the following: %s',
implode(', ', $this->modes)

View File

@ -2,13 +2,13 @@
namespace App\Validator\Constraints;
use App\Model\OrganizationalUnitClassroomMulticastModes;
use App\Model\OrganizationalUnitClassroomP2pModes;
use App\Model\OrganizationalUnitMulticastModes;
use App\Model\OrganizationalUnitP2PModes;
use App\Model\UserGroupPermissions;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class OrganizationalUnitClassroomMulticastModeValidator extends ConstraintValidator
class OrganizationalUnitMulticastModeValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint): void
{
@ -16,7 +16,7 @@ class OrganizationalUnitClassroomMulticastModeValidator extends ConstraintValida
return;
}
if (!in_array($value, OrganizationalUnitClassroomMulticastModes::getMcastModes())) {
if (!in_array($value, OrganizationalUnitMulticastModes::getMcastModes())) {
$this->context->buildViolation($constraint->message)->addViolation();
}
}

View File

@ -6,7 +6,7 @@ use App\Model\UserGroupPermissions;
use Symfony\Component\Validator\Constraint;
#[\Attribute]
class OrganizationalUnitClassroomMulticastPort extends Constraint
class OrganizationalUnitMulticastPort extends Constraint
{
public string $message;
@ -16,6 +16,4 @@ class OrganizationalUnitClassroomMulticastPort extends Constraint
$this->message = 'The multicast port is not valid. Please use a number between 9000 and 9050';
}
}

View File

@ -2,12 +2,12 @@
namespace App\Validator\Constraints;
use App\Model\OrganizationalUnitClassroomP2pModes;
use App\Model\OrganizationalUnitP2PModes;
use App\Model\UserGroupPermissions;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class OrganizationalUnitClassroomMulticastPortValidator extends ConstraintValidator
class OrganizationalUnitMulticastPortValidator extends ConstraintValidator
{
CONST int minPort = 9000;
CONST int maxPort = 9050;

View File

@ -2,12 +2,12 @@
namespace App\Validator\Constraints;
use App\Model\OrganizationalUnitClassroomP2pModes;
use App\Model\OrganizationalUnitP2PModes;
use App\Model\UserGroupPermissions;
use Symfony\Component\Validator\Constraint;
#[\Attribute]
class OrganizationalUnitClassroomP2pMode extends Constraint
class OrganizationalUnitP2PMode extends Constraint
{
private array $modes;
public string $message;
@ -16,7 +16,7 @@ class OrganizationalUnitClassroomP2pMode extends Constraint
{
parent::__construct($options, $groups, $payload);
$this->modes = OrganizationalUnitClassroomP2pModes::getP2pModes();
$this->modes = OrganizationalUnitP2PModes::getP2pModes();
$this->message = sprintf(
'The p2p mode is not valid. Please use one of the following: %s',
implode(', ', $this->modes)

View File

@ -2,12 +2,12 @@
namespace App\Validator\Constraints;
use App\Model\OrganizationalUnitClassroomP2pModes;
use App\Model\OrganizationalUnitP2PModes;
use App\Model\UserGroupPermissions;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class OrganizationalUnitClassroomP2pModeValidator extends ConstraintValidator
class OrganizationalUnitP2PModeValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint): void
{
@ -15,7 +15,7 @@ class OrganizationalUnitClassroomP2pModeValidator extends ConstraintValidator
return;
}
if (!in_array($value, OrganizationalUnitClassroomP2pModes::getP2pModes())) {
if (!in_array($value, OrganizationalUnitP2PModes::getP2pModes())) {
$this->context->buildViolation($constraint->message)->addViolation();
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Validator\Constraints;
use App\Model\OrganizationalUnitMulticastModes;
use App\Model\OrganizationalUnitTypes;
use App\Model\UserGroupPermissions;
use Symfony\Component\Validator\Constraint;
#[\Attribute]
class OrganizationalUnitType extends Constraint
{
private array $types;
public string $message;
public function __construct(mixed $options = null, ?array $groups = null, mixed $payload = null)
{
parent::__construct($options, $groups, $payload);
$this->types = OrganizationalUnitTypes::getOrganizationalUnitTypeKeys();
$this->message = sprintf(
'The organizational unit type is not valid. Please use one of the following: %s',
implode(', ', $this->types)
);
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Validator\Constraints;
use App\Model\OrganizationalUnitP2PModes;
use App\Model\OrganizationalUnitTypes;
use App\Model\UserGroupPermissions;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class OrganizationalUnitTypeValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint): void
{
if (null === $value) {
return;
}
if (!in_array($value, OrganizationalUnitTypes::getOrganizationalUnitTypeKeys())) {
$this->context->buildViolation($constraint->message)->addViolation();
}
}
}