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.
164 lines
6.2 KiB
164 lines
6.2 KiB
<?php
|
|
|
|
/* For licensing terms, see /license.txt */
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Chamilo\CoreBundle\EventSubscriber;
|
|
|
|
use Chamilo\CoreBundle\Entity\TrackELogin;
|
|
use Chamilo\CoreBundle\Entity\User;
|
|
use Chamilo\CoreBundle\Settings\SettingsManager;
|
|
use DateTime;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Bundle\SecurityBundle\Security;
|
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
|
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
|
use Symfony\Component\HttpKernel\KernelEvents;
|
|
|
|
class AnonymousUserSubscriber implements EventSubscriberInterface
|
|
{
|
|
private const MAX_ANONYMOUS_USERS = 5;
|
|
|
|
public function __construct(
|
|
private readonly Security $security,
|
|
private readonly EntityManagerInterface $entityManager,
|
|
private readonly SettingsManager $settingsManager
|
|
) {}
|
|
|
|
public function onKernelRequest(RequestEvent $event): void
|
|
{
|
|
if (null !== $this->security->getUser()) {
|
|
return;
|
|
}
|
|
|
|
$request = $event->getRequest();
|
|
$userIp = $request->getClientIp() ?: '127.0.0.1';
|
|
|
|
$anonymousUserId = $this->getOrCreateAnonymousUserId($userIp);
|
|
if (null !== $anonymousUserId) {
|
|
$trackLoginRepository = $this->entityManager->getRepository(TrackELogin::class);
|
|
|
|
// Check if a login record already exists for this user and IP
|
|
$existingLogin = $trackLoginRepository->findOneBy(['userIp' => $userIp, 'user' => $anonymousUserId]);
|
|
if (!$existingLogin) {
|
|
// Record the access if it does not exist
|
|
$trackLogin = new TrackELogin();
|
|
$trackLogin->setUserIp($userIp)
|
|
->setLoginDate(new DateTime())
|
|
->setUser($this->entityManager->getReference(User::class, $anonymousUserId))
|
|
;
|
|
|
|
$this->entityManager->persist($trackLogin);
|
|
$this->entityManager->flush();
|
|
}
|
|
|
|
$userRepository = $this->entityManager->getRepository(User::class);
|
|
$user = $userRepository->find($anonymousUserId);
|
|
|
|
if ($user) {
|
|
// Store user information in the session
|
|
$userInfo = [
|
|
'user_id' => $user->getId(),
|
|
'username' => $user->getUsername(),
|
|
'firstname' => $user->getFirstname(),
|
|
'lastname' => $user->getLastname(),
|
|
'firstName' => $user->getFirstname(),
|
|
'lastName' => $user->getLastname(),
|
|
'email' => $user->getEmail(),
|
|
'official_code' => $user->getOfficialCode(),
|
|
'picture_uri' => $user->getPictureUri(),
|
|
'status' => $user->getStatus(),
|
|
'active' => $user->isActive(),
|
|
'auth_source' => $user->getAuthSource(),
|
|
'theme' => $user->getTheme(),
|
|
'language' => $user->getLocale(),
|
|
'registration_date' => $user->getRegistrationDate()->format('Y-m-d H:i:s'),
|
|
'expiration_date' => $user->getExpirationDate() ? $user->getExpirationDate()->format('Y-m-d H:i:s') : null,
|
|
'last_login' => $user->getLastLogin() ? $user->getLastLogin()->format('Y-m-d H:i:s') : null,
|
|
'is_anonymous' => true,
|
|
];
|
|
|
|
$request->getSession()->set('_user', $userInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static function getSubscribedEvents(): array
|
|
{
|
|
return [
|
|
KernelEvents::REQUEST => 'onKernelRequest',
|
|
];
|
|
}
|
|
|
|
private function getOrCreateAnonymousUserId(string $userIp): ?int
|
|
{
|
|
$userRepository = $this->entityManager->getRepository(User::class);
|
|
$trackLoginRepository = $this->entityManager->getRepository(TrackELogin::class);
|
|
$anonymousAutoProvisioning = 'true' === $this->settingsManager->getSetting('security.anonymous_autoprovisioning');
|
|
|
|
if (!$anonymousAutoProvisioning) {
|
|
$anonymousUser = $userRepository->findOneBy(['status' => User::ANONYMOUS], ['registrationDate' => 'ASC']);
|
|
if ($anonymousUser) {
|
|
return $anonymousUser->getId();
|
|
}
|
|
|
|
return $this->createAnonymousUser()->getId();
|
|
}
|
|
|
|
$maxAnonymousUsers = (int) $this->settingsManager->getSetting('admin.max_anonymous_users');
|
|
if (0 === $maxAnonymousUsers) {
|
|
$maxAnonymousUsers = self::MAX_ANONYMOUS_USERS;
|
|
}
|
|
$anonymousUsers = $userRepository->findBy(['status' => User::ANONYMOUS], ['registrationDate' => 'ASC']);
|
|
|
|
// Check in TrackELogin if there is an anonymous user with the same IP
|
|
foreach ($anonymousUsers as $user) {
|
|
$loginRecord = $trackLoginRepository->findOneBy(['userIp' => $userIp, 'user' => $user]);
|
|
if ($loginRecord) {
|
|
return $user->getId();
|
|
}
|
|
}
|
|
|
|
// Delete excess anonymous users
|
|
while (\count($anonymousUsers) >= $maxAnonymousUsers) {
|
|
$oldestAnonymousUser = array_shift($anonymousUsers);
|
|
if ($oldestAnonymousUser) {
|
|
error_log('Deleting oldest anonymous user: '.$oldestAnonymousUser->getId());
|
|
|
|
$this->entityManager->remove($oldestAnonymousUser);
|
|
$this->entityManager->flush();
|
|
}
|
|
}
|
|
|
|
return $this->createAnonymousUser()->getId();
|
|
}
|
|
|
|
private function createAnonymousUser(): User
|
|
{
|
|
$uniqueId = uniqid('anon_');
|
|
$email = $uniqueId.'@localhost.local';
|
|
|
|
if ('true' === $this->settingsManager->getSetting('profile.login_is_email')) {
|
|
$uniqueId = $email;
|
|
}
|
|
|
|
$anonymousUser = (new User())
|
|
->setSkipResourceNode(true)
|
|
->setLastname('Joe')
|
|
->setFirstname('Anonymous')
|
|
->setUsername('anon_'.$uniqueId)
|
|
->setStatus(User::ANONYMOUS)
|
|
->setPlainPassword('anon')
|
|
->setEmail($email)
|
|
->setOfficialCode('anonymous')
|
|
->setCreatorId(1)
|
|
->addRole('ROLE_ANONYMOUS')
|
|
;
|
|
|
|
$this->entityManager->persist($anonymousUser);
|
|
$this->entityManager->flush();
|
|
|
|
return $anonymousUser;
|
|
}
|
|
}
|
|
|