diff --git a/Controller/Admin/ConfigController.php b/Controller/Admin/ConfigController.php index 9ae050b..f0809ed 100644 --- a/Controller/Admin/ConfigController.php +++ b/Controller/Admin/ConfigController.php @@ -17,6 +17,7 @@ use Plugin\TwoFactorAuthCustomer42\Form\Type\TwoFactorAuthConfigType; use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthConfigRepository; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; @@ -38,41 +39,41 @@ public function __construct(TwoFactorAuthConfigRepository $smsConfigRepository) $this->smsConfigRepository = $smsConfigRepository; } - /** - * @Route("/%eccube_admin_route%/two_factor_auth_customer42/config", name="two_factor_auth_customer42_admin_config", methods={"GET", "POST"}) - * @Template("TwoFactorAuthCustomer42/Resource/template/admin/config.twig") - * - * @param Request $request - * - * @return array - */ - public function index(Request $request) - { - // 設定情報、フォーム情報を取得 - $SmsConfig = $this->smsConfigRepository->findOne(); - $form = $this->createForm(TwoFactorAuthConfigType::class, $SmsConfig); - $form->handleRequest($request); + /** + * @Route("/%eccube_admin_route%/two_factor_auth_customer42/config", name="two_factor_auth_customer42_admin_config", methods={"GET", "POST"}) + * @Template("TwoFactorAuthCustomer42/Resource/template/admin/config.twig") + * + * @param Request $request + * + * @return RedirectResponse|array + */ + public function index(Request $request) + { + // 設定情報、フォーム情報を取得 + $SmsConfig = $this->smsConfigRepository->findOne(); + $form = $this->createForm(TwoFactorAuthConfigType::class, $SmsConfig); + $form->handleRequest($request); - // 設定画面で登録ボタンが押されたらこの処理を行う - if ($form->isSubmitted() && $form->isValid()) { - // フォームの入力データを取得 - $SmsConfig = $form->getData(); + // 設定画面で登録ボタンが押されたらこの処理を行う + if ($form->isSubmitted() && $form->isValid()) { + // フォームの入力データを取得 + $SmsConfig = $form->getData(); - // フォームの入力データを保存 - $this->entityManager->persist($SmsConfig); - $this->entityManager->flush($SmsConfig); + // フォームの入力データを保存 + $this->entityManager->persist($SmsConfig); + $this->entityManager->flush($SmsConfig); - // 完了メッセージを表示 - log_info('config', ['status' => 'Success']); - $this->addSuccess('プラグインの設定を保存しました。', 'admin'); + // 完了メッセージを表示 + log_info('config', ['status' => 'Success']); + $this->addSuccess('プラグインの設定を保存しました。', 'admin'); - // 設定画面にリダイレクト - return $this->redirectToRoute('two_factor_auth_customer42_admin_config'); - } + // 設定画面にリダイレクト + return $this->redirectToRoute('two_factor_auth_customer42_admin_config'); + } - return [ - 'SmsConfig' => $SmsConfig, - 'form' => $form->createView(), - ]; - } + return [ + 'SmsConfig' => $SmsConfig, + 'form' => $form->createView(), + ]; + } } diff --git a/Controller/CustomerPersonalValidationController.php b/Controller/CustomerPersonalValidationController.php index f8992a3..3330494 100644 --- a/Controller/CustomerPersonalValidationController.php +++ b/Controller/CustomerPersonalValidationController.php @@ -27,6 +27,8 @@ use Twig\Error\LoaderError; use Twig\Error\RuntimeError; use Twig\Error\SyntaxError; +use Twilio\Exceptions\ConfigurationException; +use Twilio\Exceptions\TwilioException; use Twilio\Rest\Api\V2010\Account\MessageInstance; class CustomerPersonalValidationController extends AbstractController @@ -49,9 +51,9 @@ class CustomerPersonalValidationController extends AbstractController /** * TwoFactorAuthCustomerController constructor. * - * @param CustomerRepository $customerRepository, - * @param CustomerTwoFactorAuthService $customerTwoFactorAuthService, - * @param Environment $twig + * @param CustomerRepository $customerRepository , + * @param CustomerTwoFactorAuthService $customerTwoFactorAuthService , + * @param Environment $twig */ public function __construct( CustomerRepository $customerRepository, @@ -146,6 +148,11 @@ public function deviceAuthInputOneTime(Request $request, $secret_key) * @param $secret_key * * @return array|RedirectResponse + * @throws ConfigurationException + * @throws LoaderError + * @throws RuntimeError + * @throws SyntaxError + * @throws TwilioException */ public function deviceAuthSendOneTime(Request $request, $secret_key) { @@ -198,6 +205,28 @@ public function deviceAuthSendOneTime(Request $request, $secret_key) ]; } + /** + * デバイス認証用のワンタイムトークンチェック. + * + * @param $Customer + * @param $token + * + * @return boolean + */ + private function checkDeviceToken($Customer, $token): bool + { + $now = new \DateTime(); + + // フォームからのハッシュしたワンタイムパスワードとDBに保存しているワンタイムパスワードのハッシュは一致しているかどうか + if ( + $Customer->getDeviceAuthOneTimeToken() !== $this->customerTwoFactorAuthService->readOneTimeToken($token) || + $Customer->getDeviceAuthOneTimeTokenExpire() < $now) { + return false; + } + + return true; + } + /** * デバイス認証用のワンタイムトークンを送信. * @@ -209,6 +238,8 @@ public function deviceAuthSendOneTime(Request $request, $secret_key) * @throws LoaderError * @throws RuntimeError * @throws SyntaxError + * @throws ConfigurationException + * @throws TwilioException */ private function sendDeviceToken(Customer $Customer, string $phoneNumber) { @@ -227,28 +258,6 @@ private function sendDeviceToken(Customer $Customer, string $phoneNumber) ]); // SMS送信 - return $this->customerTwoFactorAuthService->sendBySms($Customer, $phoneNumber, $body); - } - - /** - * デバイス認証用のワンタイムトークンチェック. - * - * @param $Customer - * @param $token - * - * @return boolean - */ - private function checkDeviceToken($Customer, $token): bool - { - $now = new \DateTime(); - - // フォームからのハッシュしたワンタイムパスワードとDBに保存しているワンタイムパスワードのハッシュは一致しているかどうか - if ( - $Customer->getDeviceAuthOneTimeToken() !== $this->customerTwoFactorAuthService->readOneTimeToken($token) || - $Customer->getDeviceAuthOneTimeTokenExpire() < $now) { - return false; - } - - return true; + return $this->customerTwoFactorAuthService->sendBySms($phoneNumber, $body); } } diff --git a/Controller/TwoFactorAuthCustomerController.php b/Controller/TwoFactorAuthCustomerController.php index bce2057..419fb6e 100644 --- a/Controller/TwoFactorAuthCustomerController.php +++ b/Controller/TwoFactorAuthCustomerController.php @@ -50,7 +50,7 @@ public function __construct( CustomerRepository $customerRepository, CustomerTwoFactorAuthService $customerTwoFactorAuthService, Environment $twig - ) { + ) { $this->customerRepository = $customerRepository; $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; $this->twig = $twig; diff --git a/Entity/BaseInfoTrait.php b/Entity/BaseInfoTrait.php index f035860..0ceda8d 100644 --- a/Entity/BaseInfoTrait.php +++ b/Entity/BaseInfoTrait.php @@ -29,6 +29,14 @@ trait BaseInfoTrait * @ORM\Column(name="two_factor_auth_use", type="boolean", nullable=false, options={"default":false}) */ private bool $two_factor_auth_use; + /** + * SMS通知の設定 + * + * @var bool + * + * @ORM\Column(name="option_activate_device", type="boolean", nullable=false, options={"default":false}) + */ + private bool $option_activate_device; /** * @return bool @@ -46,15 +54,6 @@ public function setTwoFactorAuthUse(bool $two_factor_auth_use): void $this->two_factor_auth_use = $two_factor_auth_use; } - /** - * SMS通知の設定 - * - * @var bool - * - * @ORM\Column(name="option_activate_device", type="boolean", nullable=false, options={"default":false}) - */ - private bool $option_activate_device; - /** * @return bool */ diff --git a/Entity/CustomerTrait.php b/Entity/CustomerTrait.php index bc11386..9974fea 100644 --- a/Entity/CustomerTrait.php +++ b/Entity/CustomerTrait.php @@ -53,7 +53,7 @@ trait CustomerTrait /** * 2段階認証機能の設定 * - * @var int + * @var int|null * * @ORM\Column(name="two_factor_auth_type", type="integer", nullable=true) */ @@ -98,13 +98,23 @@ public function getDeviceAuthOneTimeToken(): ?string } /** - * @param string $device_auth_one_time_token + * @param string|null $device_auth_one_time_token */ public function setDeviceAuthOneTimeToken(?string $device_auth_one_time_token): void { $this->device_auth_one_time_token = $device_auth_one_time_token; } + /** + * Get resetExpire. + * + * @return \DateTime|null + */ + public function getDeviceAuthOneTimeTokenExpire() + { + return $this->device_auth_one_time_token_expire; + } + /** * Set oneTimeTokenExpire. * @@ -119,16 +129,6 @@ public function setDeviceAuthOneTimeTokenExpire($deviceAuthOneTimeTokenExpire = return $this; } - /** - * Get resetExpire. - * - * @return \DateTime|null - */ - public function getDeviceAuthOneTimeTokenExpire() - { - return $this->device_auth_one_time_token_expire; - } - /** * @return bool */ @@ -138,7 +138,7 @@ public function isDeviceAuthed(): bool } /** - * @param bool $two_factor_auth + * @param bool $device_authed */ public function setDeviceAuthed(bool $device_authed): void { @@ -162,25 +162,25 @@ public function setDeviceAuthedPhoneNumber(?string $device_authed_phone_number): } /** - * Set two-factor auth type. + * Get sex. * - * @param TwoFactorAuthType|null $twoFactorAuthType + * @return TwoFactorAuthType|null */ - public function setTwoFactorAuthType(TwoFactorAuthType $twoFactorAuthType = null) + public function getTwoFactorAuthType() { - $this->TwoFactorAuthType = $twoFactorAuthType; - - return $this; + return $this->TwoFactorAuthType; } /** - * Get sex. + * Set two-factor auth type. * - * @return TwoFactorAuthType|null + * @param TwoFactorAuthType|null $twoFactorAuthType */ - public function getTwoFactorAuthType() + public function setTwoFactorAuthType(TwoFactorAuthType $twoFactorAuthType = null) { - return $this->TwoFactorAuthType; + $this->TwoFactorAuthType = $twoFactorAuthType; + + return $this; } /** diff --git a/Entity/TwoFactorAuthConfig.php b/Entity/TwoFactorAuthConfig.php index 73eb0a0..63c8f8c 100644 --- a/Entity/TwoFactorAuthConfig.php +++ b/Entity/TwoFactorAuthConfig.php @@ -83,6 +83,16 @@ public function getId() return $this->id; } + /** + * Get api_key. + * + * @return string + */ + public function getApiKey() + { + return $this->api_key; + } + /** * Set api_key. * @@ -98,13 +108,13 @@ public function setApiKey($apiKey) } /** - * Get api_key. + * Get api_secret. * * @return string */ - public function getApiKey() + public function getApiSecret() { - return $this->api_key; + return $this->api_secret; } /** @@ -122,13 +132,13 @@ public function setApiSecret($apiSecret) } /** - * Get api_secret. + * Get from phone number. * * @return string */ - public function getApiSecret() + public function getFromPhonenumber() { - return $this->api_secret; + return $this->from_phone_number; } /** @@ -145,28 +155,24 @@ public function setFromPhonenumber($fromTel) return $this; } - /** - * Get from phone number. - * - * @return string - */ - public function getFromPhonenumber() + public function addIncludeRoute(string $route) { - return $this->from_phone_number; + $routes = $this->getRoutes($this->getIncludeRoutes()); + + if (!in_array($route, $routes)) { + $this->setIncludeRoutes($this->include_routes.PHP_EOL.$route); + } + + return $this; } - /** - * Set include_routes. - * - * @param string|null $include_routes - * - * @return TwoFactorAuthConfig - */ - public function setIncludeRoutes($include_routes = null) + private function getRoutes(?string $routes): array { - $this->include_routes = $include_routes; + if (!$routes) { + return []; + } - return $this; + return explode(PHP_EOL, $routes); } /** @@ -179,13 +185,16 @@ public function getIncludeRoutes() return $this->include_routes; } - public function addIncludeRoute(string $route) + /** + * Set include_routes. + * + * @param string|null $include_routes + * + * @return TwoFactorAuthConfig + */ + public function setIncludeRoutes($include_routes = null) { - $routes = $this->getRoutes($this->getIncludeRoutes()); - - if (!in_array($route, $routes)) { - $this->setIncludeRoutes($this->include_routes.PHP_EOL.$route); - } + $this->include_routes = $include_routes; return $this; } @@ -202,15 +211,6 @@ public function removeIncludeRoute(string $route) return $this; } - private function getRoutes(?string $routes): array - { - if (!$routes) { - return []; - } - - return explode(PHP_EOL, $routes); - } - private function getRoutesAsString(array $routes): string { return implode(PHP_EOL, $routes); diff --git a/Entity/TwoFactorAuthCustomerCookie.php b/Entity/TwoFactorAuthCustomerCookie.php index 93c34eb..c88c42e 100644 --- a/Entity/TwoFactorAuthCustomerCookie.php +++ b/Entity/TwoFactorAuthCustomerCookie.php @@ -13,6 +13,7 @@ namespace Plugin\TwoFactorAuthCustomer42\Entity; +use DateTime; use Doctrine\ORM\Mapping as ORM; use Eccube\Entity\AbstractEntity; use Eccube\Entity\Customer; @@ -38,7 +39,6 @@ class TwoFactorAuthCustomerCookie extends AbstractEntity * @ORM\GeneratedValue(strategy="IDENTITY") */ private int $id; - /** * @var Customer * @@ -48,41 +48,36 @@ class TwoFactorAuthCustomerCookie extends AbstractEntity * }) */ private Customer $Customer; - /** * @var string * * @ORM\Column(name="cookie_name", type="string", nullable=false, length=512) */ private string $cookie_name; - /** * @var string * * @ORM\Column(name="cookie_value", type="string", nullable=false, length=512, unique=true) */ private string $cookie_value; - /** * @var \DateTime * * @ORM\Column(name="cookie_expire_date", type="datetime", nullable=true) */ private ?\DateTime $cookie_expire_date; - /** * @var \DateTime * * @ORM\Column(name="created_at", type="datetime", nullable=false) */ - protected \DateTime $createdAt; - + private \DateTime $createdAt; /** * @var \DateTime * * @ORM\Column(name="updated_at", type="datetime", nullable=false) */ - protected \DateTime $updatedAt; + private \DateTime $updatedAt; /** * @ORM\PrePersist @@ -96,6 +91,22 @@ public function updatedTimestamps(): void } } + /** + * @return \DateTime + */ + public function getCreatedAt(): \DateTime + { + return $this->createdAt; + } + + /** + * @param \DateTime $createdAt + */ + public function setCreatedAt(\DateTime $createdAt): void + { + $this->createdAt = $createdAt; + } + /** * @return int */ @@ -168,22 +179,6 @@ public function setCookieExpireDate(\DateTime $cookie_expire_date): void $this->cookie_expire_date = $cookie_expire_date; } - /** - * @return \DateTime - */ - public function getCreatedAt(): \DateTime - { - return $this->createdAt; - } - - /** - * @param \DateTime $createdAt - */ - public function setCreatedAt(\DateTime $createdAt): void - { - $this->createdAt = $createdAt; - } - /** * @return \DateTime */ diff --git a/Entity/TwoFactorAuthType.php b/Entity/TwoFactorAuthType.php index 1a0fa05..0db26b0 100644 --- a/Entity/TwoFactorAuthType.php +++ b/Entity/TwoFactorAuthType.php @@ -76,6 +76,16 @@ public function getId() return $this->id; } + /** + * Get name. + * + * @return string + */ + public function getName() + { + return $this->name; + } + /** * Set name. * @@ -91,13 +101,13 @@ public function setName($name) } /** - * Get name. + * Get route. * * @return string */ - public function getName() + public function getRoute() { - return $this->name; + return $this->route; } /** @@ -114,16 +124,6 @@ public function setRoute($route) return $this; } - /** - * Get route. - * - * @return string - */ - public function getRoute() - { - return $this->route; - } - /** * @return bool */ diff --git a/Event.php b/Event.php index 5e69bdd..3e324f3 100644 --- a/Event.php +++ b/Event.php @@ -13,71 +13,21 @@ namespace Plugin\TwoFactorAuthCustomer42; -use Doctrine\ORM\EntityManagerInterface; -use Eccube\Entity\BaseInfo; use Eccube\Event\TemplateEvent; -use Eccube\Repository\BaseInfoRepository; -use Plugin\TwoFactorAuthCustomer42\Service\CustomerTwoFactorAuthService; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Twig\Environment; /** * Class Event. */ class Event implements EventSubscriberInterface { - /** - * @var ContainerInterface - */ - protected $container; - - /** - * @var BaseInfo - */ - protected $BaseInfo; - - /** - * @var CustomerTwoFactorAuthService - */ - protected $customerTwoFactorAuthService; - - /** - * @var EntityManagerInterface - */ - private $entityManager; - - /** - * @var Environment - */ - private $twig; - - /** - * @var NotifierInterface - */ - // private $notifier; - /** * Event constructor. * - * @param ContainerInterface $container - * @param BaseInfoRepository $baseInfoRepository - * @param EntityManagerInterface $entityManager - * @param CustomerTwoFactorAuthService $customerTwoFactorAuthService - * @param Environment $twig + * @throws \Exception */ - public function __construct( - ContainerInterface $container, - BaseInfoRepository $baseInfoRepository, - EntityManagerInterface $entityManager, - CustomerTwoFactorAuthService $customerTwoFactorAuthService, - Environment $twig - ) { - $this->container = $container; - $this->BaseInfo = $baseInfoRepository->get(); - $this->entityManager = $entityManager; - $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; - $this->twig = $twig; + public function __construct() + { } public static function getSubscribedEvents(): array diff --git a/EventListener/CustomerPersonalValidationListener.php b/EventListener/CustomerPersonalValidationListener.php index 07c54d4..01ffb4f 100644 --- a/EventListener/CustomerPersonalValidationListener.php +++ b/EventListener/CustomerPersonalValidationListener.php @@ -13,8 +13,7 @@ namespace Plugin\TwoFactorAuthCustomer42\EventListener; -use Doctrine\ORM\EntityManagerInterface; -use Eccube\Common\EccubeConfig; +use Eccube\Entity\BaseInfo; use Eccube\Repository\BaseInfoRepository; use Eccube\Repository\CustomerRepository; use Eccube\Request\Context; @@ -23,7 +22,6 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\KernelEvents; @@ -35,96 +33,50 @@ class CustomerPersonalValidationListener implements EventSubscriberInterface * アクティベーション */ public const ACTIVATE_ROUTE = 'entry_activate'; - - /** - * @var EntityManagerInterface - */ - private $entityManager; - - /** - * @var EccubeConfig - */ - protected $eccubeConfig; - /** * @var Context */ protected $requestContext; - /** * @var UrlGeneratorInterface */ protected $router; - /** * @var CustomerTwoFactorAuthService */ protected $customerTwoFactorAuthService; - /** * @var BaseInfoRepository */ protected BaseInfoRepository $baseInfoRepository; - /** * @var CustomerRepository */ protected CustomerRepository $customerRepository; - /** - * @var TwoFactorAuthTypeRepository - */ - protected TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository; - - /** - * @var \Eccube\Entity\BaseInfo|object|null + * @var BaseInfo|object|null */ protected $baseInfo; /** - * @var Session - */ - protected $session; - - /** - * 個別認証ルート. - */ - protected $include_routes; - - /** - * @param EntityManagerInterface $entityManager - * @param EccubeConfig $eccubeConfig * @param Context $requestContext * @param UrlGeneratorInterface $router * @param CustomerTwoFactorAuthService $customerTwoFactorAuthService * @param BaseInfoRepository $baseInfoRepository * @param CustomerRepository $customerRepository - * @param TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository - * @param SessionInterface $session */ public function __construct( - EntityManagerInterface $entityManager, - EccubeConfig $eccubeConfig, Context $requestContext, UrlGeneratorInterface $router, CustomerTwoFactorAuthService $customerTwoFactorAuthService, BaseInfoRepository $baseInfoRepository, - CustomerRepository $customerRepository, - TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository, - SessionInterface $session + CustomerRepository $customerRepository ) { - $this->entityManager = $entityManager; - $this->eccubeConfig = $eccubeConfig; $this->requestContext = $requestContext; $this->router = $router; $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; - $this->baseInfoRepository = $baseInfoRepository; - $this->baseInfo = $this->baseInfoRepository->find(1); + $this->baseInfo = $baseInfoRepository->find(1); $this->customerRepository = $customerRepository; - $this->twoFactorAuthTypeRepository = $twoFactorAuthTypeRepository; - $this->session = $session; - - $this->include_routes = $this->customerTwoFactorAuthService->getIncludeRoutes(); } /** @@ -164,16 +116,24 @@ public function onKernelController(ControllerArgumentsEvent $event) } $route = $event->getRequest()->attributes->get('_route'); - $uri = $event->getRequest()->getRequestUri(); if ($this->isActivationRoute($route)) { // デバイス認証(アクティベーション前に介入) $this->deviceAuth($event); - - return; } + } - return; + /** + * アクティベーションルートかチェック. + * + * @param string $route + * + * @return bool + */ + private function isActivationRoute(string $route): bool + { + // ルートで認証 + return $route === self::ACTIVATE_ROUTE; } /** @@ -202,29 +162,12 @@ private function deviceAuth($event) // 仮会員登録機能:有効 / SMSによる本人認証:有効の場合 デバイス認証画面へリダイレクト $url = $this->router->generate( 'plg_customer_2fa_device_auth_send_onetime', - ['secret_key' => $secret_key], - UrlGeneratorInterface::ABSOLUTE_PATH + ['secret_key' => $secret_key] ); $event->setController(function () use ($url) { - return new RedirectResponse($url, $status = 302); + return new RedirectResponse($url, 302); }); } - - return; - } - - /** - * アクティベーションルートかチェック. - * - * @param string $route - * @param string $uri - * - * @return bool - */ - private function isActivationRoute(string $route): bool - { - // ルートで認証 - return $route === self::ACTIVATE_ROUTE; } } diff --git a/EventListener/CustomerTwoFactorAuthListener.php b/EventListener/CustomerTwoFactorAuthListener.php index 3b224a2..31c2983 100755 --- a/EventListener/CustomerTwoFactorAuthListener.php +++ b/EventListener/CustomerTwoFactorAuthListener.php @@ -13,14 +13,14 @@ namespace Plugin\TwoFactorAuthCustomer42\EventListener; -use Doctrine\ORM\EntityManagerInterface; use Eccube\Common\EccubeConfig; +use Eccube\Entity\BaseInfo; use Eccube\Entity\Customer; use Eccube\Entity\Master\CustomerStatus; use Eccube\Repository\BaseInfoRepository; -use Eccube\Repository\CustomerRepository; use Eccube\Request\Context; use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthTypeRepository; +use Plugin\TwoFactorAuthCustomer42\Repository\TwoFactorAuthCustomerCookieRepository; use Plugin\TwoFactorAuthCustomer42\Service\CustomerTwoFactorAuthService; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -31,105 +31,75 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Http\Event\LoginSuccessEvent; use Symfony\Component\Security\Http\Event\LogoutEvent; +use Symfony\Contracts\EventDispatcher\Event; class CustomerTwoFactorAuthListener implements EventSubscriberInterface { - /** - * アクティベーション - */ - public const ACTIVATE_ROUTE = 'entry_activate'; - - /** - * @var EntityManagerInterface - */ - private $entityManager; - /** * @var EccubeConfig */ protected $eccubeConfig; - /** * @var Context */ protected $requestContext; - /** * @var UrlGeneratorInterface */ protected $router; - /** * @var CustomerTwoFactorAuthService */ protected $customerTwoFactorAuthService; - - /** - * @var BaseInfoRepository - */ - protected BaseInfoRepository $baseInfoRepository; - - /** - * @var CustomerRepository - */ - protected CustomerRepository $customerRepository; - /** * @var TwoFactorAuthTypeRepository */ protected TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository; - /** - * @var \Eccube\Entity\BaseInfo|object|null + * @var TwoFactorAuthCustomerCookieRepository + */ + protected TwoFactorAuthCustomerCookieRepository $twoFactorAuthCustomerCookieRepository; + /** + * @var BaseInfo|object|null */ protected $baseInfo; - /** * @var Session */ protected $session; - /** * 通常(ログイン・マイページ)ルート. */ protected $default_routes; - /** * 重要操作ルート. */ protected $include_routes; /** - * @param EntityManagerInterface $entityManager - * @param EccubeConfig $eccubeConfig * @param Context $requestContext * @param UrlGeneratorInterface $router * @param CustomerTwoFactorAuthService $customerTwoFactorAuthService - * @param BaseInfoRepository $baseInfoRepository - * @param CustomerRepository $customerRepository * @param TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository + * @param TwoFactorAuthCustomerCookieRepository $twoFactorAuthCustomerCookieRepository + * @param BaseInfoRepository $baseInfoRepository * @param SessionInterface $session */ public function __construct( - EntityManagerInterface $entityManager, - EccubeConfig $eccubeConfig, Context $requestContext, UrlGeneratorInterface $router, CustomerTwoFactorAuthService $customerTwoFactorAuthService, - BaseInfoRepository $baseInfoRepository, - CustomerRepository $customerRepository, TwoFactorAuthTypeRepository $twoFactorAuthTypeRepository, + TwoFactorAuthCustomerCookieRepository $twoFactorAuthCustomerCookieRepository, + BaseInfoRepository $baseInfoRepository, SessionInterface $session ) { - $this->entityManager = $entityManager; - $this->eccubeConfig = $eccubeConfig; $this->requestContext = $requestContext; $this->router = $router; $this->customerTwoFactorAuthService = $customerTwoFactorAuthService; - $this->baseInfoRepository = $baseInfoRepository; - $this->baseInfo = $this->baseInfoRepository->find(1); - $this->customerRepository = $customerRepository; + $this->baseInfo = $baseInfoRepository->find(1); $this->twoFactorAuthTypeRepository = $twoFactorAuthTypeRepository; + $this->twoFactorAuthCustomerCookieRepository = $twoFactorAuthCustomerCookieRepository; $this->session = $session; $this->default_routes = $this->customerTwoFactorAuthService->getDefaultAuthRoutes(); @@ -186,16 +156,16 @@ public function onKernelController(ControllerArgumentsEvent $event) return; } - $this->multifactorAuth($event, $Customer, $route, $uri); + $this->multiFactorAuth($event, $Customer, $route); } - - return; } /** * ログイン完了 イベントハンドラ. * * @param LoginSuccessEvent $event + * + * @return RedirectResponse|void */ public function onLoginSuccess(LoginSuccessEvent $event) { @@ -220,13 +190,10 @@ public function onLoginSuccess(LoginSuccessEvent $event) return new RedirectResponse($this->router->generate('logout'), 302); } - $this->multifactorAuth( + $this->multiFactorAuth( $event, $this->requestContext->getCurrentUser(), - $event->getRequest()->attributes->get('_route'), - $event->getRequest()->getRequestUri()); - - return; + $event->getRequest()->attributes->get('_route')); } /** @@ -239,19 +206,75 @@ public function onLoginSuccess(LoginSuccessEvent $event) public function logoutEvent(LogoutEvent $logoutEvent) { $this->customerTwoFactorAuthService->clear2AuthCookies($logoutEvent->getRequest(), $logoutEvent->getResponse()); + $Customer = $this->requestContext->getCurrentUser(); + if ($Customer) { + $this->twoFactorAuthCustomerCookieRepository->deleteByCustomer($Customer); + } + } + + + /** + * ルート・URIが個別認証対象かチェック. + * + * @param string $route + * @param string $uri + * + * @return bool + */ + private function isDefaultRoute(string $route, string $uri): bool + { + return $this->isTargetRoute($this->default_routes, $route, $uri); + } + + /** + * ルート・URIが対象であるかチェック. + * + * @param array $targetRoutes + * @param string $route + * @param string $uri + * + * @return bool + */ + private function isTargetRoute(array $targetRoutes, string $route, string $uri): bool + { + // ルートで認証 + if (in_array($route, $targetRoutes)) { + return true; + } + + // URIで認証 + foreach ($targetRoutes as $r) { + if ($r != '' && $r !== '/' && strpos($uri, $r) === 0) { + return true; + } + } + + return false; + } + + /** + * ルート・URIが個別認証対象かチェック. + * + * @param string $route + * @param string $uri + * + * @return bool + */ + private function isIncludeRoute(string $route, string $uri): bool + { + return $this->isTargetRoute($this->include_routes, $route, $uri); } /** * 多要素認証. * - * @param mixed $event + * @param Event $event * @param Customer $Customer * @param string $route - * @param string $uri * * @return mixed */ - private function multifactorAuth($event, $Customer, $route, $uri) + private function multiFactorAuth($event, $Customer, $route) { if (!$this->baseInfo->isTwoFactorAuthUse()) { // MFA無効の場合処理なし @@ -270,24 +293,21 @@ private function multifactorAuth($event, $Customer, $route, $uri) log_info('[2段階認証] 実施'); if ($Customer->getTwoFactorAuthType() === null) { // 2段階認証未設定 - $this->selectAuthType($event, $Customer, $route); + $this->selectAuthType($event, $route); } else { // 2段階認証設定済み $this->auth($event, $Customer, $route); } } - - return; } /** * 多要素認証方式設定画面へリダイレクト. * * @param Event $event - * @param Customer $Customer * @param string|null $route */ - private function selectAuthType($event, Customer $Customer, ?string $route) + private function selectAuthType($event, ?string $route) { // [会員] 2段階認証が未設定の場合 // コールバックURLをセッションへ設定 @@ -302,8 +322,18 @@ private function selectAuthType($event, Customer $Customer, ?string $route) } else { $event->setResponse(new RedirectResponse($url, 302)); } + } - return; + /** + * コールバックルートをセッションへ設定. + * + * @param string|null $route + */ + private function setCallbackRoute(?string $route) + { + if ($route) { + $this->session->set(CustomerTwoFactorAuthService::SESSION_CALL_BACK_URL, $route); + } } /** @@ -327,10 +357,7 @@ private function auth($event, Customer $Customer, ?string $route) return; } - $url = $this->router->generate( - $Customer->getTwoFactorAuthType()->getRoute(), - [], - UrlGeneratorInterface::ABSOLUTE_PATH); + $url = $this->router->generate($Customer->getTwoFactorAuthType()->getRoute()); if ($event instanceof ControllerArgumentsEvent) { $event->setController(function () use ($url) { @@ -339,71 +366,6 @@ private function auth($event, Customer $Customer, ?string $route) } else { $event->setResponse(new RedirectResponse($url, 302)); } - - return; - } - - /** - * コールバックルートをセッションへ設定. - * - * @param string|null $route - */ - private function setCallbackRoute(?string $route) - { - if ($route) { - $this->session->set(CustomerTwoFactorAuthService::SESSION_CALL_BACK_URL, $route); - } - } - - /** - * ルート・URIが個別認証対象かチェック. - * - * @param string $route - * @param string $uri - * - * @return bool - */ - private function isDefaultRoute(string $route, string $uri): bool - { - return $this->isTargetRoute($this->default_routes, $route, $uri); - } - - /** - * ルート・URIが個別認証対象かチェック. - * - * @param string $route - * @param string $uri - * - * @return bool - */ - private function isIncludeRoute(string $route, string $uri): bool - { - return $this->isTargetRoute($this->include_routes, $route, $uri); } - /** - * ルート・URIが対象であるかチェック. - * - * @param array $targetRoutes - * @param string $route - * @param string $uri - * - * @return bool - */ - private function isTargetRoute($targetRoutes, string $route, string $uri): bool - { - // ルートで認証 - if (in_array($route, $targetRoutes)) { - return true; - } - - // URIで認証 - foreach ($targetRoutes as $r) { - if ($r != '' && $r !== '/' && strpos($uri, $r) === 0) { - return true; - } - } - - return false; - } } diff --git a/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php b/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php index ac1b202..5189bb2 100644 --- a/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php +++ b/Form/Type/Extension/Admin/TwoFactorAuthBaseSettingTypeExtension.php @@ -39,11 +39,19 @@ public function __construct( $this->entityManager = $entityManager; } + /** + * {@inheritDoc} + */ + public static function getExtendedTypes(): iterable + { + yield ShopMasterType::class; + } + /** * buildForm. * * @param FormBuilderInterface $builder - * @param array $options + * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { @@ -57,19 +65,10 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'required' => false, 'mapped' => true, ]) - ->add('option_activate_device', ToggleSwitchType::class, [ - 'required' => false, - 'mapped' => true, - ]) - ; + ->add('option_activate_device', ToggleSwitchType::class, [ + 'required' => false, + 'mapped' => true, + ]); }); } - - /** - * {@inheritDoc} - */ - public static function getExtendedTypes(): iterable - { - yield ShopMasterType::class; - } } diff --git a/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php b/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php index da8e32d..fe6eae8 100755 --- a/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php +++ b/Form/Type/Extension/Admin/TwoFactorAuthCustomerTypeExtension.php @@ -42,11 +42,19 @@ public function __construct( $this->entityManager = $entityManager; } + /** + * {@inheritDoc} + */ + public static function getExtendedTypes(): iterable + { + yield CustomerType::class; + } + /** * buildForm. * * @param FormBuilderInterface $builder - * @param array $options + * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { @@ -63,22 +71,13 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'mapped' => true, 'placeholder' => 'admin.customer.2fa.type_option.default', ]) - ->add('device_authed', ToggleSwitchType::class, [ - 'required' => false, - 'mapped' => true, - ]) - ->add('device_authed_phone_number', PhoneNumberType::class, [ - 'required' => false, - ]) - ; + ->add('device_authed', ToggleSwitchType::class, [ + 'required' => false, + 'mapped' => true, + ]) + ->add('device_authed_phone_number', PhoneNumberType::class, [ + 'required' => false, + ]); }); } - - /** - * {@inheritDoc} - */ - public static function getExtendedTypes(): iterable - { - yield CustomerType::class; - } } diff --git a/Form/Type/TwoFactorAuthConfigType.php b/Form/Type/TwoFactorAuthConfigType.php index 0b38d37..4d95561 100644 --- a/Form/Type/TwoFactorAuthConfigType.php +++ b/Form/Type/TwoFactorAuthConfigType.php @@ -94,7 +94,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) /** * {@inheritDoc} * - * @see \Symfony\Component\Form\AbstractType::configureOptions() + * @see AbstractType::configureOptions */ public function configureOptions(OptionsResolver $resolver) { diff --git a/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php b/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php index 20c8b70..f6e665c 100644 --- a/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php +++ b/Form/Type/TwoFactorAuthPhoneNumberTypeCustomer.php @@ -27,8 +27,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder ->add('phone_number', PhoneNumberType::class, [ 'required' => true, - ]) - ; + ]); } /** diff --git a/Form/Type/TwoFactorAuthSmsTypeCustomer.php b/Form/Type/TwoFactorAuthSmsTypeCustomer.php index f823d27..6907926 100644 --- a/Form/Type/TwoFactorAuthSmsTypeCustomer.php +++ b/Form/Type/TwoFactorAuthSmsTypeCustomer.php @@ -41,8 +41,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'maxlength' => 6, 'style' => 'width: 100px;', ], - ]) - ; + ]); } /** diff --git a/Form/Type/TwoFactorAuthTypeCustomer.php b/Form/Type/TwoFactorAuthTypeCustomer.php index 9ee180e..5240525 100644 --- a/Form/Type/TwoFactorAuthTypeCustomer.php +++ b/Form/Type/TwoFactorAuthTypeCustomer.php @@ -38,8 +38,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) }, 'choice_label' => 'name', 'mapped' => true, - ]) - ; + ]); } /** diff --git a/PluginManager.php b/PluginManager.php index 446ca42..06eceb9 100644 --- a/PluginManager.php +++ b/PluginManager.php @@ -52,33 +52,21 @@ public function enable(array $meta, ContainerInterface $container) } /** - * @param array $meta - * @param ContainerInterface $container - */ - public function disable(array $meta, ContainerInterface $container) - { - $em = $container->get('doctrine')->getManager(); - - // twigファイルを削除 - $this->removeTwigFiles($container); - - // ページ削除 - $this->removePages($em); - } - - /** - * @param array $meta - * @param ContainerInterface $container + * 設定の登録. + * + * @param EntityManagerInterface $em */ - public function uninstall(array $meta, ContainerInterface $container) + protected function createConfig(EntityManagerInterface $em) { - $em = $container->get('doctrine')->getManager(); - - // twigファイルを削除 - $this->removeTwigFiles($container); + $TwoFactorAuthConfig = $em->find(TwoFactorAuthConfig::class, 1); + if ($TwoFactorAuthConfig) { + return; + } - // ページ削除 - $this->removePages($em); + // 初期値を保存 + $TwoFactorAuthConfig = new TwoFactorAuthConfig(); + $em->persist($TwoFactorAuthConfig); + $em->flush(); } /** @@ -90,13 +78,13 @@ protected function copyTwigFiles(ContainerInterface $container) { // テンプレートファイルコピー $templatePath = $container->getParameter('eccube_theme_front_dir') - .'/TwoFactorAuthCustomer42/Resource/template/default'; + . '/TwoFactorAuthCustomer42/Resource/template/default'; $fs = new Filesystem(); if ($fs->exists($templatePath)) { return; } $fs->mkdir($templatePath); - $fs->mirror(__DIR__.'/Resource/template/default', $templatePath); + $fs->mirror(__DIR__ . '/Resource/template/default', $templatePath); } /** @@ -109,7 +97,7 @@ protected function createPages(EntityManagerInterface $em) foreach ($this->pages as $p) { $Page = $em->getRepository(Page::class)->findOneBy(['url' => $p[0]]); if (!$Page) { - /** @var \Eccube\Entity\Page $Page */ + /** @var Page $Page */ $Page = $em->getRepository(Page::class)->newPage(); $Page->setEditType(Page::EDIT_TYPE_DEFAULT); $Page->setUrl($p[0]); @@ -133,6 +121,21 @@ protected function createPages(EntityManagerInterface $em) } } + /** + * @param array $meta + * @param ContainerInterface $container + */ + public function disable(array $meta, ContainerInterface $container) + { + $em = $container->get('doctrine')->getManager(); + + // twigファイルを削除 + $this->removeTwigFiles($container); + + // ページ削除 + $this->removePages($em); + } + /** * Twigファイルの削除 * @@ -141,7 +144,7 @@ protected function createPages(EntityManagerInterface $em) protected function removeTwigFiles(ContainerInterface $container) { $templatePath = $container->getParameter('eccube_theme_front_dir') - .'/TwoFactorAuthCustomer42'; + . '/TwoFactorAuthCustomer42'; $fs = new Filesystem(); $fs->remove($templatePath); } @@ -167,20 +170,17 @@ protected function removePages(EntityManagerInterface $em) } /** - * 設定の登録. - * - * @param EntityManagerInterface $em + * @param array $meta + * @param ContainerInterface $container */ - protected function createConfig(EntityManagerInterface $em) + public function uninstall(array $meta, ContainerInterface $container) { - $TwoFactorAuthConfig = $em->find(TwoFactorAuthConfig::class, 1); - if ($TwoFactorAuthConfig) { - return; - } + $em = $container->get('doctrine')->getManager(); - // 初期値を保存 - $TwoFactorAuthConfig = new TwoFactorAuthConfig(); - $em->persist($TwoFactorAuthConfig); - $em->flush(); + // twigファイルを削除 + $this->removeTwigFiles($container); + + // ページ削除 + $this->removePages($em); } } diff --git a/Repository/TwoFactorAuthConfigRepository.php b/Repository/TwoFactorAuthConfigRepository.php index 7775206..b024e34 100644 --- a/Repository/TwoFactorAuthConfigRepository.php +++ b/Repository/TwoFactorAuthConfigRepository.php @@ -16,6 +16,7 @@ use Doctrine\Persistence\ManagerRegistry; use Eccube\Repository\AbstractRepository; use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthConfig; +use Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthCustomerCookie; /** * TwoFactorAuthConfigRepository. @@ -36,7 +37,7 @@ public function __construct(ManagerRegistry $registry) } /** - * @return $result + * @return object|TwoFactorAuthConfig|TwoFactorAuthCustomerCookie|null $result */ public function findOne() { diff --git a/Repository/TwoFactorAuthCustomerCookieRepository.php b/Repository/TwoFactorAuthCustomerCookieRepository.php index b2a05ec..b68796a 100644 --- a/Repository/TwoFactorAuthCustomerCookieRepository.php +++ b/Repository/TwoFactorAuthCustomerCookieRepository.php @@ -72,39 +72,21 @@ public function generateCookieData( } /** - * @return $result - */ - public function findOne() - { - return $this->findOneBy([], ['id' => 'DESC']); - } - - /*** - * 有効クッキーを取得する + * 過去のクッキーデータの取得 * * @param Customer $customer * @param string $cookieName - * @return TwoFactorAuthCustomerCookie[]|null + * + * @return float|int|mixed|string */ - public function searchForCookie(Customer $customer, string $cookieName) + public function findOldCookies(Customer $customer, string $cookieName) { $expireDate = Carbon::now()->setTimezone('UTC')->format('Y-m-d H:i:s'); - $something = $this->createQueryBuilder('tfcc') - ->where('tfcc.Customer = :customer_id') - ->andWhere('tfcc.cookie_name = :cookie_name') - ->andWhere('tfcc.cookie_expire_date > :expire_date') - ->setParameters([ - 'customer_id' => $customer->getId(), - 'cookie_name' => $cookieName, - 'expire_date' => $expireDate, - ]) - ->getQuery()->getSQL(); - return $this->createQueryBuilder('tfcc') ->where('tfcc.Customer = :customer_id') ->andWhere('tfcc.cookie_name = :cookie_name') - ->andWhere('tfcc.cookie_expire_date > :expire_date') + ->andWhere('tfcc.cookie_expire_date < :expire_date') ->setParameters([ 'customer_id' => $customer->getId(), 'cookie_name' => $cookieName, @@ -115,21 +97,28 @@ public function searchForCookie(Customer $customer, string $cookieName) } /** - * 過去のクッキーデータの取得 + * @return TwoFactorAuthCustomerCookie|null $result + */ + public function findOne() + { + return $this->findOneBy([], ['id' => 'DESC']); + } + + /*** + * 有効クッキーを取得する * * @param Customer $customer * @param string $cookieName - * - * @return float|int|mixed|string + * @return TwoFactorAuthCustomerCookie[]|null */ - public function findOldCookies(Customer $customer, string $cookieName) + public function searchForCookie(Customer $customer, string $cookieName) { $expireDate = Carbon::now()->setTimezone('UTC')->format('Y-m-d H:i:s'); return $this->createQueryBuilder('tfcc') ->where('tfcc.Customer = :customer_id') ->andWhere('tfcc.cookie_name = :cookie_name') - ->andWhere('tfcc.cookie_expire_date < :expire_date') + ->andWhere('tfcc.cookie_expire_date > :expire_date') ->setParameters([ 'customer_id' => $customer->getId(), 'cookie_name' => $cookieName, @@ -138,4 +127,21 @@ public function findOldCookies(Customer $customer, string $cookieName) ->getQuery() ->getResult(); } + + /*** + * 会員のクッキーを削除 + * + * @param Customer $customer + */ + public function deleteByCustomer(Customer $customer) + { + $em = $this->getEntityManager(); + $em->beginTransaction(); + + $em->createQuery("DELETE Plugin\TwoFactorAuthCustomer42\Entity\TwoFactorAuthCustomerCookie tfcc WHERE tfcc.Customer = :customer")->execute(['customer' => $customer]); + $em->flush(); + + $em->commit(); + } + } diff --git a/Repository/TwoFactorAuthTypeRepository.php b/Repository/TwoFactorAuthTypeRepository.php index d2be7b3..5672da0 100644 --- a/Repository/TwoFactorAuthTypeRepository.php +++ b/Repository/TwoFactorAuthTypeRepository.php @@ -36,7 +36,7 @@ public function __construct(ManagerRegistry $registry) } /** - * @return $result + * @return object|TwoFactorAuthType|null $result */ public function findOne() { diff --git a/Resource/locale/messages.ja.yml b/Resource/locale/messages.ja.yml index 8ce586d..c7f839a 100644 --- a/Resource/locale/messages.ja.yml +++ b/Resource/locale/messages.ja.yml @@ -6,14 +6,14 @@ admin.setting.shop.shop.customer_two_factor_auth_type: 二段階認証方法 admin.setting.shop.shop.customer_two_factor_auth_type_tooltip: admin.setting.2fa.config.title: 二段階認証設定 -admin.setting.2fa.sms.sub_title : SMS送信設定(Twilio) -admin.setting.2fa.sms.sid : SID -admin.setting.2fa.sms.api_token : APIトークン -admin.setting.2fa.sms.from_phone_number : 送信元電話番号 +admin.setting.2fa.sms.sub_title: SMS送信設定(Twilio) +admin.setting.2fa.sms.sid: SID +admin.setting.2fa.sms.api_token: APIトークン +admin.setting.2fa.sms.from_phone_number: 送信元電話番号 -admin.setting.2fa.route.sub_title : 認証ルーティング設定 -admin.setting.2fa.route.include : 重要操作ルーティング -admin.setting.2fa.route.exclude : 除外ルーティング +admin.setting.2fa.route.sub_title: 認証ルーティング設定 +admin.setting.2fa.route.include: 重要操作ルーティング +admin.setting.2fa.route.exclude: 除外ルーティング admin.customer.2fa.title: 二段階認証設定 admin.customer.2fa.device_authed: 本人認証 @@ -42,15 +42,15 @@ front.2fa.sms.send.message: | 携帯電話に認証コードを送信します。 お手持ちの携帯電話番号を入力して「認証コードを送信」をクリックしてください。 front.2fa.sms.input.message: | - 携帯電話に送信された認証コードを入力してください。 + 携帯電話に送信された認証コードを入力してください。 送信されていない場合は、「認証コードを再送信」をクリックしてください。 front.2fa.sms.phone.place_holder: 電話番号を入力してください front.2fa.sms.token.place_holder: 認証コードを入力して下さい front.2fa.complete_message: 二段階認証の設定が完了しました。 -front.2fa.invalid_message__reinput : 二段階認証の設定に失敗しました。再度入力してください。 -front.2fa.configured_warning : 二段階認証は既に設定されています。 +front.2fa.invalid_message__reinput: 二段階認証の設定に失敗しました。再度入力してください。 +front.2fa.configured_warning: 二段階認証は既に設定されています。 front.2fa.type: 二段階認証方式 front.2fa.type_message: | @@ -59,5 +59,5 @@ front.2fa.sms.send: 認証コードを送信 front.2fa.sms.resend: 認証コードを再送信 front.2fa.auth: 認証 front.2fa.setting: 認証方式を設定 -front.2fa.onetime.invalid_message__reinput : 認証に失敗しました。正しい認証コードを入力してください。 -front.2fa.sms.send.failure_message : 認証コードが送信できませんでした。正しい電話番号を入力してください。 +front.2fa.onetime.invalid_message__reinput: 認証に失敗しました。正しい認証コードを入力してください。 +front.2fa.sms.send.failure_message: 認証コードが送信できませんでした。正しい電話番号を入力してください。 diff --git a/Resource/template/admin/config.twig b/Resource/template/admin/config.twig index 826a03d..21caf01 100644 --- a/Resource/template/admin/config.twig +++ b/Resource/template/admin/config.twig @@ -29,21 +29,27 @@