diff --git a/.idea/dictionaries/darkelfe.xml b/.idea/dictionaries/darkelfe.xml new file mode 100644 index 0000000..c2fc2b6 --- /dev/null +++ b/.idea/dictionaries/darkelfe.xml @@ -0,0 +1,7 @@ + + + + participations + + + \ No newline at end of file diff --git a/composer.lock b/composer.lock index c601352..f553684 100644 --- a/composer.lock +++ b/composer.lock @@ -4742,16 +4742,16 @@ }, { "name": "symfony/security-bundle", - "version": "v5.0.3", + "version": "v5.0.4", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "786901b609390aec91846b2c4831a76bf32aaa2f" + "reference": "4e3c9cb554053e2b5b56c07b0a22492c2f1be195" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/786901b609390aec91846b2c4831a76bf32aaa2f", - "reference": "786901b609390aec91846b2c4831a76bf32aaa2f", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/4e3c9cb554053e2b5b56c07b0a22492c2f1be195", + "reference": "4e3c9cb554053e2b5b56c07b0a22492c2f1be195", "shasum": "" }, "require": { @@ -4821,7 +4821,7 @@ ], "description": "Symfony SecurityBundle", "homepage": "https://symfony.com", - "time": "2020-01-21T11:48:06+00:00" + "time": "2020-01-31T09:13:47+00:00" }, { "name": "symfony/security-core", diff --git a/config/packages/security.yaml b/config/packages/security.yaml index ce69ba7..bfc2c7b 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: - 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: email firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ diff --git a/src/Entity/User.php b/src/Entity/User.php index fb3de82..3f9b3c7 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -5,117 +5,211 @@ namespace App\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; +use Symfony\Component\Security\Core\User\UserInterface; /** * @ORM\Entity(repositoryClass="App\Repository\UserRepository") */ -class User { +class User implements UserInterface +{ /** + * @var int The internal ID of user + * * @ORM\Id() * @ORM\GeneratedValue() * @ORM\Column(type="integer") */ - private $id; + private int $id; /** - * @ORM\Column(type="string", length=70) + * @var string The user email + * + * @ORM\Column(type="string", length=180, unique=true) */ - private $email; + private string $email; /** - * @ORM\Column(type="string", length=255) + * @var array The list of user's roles + * + * @ORM\Column(type="json") */ - private $pass; + private array $roles = []; /** + * @var string The hashed password + * + * @ORM\Column(type="string") + */ + private string $password; + + /** + * @var string The user name + * * @ORM\Column(type="string", length=255) */ - private $name; + private string $name; /** + * @var string|null The user first name + * * @ORM\Column(type="string", length=255, nullable=true) */ - private $fistname; + private ?string $fist_name; /** + * @var int The user gender + * 0 = no gender + * 1 = male + * 2 = femalle + * 3 = genderqueer + * * @ORM\Column(type="smallint") */ - private $gender; + private int $gender; /** + * @var string|null The user avatar relative path + * * @ORM\Column(type="string", length=255, nullable=true) */ - private $avatar; + private ?string $avatar; /** + * @var Language The user language + * * @ORM\ManyToOne(targetEntity="App\Entity\Language") */ - private $language; + private Language $language; /** + * @var ArrayCollection The user {@see User friends} + * * @ORM\ManyToMany(targetEntity="App\Entity\User") */ - private $friends; + private ArrayCollection $friends; /** + * @var ArrayCollection The user {@see ConfigNotification configured notifications} + * * @ORM\OneToMany(targetEntity="App\Entity\ConfigNotification", mappedBy="user", orphanRemoval=true) */ - private $configNotifications; + private ArrayCollection $configNotifications; /** + * @var ArrayCollection Thue user {@see UserNotification notifications} + * * @ORM\OneToMany(targetEntity="App\Entity\UserNotification", mappedBy="user", orphanRemoval=true) */ - private $notifications; + private ArrayCollection $notifications; /** + * @var ArrayCollection The user owned {@see Wish wishes} + * * @ORM\OneToMany(targetEntity="App\Entity\Wish", mappedBy="owner") */ - private $ownedWishes; + private ArrayCollection $ownedWishes; /** + * @var ArrayCollection The user {@see Participant participations} + * * @ORM\OneToMany(targetEntity="App\Entity\Participant", mappedBy="user", orphanRemoval=true) */ - private $participations; + private ArrayCollection $participations; /** + * @var ArrayCollection The user {@see Comment comments} + * * @ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="user", orphanRemoval=true) */ - private $comments; + private ArrayCollection $comments; public function __construct () { $this->friends = new ArrayCollection(); $this->configNotifications = new ArrayCollection(); $this->notifications = new ArrayCollection(); - $this->memberOfGroups = new ArrayCollection(); $this->ownedWishes = new ArrayCollection(); $this->participations = new ArrayCollection(); $this->comments = new ArrayCollection(); } - public function getId (): ?int { + public function getId(): ?int + { return $this->id; } - public function getEmail (): ?string { + public function getEmail(): ?string + { return $this->email; } - public function setEmail (string $email): self { + public function setEmail(string $email): self + { $this->email = $email; return $this; } - public function getPass (): ?string { - return $this->pass; + /** + * A visual identifier that represents this user. + * + * @see UserInterface + */ + public function getUsername(): string + { + return (string) $this->email; } - public function setPass (string $pass): self { - $this->pass = $pass; + /** + * @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 (string) $this->password; + } + + public function setPassword(string $password): self + { + $this->password = $password; + + return $this; + } + + /** + * @see UserInterface + */ + public function getSalt() + { + // not needed when using the "bcrypt" algorithm in security.yaml + } + + /** + * @see UserInterface + */ + public function eraseCredentials() + { + // If you store any temporary, sensitive data on the user, clear it here + // $this->plainPassword = null; + } + public function getName (): ?string { return $this->name; } @@ -127,11 +221,11 @@ class User { } public function getFistname (): ?string { - return $this->fistname; + return $this->fist_name; } - public function setFistname (?string $fistname): self { - $this->fistname = $fistname; + public function setFistname (?string $fist_name): self { + $this->fist_name = $fist_name; return $this; } diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index 64f692f..b973384 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -5,6 +5,11 @@ namespace App\Repository; use App\Entity\User; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Common\Persistence\ManagerRegistry; +use Doctrine\ORM\ORMException; +use Symfony\Component\Security\Core\Exception\UnsupportedUserException; +use Symfony\Component\Security\Core\User\PasswordUpgraderInterface; +use Symfony\Component\Security\Core\User\UserInterface; +use function get_class; /** * @method User|null find($id, $lockMode = null, $lockVersion = null) @@ -12,13 +17,29 @@ use Doctrine\Common\Persistence\ManagerRegistry; * @method User[] findAll() * @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ -class UserRepository extends ServiceEntityRepository +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. + * + * @throws ORMException + */ + 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 // */