Form to change the password

This commit is contained in:
Simon Vieille 2016-12-23 10:28:09 +01:00
parent a79b443b36
commit df3035f2f1
11 changed files with 222 additions and 40 deletions

View File

@ -6,10 +6,8 @@ use Silex\Provider\RememberMeServiceProvider;
use Gist\Service\SaltGenerator;
use Gist\Security\AuthenticationProvider;
use Gist\Security\AuthenticationListener;
use Gist\Security\AuthenticationEntryPoint;
use Gist\Security\LogoutSuccessHandler;
use Silex\Provider\SessionServiceProvider;
use Symfony\Component\Security\Http\HttpUtils;
$app['enable_registration'] = true;
$app['enable_login'] = true;
@ -19,7 +17,7 @@ $app['login_required_to_view_embeded_gist'] = false;
$app['token'] = 'ThisTokenIsNotSoSecretChangeIt';
$app['salt_generator'] = $app->share(function($app) {
$app['salt_generator'] = $app->share(function ($app) {
return new SaltGenerator();
});
@ -34,10 +32,10 @@ $app['security.authentication_listener.factory.form'] = $app->protect(function (
$app['security.authentication_provider.'.$name.'.form'] = $app->share(function ($app) {
return new AuthenticationProvider($app['user.provider']);
});
$app['security.authentication_listener.'.$name.'.form'] = $app->share(function ($app) use ($name) {
return new AuthenticationListener(
$app['security.token_storage'],
$app['security.token_storage'],
$app['security.authentication_provider.'.$name.'.form']
);
});
@ -46,7 +44,7 @@ $app['security.authentication_listener.factory.form'] = $app->protect(function (
'security.authentication_provider.'.$name.'.form',
'security.authentication_listener.'.$name.'.form',
null,
'pre_auth'
'pre_auth',
];
});
@ -76,13 +74,12 @@ $firewall = [
],
'security.access_rules' => [
['^/[a-z]{2}/my.*$', 'ROLE_USER'],
]
],
];
if ($app['login_required_to_edit_gist'] || $app['login_required_to_view_gist'] || $app['login_required_to_view_embeded_gist']) {
$securityRegexp = '^/[a-z]{2}';
$exceptedUriPattern = ['login', 'register'];
if ($app['login_required_to_view_gist'] === true) {
$firewall['security.access_rules'][] = ['^/[a-z]{2}/view.*$', 'ROLE_USER'];
$firewall['security.access_rules'][] = ['^/[a-z]{2}/revs.*$', 'ROLE_USER'];
@ -90,7 +87,7 @@ if ($app['login_required_to_edit_gist'] || $app['login_required_to_view_gist'] |
$exceptedUriPattern[] = 'view';
$exceptedUriPattern[] = 'revs';
}
if ($app['login_required_to_view_embeded_gist'] === true) {
$firewall['security.access_rules'][] = ['^/[a-z]{2}/embed.*$', 'ROLE_USER'];
} else {
@ -98,10 +95,10 @@ if ($app['login_required_to_edit_gist'] || $app['login_required_to_view_gist'] |
}
if ($app['login_required_to_edit_gist'] === true) {
$firewall['security.access_rules'][] = ['^/[a-z]{2}/(?!('.implode('|', $exceptedUriPattern).')).*$', 'ROLE_USER'];
$firewall['security.access_rules'][] = ['^/[a-z]{2}/(?!('.implode('|', $exceptedUriPattern).')).*$', 'ROLE_USER'];
}
}
$app->register(new SecurityServiceProvider(), $firewall);
$app->register(new SessionServiceProvider());
$app->register(new RememberMeServiceProvider());

View File

@ -59,12 +59,15 @@ login:
form:
username:
placeholder: 'Username'
current_password:
placeholder: 'Aktuelles Passwort'
password:
placeholder: 'Password'
form:
error:
not_blank: 'This value should not be blank bro!'
password: 'Ungültiges Passwort.'
not_blank: 'Dieser Wert darf nicht leer sein.'
title:
placeholder: 'Titel'
cipher:
@ -75,7 +78,9 @@ form:
no: 'No'
submit: 'Senden'
filter: 'Filter'
confirm: 'Bestätigen Sie?'
success:
password: 'Passwort aktualisiert.'
gist: 'Gist removed.'
type:
label: 'Language: %value%'

View File

@ -59,11 +59,14 @@ login:
form:
username:
placeholder: 'Username'
current_password:
placeholder: 'Current password'
password:
placeholder: 'Password'
form:
error:
password: 'Invalid password.'
not_blank: 'This value should not be blank bro!'
title:
placeholder: 'Title'
@ -75,7 +78,9 @@ form:
no: 'No'
submit: 'Send'
filter: 'Filter'
confirm: 'Do you confirm?'
success:
password: 'Password updated.'
gist: 'Gist removed.'
type:
label: 'Language: %value%'

View File

@ -59,11 +59,14 @@ login:
form:
username:
placeholder: 'Nombre de usuario'
current_password:
placeholder: 'Contraseña actual'
password:
placeholder: 'Contraseña'
form:
error:
password: 'Contraseña no válida.'
not_blank: 'Se necesita introducir este dato.'
title:
placeholder: 'Título'
@ -75,7 +78,9 @@ form:
no: 'No'
submit: 'Enviar'
filter: 'Filtrar'
confirm: '¿Confirmas?'
success:
password: 'Contraseña cambiada.'
gist: 'Su Gist ha sido eliminado.'
type:
label: 'Lenguaje : %value%'

View File

@ -59,11 +59,14 @@ login:
form:
username:
placeholder: 'Nom d''utilisateur'
current_password:
placeholder: 'Mot de passe courrant'
password:
placeholder: 'Mot de passe'
form:
error:
password: 'Mot de passe invalide.'
not_blank: 'Vous devez saisir cette donnée.'
title:
placeholder: 'Titre'
@ -75,7 +78,9 @@ form:
no: 'Non'
submit: 'Envoyer'
filter: 'Filtrer'
confirm: 'Confirmez-vous ?'
success:
password: 'Mot de passe modifié.'
gist: 'Votre Gist a bien a été supprimé.'
type:
label: 'Langage : %value%'

View File

@ -5,6 +5,8 @@ namespace Gist\Controller;
use Symfony\Component\HttpFoundation\Request;
use Gist\Form\DeleteGistForm;
use Gist\Form\FilterGistForm;
use Gist\Form\UserPasswordForm;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Class MyController.
@ -43,6 +45,9 @@ class MyController extends Controller
$filterForm = $filterForm->build()->getForm();
$passwordForm = new UserPasswordForm($app['form.factory'], $app['translator']);
$passwordForm = $passwordForm->build()->getForm();
if ($request->query->has('filter')) {
$filterForm->submit($request);
@ -54,9 +59,10 @@ class MyController extends Controller
$gists = $this->getUser()->getGistsPager($page, $options);
if ($request->isMethod('post')) {
$deleteForm->submit($request);
$deleteForm->handleRequest($request);
$passwordForm->handleRequest($request);
if ($deleteForm->isValid()) {
if ($deleteForm->isSubmitted() && $deleteForm->isValid()) {
$id = (int) $deleteForm->getData()['id'];
foreach ($gists as $gist) {
@ -67,6 +73,30 @@ class MyController extends Controller
}
}
}
if ($passwordForm->isSubmitted() && $passwordForm->isValid()) {
$currentPassword = $passwordForm->getData()['currentPassword'];
$newPassword = $passwordForm->getData()['newPassword'];
$passwordUpdated = 0;
if ($app['user.provider']->isCurrentUserPassword($this->getUser(), $currentPassword)) {
$app['user.provider']->updateUserPassword(
$this->getUser(),
$newPassword
);
$passwordUpdated = 1;
}
return new RedirectResponse(
$app['url_generator']->generate(
'my',
[
'passwordUpdated' => $passwordUpdated,
]
)
);
}
}
return $this->render(
@ -76,6 +106,7 @@ class MyController extends Controller
'page' => $page,
'deleteForm' => $deleteForm->createView(),
'filterForm' => $filterForm->createView(),
'passwordForm' => $passwordForm->createView(),
'deleted' => !empty($deleted),
)
);

View File

@ -0,0 +1,65 @@
<?php
namespace Gist\Form;
use Symfony\Component\Validator\Constraints\NotBlank;
/**
* Class UserPasswordForm.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class UserPasswordForm extends AbstractForm
{
/**
* {@inheritdoc}
*/
public function build(array $options = array())
{
$this->builder->add(
'currentPassword',
'password',
array(
'required' => true,
'attr' => array(
'class' => 'form-control',
'placeholder' => $this->translator->trans('login.register.form.current_password.placeholder'),
),
'trim' => false,
'constraints' => array(
new NotBlank(array(
'message' => $this->translator->trans('form.error.not_blank'),
)),
),
)
);
$this->builder->add(
'newPassword',
'password',
array(
'required' => true,
'attr' => array(
'class' => 'form-control',
'placeholder' => $this->translator->trans('login.register.form.password.placeholder'),
),
'trim' => false,
'constraints' => array(
new NotBlank(array(
'message' => $this->translator->trans('form.error.not_blank'),
)),
),
)
);
return $this->builder;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'password';
}
}

View File

@ -4,6 +4,20 @@
{% block body %}
<div class="row">
{% if app.request.query.has('passwordUpdated') %}
<div class="col-md-12">
{% if app.request.query.get('passwordUpdated') %}
<div class="alert alert-success">
<p>{{ 'form.success.password'|trans }}</p>
</div>
{% else %}
<div class="alert alert-warning">
<p>{{ 'form.error.password'|trans }}</p>
</div>
{% endif %}
</div>
{% endif %}
{% if deleted %}
<div class="col-md-12">
<div class="alert alert-success">
@ -11,6 +25,7 @@
</div>
</div>
{% endif %}
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
@ -42,15 +57,15 @@
<ul class="dropdown-menu">
{% for item in filterForm.type.vars.choices %}
<li>
<input
{% if item.value == filterForm.type.vars.value %}checked{% endif %}
data-id="#type-label" type="radio" class="hide"
data-title="{{ item.label }}"
value="{{ item.value }}"
name="filter[type]"
<input
{% if item.value == filterForm.type.vars.value %}checked{% endif %}
data-id="#type-label" type="radio" class="hide"
data-title="{{ item.label }}"
value="{{ item.value }}"
name="filter[type]"
id="type-{{ loop.index }}" />
<a href="#">
<a href="#">
<label for="type-{{ loop.index }}">
{{ item.label }}
</label>
@ -68,15 +83,15 @@
<ul class="dropdown-menu" role="menu">
{% for item in filterForm.cipher.vars.choices %}
<li>
<input
{% if item.value == filterForm.cipher.vars.value %}checked{% endif %}
data-id="#cipher-label" type="radio" class="hide cipher-input"
data-title="{{ item.label }}"
value="{{ item.value }}"
<input
{% if item.value == filterForm.cipher.vars.value %}checked{% endif %}
data-id="#cipher-label" type="radio" class="hide cipher-input"
data-title="{{ item.label }}"
value="{{ item.value }}"
name="filter[cipher]"
id="cipher-{{ loop.index }}" />
<a href="#">
<a href="#">
<label for="cipher-{{ loop.index }}">
{{ item.label }}
</label>
@ -118,7 +133,7 @@
</span>
</a>
</li>
{% for p in gists.links(10) %}
<li {% if p == page %}class="active"{% endif %}>
{% set params = params|merge({page: p}) %}
@ -126,7 +141,7 @@
<a href="{{ path('my', params) }}">{{ p }}</a>
</li>
{% endfor %}
<li>
{% set params = params|merge({page: gists.nextPage}) %}
@ -136,7 +151,7 @@
</span>
</a>
</li>
<li>
{% set params = params|merge({page: gists.lastPage}) %}
@ -149,19 +164,19 @@
</ul>
{% endif %}
{% endset %}
{{ pager }}
{% for gist in gists %}
<div class="commit">
<p>
<strong>{{ gist.title ? gist.title : 'gist.untitled'|trans }}</strong>,
<strong>{{ gist.title ? gist.title : 'gist.untitled'|trans }}</strong>,
{{ gist.createdAt|date('date.format'|trans) }}
</p>
<p>
<button class="btn btn-info btn-sm">
{{ gist.type }}
{{ gist.type }}
</button>
{% if not gist.cipher %}
@ -173,19 +188,45 @@
<span class="glyphicon glyphicon-lock"></span>
</button>
{% endif %}
<button class="btn btn-delete btn-sm" data-id="{{ gist.id }}">
<span class="glyphicon btn-delete glyphicon-remove" data-id="{{ gist.id }}"></span>
</button>
</p>
</div>
{% endfor %}
{{ pager }}
{% endif %}
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
{{ 'login.login.form.password.placeholder'|trans }}
</div>
<div class="panel-body">
<div class="tab-content">
<form action="{{ path('my', params) }}" method="post">
<p>
{{ form_errors(passwordForm.currentPassword) }}
{{ form_widget(passwordForm.currentPassword) }}
</p>
<p>
{{ form_errors(passwordForm.newPassword) }}
{{ form_widget(passwordForm.newPassword) }}
</p>
<p>
{{ form_rest(passwordForm) }}
<input type="submit" class="btn btn-primary" value="{{ 'form.submit'|trans }}">
</p>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -94,6 +94,19 @@
{% endblock %}
</div>
{% block js %}
<script>
var trans = function(key) {
var translations = {
'form.confirm': '{{ 'form.confirm'|trans }}',
};
if (translations.hasOwnProperty(key)) {
return translations[key];
}
return key;
}
</script>
<script src="{{ web_path }}components/jquery/dist/jquery.min.js"></script>
<script src="{{ web_path }}components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="{{ web_path }}app/js/cipher.js"></script>

View File

@ -166,6 +166,19 @@ class UserProvider implements UserProviderInterface
return $user;
}
/*
* Checks if the given password is the current user password.
*
* @param User $user
* @param string $password
*
* @return bool
*/
public function isCurrentUserPassword(User $user, $password)
{
return $this->encoder->encodePassword($password, $user->getSalt()) === $user->getPassword();
}
/**
* Refresh an user.
*

View File

@ -93,8 +93,10 @@ var editorEvents = function() {
var myEvents = function() {
$('.btn-delete').click(function() {
$('#delete_id').val($(this).data('id'));
$('#form-deletion form').submit();
if (confirm(trans('form.confirm'))) {
$('#delete_id').val($(this).data('id'));
$('#form-deletion form').submit();
}
});
}
@ -136,7 +138,7 @@ var viewerEvents = function() {
$(document).ready(function() {
var key = getKey();
var $cipherEditor = $('.cipher-editor');
var $embedInput = $('#embed-input');