From 5a15194c5bab0fee8dcc16eb06406122166b0bc3 Mon Sep 17 00:00:00 2001 From: tracer <tracer@24unix.net> Date: Sun, 30 May 2021 17:41:18 +0200 Subject: [PATCH] added User entity --- .env | 2 +- config/packages/doctrine.yaml | 2 +- config/packages/security.yaml | 12 +- migrations/Version20210530154026.php | 31 +++++ src/Entity/User.php | 197 +++++++++++++++++++++++++++ src/Repository/UserRepository.php | 67 +++++++++ 6 files changed, 307 insertions(+), 4 deletions(-) create mode 100644 migrations/Version20210530154026.php create mode 100644 src/Entity/User.php create mode 100644 src/Repository/UserRepository.php diff --git a/.env b/.env index 79fbd43..938848d 100644 --- a/.env +++ b/.env @@ -24,5 +24,5 @@ APP_SECRET=cd0ae68f915f2a06b82007f2906e54e8 # # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" # DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7" -DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=13&charset=utf8" +DATABASE_URL="mysql://24unix:24.unix@127.0.0.1:3306/24unix" ###< doctrine/doctrine-bundle ### diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index c319176..ab72e09 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -4,7 +4,7 @@ doctrine: # IMPORTANT: You MUST configure your server version, # either here or in the DATABASE_URL env var (see .env file) - #server_version: '13' + server_version: '10.5.9-MariaDB-log' orm: auto_generate_proxy_classes: true naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 0e4cf3d..31bce8a 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -1,7 +1,15 @@ security: + encoders: + App\Entity\User: + algorithm: auto + # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers providers: - users_in_memory: { memory: null } + # 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)/ @@ -9,7 +17,7 @@ security: main: anonymous: true lazy: true - provider: users_in_memory + provider: app_user_provider # activate different ways to authenticate # https://symfony.com/doc/current/security.html#firewalls-authentication diff --git a/migrations/Version20210530154026.php b/migrations/Version20210530154026.php new file mode 100644 index 0000000..39c4186 --- /dev/null +++ b/migrations/Version20210530154026.php @@ -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 Version20210530154026 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 user (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(180) NOT NULL, roles LONGTEXT NOT NULL COMMENT \'(DC2Type:json)\', password VARCHAR(255) NOT NULL, first_name VARCHAR(255) DEFAULT NULL, last_name VARCHAR(255) DEFAULT NULL, email VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, last_login_at DATETIME DEFAULT NULL, UNIQUE INDEX UNIQ_8D93D649F85E0677 (username), 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 user'); + } +} diff --git a/src/Entity/User.php b/src/Entity/User.php new file mode 100644 index 0000000..6792c54 --- /dev/null +++ b/src/Entity/User.php @@ -0,0 +1,197 @@ +<?php + +namespace App\Entity; + +use App\Repository\UserRepository; +use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Security\Core\User\UserInterface; + +/** + * @ORM\Entity(repositoryClass=UserRepository::class) + */ +class User implements UserInterface +{ + /** + * @ORM\Id + * @ORM\GeneratedValue + * @ORM\Column(type="integer") + */ + private $id; + + /** + * @ORM\Column(type="string", length=180, unique=true) + */ + private $username; + + /** + * @ORM\Column(type="json") + */ + private $roles = []; + + /** + * @var string The hashed password + * @ORM\Column(type="string") + */ + private $password; + + /** + * @ORM\Column(type="string", length=255, nullable=true) + */ + private $firstName; + + /** + * @ORM\Column(type="string", length=255, nullable=true) + */ + private $lastName; + + /** + * @ORM\Column(type="string", length=255) + */ + private $email; + + /** + * @ORM\Column(type="datetime") + */ + private $createdAt; + + /** + * @ORM\Column(type="datetime", nullable=true) + */ + private $lastLoginAt; + + public function getId(): ?int + { + return $this->id; + } + + /** + * A visual identifier that represents this user. + * + * @see UserInterface + */ + public function getUsername(): string + { + return (string) $this->username; + } + + public function setUsername(string $username): self + { + $this->username = $username; + + return $this; + } + + /** + * @see UserInterface + */ + public function getRoles(): array + { + $roles = $this->roles; + // guarantee every user at least has ROLE_USER + $roles[] = 'ROLE_USER'; + + return array_unique($roles); + } + + public function setRoles(array $roles): self + { + $this->roles = $roles; + + return $this; + } + + /** + * @see UserInterface + */ + public function getPassword(): string + { + return $this->password; + } + + public function setPassword(string $password): self + { + $this->password = $password; + + return $this; + } + + /** + * Returning a salt is only needed, if you are not using a modern + * hashing algorithm (e.g. bcrypt or sodium) in your security.yaml. + * + * @see UserInterface + */ + public function getSalt(): ?string + { + return null; + } + + /** + * @see UserInterface + */ + public function eraseCredentials() + { + // If you store any temporary, sensitive data on the user, clear it here + // $this->plainPassword = null; + } + + public function getFirstName(): ?string + { + return $this->firstName; + } + + public function setFirstName(?string $firstName): self + { + $this->firstName = $firstName; + + return $this; + } + + public function getLastName(): ?string + { + return $this->lastName; + } + + public function setLastName(?string $lastName): self + { + $this->lastName = $lastName; + + return $this; + } + + public function getEmail(): ?string + { + return $this->email; + } + + public function setEmail(string $email): self + { + $this->email = $email; + + return $this; + } + + public function getCreatedAt(): ?\DateTimeInterface + { + return $this->createdAt; + } + + public function setCreatedAt(\DateTimeInterface $createdAt): self + { + $this->createdAt = $createdAt; + + return $this; + } + + public function getLastLoginAt(): ?\DateTimeInterface + { + return $this->lastLoginAt; + } + + public function setLastLoginAt(?\DateTimeInterface $lastLoginAt): self + { + $this->lastLoginAt = $lastLoginAt; + + return $this; + } +} diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php new file mode 100644 index 0000000..1a38975 --- /dev/null +++ b/src/Repository/UserRepository.php @@ -0,0 +1,67 @@ +<?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\PasswordUpgraderInterface; +use Symfony\Component\Security\Core\User\UserInterface; + +/** + * @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(UserInterface $user, string $newEncodedPassword): void + { + if (!$user instanceof User) { + throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user))); + } + + $user->setPassword($newEncodedPassword); + $this->_em->persist($user); + $this->_em->flush(); + } + + // /** + // * @return User[] Returns an array of User objects + // */ + /* + public function findByExampleField($value) + { + 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() + ; + } + */ +}