Symfony Demo Application - where to find twigs? - symfony

I'm trying to orientate myself with Symfony framework by going through the "Symfony Demo application" and am trying to work my way through the interconnections. However in the below code snippet I can't find where this twig reference is getting defined value="{{ last_username }}":
\app\Resources\view\security\login.html.twig
{% extends 'base.html.twig' %}
{% block body_id 'login' %}
{% block main %}
{% if error %}
<div class="alert alert-danger">
{{ error.messageKey|trans(error.messageData) }}
</div>
{% endif %}
<div class="row">
<div class="col-sm-5">
<div class="well">
<form action="{{ path('security_login_check') }}" method="post">
<fieldset>
<legend><i class="fa fa-lock"></i> Secure Sign in</legend>
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" class="form-control"/>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="password" name="_password" class="form-control" />
</div>
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}"/>
<button type="submit" class="btn btn-primary">
<i class="fa fa-sign-in"></i> Sign in
</button>
</fieldset>
</form>
</div>
</div>
I have searched the whole demo application for last_username and it only appears in these four files:
\app\cache\dev\classes.php
\app\cache\prod\classes.php
\vendor\symfony\symfony\src\Symfony\Component\Security\Core\SecurityContextInterface.php
\vendor\symfony\symfony\src\Symfony\Component\Security\Core\Security.php
...all of which don't seem to offer anything helpful of defining last_username.

The last_username parameter is passed to the template via the SecurityController, which is defined in the src/AppBundle/Controller/SecurityController.php file.
One of the coolest features of the Symfony Demo application is that all pages include a Show code which shows you both the controller and the template used to create the page you are looking at. For example, in the case of the login page:

Related

Invalid CSRF token when resetting password

I have a resetting password feature in my site, however, form is not working. When trying to set the password, a "Invalid CSRF token" is shown.
This my actual resetting password form:
<div class="login-form">
<form name="fos_user_resetting_form" method="post" action="{{ path('fos_user_resetting_reset', {'token': token}) }}" class="needs-validation" novalidate>
<div class="form-group">
<label for="fos_user_resetting_form_plainPassword_first" class="required">{{ 'form.password'|trans }}</label>
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-key"></i></div>
<input type="password" class="form-control" id="fos_user_resetting_form_plainPassword_first" name="fos_user_resetting_form[plainPassword][first]" required="required" autocomplete="new-password" />
<div class="invalid-tooltip">Por favor, ingrese la nueva contraseña.</div>
</div>
</div>
<div class="form-group">
<label for="fos_user_resetting_form_plainPassword_second" class="required">{{ 'form.password_confirmation'|trans }}</label>
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-key"></i></div>
<input type="password" class="form-control" id="fos_user_resetting_form_plainPassword_second" name="fos_user_resetting_form[plainPassword][second]" required="required" autocomplete="new-password" />
<div class="invalid-tooltip" id="confirm_password_error">Por favor, ingrese la nueva contraseña.</div>
</div>
</div>
<div>
<button type="submit" id="_submit" name="_submit" class="btn btn-success btn-flat m-b-30 m-t-30">{{ 'resetting.reset.submit'|trans }}</button>
</div>
</form>
</div>
I Know I need to add a _csrf_token hidden input to form, but, how?
I tried with
{% if csrf_token %}
<input type="hidden" name="_csrf_token" value="{{ csrf_token }}" />
{% endif %}
With:
{% if _token %}
<input type="hidden" name="_csrf_token" value="{{ _token }}" />
{% endif %}
With:
<input type="hidden" id="fos_user_resetting_form__token" name="fos_user_resetting_form[_token]" value="{{ _token }}" />
And other attempts... but none works. In all cases, twig error is shown with 'Variable "_token" does not exist.'
When using Symfony debug toolbar, I see clearly the variable is called "_token". I don't know what else to try.
EDIT: when seeing Symfony Profiler, this is shown. Variable "_token" does exist, but I don't find a way to use it in the view.
when using the default FOSUserBundle form, the value of _token is rendered. I could not find how it is actually rendered, since it uses {{ form_widget(form) }} and when I saw the corresponding Form Type, I did not see any clue about this.
Thanks
Jaime
Finally, it was easier than I thought.
I added simply {{ form_widget(form._token) }} where the token should be in the form. That way, the correct token value was rendered for the hidden input field.
Regards
Jaime
Have you tried the following? From How to Implement CSRF Protection
<input type="hidden" name="_csrf_token"
value="{{ csrf_token('authenticate') }}"
>
For anyone trying to add the csrf token without generating the whole form, you can use in your twig template {{ fos_csrf_provider.refreshToken('resetting') }}. Example :
<!-- Form -->
<form id="change-password-form" action="{{ path("user_resetting_reset",{'token': token}) }}" method="post" name="change-password-form">
<div class="form-group">
<input id="change_password_first_password" class="input form-control" required type="password" name="first" placeholder="{% trans %}New password{% endtrans %}">
</div>
<div class="form-group">
<input id="change_password_second_password" class="input form-control" required type="password" name="second" placeholder="{% trans %}Retype new password{% endtrans %}">
</div>
<input type="hidden" id="profile_token" name="_token" value="{{ fos_csrf_provider.refreshToken('resetting') }}" />
<button type="submit" class="btn btn-block ui-gradient-green shadow-md">Reset</button>
</form>
<!-- Form -->

