You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
expire-email-validation/EventListener/CheckExpiryListener.php

189 lines
5.8 KiB

<?php
namespace vierbergenlars\AuthserverExpireEmailValidationBundle\EventListener;
use App\AppEvents;
use App\Event\UserCheckerEvent;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Exception\AccountExpiredException;
use Symfony\Component\Security\Core\AuthenticationEvents;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use vierbergenlars\AuthserverExpireEmailValidationBundle\Entity\ExpiredUser;
use vierbergenlars\AuthserverStatsBundle\Event\StatsEvent;
use Symfony\Component\VarDumper\VarDumper;
use Psr\Log\LoggerInterface;
use App\Mail\PrimedTwigMailer;
use Symfony\Component\Security\Core\Role\SwitchUserRole;
class CheckExpiryListener implements EventSubscriberInterface
{
/**
*
* @var EntityManagerInterface
*/
private $em;
/**
*
* @var LoggerInterface
*/
private $logger;
/**
*
* @var PrimedTwigMailer
*/
private $mailer;
public static function getSubscribedEvents()
{
return [
AppEvents::SECURITY_USER_CHECK_POST => [
'onUserCheck'
],
AuthenticationEvents::AUTHENTICATION_SUCCESS => [
'onAuthenticationSuccess'
],
StatsEvent::class => [
'getExpiryStats',
-10
]
];
}
public function __construct(EntityManagerInterface $em, PrimedTwigMailer $mailer, LoggerInterface $logger)
{
$this->em = $em;
$this->mailer = $mailer;
$this->logger = $logger;
}
/**
*
* @return EntityRepository
*/
private function getRepository()
{
return $this->em->getRepository(ExpiredUser::class);
}
/**
*
* @param User $user
* @return ExpiredUser|null
*/
private function getExpiredUserForUser(User $user)
{
return $this->getRepository()->findOneBy([
'user' => $user
]);
}
public function onUserCheck(UserCheckerEvent $event)
{
$user = $event->getUser();
$this->logger->debug("Checking expiry of user", [
'user' => $user
]);
if (!($user instanceof User)) {
$this->logger->debug('Not applicable to this type of user', [
'user' => $user
]);
return;
}
/* @var $user User */
$expiredUser = $this->getExpiredUserForUser($user);
$this->logger->debug('Fetched user expiry record', [
'expired_user' => $expiredUser,
'is_expired' => $expiredUser ? $expiredUser->isExpired() : null
]);
if ($expiredUser !== null && $expiredUser->isExpired()) {
$emailAddresses = $user->getEmailAddresses()->toArray();
$this->logger->info('User marked as expired. Unverifying all email addresses.', [
'user' => $user,
'email_addresses' => $emailAddresses
]);
foreach ($emailAddresses as $emailAddress) {
/* @var $emailAddress \App\Entity\EmailAddress */
$emailAddress->setVerified(false);
if (!$this->mailer->sendMessage($emailAddress->getEmail(), $emailAddress)) {
$this->logger->error('Verification email could not be sent.', [
'email_address' => $emailAddress
]);
}
}
$this->em->flush();
throw new AccountExpiredException('Email address verification expired. An email has been sent to your email addresses to reactivate your account.');
}
}
public function onAuthenticationSuccess(AuthenticationEvent $event)
{
$this->logger->debug("Updating last login time of user", [
'token' => $event->getAuthenticationToken(),
'user' => $event->getAuthenticationToken()
->getUser()
]);
$token = $event->getAuthenticationToken();
foreach ($token->getRoles() as $role) {
if ($role instanceof SwitchUserRole) {
$this->logger->info('Authentication success event is caused by an impersonation. Not registering a new login.', [
'role' => $role
]);
return;
}
}
$user = $token->getUser();
if (!($user instanceof User)) {
$this->logger->debug('Not applicable to this type of user', [
'user' => $user
]);
return;
}
$expiredUser = $this->getExpiredUserForUser($user);
$this->logger->debug('Fetched user expiry record', [
'expired_user' => $expiredUser,
'is_expired' => $expiredUser ? $expiredUser->isExpired() : null
]);
if ($expiredUser === null) {
$this->logger->debug('No user expiry record exists. Creating a new one.');
$expiredUser = new ExpiredUser($user);
$this->em->persist($expiredUser);
}
$expiredUser->setLastLogin(new \DateTime());
$this->em->flush($expiredUser);
}
public function getExpiryStats(StatsEvent $event)
{
if (!$event->isEnabled('autoexpire'))
return;
$event->setMuninConfig('user', $event->getMuninConfig('user') + [
'autoexpire.label' => 'Expired users',
'autoexpire.draw' => 'LINE'
]);
$expiredUsers = $this->getRepository()
->createQueryBuilder('e')
->select('count(e.expiredAt)')
->where('e.expiredAt IS NOT NULL AND e.expiredAt < :now')
->setParameter('now', new \DateTime())
->getQuery()
->getSingleScalarResult();
$event->addStatistic('user.autoexpire', $expiredUsers);
}
}