EasyAdmin - Implemetanción inicial.

Añadido menú para gestionar las Categorias.
This commit is contained in:
2024-04-22 20:15:44 +02:00
parent fcfe2f9250
commit 34ecf58097
21 changed files with 2326 additions and 484 deletions
+1 -1
View File
@@ -26,5 +26,5 @@ APP_SECRET=d130654a5d6a8ab5945b20b22dfeee74
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://app:[email protected]:3306/app?serverVersion=8.0.32&charset=utf8mb4"
# DATABASE_URL="mysql://app:[email protected]:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
DATABASE_URL="postgresql://app:[email protected]:51223/app?serverVersion=16&charset=utf8"
DATABASE_URL="postgresql://app:[email protected]:54195/app?serverVersion=16&charset=utf8"
###< doctrine/doctrine-bundle ###
+1 -1
View File
@@ -26,5 +26,5 @@ services:
###> doctrine/doctrine-bundle ###
database:
ports:
- "5432"
- 54195:5432
###< doctrine/doctrine-bundle ###
+2
View File
@@ -13,6 +13,7 @@
"doctrine/doctrine-bundle": "^2.12",
"doctrine/doctrine-migrations-bundle": "^3.3",
"doctrine/orm": "^3.1",
"easycorp/easyadmin-bundle": "^4.10",
"phpdocumentor/reflection-docblock": "^5.4",
"phpstan/phpdoc-parser": "^1.28",
"runtime/frankenphp-symfony": "^0.2.0",
@@ -23,6 +24,7 @@
"symfony/property-access": "7.0.*",
"symfony/property-info": "7.0.*",
"symfony/runtime": "7.0.*",
"symfony/security-bundle": "7.0.*",
"symfony/serializer": "7.0.*",
"symfony/yaml": "7.0.*"
},
Generated
+1857 -479
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -7,4 +7,6 @@ return [
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true],
];
+43
View File
@@ -0,0 +1,43 @@
security:
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: app_user_provider
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#the-firewall
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
when@test:
security:
password_hashers:
# By default, password hashers are resource intensive and take time. This is
# important to generate secure password hashes. In tests however, secure hashes
# are not important, waste resources and increase test times. The following
# reduces the work factor to the lowest possible values.
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
algorithm: auto
cost: 4 # Lowest possible value for bcrypt
time_cost: 3 # Lowest possible value for argon
memory_cost: 10 # Lowest possible value for argon
+7
View File
@@ -0,0 +1,7 @@
framework:
default_locale: en
translator:
default_path: '%kernel.project_dir%/translations'
fallbacks:
- en
providers:
+11
View File
@@ -0,0 +1,11 @@
framework:
validation:
# Enables validator auto-mapping support.
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
#auto_mapping:
# App\Entity\: []
when@test:
framework:
validation:
not_compromised_password: false
+3
View File
@@ -0,0 +1,3 @@
_security_logout:
resource: security.route_loader.logout
type: service
+35
View File
@@ -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 Version20240422163212 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 SEQUENCE "user_id_seq" INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE TABLE "user" (id INT NOT NULL, username VARCHAR(180) NOT NULL, roles JSON NOT NULL, password VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE UNIQUE INDEX UNIQ_IDENTIFIER_USERNAME ON "user" (username)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('DROP SEQUENCE "user_id_seq" CASCADE');
$this->addSql('DROP TABLE "user"');
}
}
@@ -0,0 +1,38 @@
<?php
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Field\Field;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField;
use App\Entity\RoomCategory;
class RoomCategoryCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return RoomCategory::class;
}
public function configureCrud(Crud $crud): Crud
{
return $crud;
}
public function configureFields(string $pageName): iterable
{
return [
TextField::new('name'),
TextEditorField::new('description'),
TextField::new('bedType'),
IntegerField::new('maxGuestNum'),
CollectionField::new('roomCategoryDetails')->useEntryCrudForm(),
CollectionField::new('roomCategoryPhotos')->useEntryCrudForm()
];
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Controller\Admin;
use App\Entity\RoomCategoryDetails;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
class RoomCategoryDetailsCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return RoomCategoryDetails::class;
}
public function configureFields(string $pageName): iterable
{
return [
TextField::new('detailsSection'),
TextEditorField::new('detailValue'),
];
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Controller\Admin;
use App\Entity\RoomCategoryPhoto;
use App\Entity\RoomCategoryPhotoKinds;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
class RoomCategoryPhotoCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return RoomCategoryPhoto::class;
}
public function configureFields(string $pageName): iterable
{
yield TextField::new('path');
yield TextEditorField::new('altText');
yield ChoiceField::new('kind')->setChoices(['Main' => 'main', 'Bathroom' => 'bathroom', 'Other' => 'other']);
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Entity\RoomCategory;
class SomniaDashboardController extends AbstractDashboardController
{
#[Route('/admin', name: 'admin')]
public function index(): Response
{
return $this->render('admin/somniaDashboard.html.twig');
}
public function configureDashboard(): Dashboard
{
return Dashboard::new()
->setTitle('SomniaRooms');
}
public function configureMenuItems(): iterable
{
yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home');
yield MenuItem::Section('Room Management');
yield MenuItem::linkToCrud('Category', 'fas fa-list', RoomCategory::class);
}
}
+2 -2
View File
@@ -32,13 +32,13 @@ class RoomCategory
/**
* @var Collection<int, RoomCategoryPhoto>
*/
#[ORM\OneToMany(targetEntity: RoomCategoryPhoto::class, mappedBy: 'roomCategory', orphanRemoval: true)]
#[ORM\OneToMany(targetEntity: RoomCategoryPhoto::class, mappedBy: 'roomCategory', orphanRemoval: true, cascade: ['persist'])]
private Collection $roomCategoryPhotos;
/**
* @var Collection<int, RoomCategoryDetails>
*/
#[ORM\OneToMany(targetEntity: RoomCategoryDetails::class, mappedBy: 'roomCategory', orphanRemoval: true)]
#[ORM\OneToMany(targetEntity: RoomCategoryDetails::class, mappedBy: 'roomCategory', orphanRemoval: true, cascade: ['persist'])]
private Collection $roomCategoryDetails;
public function __construct()
+1 -1
View File
@@ -82,4 +82,4 @@ class RoomCategoryPhoto
return $this;
}
}
}
+109
View File
@@ -0,0 +1,109 @@
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\Table(name: '`user`')]
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_USERNAME', fields: ['username'])]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 180)]
private ?string $username = null;
/**
* @var list<string> The user roles
*/
#[ORM\Column]
private array $roles = [];
/**
* @var string The hashed password
*/
#[ORM\Column]
private ?string $password = null;
public function getId(): ?int
{
return $this->id;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): static
{
$this->username = $username;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->username;
}
/**
* @see UserInterface
*
* @return list<string>
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
/**
* @param list<string> $roles
*/
public function setRoles(array $roles): static
{
$this->roles = $roles;
return $this;
}
/**
* @see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): static
{
$this->password = $password;
return $this;
}
/**
* @see UserInterface
*/
public function eraseCredentials(): void
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
}
+65
View File
@@ -0,0 +1,65 @@
<?php
namespace App\Repository;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
/**
* @extends ServiceEntityRepository<User>
*
* @method User|null find($id, $lockMode = null, $lockVersion = null)
* @method User|null findOneBy(array $criteria, array $orderBy = null)
* @method User[] findAll()
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, User::class);
}
/**
* Used to upgrade (rehash) the user's password automatically over time.
*/
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class));
}
$user->setPassword($newHashedPassword);
$this->getEntityManager()->persist($user);
$this->getEntityManager()->flush();
}
// /**
// * @return User[] Returns an array of User objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('u')
// ->andWhere('u.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('u.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?User
// {
// return $this->createQueryBuilder('u')
// ->andWhere('u.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
+56
View File
@@ -26,6 +26,15 @@
"./migrations/.gitignore"
]
},
"easycorp/easyadmin-bundle": {
"version": "4.10",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.0",
"ref": "b131e6cbfe1b898a508987851963fff485986285"
}
},
"symfony/console": {
"version": "7.0",
"recipe": {
@@ -91,6 +100,32 @@
"config/routes.yaml"
]
},
"symfony/security-bundle": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "2ae08430db28c8eb4476605894296c82a642028f"
},
"files": [
"./config/packages/security.yaml",
"./config/routes/security.yaml"
]
},
"symfony/translation": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.3",
"ref": "e28e27f53663cc34f0be2837aba18e3a1bef8e7b"
},
"files": [
"./config/packages/translation.yaml",
"./translations/.gitignore"
]
},
"symfony/twig-bundle": {
"version": "7.0",
"recipe": {
@@ -104,6 +139,27 @@
"./templates/base.html.twig"
]
},
"symfony/uid": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "0df5844274d871b37fc3816c57a768ffc60a43a5"
}
},
"symfony/validator": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "8c1c4e28d26a124b0bb273f537ca8ce443472bfd"
},
"files": [
"./config/packages/validator.yaml"
]
},
"symfony/web-profiler-bundle": {
"version": "7.0",
"recipe": {
@@ -0,0 +1,6 @@
{# templates/admin/somniaDashboard.html.html.twig #}
{% extends '@EasyAdmin/layout.html.twig' %}
{% block main %}
{# ... #}
{% endblock main %}
View File