diff options
author | Nicolas LÅ“uillet <nicolas.loeuillet@smile.fr> | 2015-10-13 22:43:15 +0200 |
---|---|---|
committer | Nicolas LÅ“uillet <nicolas.loeuillet@smile.fr> | 2015-10-13 22:43:15 +0200 |
commit | 2db616b586f473238706e554e809086935e0f33a (patch) | |
tree | 769c1a8f7c7541a11c2d71fa97a9ff6871d3d210 /src | |
parent | cf0ea8f113548191cdeb8d3727dd6d2ad25d19ed (diff) | |
download | wallabag-2db616b586f473238706e554e809086935e0f33a.tar.gz wallabag-2db616b586f473238706e554e809086935e0f33a.tar.zst wallabag-2db616b586f473238706e554e809086935e0f33a.zip |
2factor authentication via email
Diffstat (limited to 'src')
7 files changed, 168 insertions, 1 deletions
diff --git a/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php b/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php index 84f02013..e06c937d 100644 --- a/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php +++ b/src/Wallabag/CoreBundle/Form/Type/UserInformationType.php | |||
@@ -13,6 +13,7 @@ class UserInformationType extends AbstractType | |||
13 | $builder | 13 | $builder |
14 | ->add('name', 'text') | 14 | ->add('name', 'text') |
15 | ->add('email', 'email') | 15 | ->add('email', 'email') |
16 | ->add('twoFactorAuthentication', 'checkbox', array('required' => false)) | ||
16 | ->add('save', 'submit') | 17 | ->add('save', 'submit') |
17 | ->remove('username') | 18 | ->remove('username') |
18 | ->remove('plainPassword') | 19 | ->remove('plainPassword') |
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig index 64305b16..cee4f672 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig | |||
@@ -100,6 +100,14 @@ | |||
100 | </div> | 100 | </div> |
101 | </fieldset> | 101 | </fieldset> |
102 | 102 | ||
103 | <fieldset class="w500p inline"> | ||
104 | <div class="row"> | ||
105 | {{ form_label(form.user.twoFactorAuthentication) }} | ||
106 | {{ form_errors(form.user.twoFactorAuthentication) }} | ||
107 | {{ form_widget(form.user.twoFactorAuthentication) }} | ||
108 | </div> | ||
109 | </fieldset> | ||
110 | |||
103 | {{ form_rest(form.user) }} | 111 | {{ form_rest(form.user) }} |
104 | </form> | 112 | </form> |
105 | 113 | ||
diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig index 0d8e9f24..b20c4ea5 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig | |||
@@ -132,6 +132,14 @@ | |||
132 | </div> | 132 | </div> |
133 | </div> | 133 | </div> |
134 | 134 | ||
135 | <div class="row"> | ||
136 | <div class="input-field col s12"> | ||
137 | {{ form_widget(form.user.twoFactorAuthentication) }} | ||
138 | {{ form_label(form.user.twoFactorAuthentication) }} | ||
139 | {{ form_errors(form.user.twoFactorAuthentication) }} | ||
140 | </div> | ||
141 | </div> | ||
142 | |||
135 | <div class="hidden">{{ form_rest(form.user) }}</div> | 143 | <div class="hidden">{{ form_rest(form.user) }}</div> |
136 | <button class="btn waves-effect waves-light" type="submit" name="action"> | 144 | <button class="btn waves-effect waves-light" type="submit" name="action"> |
137 | {% trans %}Save{% endtrans %} | 145 | {% trans %}Save{% endtrans %} |
diff --git a/src/Wallabag/UserBundle/Entity/User.php b/src/Wallabag/UserBundle/Entity/User.php index 8f02e070..d2efd200 100644 --- a/src/Wallabag/UserBundle/Entity/User.php +++ b/src/Wallabag/UserBundle/Entity/User.php | |||
@@ -4,6 +4,8 @@ namespace Wallabag\UserBundle\Entity; | |||
4 | 4 | ||
5 | use Doctrine\Common\Collections\ArrayCollection; | 5 | use Doctrine\Common\Collections\ArrayCollection; |
6 | use Doctrine\ORM\Mapping as ORM; | 6 | use Doctrine\ORM\Mapping as ORM; |
7 | use Scheb\TwoFactorBundle\Model\Email\TwoFactorInterface; | ||
8 | use Scheb\TwoFactorBundle\Model\TrustedComputerInterface; | ||
7 | use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; | 9 | use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; |
8 | use Symfony\Component\Security\Core\User\UserInterface; | 10 | use Symfony\Component\Security\Core\User\UserInterface; |
9 | use JMS\Serializer\Annotation\ExclusionPolicy; | 11 | use JMS\Serializer\Annotation\ExclusionPolicy; |
@@ -24,7 +26,7 @@ use Wallabag\CoreBundle\Entity\Tag; | |||
24 | * @UniqueEntity("email") | 26 | * @UniqueEntity("email") |
25 | * @UniqueEntity("username") | 27 | * @UniqueEntity("username") |
26 | */ | 28 | */ |
27 | class User extends BaseUser | 29 | class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterface |
28 | { | 30 | { |
29 | /** | 31 | /** |
30 | * @var int | 32 | * @var int |
@@ -72,6 +74,22 @@ class User extends BaseUser | |||
72 | */ | 74 | */ |
73 | protected $tags; | 75 | protected $tags; |
74 | 76 | ||
77 | /** | ||
78 | * @ORM\Column(type="integer", nullable=true) | ||
79 | */ | ||
80 | private $authCode; | ||
81 | |||
82 | /** | ||
83 | * @var bool Enabled yes/no | ||
84 | * @ORM\Column(type="boolean") | ||
85 | */ | ||
86 | private $twoFactorAuthentication = false; | ||
87 | |||
88 | /** | ||
89 | * @ORM\Column(type="json_array", nullable=true) | ||
90 | */ | ||
91 | private $trusted; | ||
92 | |||
75 | public function __construct() | 93 | public function __construct() |
76 | { | 94 | { |
77 | parent::__construct(); | 95 | parent::__construct(); |
@@ -201,4 +219,52 @@ class User extends BaseUser | |||
201 | { | 219 | { |
202 | return $this->config; | 220 | return $this->config; |
203 | } | 221 | } |
222 | |||
223 | /** | ||
224 | * @return bool | ||
225 | */ | ||
226 | public function isTwoFactorAuthentication() | ||
227 | { | ||
228 | return $this->twoFactorAuthentication; | ||
229 | } | ||
230 | |||
231 | /** | ||
232 | * @param bool $twoFactorAuthentication | ||
233 | */ | ||
234 | public function setTwoFactorAuthentication($twoFactorAuthentication) | ||
235 | { | ||
236 | $this->twoFactorAuthentication = $twoFactorAuthentication; | ||
237 | } | ||
238 | |||
239 | public function isEmailAuthEnabled() | ||
240 | { | ||
241 | return $this->twoFactorAuthentication; | ||
242 | } | ||
243 | |||
244 | public function getEmailAuthCode() | ||
245 | { | ||
246 | return $this->authCode; | ||
247 | } | ||
248 | |||
249 | public function setEmailAuthCode($authCode) | ||
250 | { | ||
251 | $this->authCode = $authCode; | ||
252 | } | ||
253 | |||
254 | public function addTrustedComputer($token, \DateTime $validUntil) | ||
255 | { | ||
256 | $this->trusted[$token] = $validUntil->format('r'); | ||
257 | } | ||
258 | |||
259 | public function isTrustedComputer($token) | ||
260 | { | ||
261 | if (isset($this->trusted[$token])) { | ||
262 | $now = new \DateTime(); | ||
263 | $validUntil = new \DateTime($this->trusted[$token]); | ||
264 | |||
265 | return $now < $validUntil; | ||
266 | } | ||
267 | |||
268 | return false; | ||
269 | } | ||
204 | } | 270 | } |
diff --git a/src/Wallabag/UserBundle/Resources/config/services.yml b/src/Wallabag/UserBundle/Resources/config/services.yml index e69de29b..9cdd247d 100644 --- a/src/Wallabag/UserBundle/Resources/config/services.yml +++ b/src/Wallabag/UserBundle/Resources/config/services.yml | |||
@@ -0,0 +1,19 @@ | |||
1 | parameters: | ||
2 | wallabag_user.twofactor.email.provider.class: Wallabag\UserBundle\Security\TwoFactor\Email\Helper | ||
3 | wallabag_user.twofactor.email.interactive_login_listener.class: Wallabag\UserBundle\Security\TwoFactor\Email\InteractiveLoginListener | ||
4 | wallabag_user.twofactor.email.request_listener.class: Wallabag\UserBundle\Security\TwoFactor\Email\RequestListener | ||
5 | |||
6 | services: | ||
7 | wallabag_user.twofactor.email.provider: | ||
8 | class: %wallabag_user.twofactor.email.provider.class% | ||
9 | arguments: ['@doctrine.orm.entity_manager', '@mailer'] | ||
10 | wallabag_user.twofactor.email.interactive_login_listener: | ||
11 | class: %wallabag_user.twofactor.email.interactive_login_listener.class% | ||
12 | tags: | ||
13 | - { name: kernel.event_listener, event: security.interactive_login, method: onSecurityInteractiveLogin } | ||
14 | arguments: ['@wallabag_user.twofactor.email.provider'] | ||
15 | wallabag_user.twofactor.email.request_listener: | ||
16 | class: %wallabag_user.twofactor.email.request_listener.class% | ||
17 | tags: | ||
18 | - { name: kernel.event_listener, event: kernel.request, method: onCoreRequest, priority: -1 } | ||
19 | arguments: ['@wallabag_user.twofactor.email.provider', '@security.context', '@templating', '@router'] | ||
diff --git a/src/Wallabag/UserBundle/Resources/views/themes/baggy/Authentication/form.html.twig b/src/Wallabag/UserBundle/Resources/views/themes/baggy/Authentication/form.html.twig new file mode 100644 index 00000000..5bb91081 --- /dev/null +++ b/src/Wallabag/UserBundle/Resources/views/themes/baggy/Authentication/form.html.twig | |||
@@ -0,0 +1,32 @@ | |||
1 | {% extends "WallabagUserBundle::layout.html.twig" %} | ||
2 | |||
3 | {% block fos_user_content %} | ||
4 | <form class="form" action="" method="post"> | ||
5 | <fieldset class="w500p center"> | ||
6 | {% for flashMessage in app.session.flashbag.get("two_factor") %} | ||
7 | <p class="error">{{ flashMessage|trans }}</p> | ||
8 | {% endfor %} | ||
9 | |||
10 | <div class="row"> | ||
11 | <label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label> | ||
12 | <input id="_auth_code" type="text" autocomplete="off" name="_auth_code" /> | ||
13 | </div> | ||
14 | |||
15 | {% if useTrustedOption %} | ||
16 | <div class="row"> | ||
17 | <input id="_trusted" type="checkbox" name="_trusted" /> | ||
18 | <label for="_trusted">{{ "scheb_two_factor.trusted"|trans }}</label> | ||
19 | </div> | ||
20 | {% endif %} | ||
21 | |||
22 | <div class="row mts txtcenter"> | ||
23 | <a href="{{ path('fos_user_security_logout') }}" class="waves-effect waves-light grey btn"><i class="material-icons left"></i> {% trans %}Cancel{% endtrans %}</a> | ||
24 | <button type="submit" name="send"> | ||
25 | {{ "scheb_two_factor.login"|trans }} | ||
26 | <i class="mdi-content-send right"></i> | ||
27 | </button> | ||
28 | </div> | ||
29 | </fieldset> | ||
30 | |||
31 | </form> | ||
32 | {% endblock %} | ||
diff --git a/src/Wallabag/UserBundle/Resources/views/themes/material/Authentication/form.html.twig b/src/Wallabag/UserBundle/Resources/views/themes/material/Authentication/form.html.twig new file mode 100644 index 00000000..fa0e3dc1 --- /dev/null +++ b/src/Wallabag/UserBundle/Resources/views/themes/material/Authentication/form.html.twig | |||
@@ -0,0 +1,33 @@ | |||
1 | {% extends "WallabagUserBundle::layout.html.twig" %} | ||
2 | |||
3 | {% block fos_user_content %} | ||
4 | <form class="form" action="" method="post"> | ||
5 | <div class="card-content"> | ||
6 | <div class="row"> | ||
7 | |||
8 | {% for flashMessage in app.session.flashbag.get("two_factor") %} | ||
9 | <p class="error">{{ flashMessage|trans }}</p> | ||
10 | {% endfor %} | ||
11 | |||
12 | <div class="input-field col s12"> | ||
13 | <label for="_auth_code">{{ "scheb_two_factor.auth_code"|trans }}</label> | ||
14 | <input id="_auth_code" type="text" autocomplete="off" name="_auth_code" /> | ||
15 | </div> | ||
16 | |||
17 | {% if useTrustedOption %} | ||
18 | <div class="input-field col s12"> | ||
19 | <input id="_trusted" type="checkbox" name="_trusted" /> | ||
20 | <label for="_trusted">{{ "scheb_two_factor.trusted"|trans }}</label> | ||
21 | </div> | ||
22 | {% endif %} | ||
23 | </div> | ||
24 | </div> | ||
25 | <div class="card-action center"> | ||
26 | <a href="{{ path('fos_user_security_logout') }}" class="waves-effect waves-light grey btn"><i class="material-icons left"></i> {% trans %}Cancel{% endtrans %}</a> | ||
27 | <button class="btn waves-effect waves-light" type="submit" name="send"> | ||
28 | {{ "scheb_two_factor.login"|trans }} | ||
29 | <i class="mdi-content-send right"></i> | ||
30 | </button> | ||
31 | </div> | ||
32 | </form> | ||
33 | {% endblock %} | ||