X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=src%2FWallabag%2FUserBundle%2FEntity%2FUser.php;h=43fa6a80fc2bb47b40970b936a21a2612de0a59a;hb=9f0957b831622ee577fa7d8f92ec0df6f3a8e274;hp=aba76ca74a262e3ddcc83b90d26519a0af151d2d;hpb=873f6b8e03079d11fab541aa5b0bc6f8fe2d645e;p=github%2Fwallabag%2Fwallabag.git diff --git a/src/Wallabag/UserBundle/Entity/User.php b/src/Wallabag/UserBundle/Entity/User.php index aba76ca7..43fa6a80 100644 --- a/src/Wallabag/UserBundle/Entity/User.php +++ b/src/Wallabag/UserBundle/Entity/User.php @@ -4,17 +4,19 @@ namespace Wallabag\UserBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; +use FOS\UserBundle\Model\User as BaseUser; +use JMS\Serializer\Annotation\Accessor; use JMS\Serializer\Annotation\Groups; use JMS\Serializer\Annotation\XmlRoot; -use JMS\Serializer\Annotation\Accessor; -use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface; -use Scheb\TwoFactorBundle\Model\TrustedComputerInterface; -use FOS\UserBundle\Model\User as BaseUser; +use Scheb\TwoFactorBundle\Model\BackupCodeInterface; +use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface as EmailTwoFactorInterface; +use Scheb\TwoFactorBundle\Model\Google\TwoFactorInterface as GoogleTwoFactorInterface; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Security\Core\User\UserInterface; use Wallabag\ApiBundle\Entity\Client; use Wallabag\CoreBundle\Entity\Config; use Wallabag\CoreBundle\Entity\Entry; +use Wallabag\CoreBundle\Helper\EntityTimestampsTrait; /** * User. @@ -27,8 +29,10 @@ use Wallabag\CoreBundle\Entity\Entry; * @UniqueEntity("email") * @UniqueEntity("username") */ -class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterface +class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorInterface, BackupCodeInterface { + use EntityTimestampsTrait; + /** @Serializer\XmlAttribute */ /** * @var int @@ -93,21 +97,11 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf protected $config; /** - * @ORM\Column(type="integer", nullable=true) - */ - private $authCode; - - /** - * @var bool + * @var ArrayCollection * - * @ORM\Column(type="boolean") + * @ORM\OneToMany(targetEntity="Wallabag\CoreBundle\Entity\SiteCredential", mappedBy="user", cascade={"remove"}) */ - private $twoFactorAuthentication = false; - - /** - * @ORM\Column(type="json_array", nullable=true) - */ - private $trusted; + protected $siteCredentials; /** * @var ArrayCollection @@ -124,6 +118,28 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf */ protected $default_client; + /** + * @ORM\Column(type="integer", nullable=true) + */ + private $authCode; + + /** + * @ORM\Column(name="googleAuthenticatorSecret", type="string", nullable=true) + */ + private $googleAuthenticatorSecret; + + /** + * @ORM\Column(type="json_array", nullable=true) + */ + private $backupCodes; + + /** + * @var bool + * + * @ORM\Column(type="boolean") + */ + private $emailTwoFactor = false; + public function __construct() { parent::__construct(); @@ -131,19 +147,6 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf $this->roles = ['ROLE_USER']; } - /** - * @ORM\PrePersist - * @ORM\PreUpdate - */ - public function timestamps() - { - if (is_null($this->createdAt)) { - $this->createdAt = new \DateTime(); - } - - $this->updatedAt = new \DateTime(); - } - /** * Set name. * @@ -236,49 +239,119 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf /** * @return bool */ - public function isTwoFactorAuthentication() + public function isEmailTwoFactor() + { + return $this->emailTwoFactor; + } + + /** + * @param bool $emailTwoFactor + */ + public function setEmailTwoFactor($emailTwoFactor) { - return $this->twoFactorAuthentication; + $this->emailTwoFactor = $emailTwoFactor; } /** - * @param bool $twoFactorAuthentication + * Used in the user config form to be "like" the email option. */ - public function setTwoFactorAuthentication($twoFactorAuthentication) + public function isGoogleTwoFactor() { - $this->twoFactorAuthentication = $twoFactorAuthentication; + return $this->isGoogleAuthenticatorEnabled(); } - public function isEmailAuthEnabled() + /** + * {@inheritdoc} + */ + public function isEmailAuthEnabled(): bool { - return $this->twoFactorAuthentication; + return $this->emailTwoFactor; } - public function getEmailAuthCode() + /** + * {@inheritdoc} + */ + public function getEmailAuthCode(): string { return $this->authCode; } - public function setEmailAuthCode($authCode) + /** + * {@inheritdoc} + */ + public function setEmailAuthCode(string $authCode): void { $this->authCode = $authCode; } - public function addTrustedComputer($token, \DateTime $validUntil) + /** + * {@inheritdoc} + */ + public function getEmailAuthRecipient(): string { - $this->trusted[$token] = $validUntil->format('r'); + return $this->email; } - public function isTrustedComputer($token) + /** + * {@inheritdoc} + */ + public function isGoogleAuthenticatorEnabled(): bool { - if (isset($this->trusted[$token])) { - $now = new \DateTime(); - $validUntil = new \DateTime($this->trusted[$token]); + return $this->googleAuthenticatorSecret ? true : false; + } - return $now < $validUntil; - } + /** + * {@inheritdoc} + */ + public function getGoogleAuthenticatorUsername(): string + { + return $this->username; + } - return false; + /** + * {@inheritdoc} + */ + public function getGoogleAuthenticatorSecret(): string + { + return $this->googleAuthenticatorSecret; + } + + /** + * {@inheritdoc} + */ + public function setGoogleAuthenticatorSecret(?string $googleAuthenticatorSecret): void + { + $this->googleAuthenticatorSecret = $googleAuthenticatorSecret; + } + + public function setBackupCodes(array $codes = null) + { + $this->backupCodes = $codes; + } + + public function getBackupCodes() + { + return $this->backupCodes; + } + + /** + * {@inheritdoc} + */ + public function isBackupCode(string $code): bool + { + return false === $this->findBackupCode($code) ? false : true; + } + + /** + * {@inheritdoc} + */ + public function invalidateBackupCode(string $code): void + { + $key = $this->findBackupCode($code); + + if (false !== $key) { + unset($this->backupCodes[$key]); + } } /** @@ -312,4 +385,24 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf return $this->clients->first(); } } + + /** + * Try to find a backup code from the list of backup codes of the current user. + * + * @param string $code Given code from the user + * + * @return string|false + */ + private function findBackupCode(string $code) + { + foreach ($this->backupCodes as $key => $backupCode) { + // backup code are hashed using `password_hash` + // see ConfigController->otpAppAction + if (password_verify($code, $backupCode)) { + return $key; + } + } + + return false; + } }