FOSUserBundle Custom forms using Bootstrap

I'm using FOSUserBundle in my Symfony application. Everything work but i would like to know how to custom the render of the forms delivered by the bundle.
I have already succesfully custom the login form but i didn't find the way to custom for example the changePassword.html.twig.
I'have checked in ChangePasswordFormType.php to see if I can get the differents fields of the form but I must have missed something.
For example in my FOSUserBundle login.html.twig:
<form class="form-group-lg" action="{{ path("fos_user_security_check") }}" method="post">
<input type="hidden" name="_csrf_token" value="{{ csrf_token }}" />
<fieldset>
{% if error %}
<div class="row">
<div class="alert alert-danger" role="alert">{{ error|trans({}, 'FOSUserBundle') }}</div>
</div>
{% endif %}
<div class="row">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input class="form-control" for="username" placeholder="{{ 'security.login.username'|trans({}, 'FOSUserBundle') }}" type="text" id="username" name="_username" value="{{ last_username }}" required="required" />
</div>
</div>
<div class="row">
</div>
<br>
<div class="row">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input class="form-control" for="password" placeholder="{{ 'security.login.password'|trans({}, 'FOSUserBundle') }}" type="password" id="password" name="_password" required="required" />
</div>
<p class="text-right"> <a href={{ path('fos_user_resetting_request') }}> Mot de passe oublié ?</a></p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" for="remember_me"/>{{ 'security.login.remember_me'|trans({}, 'FOSUserBundle') }}
</label>
</div>
<input class="btn btn-lg btn-primary btn-block" type="submit" id="_submit" name="_submit" value="{{ 'security.login.submit'|trans({}, 'FOSUserBundle') }}" />
</fieldset>
</form>
I'm looking for using the same syntax as {{ 'security.login.username'|trans({}, 'FOSUserBundle') }} for the others template provided by FOSUserBundleto get boostrap theme on it.
If someone have already done that i would like to know how you've done this.
Thanks.
FOSUserBundle templates are located at : vendor/friendsofsymfony/user-bundle/Resources/views/
To override these templates, create the folder app/Resources/FOSUserBundle/views then, you create a template with the same name as the FOSUserBundle template you want to override.
For example to override the change passord template :
vendor/friendsofsymfony/user-bundle/Resources/views/ChangePassword/change_password.html.twig
You must create app/Resources/FOSUserBundle/views/ChangePassword/change_passord.html.twig

Sonata Admin : Forgotten Password

