From 3a8fc71eb2a3e722cddd881c84353fedc14f19f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Melaine=20G=C3=A9rard?= Date: Fri, 24 Jan 2025 00:16:16 +0100 Subject: [PATCH] =?UTF-8?q?:sparkles:=20V0.1=20de=20la=20version=20public/?= =?UTF-8?q?priv=C3=A9=20au=20niveau=20des=20dossiers=20pareents?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/packages/symfonycasts_tailwind.yaml | 2 ++ migrations/Version20250123225212.php | 40 +++++++++++++++++++++ migrations/Version20250123230226.php | 36 +++++++++++++++++++ src/Controller/FilesController.php | 24 +++++++------ src/Entity/ParentDirectory.php | 31 ++++++++++++++++ src/Entity/User.php | 41 ++++++++++++++++++++++ src/Security/Voter/FileVoter.php | 37 +++++++++++++++++++ 7 files changed, 201 insertions(+), 10 deletions(-) create mode 100644 config/packages/symfonycasts_tailwind.yaml create mode 100644 migrations/Version20250123225212.php create mode 100644 migrations/Version20250123230226.php create mode 100644 src/Security/Voter/FileVoter.php diff --git a/config/packages/symfonycasts_tailwind.yaml b/config/packages/symfonycasts_tailwind.yaml new file mode 100644 index 0000000..ef4e3b9 --- /dev/null +++ b/config/packages/symfonycasts_tailwind.yaml @@ -0,0 +1,2 @@ +symfonycasts_tailwind: + binary_version: 'v3.4.17' \ No newline at end of file diff --git a/migrations/Version20250123225212.php b/migrations/Version20250123225212.php new file mode 100644 index 0000000..0b47ecd --- /dev/null +++ b/migrations/Version20250123225212.php @@ -0,0 +1,40 @@ +addSql('CREATE TEMPORARY TABLE __temp__parent_directory AS SELECT id, name, owner_role FROM parent_directory'); + $this->addSql('DROP TABLE parent_directory'); + $this->addSql('CREATE TABLE parent_directory (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, owner_role VARCHAR(255) NOT NULL, user_created_id INTEGER NOT NULL, CONSTRAINT FK_B7336B34F987D8A8 FOREIGN KEY (user_created_id) REFERENCES "user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE)'); + $this->addSql('INSERT INTO parent_directory (id, name, owner_role) SELECT id, name, owner_role FROM __temp__parent_directory'); + $this->addSql('DROP TABLE __temp__parent_directory'); + $this->addSql('CREATE INDEX IDX_B7336B34F987D8A8 ON parent_directory (user_created_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE TEMPORARY TABLE __temp__parent_directory AS SELECT id, name, owner_role FROM parent_directory'); + $this->addSql('DROP TABLE parent_directory'); + $this->addSql('CREATE TABLE parent_directory (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, owner_role VARCHAR(255) NOT NULL)'); + $this->addSql('INSERT INTO parent_directory (id, name, owner_role) SELECT id, name, owner_role FROM __temp__parent_directory'); + $this->addSql('DROP TABLE __temp__parent_directory'); + } +} diff --git a/migrations/Version20250123230226.php b/migrations/Version20250123230226.php new file mode 100644 index 0000000..fb7ff4d --- /dev/null +++ b/migrations/Version20250123230226.php @@ -0,0 +1,36 @@ +addSql('ALTER TABLE parent_directory ADD COLUMN is_public BOOLEAN NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE TEMPORARY TABLE __temp__parent_directory AS SELECT id, name, owner_role, user_created_id FROM parent_directory'); + $this->addSql('DROP TABLE parent_directory'); + $this->addSql('CREATE TABLE parent_directory (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR(255) NOT NULL, owner_role VARCHAR(255) NOT NULL, user_created_id INTEGER NOT NULL, CONSTRAINT FK_B7336B34F987D8A8 FOREIGN KEY (user_created_id) REFERENCES "user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE)'); + $this->addSql('INSERT INTO parent_directory (id, name, owner_role, user_created_id) SELECT id, name, owner_role, user_created_id FROM __temp__parent_directory'); + $this->addSql('DROP TABLE __temp__parent_directory'); + $this->addSql('CREATE INDEX IDX_B7336B34F987D8A8 ON parent_directory (user_created_id)'); + } +} diff --git a/src/Controller/FilesController.php b/src/Controller/FilesController.php index 2a0a083..f20b871 100755 --- a/src/Controller/FilesController.php +++ b/src/Controller/FilesController.php @@ -55,7 +55,9 @@ class FilesController extends AbstractController throw $this->createNotFoundException("Ce dossier n'existe pas !"); } - if ($parentDir->getOwnerRole() !== $user->getFolderRole() && !in_array($user->getFolderRole(), $parentDir->getOwnerRole()->getHigherRoles(), true)) { + + + if (!$this->isGranted('file', $parentDir)) { throw $this->createNotFoundException("Vous n'avez pas le droit d'accéder à ce dossier !"); } } @@ -72,13 +74,13 @@ class FilesController extends AbstractController if ('' !== $path) { $parentDir = $this->parentDirectoryRepository->findOneBy(['name' => $pathFile[0]]); - if (null === $parentDir || ($parentDir->getOwnerRole() !== $user->getFolderRole() && !in_array($user->getFolderRole(), $parentDir->getOwnerRole()->getHigherRoles(), true))) { + if (null === $parentDir || !$this->isGranted('file', $parentDir)) { continue; } } elseif ('file' !== $file['type']) { $parentDir = $this->parentDirectoryRepository->findOneBy(['name' => $filename]); - if (null === $parentDir || ($parentDir->getOwnerRole() !== $user->getFolderRole() && !in_array($user->getFolderRole(), $parentDir->getOwnerRole()->getHigherRoles(), true))) { + if (null === $parentDir || !$this->isGranted('file', $parentDir)) { continue; } } @@ -132,7 +134,7 @@ class FilesController extends AbstractController */ $user = $this->getUser(); - if ($parentDir->getOwnerRole() !== $user->getFolderRole() && !in_array($user->getFolderRole(), $parentDir->getOwnerRole()->getHigherRoles(), true)) { + if (!$this->isGranted('file', $parentDir)) { throw $this->createNotFoundException("Vous n'avez pas le droit d'accéder à ce fichier !"); } } @@ -176,7 +178,7 @@ class FilesController extends AbstractController if (count($realPath) > 1) { $parentDir = $this->parentDirectoryRepository->findOneBy(['name' => $realPath[0]]); - if (null === $parentDir || ($parentDir->getOwnerRole() !== $user->getFolderRole() && !in_array($user->getFolderRole(), $parentDir->getOwnerRole()->getHigherRoles(), true))) { + if (null === $parentDir || !$this->isGranted('file', $parentDir)) { throw $this->createNotFoundException("Vous n'avez pas le droit de supprimer ce fichier !"); } } @@ -210,7 +212,7 @@ class FilesController extends AbstractController $realPath = explode('/', $path); $parentDir = $this->parentDirectoryRepository->findOneBy(['name' => $realPath[0]]); - if (null === $parentDir || ($parentDir->getOwnerRole() !== $user->getFolderRole() && !in_array($user->getFolderRole(), $parentDir->getOwnerRole()->getHigherRoles(), true))) { + if (null === $parentDir || !$this->isGranted('file', $parentDir)) { throw $this->createNotFoundException("Vous n'avez pas le droit de supprimer ce dossier !"); } @@ -249,7 +251,7 @@ class FilesController extends AbstractController if (count($realPath) > 1) { $parentDir = $this->parentDirectoryRepository->findOneBy(['name' => $realPath[0]]); - if (null === $parentDir || ($parentDir->getOwnerRole() !== $user->getFolderRole() && !in_array($user->getFolderRole(), $parentDir->getOwnerRole()->getHigherRoles(), true))) { + if (null === $parentDir || !$this->isGranted('file', $parentDir)) { throw $this->createNotFoundException("Vous n'avez pas le droit de renommer ce fichier !"); } } @@ -300,7 +302,7 @@ class FilesController extends AbstractController if (count($realPath) > 1) { $parentDir = $this->parentDirectoryRepository->findOneBy(['name' => $realPath[0]]); - if (null === $parentDir || ($parentDir->getOwnerRole() !== $user->getFolderRole() && !in_array($user->getFolderRole(), $parentDir->getOwnerRole()->getHigherRoles(), true))) { + if (null === $parentDir || !$this->isGranted('file', $parentDir)) { throw $this->createNotFoundException("Vous n'avez pas le droit de créer de sous-dossier dans ce dossier !"); } } @@ -338,6 +340,8 @@ class FilesController extends AbstractController $parentDirectory = new ParentDirectory(); $parentDirectory->setName($name); $parentDirectory->setOwnerRole($user->getFolderRole()); + $parentDirectory->setIsPublic(false); + $parentDirectory->setUserCreated($user); $this->entityManager->persist($parentDirectory); $this->entityManager->flush(); @@ -372,7 +376,7 @@ class FilesController extends AbstractController $realPath = explode('/', $filepath); $parentDir = $this->parentDirectoryRepository->findOneBy(['name' => $realPath[0]]); - if (null === $parentDir || ($parentDir->getOwnerRole() !== $user->getFolderRole() && !in_array($user->getFolderRole(), $parentDir->getOwnerRole()->getHigherRoles(), true))) { + if (null === $parentDir || !$this->isGranted('file', $parentDir)) { throw $this->createNotFoundException("Vous n'avez pas le droit de renommer ce dossier !"); } @@ -431,7 +435,7 @@ class FilesController extends AbstractController $realPath = explode('/', $path); $parentDir = $this->parentDirectoryRepository->findOneBy(['name' => $realPath[0]]); - if (null === $parentDir || ($parentDir->getOwnerRole() !== $user->getFolderRole() && !in_array($user->getFolderRole(), $parentDir->getOwnerRole()->getHigherRoles(), true))) { + if (null === $parentDir || !$this->isGranted('file', $parentDir)) { throw $this->createNotFoundException("Vous n'avez pas le droit d'uploader des fichiers dans ce dossier !"); } diff --git a/src/Entity/ParentDirectory.php b/src/Entity/ParentDirectory.php index 379bce2..87ace68 100644 --- a/src/Entity/ParentDirectory.php +++ b/src/Entity/ParentDirectory.php @@ -22,6 +22,13 @@ class ParentDirectory #[ORM\Column(enumType: RoleEnum::class)] private ?RoleEnum $ownerRole = null; + #[ORM\ManyToOne(inversedBy: 'parentDirectories')] + #[ORM\JoinColumn(nullable: false)] + private ?User $userCreated = null; + + #[ORM\Column] + private ?bool $isPublic = null; + public function getId(): ?int { return $this->id; @@ -50,4 +57,28 @@ class ParentDirectory return $this; } + + public function getUserCreated(): ?User + { + return $this->userCreated; + } + + public function setUserCreated(?User $userCreated): static + { + $this->userCreated = $userCreated; + + return $this; + } + + public function isPublic(): ?bool + { + return $this->isPublic; + } + + public function setIsPublic(bool $isPublic): static + { + $this->isPublic = $isPublic; + + return $this; + } } diff --git a/src/Entity/User.php b/src/Entity/User.php index a408e1d..10c4015 100755 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -6,6 +6,8 @@ namespace App\Entity; use App\Enum\RoleEnum; use App\Repository\UserRepository; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; @@ -44,6 +46,17 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\Column(length: 255)] private ?string $fullname = null; + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: ParentDirectory::class, mappedBy: 'userCreated')] + private Collection $parentDirectories; + + public function __construct() + { + $this->parentDirectories = new ArrayCollection(); + } + public function getId(): ?int { return $this->id; @@ -142,4 +155,32 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface return $this; } + + /** + * @return Collection + */ + public function getParentDirectories(): Collection + { + return $this->parentDirectories; + } + + public function addParentDirectory(ParentDirectory $parentDirectory): static + { + if (!$this->parentDirectories->contains($parentDirectory)) { + $this->parentDirectories->add($parentDirectory); + $parentDirectory->setUserCreated($this); + } + + return $this; + } + + public function removeParentDirectory(ParentDirectory $parentDirectory): static + { + // set the owning side to null (unless already changed) + if ($this->parentDirectories->removeElement($parentDirectory) && $parentDirectory->getUserCreated() === $this) { + $parentDirectory->setUserCreated(null); + } + + return $this; + } } diff --git a/src/Security/Voter/FileVoter.php b/src/Security/Voter/FileVoter.php new file mode 100644 index 0000000..01d3b40 --- /dev/null +++ b/src/Security/Voter/FileVoter.php @@ -0,0 +1,37 @@ +getUser(); + if (!$user instanceof User) { + return false; + } + + if ($realSubject->getUserCreated() === $user) { + return true; + } + return $realSubject->isPublic() && ($realSubject->getOwnerRole() === $user->getFolderRole() || in_array($user->getFolderRole(), $realSubject->getOwnerRole()->getHigherRoles(), true)); + } +}