src/Entity/User.php line 20

Open in your IDE?
  1. <?php
  2. namespace App\Entity;
  3. use App\Repository\UserRepository;
  4. use Doctrine\ORM\Mapping as ORM;
  5. use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface as EmailTwoFactorInterface;
  6. use Scheb\TwoFactorBundle\Model\Totp\TotpConfiguration;
  7. use Scheb\TwoFactorBundle\Model\Totp\TotpConfigurationInterface;
  8. use Scheb\TwoFactorBundle\Model\Totp\TwoFactorInterface as TotpTwoFactorInterface;
  9. use Scheb\TwoFactorBundle\Model\TrustedDeviceInterface;
  10. use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  11. use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
  12. use Symfony\Component\Security\Core\User\UserInterface;
  13. use Symfony\Component\Validator\Constraints as Assert;
  14. #[ORM\Entity(repositoryClass: UserRepository::class)]
  15. #[UniqueEntity(['email'])]
  16. #[UniqueEntity(['username'])]
  17. class User implements UserInterface,
  18.     PasswordAuthenticatedUserInterface,
  19.     EmailTwoFactorInterface,
  20.     TotpTwoFactorInterface,
  21.     TrustedDeviceInterface
  22. {
  23.     final const USER_SUPER_ADMIN_ID = 1;
  24.     final const USER_DEFAULT_ID = 2;
  25.     #[ORM\Id]
  26.     #[ORM\GeneratedValue]
  27.     #[ORM\Column(type: 'integer')]
  28.     private ?int $id;
  29.     #[ORM\Column(type: 'string', length: 180, unique: true)]
  30.     #[Assert\Email]
  31.     #[Assert\NotNull]
  32.     private ?string $email;
  33.     #[ORM\Column(length: 255)]
  34. //    #[Assert\Length(
  35. //        min: 3,
  36. //        max: 4096,
  37. //        minMessage: " the username must have minimum {{ limit }} characters")]
  38. //    #[Assert\NotNull]
  39.     private ?string $username = null;
  40.     #[ORM\Column(type: 'json')]
  41.     private array $roles = [];
  42.     #[ORM\Column(type: 'string')]
  43.     #[Assert\Length(min: 6, minMessage: 'Your password should be at least {{ limit }} characters')]
  44.     private ?string $password=  null;
  45.     #[ORM\OneToOne(inversedBy: 'user', targetEntity: Personal::class, cascade: ['persist', 'remove'])]
  46.     private ?Personal $personal;
  47.     #[ORM\Column(type: 'boolean')]
  48.     private bool $isVerified = false;
  49.     #[ORM\Column(nullable: false)]
  50.     private ?bool $active = null;
  51.     #[ORM\ManyToOne(cascade: ['persist'])]
  52.     private ?Customer $customer = null;
  53.     #[ORM\Column(length: 255,nullable: true)]
  54.     private ?string $google_id = null;
  55.     // =============================================
  56.     // Two-Factor Authentication Fields
  57.     // =============================================
  58.     /**
  59.      * Temporary 6-digit code sent via email for 2FA
  60.      */
  61.     #[ORM\Column(type: 'string', length: 6, nullable: true)]
  62.     private ?string $emailAuthCode = null;
  63.     /**
  64.      * Base32 encoded TOTP secret for authenticator apps
  65.      */
  66.     #[ORM\Column(type: 'string', length: 255, nullable: true)]
  67.     private ?string $totpSecret = null;
  68.     /**
  69.      * Selected 2FA method: 'email', 'totp', or null (disabled)
  70.      */
  71.     #[ORM\Column(type: 'string', length: 10, nullable: true)]
  72.     private ?string $twoFactorMethod = null;
  73.     /**
  74.      * Transient (non-persisted) field set from session during login flow.
  75.      */
  76.     private ?string $sessionTwoFactorMethod = null;
  77.     /**
  78.      * Version counter for trusted device invalidation
  79.      * Increment this to invalidate all trusted devices for this user
  80.      */
  81.     #[ORM\Column(type: 'integer', options: ['default' => 0])]
  82.     private int $trustedTokenVersion = 0;
  83.     #[ORM\Column(type: 'boolean', nullable: true, options: ['default' => 0])]
  84.     private bool $apiClient = false;
  85.     public function __construct()
  86.     {
  87.     }
  88.     public function getId(): ?int
  89.     {
  90.         return $this->id;
  91.     }
  92.     public function getEmail(): ?string
  93.     {
  94.         return $this->email;
  95.     }
  96.     public function setEmail(?string $email): self
  97.     {
  98.         $this->email = $email;
  99.         return $this;
  100.     }
  101.     /**
  102.      * A visual identifier that represents this user.
  103.      *
  104.      * @see UserInterface
  105.      */
  106.     public function getUserIdentifier(): string
  107.     {
  108.         return (string)$this->email;
  109.     }
  110.     /**
  111.      * @see UserInterface
  112.      */
  113.     public function getRoles(): array
  114.     {
  115.         $roles = $this->roles;
  116.         // guarantee every user at least has ROLE_USER
  117.         $roles[] = 'ROLE_USER';
  118.         return array_unique($roles);
  119.     }
  120.     public function getRole(): string
  121.     {
  122.         if ($this->roles && count($this->roles) > 0) {
  123.             return $this->roles[0];
  124.         }
  125.         return '';
  126.     }
  127.     public function setRoles(array $roles): self
  128.     {
  129.         $this->roles = $roles;
  130.         return $this;
  131.     }
  132.     /**
  133.      * @see PasswordAuthenticatedUserInterface
  134.      */
  135.     public function getPassword(): ?string
  136.     {
  137.         return $this->password;
  138.     }
  139.     public function setPassword(?string $password): self
  140.     {
  141.         $this->password = $password;
  142.         return $this;
  143.     }
  144.     /**
  145.      * @see UserInterface
  146.      */
  147.     public function eraseCredentials()
  148.     {
  149.         // If you store any temporary, sensitive data on the user, clear it here
  150.         // $this->plainPassword = null;
  151.     }
  152.     public function getPersonal(): ?Personal
  153.     {
  154.         return $this->personal;
  155.     }
  156.     public function setPersonal(?Personal $personal): self
  157.     {
  158.         $this->personal = $personal;
  159.         return $this;
  160.     }
  161.     public function isVerified(): bool
  162.     {
  163.         return $this->isVerified;
  164.     }
  165.     public function setIsVerified(bool $isVerified): self
  166.     {
  167.         $this->isVerified = $isVerified;
  168.         return $this;
  169.     }
  170.     public function getUsername(): ?string
  171.     {
  172.         return $this->username;
  173.     }
  174.     public function setUsername(string $username): self
  175.     {
  176.         $this->username = $username;
  177.         return $this;
  178.     }
  179.     public function isActive(): ?bool
  180.     {
  181.         return $this->active;
  182.     }
  183.     public function setActive(?bool $active): self
  184.     {
  185.         $this->active = $active;
  186.         return $this;
  187.     }
  188.     public function getCustomer(): ?Customer
  189.     {
  190.         return $this->customer;
  191.     }
  192.     public function setCustomer(?Customer $customer): self
  193.     {
  194.         $this->customer = $customer;
  195.         return $this;
  196.     }
  197.     public function __toString(): string
  198.     {
  199.         return $this->username;
  200.     }
  201.     public function getGoogleId(): ?string
  202.     {
  203.         return $this->google_id;
  204.     }
  205.     public function setGoogleId(string $google_id): static
  206.     {
  207.         $this->google_id = $google_id;
  208.         return $this;
  209.     }
  210.     public function isApiClient(): bool
  211.     {
  212.         return $this->apiClient;
  213.     }
  214.     public function setApiClient(bool $apiClient): void
  215.     {
  216.         $this->apiClient = $apiClient;
  217.     }
  218.     // =============================================
  219.     // Email Two-Factor Authentication Methods
  220.     // =============================================
  221.     /**
  222.      * Return the email address to which the authentication code is sent
  223.      */
  224.     public function getEmailAuthRecipient(): string
  225.     {
  226.         return $this->email;
  227.     }
  228.     /**
  229.      * Return the authentication code
  230.      */
  231.     public function getEmailAuthCode(): ?string
  232.     {
  233.         return $this->emailAuthCode;
  234.     }
  235.     /**
  236.      * Set the authentication code
  237.      */
  238.     public function setEmailAuthCode(?string $authCode): void
  239.     {
  240.         $this->emailAuthCode = $authCode;
  241.     }
  242.     /**
  243.      * Check if the user has email 2FA enabled.
  244.      * Session method takes priority over DB method.
  245.      */
  246.     public function isEmailAuthEnabled(): bool
  247.     {
  248.         return $this->sessionTwoFactorMethod === 'email' || $this->twoFactorMethod === 'email';
  249.     }
  250.     // =============================================
  251.     // TOTP Two-Factor Authentication Methods
  252.     // =============================================
  253.     /**
  254.      * Check if the user has TOTP 2FA enabled.
  255.      * Session method takes priority over DB method.
  256.      */
  257.     public function isTotpAuthenticationEnabled(): bool
  258.     {
  259.         return ($this->sessionTwoFactorMethod === 'totp' || $this->twoFactorMethod === 'totp')
  260.             && $this->totpSecret !== null;
  261.     }
  262.     /**
  263.      * Return the username shown in authenticator apps
  264.      */
  265.     public function getTotpAuthenticationUsername(): string
  266.     {
  267.         return $this->email;
  268.     }
  269.     /**
  270.      * Get TOTP configuration for the user
  271.      */
  272.     public function getTotpAuthenticationConfiguration(): ?TotpConfigurationInterface
  273.     {
  274.         if (!$this->totpSecret) {
  275.             return null;
  276.         }
  277.         return new TotpConfiguration(
  278.             $this->totpSecret,
  279.             TotpConfiguration::ALGORITHM_SHA1,
  280.             30,
  281.             6
  282.         );
  283.     }
  284.     /**
  285.      * Get the TOTP secret
  286.      */
  287.     public function getTotpSecret(): ?string
  288.     {
  289.         return $this->totpSecret;
  290.     }
  291.     /**
  292.      * Set the TOTP secret
  293.      */
  294.     public function setTotpSecret(?string $totpSecret): self
  295.     {
  296.         $this->totpSecret = $totpSecret;
  297.         return $this;
  298.     }
  299.     // =============================================
  300.     // Two-Factor Method Management
  301.     // =============================================
  302.     /**
  303.      * Get the currently active 2FA method
  304.      */
  305.     public function getTwoFactorMethod(): ?string
  306.     {
  307.         return $this->twoFactorMethod;
  308.     }
  309.     /**
  310.      * Set the 2FA method ('email', 'totp', or null to disable)
  311.      */
  312.     public function setTwoFactorMethod(?string $method): self
  313.     {
  314.         $this->twoFactorMethod = $method;
  315.         return $this;
  316.     }
  317.     /**
  318.      * Check if user has any 2FA method enabled.
  319.      * Session method takes priority over DB method.
  320.      */
  321.     public function isTwoFactorEnabled(): bool
  322.     {
  323.         return $this->sessionTwoFactorMethod !== null || $this->twoFactorMethod !== null;
  324.     }
  325.     // =============================================
  326.     // Session Two-Factor Method (transient)
  327.     // =============================================
  328.     public function getSessionTwoFactorMethod(): ?string
  329.     {
  330.         return $this->sessionTwoFactorMethod;
  331.     }
  332.     public function setSessionTwoFactorMethod(?string $method): self
  333.     {
  334.         $this->sessionTwoFactorMethod = $method;
  335.         return $this;
  336.     }
  337.     // =============================================
  338.     // Trusted Device Methods
  339.     // =============================================
  340.     /**
  341.      * Get trusted device token version
  342.      * Used by scheb/2fa-trusted-device to validate trusted cookies
  343.      */
  344.     public function getTrustedTokenVersion(): int
  345.     {
  346.         return $this->trustedTokenVersion;
  347.     }
  348.     /**
  349.      * Increment token version to invalidate all trusted devices
  350.      */
  351.     public function invalidateTrustedDevices(): self
  352.     {
  353.         $this->trustedTokenVersion++;
  354.         return $this;
  355.     }
  356.     /**
  357.      * Set trusted token version (mainly for persistence)
  358.      */
  359.     public function setTrustedTokenVersion(int $version): self
  360.     {
  361.         $this->trustedTokenVersion = $version;
  362.         return $this;
  363.     }
  364. }