I am using Sonata Admin with SonataUser/FosUser bundles.
I want to integrate the "reset password" functionality from FosUser into Sonata. Is there a quick way to :
integrate the "forgot your password" link into the sonata login page ?
integrate the functionality with the "admin/" url prefix and the sonata html/twig layout ?
I have modified the admin login template to add the reset password link, you must extend the SonataUserBundle in order to use your custom template, follow the documentation.
The custom template must have the same name and the same directory as in SonataUserBundle. Here is the template I used :
Application\Sonata\UserBundle\Resources\views\Admin\Security\login.html.twig
{% extends base_template %}
{% block content %}
<div class="connection">
<form action="{{ path("sonata_user_admin_security_check") }}" method="post">
{% if error %}
<div class="alert alert-error">{{ error|trans({}, 'SonataUserBundle') }}</div>
{% endif %}
<input type="hidden" name="_csrf_token" value="{{ csrf_token }}" />
<div class="control-group">
<label for="username">{{ 'security.login.username'|trans({}, 'FOSUserBundle') }}</label>
<div class="controls">
<input type="text" id="username" name="_username" value="{{ last_username }}" class="big sonata-medium"/>
</div>
</div>
<div class="control-group">
<label for="password">{{ 'security.login.password'|trans({}, 'FOSUserBundle') }}</label>
<div class="controls">
<input type="password" id="password" name="_password" class="big sonata-medium" />
</div>
</div>
<div class="control-group">
<label for="remember_me">
<input type="checkbox" id="remember_me" name="_remember_me" value="on" />
{{ 'security.login.remember_me'|trans({}, 'FOSUserBundle') }}
</label>
</div>
<div class="control-group">
<a href="{{ path('fos_user_resetting_request') }}">
{{ 'forgotten_password'|trans({}, 'SonataUserBundle') }}
</a>
</div>
<div class="form-actions">
<input type="submit" class="btn btn-primary" id="_submit" name="_submit" value="{{ 'security.login.submit'|trans({}, 'FOSUserBundle') }}" />
</div>
</form>
</div>
{% endblock content %}

Django styling login forms and adding additional spans

I have two questions in form-styling.
For my login, I am using Django's default auth features and haven't written any views or forms manually.
urls.py
urlpatterns += patterns(
'django.contrib.auth.views',
url(r'^login/$','login',
{'template_name':'login.html'},
name='qna_login'),
url(r'^logout/$','logout',
{'next_page':'qna_home'},
name='qna_logout'),
)
login.html
{% extends "base.html" %}
{% block content%}
{% if form.errors %}
<p class="text-warning"> Your username and/or password didn't match </p>
{% endif%}
<form role="form" class="form-horizontal" method="post" action="{% url 'django.contrib.auth.views.login' %}">
<div class="form-group">
{% csrf_token %}
{{ form }}
<input type="submit" class="btn btn-primary" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</div>
</form>
{% endblock %}
How do I add bootstrap styling to it?
For new user registration, I have added some bootstrap specific styles, but need to add additional spans and replace the labels with Glyphicons.
forms.py
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password')
def __init__(self, *args, **kwargs):
super(UserForm,self).__init__(*args,**kwargs)
self.fields['username'].widget.attrs.update({'class':'form-control','placeholder':'Username'})
self.fields['email'].widget.attrs.update({'class':'form-control','placeholder':'Email'})
self.fields['password'].widget.attrs.update({'class':'form-control','placeholder':'Password'})
What I need to do is replace what is generated in the template, such as
<p><label for="id_username">Username:</label> <input class="form-control" id="id_username" maxlength="30" name="username" placeholder="Username" type="text" /> <span class="helptext">Required. 30 characters or fewer. Letters, numbers and #/./+/-/_ characters</span></p>
by a custom bootstrap addon and glyphicon, like
<div class="input-group">
<span class="input-group-addon" style="background-color:#b77b48; color:white"><span class="glyphicon glyphicon-user"></span></span>
<input type="text" class="form-control" placeholder="Username">
</div>
You can render each field individually instead of letting Django render the whole form with {{ form }}. You can write the template like this -
<form role="form" class="form-horizontal" method="post" action="{% url 'django.contrib.auth.views.login' %}">{% csrf_token %}
<div class="form-group">
{% for field in form %}
<div class="input-group">
<span class="input-group-addon" style="background-color:#b77b48; color:white"><span class="glyphicon glyphicon-user"></span></span>
<input class="form-control" id="{{ field.id_for_label }}" maxlength="30" name="{{ field.html_name }}" value="{{ field.value }}" type="text" />
{{ field.errors }}
</div>
{% endfor %}
<input type="submit" class="btn btn-primary" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</div>
</form>
As always, like everything else, Django documentation has everything.

