mirror of
https://github.com/wallabag/wallabag.git
synced 2025-07-22 17:18:37 +00:00
2factor authentication via email
This commit is contained in:
parent
cf0ea8f113
commit
2db616b586
11 changed files with 394 additions and 111 deletions
|
@ -13,6 +13,7 @@ class UserInformationType extends AbstractType
|
|||
$builder
|
||||
->add('name', 'text')
|
||||
->add('email', 'email')
|
||||
->add('twoFactorAuthentication', 'checkbox', array('required' => false))
|
||||
->add('save', 'submit')
|
||||
->remove('username')
|
||||
->remove('plainPassword')
|
||||
|
|
|
@ -100,6 +100,14 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="w500p inline">
|
||||
<div class="row">
|
||||
{{ form_label(form.user.twoFactorAuthentication) }}
|
||||
{{ form_errors(form.user.twoFactorAuthentication) }}
|
||||
{{ form_widget(form.user.twoFactorAuthentication) }}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
{{ form_rest(form.user) }}
|
||||
</form>
|
||||
|
||||
|
|
|
@ -132,6 +132,14 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
{{ form_widget(form.user.twoFactorAuthentication) }}
|
||||
{{ form_label(form.user.twoFactorAuthentication) }}
|
||||
{{ form_errors(form.user.twoFactorAuthentication) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hidden">{{ form_rest(form.user) }}</div>
|
||||
<button class="btn waves-effect waves-light" type="submit" name="action">
|
||||
{% trans %}Save{% endtrans %}
|
||||
|
|
|
@ -4,6 +4,8 @@ namespace Wallabag\UserBundle\Entity;
|
|||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface;
|
||||
use Scheb\TwoFactorBundle\Model\TrustedComputerInterface;
|
||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use JMS\Serializer\Annotation\ExclusionPolicy;
|
||||
|
@ -24,7 +26,7 @@ use Wallabag\CoreBundle\Entity\Tag;
|
|||
* @UniqueEntity("email")
|
||||
* @UniqueEntity("username")
|
||||
*/
|
||||
class User extends BaseUser
|
||||
class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
|
@ -72,6 +74,22 @@ class User extends BaseUser
|
|||
*/
|
||||
protected $tags;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer", nullable=true)
|
||||
*/
|
||||
private $authCode;
|
||||
|
||||
/**
|
||||
* @var bool Enabled yes/no
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $twoFactorAuthentication = false;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json_array", nullable=true)
|
||||
*/
|
||||
private $trusted;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
@ -201,4 +219,52 @@ class User extends BaseUser
|
|||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isTwoFactorAuthentication()
|
||||
{
|
||||
return $this->twoFactorAuthentication;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $twoFactorAuthentication
|
||||
*/
|
||||
public function setTwoFactorAuthentication($twoFactorAuthentication)
|
||||
{
|
||||
$this->twoFactorAuthentication = $twoFactorAuthentication;
|
||||
}
|
||||
|
||||
public function isEmailAuthEnabled()
|
||||
{
|
||||
return $this->twoFactorAuthentication;
|
||||
}
|
||||
|
||||
public function getEmailAuthCode()
|
||||
{
|
||||
return $this->authCode;
|
||||
}
|
||||
|
||||
public function setEmailAuthCode($authCode)
|
||||
{
|
||||
$this->authCode = $authCode;
|
||||
}
|
||||
|
||||
public function addTrustedComputer($token, \DateTime $validUntil)
|
||||
{
|
||||
$this->trusted[$token] = $validUntil->format('r');
|
||||
}
|
||||
|
||||
public function isTrustedComputer($token)
|
||||
{
|
||||
if (isset($this->trusted[$token])) {
|
||||
$now = new \DateTime();
|
||||
$validUntil = new \DateTime($this->trusted[$token]);
|
||||
|
||||
return $now < $validUntil;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
parameters:
|
||||
wallabag_user.twofactor.email.provider.class: Wallabag\UserBundle\Security\TwoFactor\Email\Helper
|
||||
wallabag_user.twofactor.email.interactive_login_listener.class: Wallabag\UserBundle\Security\TwoFactor\Email\InteractiveLoginListener
|
||||
wallabag_user.twofactor.email.request_listener.class: Wallabag\UserBundle\Security\TwoFactor\Email\RequestListener
|
||||
|
||||
services:
|
||||
wallabag_user.twofactor.email.provider:
|
||||
class: %wallabag_user.twofactor.email.provider.class%
|
||||
arguments: ['@doctrine.orm.entity_manager', '@mailer']
|
||||
wallabag_user.twofactor.email.interactive_login_listener:
|
||||
class: %wallabag_user.twofactor.email.interactive_login_listener.class%
|
||||
tags:
|
||||
- { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin }
|
||||
arguments: ['@wallabag_user.twofactor.email.provider']
|
||||
wallabag_user.twofactor.email.request_listener:
|
||||
class: %wallabag_user.twofactor.email.request_listener.class%
|
||||
tags:
|
||||
- { name: kernel.event_listener, event: kernel.request, method: onCoreRequest, priority: -1 }
|
||||
arguments: ['@wallabag_user.twofactor.email.provider', '@security.context', '@templating', '@router']
|
|
@ -0,0 +1,32 @@
|
|||
{% extends "WallabagUserBundle::layout.html.twig" %}
|
||||
|
||||
{% block fos_user_content %}
|
||||
<form class="form" action="" method="post">
|
||||
<fieldset class="w500p center">
|
||||
{% for flashMessage in app.session.flashbag.get("two_factor") %}
|
||||
<p class="error">{{ flashMessage|trans }}</p>
|
||||
{% endfor %}
|
||||
|
||||
<div class="row">
|
||||
<label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label>
|
||||
<input id="_auth_code" type="text" autocomplete="off" name="_auth_code" />
|
||||
</div>
|
||||
|
||||
{% if useTrustedOption %}
|
||||
<div class="row">
|
||||
<input id="_trusted" type="checkbox" name="_trusted" />
|
||||
<label for="_trusted">{{ "scheb_two_factor.trusted"|trans }}</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="row mts txtcenter">
|
||||
<a href="{{ path('fos_user_security_logout') }}" class="waves-effect waves-light grey btn"><i class="material-icons left"></i> {% trans %}Cancel{% endtrans %}</a>
|
||||
<button type="submit" name="send">
|
||||
{{ "scheb_two_factor.login"|trans }}
|
||||
<i class="mdi-content-send right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -0,0 +1,33 @@
|
|||
{% extends "WallabagUserBundle::layout.html.twig" %}
|
||||
|
||||
{% block fos_user_content %}
|
||||
<form class="form" action="" method="post">
|
||||
<div class="card-content">
|
||||
<div class="row">
|
||||
|
||||
{% for flashMessage in app.session.flashbag.get("two_factor") %}
|
||||
<p class="error">{{ flashMessage|trans }}</p>
|
||||
{% endfor %}
|
||||
|
||||
<div class="input-field col s12">
|
||||
<label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label>
|
||||
<input id="_auth_code" type="text" autocomplete="off" name="_auth_code" />
|
||||
</div>
|
||||
|
||||
{% if useTrustedOption %}
|
||||
<div class="input-field col s12">
|
||||
<input id="_trusted" type="checkbox" name="_trusted" />
|
||||
<label for="_trusted">{{ "scheb_two_factor.trusted"|trans }}</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-action center">
|
||||
<a href="{{ path('fos_user_security_logout') }}" class="waves-effect waves-light grey btn"><i class="material-icons left"></i> {% trans %}Cancel{% endtrans %}</a>
|
||||
<button class="btn waves-effect waves-light" type="submit" name="send">
|
||||
{{ "scheb_two_factor.login"|trans }}
|
||||
<i class="mdi-content-send right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
Loading…
Add table
Add a link
Reference in a new issue