SchulIT /
idp
| 1 | <?php |
||
| 2 | |||
| 3 | namespace App\Security\EmailConfirmation; |
||
| 4 | |||
| 5 | use App\Converter\UserStringConverter; |
||
| 6 | use App\Entity\EmailConfirmation; |
||
| 7 | use App\Entity\User; |
||
| 8 | use App\Repository\EmailConfirmationRepositoryInterface; |
||
| 9 | use App\Repository\UserRepositoryInterface; |
||
| 10 | use SchulIT\CommonBundle\Helper\DateHelper; |
||
| 11 | use Symfony\Bridge\Twig\Mime\TemplatedEmail; |
||
| 12 | use Symfony\Component\Mailer\MailerInterface; |
||
| 13 | use Symfony\Component\Mime\Address; |
||
| 14 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
||
| 15 | use Symfony\Contracts\Translation\TranslatorInterface; |
||
| 16 | |||
| 17 | class ConfirmationManager { |
||
| 18 | |||
| 19 | private const Lifetime = '+2 hours'; |
||
| 20 | |||
| 21 | public function __construct(private DateHelper $dateHelper, private EmailConfirmationRepositoryInterface $repository, private UserRepositoryInterface $userRepository, private TranslatorInterface $translator, private MailerInterface $mailer, private UserStringConverter $userConverter, private UrlGeneratorInterface $urlGenerator) |
||
| 22 | { |
||
| 23 | } |
||
| 24 | |||
| 25 | public function hasConfirmation(User $user): bool { |
||
| 26 | 11 | return $this->repository->findOneByUser($user) !== null; |
|
| 27 | } |
||
| 28 | 11 | ||
| 29 | 11 | public function newConfirmation(User $user, string $email): void { |
|
| 30 | 11 | $confirmation = $this->repository->findOneByUser($user); |
|
| 31 | 11 | ||
| 32 | 11 | if($confirmation !== null && $confirmation->getValidUntil() <= $this->dateHelper->getNow()) { |
|
| 33 | 11 | return; |
|
| 34 | 11 | } |
|
| 35 | 11 | ||
| 36 | if($confirmation !== null) { |
||
| 37 | $this->repository->remove($confirmation); |
||
| 38 | } |
||
| 39 | |||
| 40 | $confirmation = (new EmailConfirmation()) |
||
| 41 | ->setUser($user) |
||
| 42 | ->setEmailAddress($email) |
||
| 43 | ->setValidUntil($this->dateHelper->getNow()->modify(self::Lifetime)); |
||
| 44 | |||
| 45 | do { |
||
| 46 | $confirmation->setToken(bin2hex(openssl_random_pseudo_bytes(64))); |
||
| 47 | } while($this->repository->findOneByToken($confirmation->getToken()) !== null); |
||
| 48 | |||
| 49 | $this->repository->persist($confirmation); |
||
| 50 | $email = (new TemplatedEmail()) |
||
| 51 | ->subject($this->translator->trans('registration.title', [], 'mail')) |
||
| 52 | ->to(new Address($confirmation->getEmailAddress(), $this->userConverter->convert($user))) |
||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 53 | ->textTemplate('mail/email_confirmation.txt.twig') |
||
| 54 | ->htmlTemplate('mail/email_confirmation.html.twig') |
||
| 55 | ->context([ |
||
| 56 | 'username' => $user->getUsername(), |
||
| 57 | 'token' => $confirmation->getToken(), |
||
| 58 | 'link' => $this->urlGenerator->generate('confirm_email', [ |
||
| 59 | 'token' => $confirmation->getToken() |
||
| 60 | ], UrlGeneratorInterface::ABSOLUTE_URL), |
||
| 61 | 'expiry_date' => $confirmation->getValidUntil() |
||
| 62 | ]); |
||
| 63 | |||
| 64 | $this->mailer->send($email); |
||
| 65 | } |
||
| 66 | |||
| 67 | /** |
||
| 68 | * @throws TokenNotFoundException |
||
| 69 | */ |
||
| 70 | public function confirm(string $token): void { |
||
| 71 | $confirmation = $this->repository->findOneByToken($token); |
||
| 72 | |||
| 73 | if($confirmation === null) { |
||
| 74 | throw new TokenNotFoundException($token); |
||
| 75 | } |
||
| 76 | |||
| 77 | $user = $confirmation->getUser(); |
||
| 78 | $user->setEmail($confirmation->getEmailAddress()); |
||
| 79 | $user->setIsEmailConfirmationPending(false); |
||
| 80 | |||
| 81 | $this->userRepository->persist($user); |
||
| 82 | $this->repository->remove($confirmation); |
||
| 83 | } |
||
| 84 | |||
| 85 | public function removeOldConfirmations(): int { |
||
| 86 | return $this->repository->removeExpired($this->dateHelper->getNow()); |
||
| 87 | } |
||
| 88 | } |