<?php
namespace Customize\Controller;
use Eccube\Form\Type\Front\CustomerLoginType;
use Eccube\Repository\NewsRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Eccube\Event\EventArgs;
use Eccube\Entity\Customer;
use Eccube\Event\EccubeEvents;
use Eccube\Controller\AbstractController;
use Eccube\Repository\CustomerRepository;
use Eccube\Form\Type\Front\EntryType;
use Eccube\Repository\PageRepository;
use Eccube\Service\MailService;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Eccube\Repository\BaseInfoRepository;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Eccube\Entity\Master\CustomerStatus;
use Eccube\Service\CartService;
use Eccube\Repository\Master\CustomerStatusRepository;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpKernel\Exception as HttpException;
use Eccube\Form\Type\Front\ForgotType;
use Eccube\Form\Type\Front\PasswordResetType;
use Exception;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class AuthController extends AbstractController
{
/**
* @var CustomerRepository
*/
protected $customerRepository;
/**
* @var PageRepository
*/
protected $pageRepository;
/**
* @var EncoderFactoryInterface
*/
protected $encoderFactory;
/**
* @var CustomerStatusRepository
*/
protected $customerStatusRepository;
/**
* @var BaseInfo
*/
protected $BaseInfo;
/**
* @var MailService
*/
protected $mailService;
/**
* @var \Eccube\Service\CartService
*/
protected $cartService;
/**
* @var ValidatorInterface
*/
protected $recursiveValidator;
/**
* @var TokenStorageInterface
*/
protected $tokenStorage;
public function __construct(
CustomerRepository $customerRepository,
PageRepository $pageRepository,
BaseInfoRepository $baseInfoRepository,
MailService $mailService,
EncoderFactoryInterface $encoderFactory,
ValidatorInterface $validatorInterface,
CartService $cartService,
CustomerStatusRepository $customerStatusRepository,
TokenStorageInterface $tokenStorage
) {
$this->BaseInfo = $baseInfoRepository->get();
$this->customerRepository = $customerRepository;
$this->pageRepository = $pageRepository;
$this->encoderFactory = $encoderFactory;
$this->mailService = $mailService;
$this->recursiveValidator = $validatorInterface;
$this->cartService = $cartService;
$this->customerStatusRepository = $customerStatusRepository;
$this->tokenStorage = $tokenStorage;
}
/**
* @Route("/mypage-login", name="mypage-login", methods={"GET", "POST"})
* @Template("@user_data/auth/mypage_login.twig")
*/
public function login(Request $request, AuthenticationUtils $utils)
{
if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
log_info('認証済のためログイン処理をスキップ');
return $this->redirectToRoute('mypage_index');
}
/* @var $form \Symfony\Component\Form\FormInterface */
$builder = $this->formFactory
->createNamedBuilder('', CustomerLoginType::class);
$builder->get('login_memory')->setData((bool) $request->getSession()->get('_security.login_memory'));
if ($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
$Customer = $this->getUser();
if ($Customer instanceof Customer) {
$builder->get('login_email')
->setData($Customer->getEmail());
}
}
$event = new EventArgs(
[
'builder' => $builder,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_MYPAGE_MYPAGE_LOGIN_INITIALIZE);
$form = $builder->getForm();
$this->tokenStorage->setToken(null);
return [
'error' => $utils->getLastAuthenticationError(false),
'form' => $form->createView(),
];
}
/**
* Logout
*
* @Route("/customer_logout", name="customer_logout", methods={"GET"})
*/
public function logout()
{
if ($this->tokenStorage->getToken() && $this->tokenStorage->getToken()->getUser() instanceof Customer) {
$this->tokenStorage->setToken(null);
return $this->redirectToRoute('homepage');
}
}
/**
* 会員登録画面.
*
* @Route("/register", name="register", methods={"GET", "POST"})
* @Route("/register", name="register_confirm", methods={"GET", "POST"})
* @Template("@user_data/auth/mypage_register.twig")
*/
public function index(Request $request)
{
if ($this->isGranted('ROLE_USER')) {
log_info('認証済のためログイン処理をスキップ');
return $this->redirectToRoute('mypage_index');
}
/** @var $Customer \Eccube\Entity\Customer */
$Customer = $this->customerRepository->newCustomer();
/* @var $builder \Symfony\Component\Form\FormBuilderInterface */
$builder = $this->formFactory->createBuilder(EntryType::class, $Customer);
$event = new EventArgs(
[
'builder' => $builder,
'Customer' => $Customer,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_ENTRY_INDEX_INITIALIZE);
/* @var $form \Symfony\Component\Form\FormInterface */
$form = $builder->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$mailmagaFlg = $form->get('mailmaga_flg')->getData() ? 1 : 0;
$Customer->setMailmagaFlg($mailmagaFlg);
switch ($request->get('mode')) {
case 'confirm':
log_info('会員登録確認開始');
log_info('会員登録確認完了');
return $this->render(
'@user_data/auth/mypage_register_confirm.twig',
[
'form' => $form->createView(),
'Page' => $this->pageRepository->getPageByRoute('register_confirm'),
]
);
case 'complete':
log_info('会員登録開始');
$encoder = $this->encoderFactory->getEncoder($Customer);
$salt = $encoder->createSalt();
$password = $encoder->encodePassword($Customer->getPlainPassword(), $salt);
$secretKey = $this->customerRepository->getUniqueSecretKey();
$Customer
->setSalt($salt)
->setPassword($password)
->setSecretKey($secretKey)
->setPoint(0);
$this->entityManager->persist($Customer);
$this->entityManager->flush();
log_info('会員登録完了');
$event = new EventArgs(
[
'form' => $form,
'Customer' => $Customer,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_ENTRY_INDEX_COMPLETE);
$activateFlg = $this->BaseInfo->isOptionCustomerActivate();
// 仮会員設定が有効な場合は、確認メールを送信し完了画面表示.
if ($activateFlg) {
$activateUrl = $this->generateUrl('register_activate', ['secret_key' => $Customer->getSecretKey()], UrlGeneratorInterface::ABSOLUTE_URL);
// メール送信
$this->mailService->sendCustomerConfirmMail($Customer, $activateUrl);
if ($event->hasResponse()) {
return $event->getResponse();
}
log_info('仮会員登録完了画面へリダイレクト');
return $this->redirectToRoute('register_complete');
} else {
// 仮会員設定が無効な場合は、会員登録を完了させる.
$qtyInCart = $this->entryActivate($request, $Customer->getSecretKey());
// URLを変更するため完了画面にリダイレクト
return $this->redirectToRoute('register_activate', [
'secret_key' => $Customer->getSecretKey(),
'qtyInCart' => $qtyInCart,
]);
}
}
}
return [
'form' => $form->createView(),
];
}
/**
* 会員登録完了画面.
*
* @Route("/register/complete", name="register_complete", methods={"GET"})
* @Template("@user_data/auth/mypage_register_complete.twig")
*/
public function register_complete()
{
return [];
}
/**
* 会員のアクティベート(本会員化)を行う.
*
* @Route("/register/activate/{secret_key}/{qtyInCart}", name="register_activate", methods={"GET"})
* @Template("@user_data/auth/mypage_register_activate.twig")
*/
public function activate(Request $request, $secret_key, $qtyInCart = null)
{
$errors = $this->recursiveValidator->validate(
$secret_key,
[
new Assert\NotBlank(),
new Assert\Regex(
[
'pattern' => '/^[a-zA-Z0-9]+$/',
]
),
]
);
if (!$this->session->has('eccube.login.target.path')) {
$this->setLoginTargetPath($this->generateUrl('mypage', [], UrlGeneratorInterface::ABSOLUTE_URL));
}
if (!is_null($qtyInCart)) {
return [
'qtyInCart' => $qtyInCart,
];
} elseif ($request->getMethod() === 'GET' && count($errors) === 0) {
// 会員登録処理を行う
try {
$qtyInCart = $this->entryActivate($request, $secret_key);
return [
'qtyInCart' => $qtyInCart,
];
} catch(Exception $e) {
return $this->redirectToRoute('homepage');
}
}
throw new HttpException\NotFoundHttpException();
}
/**
* 会員登録処理を行う
*
* @param Request $request
* @param $secret_key
*
* @return \Eccube\Entity\Cart|mixed
*/
private function entryActivate(Request $request, $secret_key)
{
log_info('本会員登録開始');
$Customer = $this->customerRepository->getProvisionalCustomerBySecretKey($secret_key);
if (is_null($Customer)) {
throw new HttpException\NotFoundHttpException();
}
$CustomerStatus = $this->customerStatusRepository->find(CustomerStatus::REGULAR);
$Customer->setStatus($CustomerStatus);
$this->entityManager->persist($Customer);
$this->entityManager->flush();
log_info('本会員登録完了');
$event = new EventArgs(
[
'Customer' => $Customer,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_ENTRY_ACTIVATE_COMPLETE);
// メール送信
$this->mailService->sendCustomerCompleteMail($Customer);
// Assign session carts into customer carts
$Carts = $this->cartService->getCarts();
$qtyInCart = 0;
foreach ($Carts as $Cart) {
$qtyInCart += $Cart->getTotalQuantity();
}
if ($qtyInCart) {
$this->cartService->save();
}
return $qtyInCart;
}
/**
* パスワードリマインダ.
*
* @Route("/forgot_password", name="forgot_password", methods={"GET", "POST"})
* @Template("@user_data/auth/mypage_forgot_password.twig")
*/
public function forgot(Request $request)
{
if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
throw new HttpException\NotFoundHttpException();
}
$builder = $this->formFactory
->createNamedBuilder('', ForgotType::class);
$event = new EventArgs(
[
'builder' => $builder,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_FORGOT_INDEX_INITIALIZE);
$form = $builder->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$Customer = $this->customerRepository
->getRegularCustomerByEmail($form->get('login_email')->getData());
if (!is_null($Customer)) {
// リセットキーの発行・有効期限の設定
$Customer
->setResetKey($this->customerRepository->getUniqueResetKey())
->setResetExpire(new \DateTime('+' . $this->eccubeConfig['eccube_customer_reset_expire'] . ' min'));
// リセットキーを更新
$this->entityManager->persist($Customer);
$this->entityManager->flush();
$event = new EventArgs(
[
'form' => $form,
'Customer' => $Customer,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_FORGOT_INDEX_COMPLETE);
// 完了URLの生成
$reset_url = $this->generateUrl('forgot_password_reset', ['reset_key' => $Customer->getResetKey()], UrlGeneratorInterface::ABSOLUTE_URL);
// メール送信
$this->mailService->sendPasswordResetNotificationMail($Customer, $reset_url);
// ログ出力
log_info('send reset password mail to:' . "{$Customer->getId()} {$Customer->getEmail()} {$request->getClientIp()}");
} else {
log_warning(
'Un active customer try send reset password email: ',
['Enter email' => $form->get('login_email')->getData()]
);
}
return $this->redirectToRoute('forgot_password_complete');
}
return [
'form' => $form->createView(),
];
}
/**
* 再設定URL送信完了画面.
*
* @Route("/forgot_password/complete", name="forgot_password_complete", methods={"GET"})
* @Template("@user_data/auth/forgot_password_complete.twig")
*/
public function complete(Request $request)
{
if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
throw new HttpException\NotFoundHttpException();
}
return [];
}
/**
* パスワード再発行実行画面.
*
* @Route("/forgot_password/reset/{reset_key}", name="forgot_password_reset", methods={"GET", "POST"})
* @Template("@user_data/auth/mypage_reset_password.twig")
*/
public function reset(Request $request, $reset_key)
{
if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
throw new HttpException\NotFoundHttpException();
}
$errors = $this->recursiveValidator->validate(
$reset_key,
[
new Assert\NotBlank(),
new Assert\Regex(
[
'pattern' => '/^[a-zA-Z0-9]+$/',
]
),
]
);
if (count($errors) > 0) {
// リセットキーに異常がある場合
throw new HttpException\NotFoundHttpException();
}
$Customer = $this->customerRepository
->getRegularCustomerByResetKey($reset_key);
if (null === $Customer) {
// リセットキーから会員データが取得できない場合
throw new HttpException\NotFoundHttpException();
}
$builder = $this->formFactory
->createNamedBuilder('', PasswordResetType::class);
$form = $builder->getForm();
$form->handleRequest($request);
$error = null;
if ($form->isSubmitted() && $form->isValid()) {
// リセットキー・入力メールアドレスで会員情報検索
$Customer = $this->customerRepository
->getRegularCustomerByResetKey($reset_key, $form->get('login_email')->getData());
if ($Customer) {
// パスワードの発行・更新
$encoder = $this->encoderFactory->getEncoder($Customer);
$pass = $form->get('password')->getData();
$Customer->setPassword($pass);
// 発行したパスワードの暗号化
if ($Customer->getSalt() === null) {
$Customer->setSalt($this->encoderFactory->getEncoder($Customer)->createSalt());
}
$encPass = $encoder->encodePassword($pass, $Customer->getSalt());
// パスワードを更新
$Customer->setPassword($encPass);
// リセットキーをクリア
$Customer->setResetKey(null);
// パスワードを更新
$this->entityManager->persist($Customer);
$this->entityManager->flush();
$event = new EventArgs(
[
'Customer' => $Customer,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_FORGOT_RESET_COMPLETE);
// 完了メッセージを設定
$this->addFlash('password_reset_complete', trans('front.forgot.reset_complete'));
// ログインページへリダイレクト
return $this->redirectToRoute('mypage-login');
} else {
// リセットキー・メールアドレスから会員データが取得できない場合
$error = trans('front.forgot.reset_not_found');
}
}
return [
'error' => $error,
'form' => $form->createView(),
];
}
}