<?php
namespace Plugin\AlwaysReCaptcha42;
use Eccube\Common\Constant;
use Eccube\Event\TemplateEvent;
use Eccube\Form\Type\Admin\LoginType;
use Customize\Form\Type\Front\CustomerLoginType;
use Plugin\AlwaysReCaptcha42\Entity\Config;
use Plugin\AlwaysReCaptcha42\Exception\TokenNotFoundException;
use Plugin\AlwaysReCaptcha42\Exception\VerifyFailException;
use Plugin\AlwaysReCaptcha42\Repository\ConfigRepository;
use ReCaptcha\ReCaptcha;
use ReCaptcha\RequestMethod\CurlPost;
use ReCaptcha\RequestMethod\Post;
use ReCaptcha\RequestMethod\SocketPost;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Security;
use function Symfony\Component\Translation\t;
class Event implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
{
/** @var ConfigRepository */
protected $configRepository;
/** @var FormFactoryInterface */
private $formFactory;
/**
* ConfigController constructor.
*
* @param ConfigRepository $configRepository
* @param FormFactoryInterface $formFactory
*/
public function __construct(
ConfigRepository $configRepository,
FormFactoryInterface $formFactory
) {
$this->configRepository = $configRepository;
$this->formFactory = $formFactory;
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents(): array
{
return [
'Entry/index.twig' => 'entryIndexTwig',
'Entry/confirm.twig' => 'entryConfirmTwig',
'Forgot/index.twig' => 'forgotIndexTwig',
'Contact/index.twig' => 'contactIndexTwig',
'Contact/confirm.twig' => 'contactConfirmTwig',
'Mypage/login.twig' => 'mypageLoginTwig',
'Shopping/index.twig' => 'shoppingIndexTwig',
'Shopping/confirm.twig' => 'shoppingConfirmTwig',
'Shopping/login.twig' => 'shoppingLoginTwig',
'Shopping/nonmember.twig' => 'shoppingNonMemberTwig',
KernelEvents::REQUEST => ['onKernelRequest', 9],
];
}
/**
* @param TemplateEvent $event
*/
public function entryIndexTwig(TemplateEvent $event)
{
/** @var Config $Config */
$Config = $this->configRepository->get();
if ($Config->isEnableEntry() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())) {
$this->addReCaptchaSnippet($event, true, $Config->getSiteKey(), $Config->isHideBadge(), 'entry_recaptcha_response', 'entry');
}
}
/**
* @param TemplateEvent $event
*/
public function entryConfirmTwig(TemplateEvent $event)
{
/** @var Config $Config */
$Config = $this->configRepository->get();
if ($Config->isEnableEntry() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())) {
$this->addReCaptchaSnippet($event, true, $Config->getSiteKey(), $Config->isHideBadge(), 'entry_recaptcha_response', 'entry');
}
}
/**
* @param TemplateEvent $event
*/
public function forgotIndexTwig(TemplateEvent $event)
{
/** @var Config $Config */
$Config = $this->configRepository->get();
if ($Config->isEnableForgot() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())) {
$this->addReCaptchaSnippet($event, false, $Config->getSiteKey(), $Config->isHideBadge(), 'form1', 'forgot');
}
}
/**
* @param TemplateEvent $event
*/
public function contactIndexTwig(TemplateEvent $event)
{
/** @var Config $Config */
$Config = $this->configRepository->get();
if ($Config->isEnableContact() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())) {
$this->addReCaptchaSnippet($event, true, $Config->getSiteKey(), $Config->isHideBadge(), 'contact_recaptcha_response', 'contact');
}
}
/**
* @param TemplateEvent $event
*/
public function contactConfirmTwig(TemplateEvent $event)
{
/** @var Config $Config */
$Config = $this->configRepository->get();
if ($Config->isEnableContact() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())) {
$this->addReCaptchaSnippet($event, true, $Config->getSiteKey(), $Config->isHideBadge(), 'contact_recaptcha_response', 'contact');
}
}
/**
* @param TemplateEvent $event
*/
public function mypageLoginTwig(TemplateEvent $event)
{
/** @var Config $Config */
$Config = $this->configRepository->get();
if ($Config->isEnableFrontLogin() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())) {
$this->addReCaptchaSnippet($event, false, $Config->getSiteKey(), $Config->isHideBadge(), 'login_mypage', 'login');
}
}
/**
* @param TemplateEvent $event
*/
public function shoppingIndexTwig(TemplateEvent $event)
{
/** @var Config $Config */
$Config = $this->configRepository->get();
if ($Config->isEnableShopping() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())) {
$this->addReCaptchaSnippet($event, false, $Config->getSiteKey(), $Config->isHideBadge(), 'shopping-form', 'shopping');
}
}
/**
* @param TemplateEvent $event
*/
public function shoppingConfirmTwig(TemplateEvent $event)
{
/** @var Config $Config */
$Config = $this->configRepository->get();
if ($Config->isEnableShopping() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())) {
$this->addReCaptchaSnippet($event, false, $Config->getSiteKey(), $Config->isHideBadge(), 'shopping-form', 'shopping');
}
}
/**
* @param TemplateEvent $event
*/
public function shoppingLoginTwig(TemplateEvent $event)
{
/** @var Config $Config */
$Config = $this->configRepository->get();
if ($Config->isEnableFrontLogin() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())) {
$this->addReCaptchaSnippet($event, false, $Config->getSiteKey(), $Config->isHideBadge(), 'shopping_login', 'login');
}
}
/**
* @param TemplateEvent $event
*/
public function shoppingNonMemberTwig(TemplateEvent $event)
{
/** @var Config $Config */
$Config = $this->configRepository->get();
if ($Config->isEnableNonMember() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())) {
$event->addSnippet('@AlwaysReCaptcha42/Form/non_member_snippet.twig');
$event->setParameter('recaptcha_site_key', $Config->getSiteKey());
$event->setParameter('recaptcha_action', 'non_member');
if ($Config->isHideBadge()) {
$event->addAsset('@AlwaysReCaptcha42/Form/hide_badge_asset.twig');
}
}
}
/**
* @param TemplateEvent $event
* @param bool $withConfirm
* @param string $siteKey
* @param bool $hideBadge
* @param string $formId
* @param string $action
*/
private function addReCaptchaSnippet(
TemplateEvent $event,
bool $withConfirm,
string $siteKey,
bool $hideBadge,
string $formId,
string $action
) {
if ($withConfirm) {
$event->addSnippet('@AlwaysReCaptcha42/Form/with_confirm_snippet.twig');
$event->setParameter('recaptcha_input_id', $formId);
} else {
$event->addSnippet('@AlwaysReCaptcha42/Form/no_confirm_snippet.twig');
$event->setParameter('recaptcha_form_id', $formId);
}
$event->setParameter('recaptcha_site_key', $siteKey);
$event->setParameter('recaptcha_action', $action);
if ($hideBadge) {
$event->addAsset('@AlwaysReCaptcha42/Form/hide_badge_asset.twig');
}
}
public function onKernelRequest(RequestEvent $event)
{
/** @var Config $Config */
$Config = $this->configRepository->get();
$route = $event->getRequest()->attributes->get('_route');
if (
'admin_login' === $route
&& $Config->isEnableAdminLogin() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())
) {
$loginForm = $this->formFactory->createNamed('', LoginType::class);
$loginForm->handleRequest($event->getRequest());
if (!$loginForm->isSubmitted()) {
return;
}
$threshold = $Config->getThresholdAdminLogin();
$userName = $loginForm->get('login_id')->getData();
} elseif (
('shopping_login' === $route || 'mypage_login' === $route)
&& $Config->isEnableFrontLogin() && !empty($Config->getSiteKey()) && !empty($Config->getSecretKey())
) {
$loginForm = $this->formFactory->createNamed('', CustomerLoginType::class);
$loginForm->handleRequest($event->getRequest());
if (!$loginForm->isSubmitted()) {
return;
}
$threshold = $Config->getThreshold();
$userName = $loginForm->get('login_email')->getData();
} else {
return;
}
$request = $event->getRequest();
$session = $request->getSession();
$recaptchaToken = $loginForm->get('recaptcha_response')->getData();
if (empty($recaptchaToken)) {
$session->set(Security::AUTHENTICATION_ERROR, new TokenNotFoundException('Google reCAPTCHA Token is not set. Try again later or contact the site administrator.'));
} else {
switch ($Config->getRequestMethod()) {
case Config::REQUEST_METHOD_CURL:
$requestMethod = new CurlPost();
break;
case Config::REQUEST_METHOD_SOCKET:
$requestMethod = new SocketPost();
break;
default:
$requestMethod = new Post();
break;
}
$recaptcha = new ReCaptcha($Config->getSecretKey(), $requestMethod);
$resp = $recaptcha->setExpectedHostname($request->getHost())
->setExpectedAction('login')
->setScoreThreshold($threshold)
->verify($recaptchaToken, $request->getClientIp());
if ($resp->isSuccess()) {
if ($Config->getLogMode() == Config::LOG_MODE_ALL) {
log_info('いつも reCAPTCHA 認証ログ', [$resp->toArray()]);
}
return;
}
$session->set(Security::AUTHENTICATION_ERROR, new VerifyFailException('Google reCAPTCHA verification is failed. Try again later or contact the site administrator.'));
log_warning('いつも reCAPTCHA 認証ログ', [$resp->toArray()]);
}
$session->set(Security::LAST_USERNAME, $userName);
//to prevent request to call next event
$event->setResponse(new RedirectResponse($event->getRequest()->getRequestUri()));
}
}