How to style a django form - bootstrap

I am styling my django app but Iam having trouble styling the forms. I have a contact form, in my forms.py and then I have use it in a template.
<form class="form-contact" action="" method="POST">
{% csrf_token %}
<input type="text" name="Name" id="id_name" value="{{form.name}}" />
<input type="submit" value="Submit" class="btn btn-primary">
</form>
That isn't working. I have also tried this, but still no luck, it shows styled fields but doesn't retrieve the information ( I get a message under my {{form.errors}} .
<form class="form-contact" action="" method="POST">
{% csrf_token %}
{% for field in form %}
<fieldset class="form-group">
<label class="control-label" for="id_{{ field.name }}">{{ field.label }}</label>
<div class="form-control">
<input type="text" class="form-control"
name="{{ field.label }}"
id="{{ field.name }}"
value="{{ field.name }}" >
{{ field }}
<p class="help-text">{{ field.help_text }} </p>
</div>
</fieldset>
{% endfor %}
<input type="submit" value="Submit" class="btn btn-primary">
</form>
Any hint would be apreciated.
Regards.
EDIT:
This second code, is actually showing 2 input fields for each form field. If I fill the second one, the form works but, this second input has no styling...
"EDIT: This second code, is actually showing 2 input fields for each
form field."
The first input is being generated by the <input> tag that you've explicitly written:
<input type="text" class="form-control"
name="{{ field.label }}"
id="{{ field.name }}"
value="{{ field.name }}" >
The second input is being generated by the {{ field }} variable:
<div class="form-control">
<input type="text" class="form-control"
name="{{ field.label }}"
id="{{ field.name }}"
value="{{ field.name }}" >
{{ field }} <-- this one
<p class="help-text">{{ field.help_text }} </p>
</div>
"If I fill the second one, the form works but, this second
input has no styling..."
The styling isn't working because when the {{ field }} input is rendered, there's no css classes on it.
Additionally, you've switched some of the attributes of each field object (see "What changed" section below for more).
Try this code:
<form class="form-contact" action="" method="POST">
{% csrf_token %}
{% for field in form %}
<fieldset class="form-group">
<label class="control-label" for="id_{{ field.name }}">{{ field.label }}</label>
<div class="form-control">
<input type="text" class="form-control"
name="{{ field.name }}"
id="id_{{ field.name }}"
value="{{ field.value }}" >
<p class="help-text">{{ field.help_text }} </p>
</div>
</fieldset>
{% endfor %}
<input type="submit" value="Submit" class="btn btn-primary">
</form>
For more on how this works, check out the "Looping over a form's fields" section of the docs. You might also be interested in "Django Bootstrap Form", a third-party-package that allows for quick and easy form styling.
What changed:
1. Removed the {{ field }} variable within the loop
2. {{ field.label }} replaced with {{ field.name }} within the name attribute
3. {{ field.name }} replaced with {{ field.value }} within the value attribute
Wrap the form in div's with container, row, and col. Also, add the input type.
<style>
.help-text {
font-style: italic;
font-variant: all-small-caps;
}
</style>
<div class="container">
<form class="my-form" action="." method="POST">
{% csrf_token %}
{% for field in form %}
<div class="form-group row">
<label class="col-12 col-form-label" for="id_{{ field.name }}">{{ field.label }}</label>
<div class="col-12">
<input
type="{{ field.field.widget.input_type }}"
class="form-control"
name="{{ field.name }}"
id="id_{{ field.name }}"
value="{{ field.value|default:'' }}"
>
</div>
<div class="col-12 help-text">{{ field.help_text }} </div>
</div>
{% endfor %}
<div class="row">
<div class="col-12">
<input type="submit" value="Submit" class="btn btn-primary">
</div>
</div>
</form>
</div>
Alternatively you can use, forms.py file for creating forms.
And install django-bootstrap and work.. It will be very interesting.

Resources