SuperSeller3000/src/Domain/Auth/User.php
Simon Kuehn 0706fdad58 feat: add self-service password change page at /account/password
Validates current password, enforces 8-char minimum, links from
EasyAdmin user menu. Also fixes route loader (attribute scan instead
of broken easyadmin.routes type).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 18:41:45 +00:00

145 lines
3.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Domain\Auth;
use Doctrine\ORM\Mapping as ORM;
use Scheb\TwoFactorBundle\Model\Totp\TotpConfiguration;
use Scheb\TwoFactorBundle\Model\Totp\TotpConfigurationInterface;
use Scheb\TwoFactorBundle\Model\Totp\TwoFactorInterface as TotpTwoFactorInterface;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Uid\Uuid;
#[ORM\Entity]
#[ORM\Table(name: 'users', schema: 'app')]
class User implements UserInterface, PasswordAuthenticatedUserInterface, TotpTwoFactorInterface
{
#[ORM\Id]
#[ORM\Column(type: 'uuid')]
private Uuid $id;
#[ORM\Column(type: 'string', length: 255, unique: true)]
private string $email;
#[ORM\Column(type: 'string')]
private string $passwordHash;
#[ORM\Column(type: 'string', nullable: true)]
private ?string $totpSecret = null;
/** @var array<string, bool> */
#[ORM\Column(type: 'json')]
private array $permissions = [];
#[ORM\Column(type: 'boolean')]
private bool $isActive = true;
public function __construct(string $email, string $passwordHash)
{
$this->id = Uuid::v7();
$this->email = $email;
$this->passwordHash = $passwordHash;
}
public function getId(): Uuid
{
return $this->id;
}
public function getEmail(): string
{
return $this->email;
}
public function getPassword(): string
{
return $this->passwordHash;
}
/** @return non-empty-string */
public function getUserIdentifier(): string
{
\assert('' !== $this->email);
return $this->email;
}
/** @return list<string> */
public function getRoles(): array
{
return ['ROLE_USER'];
}
public function eraseCredentials(): void
{
}
public function isTotpAuthenticationEnabled(): bool
{
return null !== $this->totpSecret;
}
public function getTotpAuthenticationUsername(): string
{
\assert('' !== $this->email);
return $this->email;
}
public function getTotpAuthenticationConfiguration(): ?TotpConfigurationInterface
{
if (null === $this->totpSecret) {
return null;
}
return new TotpConfiguration($this->totpSecret, TotpConfiguration::ALGORITHM_SHA1, 30, 6);
}
public function getTotpSecret(): ?string
{
return $this->totpSecret;
}
public function setTotpSecret(?string $secret): void
{
$this->totpSecret = $secret;
}
public function isActive(): bool
{
return $this->isActive;
}
public function setPasswordHash(string $passwordHash): void
{
$this->passwordHash = $passwordHash;
}
public function setIsActive(bool $active): void
{
$this->isActive = $active;
}
/** @return array<string, bool> */
public function getPermissions(): array
{
return $this->permissions;
}
public function hasPermission(string $permission): bool
{
return $this->permissions[$permission] ?? false;
}
public function grantPermission(string $permission): void
{
$this->permissions[$permission] = true;
}
public function revokePermission(string $permission): void
{
unset($this->permissions[$permission]);
}
}