<?php
namespace App\Security;
use App\Entity\{User, UserLoginHistory};
use App\Repository\UserLoginHistoryRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\{RedirectResponse, Request, Response};
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\{CsrfTokenBadge, RememberMeBadge, UserBadge};
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
use App\Entity\UserLog;
use Symfony\Component\Security\Core\Security;
use Nzo\UrlEncryptorBundle\Encryptor\Encryptor;
class AppPhcAuthenticator extends AbstractLoginFormAuthenticator
{
use TargetPathTrait;
private $params;
private $encryptor;
public function __construct(private EntityManagerInterface $entityManager, private RouterInterface $router, Encryptor $encryptor)
{
$this->encryptor = $encryptor;
}
public function supports(Request $request): bool
{
return 'app_login' === $request->attributes->get('_route') && $request->isMethod('POST');
}
public function verifyGoogleRecaptcha($token)
{
$ip2020 = "";
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip2020 = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip2020 = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip2020 = $_SERVER['REMOTE_ADDR'];
}
$endpoint = 'https://www.google.com/recaptcha/api/siteverify';
$secretKey = $_ENV['GOOGLE_RECAPTCHA_SECRET_KEY'];
$arrParams = "secret=$secretKey" . "&response=$token" . "&remoteip=$ip2020";
$ch = @curl_init();
@curl_setopt($ch, CURLOPT_POST, true);
@curl_setopt($ch, CURLOPT_POSTFIELDS, $arrParams);
@curl_setopt($ch, CURLOPT_URL, $endpoint);
@curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/x-www-form-urlencoded'
));
@curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = @curl_exec($ch); //Log the response from HubSpot as needed.
@curl_close($ch);
return json_decode($response, true);
}
public function authenticate(Request $request): Passport
{
// $token = $request->request->get('g-recaptcha-response');
// $responses = $this->verifyGoogleRecaptcha($token);
// if (!$responses['success']) {
// throw new UserNotFoundException();
// }
$username = $request->request->get('_username');
$password = $request->request->get('_password');
return new Passport(
new UserBadge($username, function ($userIdentifier) {
$user = $this->entityManager->getRepository(User::class)->findOneBy(['username' => $userIdentifier]);
if (!$user) {
throw new UserNotFoundException();
}
return $user;
}),
new PasswordCredentials($password),
[
new CsrfTokenBadge(
'authenticate',
$request->request->get('_csrf_token')
),
$request->request->has('_remember_me') ? (new RememberMeBadge())->enable() : new RememberMeBadge()
]
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
/** @var User $user */
$user = $token->getUser();
date_default_timezone_set('Asia/Kolkata');
$user->setLastLogin(new \DateTime());
$user->setIsActive(true);
$this->entityManager->persist($user);
$history = new UserLoginHistory();
$history
->setUser($user)
->setUserIp($request->getClientIp())
->setLoginAttempts(0);
$this->entityManager->persist($history);
$this->entityManager->flush();
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
return new RedirectResponse($targetPath);
}
$this->entityManager->getConnection()->setAutoCommit(false);
$this->entityManager->beginTransaction();
$currentDate = new \Datetime();
$uid = $token->getUser()->getId();
$Filename = $uid . '_' . date('d-m-Y') . '.csv';
$baseUrl = $request->getBaseUrl();
$filePath = $baseUrl . '/uploads/activity_log/' . $uid . '/' . $Filename;
$userLog = new UserLog();
$userLog->setUserId($user->getId());
$userLog->setAction($request->getMethod());
$userLog->setFilePath($Filename);
$userLog->setHospitalId($user->getProfile()->getHospital()->getId());
$userLog->setCreatedDate($currentDate);
$userLog->setUpdatedAt($currentDate);
$userLog->setCreatedDate($currentDate);
$this->entityManager->persist($userLog);
$this->entityManager->flush();
$this->entityManager->commit();
$role = $token->getUser()->getRoles()[0];
$id = $token->getUser()->getProfile()->getId();
if (($token->getUser()->getProfile()->getIsUpdate() != '' && $token->getUser()->getProfile()->getIsUpdate() == 0) && ($role != '' && $role == "ROLE_HR")) {
return new RedirectResponse($this->router->generate('staff_profile_edit', ['id' => $this->encryptor->encrypt($id)]));
}
return new RedirectResponse($this->router->generate('dashboard'));
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
{
$history = new UserLoginHistory();
$user = new User();
$failure = 0;
$user = $this->entityManager->getRepository(User::class)->findOneBy(['username' => $request->request->get('_username')]);
if ($request->request->get('_username')) {
$failure += 1;
}
if ($user) {
date_default_timezone_set('Asia/Kolkata');
$uID = $user->getId();
$fileName = $user->getId() . '_' . date('d-m-Y') . '.csv';
if (!file_exists('../public/uploads/login_failure/' . $uID)) {
$userId = mkdir('../public/uploads/login_failure/' . $uID, 0777, true);
} else {
$userId = $uID;
}
$filePath = '../public/uploads/login_failure/' . $userId . '/' . $fileName;
$failureFile = fopen($filePath, "a") or die('Unable to open file');
$dataArr = [
'username' => $request->request->get('_username'),
'login_attempts' => $failure,
'client_ip' => $request->getClientIp(),
'date/time' => date('d-m-Y h:i:s'),
];
fputcsv($failureFile, $dataArr);
fclose($failureFile);
$data = $this->entityManager->getRepository(UserLoginHistory::class)->getLoginHistoryByUserId($user->getId());
$this->entityManager->getRepository(UserLoginHistory::class)->UpdateLoginHistoryByUserId($user->getId());
if ($data) {
if ($data[0]['total'] >= 8) {
$user->setIsActive(false);
}
}
$history
->setUser($user)
->setLoginAttempts($failure)
->setUserIp($request->getClientIp())
->setFileUrl($fileName);
$this->entityManager->persist($history);
$this->entityManager->flush();
}
$request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
return new RedirectResponse($this->router->generate('app_login'));
}
protected function getLoginUrl(Request $request): string
{
return $this->router->generate('app_login');
}
}