refs #421. Some improvements
parent
14c9f44c63
commit
5d1b553c0b
|
@ -11,8 +11,8 @@ resources:
|
|||
ApiPlatform\Metadata\GetCollection:
|
||||
provider: App\State\Provider\OperativeSystemProvider
|
||||
filters:
|
||||
- 'api_platform.filter.operative-system.order'
|
||||
- 'api_platform.filter.operative-system.search'
|
||||
- 'api_platform.filter.operative_system.order'
|
||||
- 'api_platform.filter.operative_system.search'
|
||||
|
||||
ApiPlatform\Metadata\Get:
|
||||
provider: App\State\Provider\OperativeSystemProvider
|
||||
|
|
|
@ -7,13 +7,16 @@ 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
|
||||
filters:
|
||||
- 'api_platform.filter.organizational_unit.order'
|
||||
- 'api_platform.filter.organizational_unit.search'
|
||||
ApiPlatform\Metadata\Get:
|
||||
security: 'is_granted("ORGANIZATIONAL_UNIT_VIEW", object)'
|
||||
provider: App\State\Provider\OrganizationalUnitProvider
|
||||
securityMessage: 'Sorry, but you are not allowed to access this resource.'
|
||||
ApiPlatform\Metadata\Put:
|
||||
provider: App\State\Provider\OrganizationalUnitProvider
|
||||
ApiPlatform\Metadata\Patch:
|
||||
|
|
|
@ -4,7 +4,14 @@ api_platform:
|
|||
version: 1.0.0
|
||||
path_segment_name_generator: 'api_platform.path_segment_name_generator.dash'
|
||||
formats:
|
||||
jsonld: ['application/ld+json', 'application/json']
|
||||
jsonld: [ 'application/ld+json' ]
|
||||
jsonhal: [ 'application/hal+json' ]
|
||||
jsonapi: [ 'application/vnd.api+json' ]
|
||||
json: [ 'application/json' ]
|
||||
xml: [ 'application/xml', 'text/xml' ]
|
||||
yaml: [ 'application/x-yaml' ]
|
||||
csv: [ 'text/csv' ]
|
||||
html: [ 'text/html' ]
|
||||
patch_formats:
|
||||
jsonld: ['application/ld+json', 'application/json']
|
||||
mapping:
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
# This file is the entry point to configure your own services.
|
||||
# Files in the packages/ subdirectory configure your dependencies.
|
||||
|
||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
||||
parameters:
|
||||
|
||||
services:
|
||||
|
@ -11,8 +6,6 @@ services:
|
|||
autowire: true # Automatically injects dependencies in your services.
|
||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||
|
||||
# makes classes in src/ available to be used as services
|
||||
# this creates a service per class whose id is the fully-qualified class name
|
||||
App\:
|
||||
resource: '../src/'
|
||||
exclude:
|
||||
|
@ -20,6 +13,11 @@ services:
|
|||
- '../src/Entity/'
|
||||
- '../src/Kernel.php'
|
||||
|
||||
App\Doctrine\UserAllowedOrganizationalUnitExtension:
|
||||
tags:
|
||||
- { name: api_platform.doctrine.orm.query_extension.collection }
|
||||
- { name: api_platform.doctrine.orm.query_extension.item }
|
||||
|
||||
App\OpenApi\OpenApiFactory:
|
||||
decorates: 'api_platform.openapi.factory'
|
||||
arguments: [ '@App\OpenApi\OpenApiFactory.inner' ]
|
||||
|
|
|
@ -41,6 +41,19 @@ services:
|
|||
tags:
|
||||
- [ 'api_platform.filter' ]
|
||||
|
||||
api_platform.filter.organizational_unit.order:
|
||||
parent: 'api_platform.doctrine.orm.order_filter'
|
||||
arguments:
|
||||
$properties: { 'id': ~, 'name': ~, 'type': ~ }
|
||||
$orderParameterName: 'order'
|
||||
tags:
|
||||
- [ 'api_platform.filter' ]
|
||||
|
||||
api_platform.filter.organizational_unit.search:
|
||||
parent: 'api_platform.doctrine.orm.search_filter'
|
||||
arguments: [ { 'id': 'exact', 'name': 'exact', 'type': 'exact' } ]
|
||||
tags:
|
||||
- [ 'api_platform.filter' ]
|
||||
|
||||
api_platform.filter.partition.order:
|
||||
parent: 'api_platform.doctrine.orm.order_filter'
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?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 Version20240620095914 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 `partition` DROP FOREIGN KEY FK_9EB910E419EB6921');
|
||||
$this->addSql('ALTER TABLE `partition` ADD CONSTRAINT FK_9EB910E419EB6921 FOREIGN KEY (client_id) REFERENCES client (id) ON DELETE SET NULL');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE `partition` DROP FOREIGN KEY FK_9EB910E419EB6921');
|
||||
$this->addSql('ALTER TABLE `partition` ADD CONSTRAINT FK_9EB910E419EB6921 FOREIGN KEY (client_id) REFERENCES client (id)');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?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 Version20240620100039 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 `partition` DROP FOREIGN KEY FK_9EB910E419EB6921');
|
||||
$this->addSql('ALTER TABLE `partition` ADD CONSTRAINT FK_9EB910E419EB6921 FOREIGN KEY (client_id) REFERENCES client (id) ON DELETE CASCADE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE `partition` DROP FOREIGN KEY FK_9EB910E419EB6921');
|
||||
$this->addSql('ALTER TABLE `partition` ADD CONSTRAINT FK_9EB910E419EB6921 FOREIGN KEY (client_id) REFERENCES client (id) ON DELETE SET NULL');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?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\OrganizationalUnit;
|
||||
use App\Entity\User;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
|
||||
readonly class UserAllowedOrganizationalUnitExtension 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
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->security->getUser();
|
||||
|
||||
if (OrganizationalUnit::class !== $resourceClass || null === $user || in_array('ROLE_SUPER_ADMIN', $user->getRoles())) {
|
||||
return;
|
||||
}
|
||||
$organizationalUnitIds = [];
|
||||
foreach ($user->getAllowedOrganizationalUnits() as $allowedOrganizationalUnit) {
|
||||
$organizationalUnitIds[] = $allowedOrganizationalUnit->getId();
|
||||
}
|
||||
|
||||
$rootAlias = $queryBuilder->getRootAliases()[0];
|
||||
$queryBuilder->andWhere(sprintf('%s.id in (:ou)', $rootAlias));
|
||||
$queryBuilder->setParameter('ou', $organizationalUnitIds);
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ class Partition extends AbstractEntity
|
|||
private ?string $filesystem = null;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'partitions')]
|
||||
#[ORM\JoinColumn( onDelete: 'CASCADE')]
|
||||
private ?Client $client = null;
|
||||
|
||||
#[ORM\Column]
|
||||
|
|
|
@ -17,8 +17,8 @@ class User extends AbstractEntity implements UserInterface, PasswordAuthenticate
|
|||
{
|
||||
use ToggleableTrait;
|
||||
|
||||
const ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN';
|
||||
const ROLE_USER = 'ROLE_USER';
|
||||
const string ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN';
|
||||
const string ROLE_USER = 'ROLE_USER';
|
||||
|
||||
#[ORM\Column(length: 180)]
|
||||
private ?string $username = null;
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Security\Voter;
|
||||
|
||||
use App\Dto\Output\OrganizationalUnitOutput;
|
||||
use App\Entity\OrganizationalUnit;
|
||||
use App\Entity\User;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
class OrganizationalUnitVoter extends Voter
|
||||
{
|
||||
public const string VIEW = 'ORGANIZATIONAL_UNIT_VIEW';
|
||||
|
||||
protected function supports(string $attribute, mixed $subject): bool
|
||||
{
|
||||
return $attribute === self::VIEW
|
||||
&& $subject instanceof OrganizationalUnitOutput;
|
||||
}
|
||||
|
||||
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $token->getUser();
|
||||
|
||||
// if the user is anonymous, do not grant access
|
||||
if (!$user instanceof UserInterface) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($attribute === 'ORGANIZATIONAL_UNIT_VIEW' ) {
|
||||
foreach ($user->getAllowedOrganizationalUnits() as $allowedOrganizationalUnit) {
|
||||
if ($allowedOrganizationalUnit->getId() === $subject->getEntity()->getId()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue