Symfony3 Doctrine queryBuilder for pagerfanta on ManyToMany realationship - pagination

I have strange problem here but first a quick explanation of what is the idea. We have system where all users can upload files. Each user will have favorite files and I need to add pagination.
My User entity:
/**
* User
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="STInfoSystemBundle\Repository\UserRepository")
*/
class User implements UserInterface
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=100, unique=true)
*/
private $email;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
/**
* #var UserDetails
*
* #ORM\OneToOne(targetEntity="STInfoSystemBundle\Entity\UserDetails", mappedBy="user", cascade={"persist"})
*/
private $userDetails;
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="STInfoSystemBundle\Entity\Role")
* #ORM\JoinTable(name="user_roles",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="role_id", referencedColumnName="id")}
* )
*
*/
private $roles;
/**
* #var FileUpload[]
* #ORM\ManyToMany(targetEntity="STInfoSystemBundle\Entity\FileUpload")
* #ORM\JoinTable(name="users_favorites",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="file_id", referencedColumnName="id")})
*/
private $favoriteFiles;
/**
* #var FileUpload[]
*
* #ORM\OneToMany(targetEntity="STInfoSystemBundle\Entity\FileUpload", mappedBy="user")
*
*/
private $files;
/** #var Event[]
* #ORM\OneToMany(targetEntity="STInfoSystemBundle\Entity\Event", mappedBy="user")
*/
private $events;
public function __construct()
{
$this->roles = new ArrayCollection();
$this->files = new ArrayCollection();
$this->favoriteFiles = new ArrayCollection();
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
My FileUpload entity:
/**
* #ORM\Entity
* #Vich\Uploadable
* #Table(name="uploaded_files")
* #ORM\Entity(repositoryClass="STInfoSystemBundle\Repository\FileUploadRepository")
*/
class FileUpload
{
const FILES_PER_PAGE = 3;
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// * mimeTypesMessage="Allowed files are pdf and MS word.",
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="generic_file", fileNameProperty="fileName")
* #Assert\File(
* maxSize = "5M",
* mimeTypes = {"application/pdf"},
* maxSizeMessage="The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}."
* )
* #var File
*/
private $file;
//TODO: ..... other fields if any
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $fileName;
/**
* #ORM\Column(type="datetime")
*
* #var \DateTime
*/
private $updatedAt;
/**
* #var
* #ORM\ManyToOne(targetEntity="STInfoSystemBundle\Entity\User", inversedBy="files")
*/
private $user;
/** #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="STInfoSystemBundle\Entity\User", mappedBy="favoriteFiles")
*
*/
private $favoriteUsers;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255)
*/
private $description;
/** #var Specialty
*
* #ORM\ManyToOne(targetEntity="STInfoSystemBundle\Entity\Specialty", inversedBy="files")
*/
private $specialty;
public function __construct()
{
$this->favoriteUsers = new ArrayCollection();
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
FileUploadRepository:
/**
* FileUploadRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class FileUploadRepository extends \Doctrine\ORM\EntityRepository
{
/**
* #param $userId
* #return \Doctrine\ORM\Query
*/
public function findUserMaterialsQuery($user)
{
return $this->createQueryBuilder('m')
->andWhere('m.user = :user')
->setParameter('user', $user)
->getQuery();
}
/**
* #param int $page
* #param $user
* #return Pagerfanta
*/
public function findUserMaterials($page = 1,$user){
$paginator = new Pagerfanta(new DoctrineORMAdapter($this->findUserMaterialsQuery($user)), false);
$paginator->setMaxPerPage(FileUpload::FILES_PER_PAGE);
$paginator->setCurrentPage($page);
return $paginator;
}
/**
* #param $specialty
* #return \Doctrine\ORM\Query
*/
public function findUserSpecialtyMaterialsQuery($specialty)
{
return $this->createQueryBuilder('m')
->andWhere('m.specialty = :specialty')
->setParameter('specialty', $specialty)
->getQuery();
}
/**
* #param int $page
* #param $specialty
* #return Pagerfanta
*/
public function findUserSpecialtyMaterials($page = 1,$specialty){
$paginator = new Pagerfanta(new DoctrineORMAdapter($this->findUserSpecialtyMaterialsQuery($specialty)), false);
$paginator->setMaxPerPage(FileUpload::FILES_PER_PAGE);
$paginator->setCurrentPage($page);
return $paginator;
}
}
UserRepository :
class UserRepository extends \Doctrine\ORM\EntityRepository
{
/**
* #param $userId
* #return \Doctrine\ORM\Query
*/
public function findUserFavoriteMaterialsQuery($userId)
{
return $this->createQueryBuilder('u')
->addSelect('u.favoriteFiles')
->andWhere('u.id = :userId')
->setParameter('user', $userId)
->getQuery();
}
/**
* #param int $page
* #param $userId
* #return Pagerfanta
*/
public function findUserFavoriteMaterials($page = 1,$userId){
$paginator = new Pagerfanta(new DoctrineORMAdapter($this->findUserFavoriteMaterialsQuery($userId)), false);
$paginator->setMaxPerPage(3);
$paginator->setCurrentPage($page);
return $paginator;
}
}
materials.html.twig
{% extends 'base.html.twig' %}
{% block main %}
<h4>Favorite/My materials/All materials</h4>
{% for material in materials %}
<div class="col-sm-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{ material.title }}</h3>
</div>
<div class="panel-body">
{{ material.shortDescription }}
<hr>
Read
<br>
<a href="{{ path("toggle_favorite", {id: material.id}) }}" class="">
{% if material.favorite(app.user) %}
Remove from favorites
{% else %}
Add to favorites
{% endif %}
</a>
<br>
{% if app.user.isTeacher %}
Edit/delete - TO BE DONE
{% endif %}
</div>
<div class="panel-footer">
{{ material.specialty }}
{#TODO: pagination#}
</div>
</div>
</div>
{% endfor %}
<div class="col-sm-12">
{% if materials.haveToPaginate %}
<div class="navigation text-center">
{#{{ pagerfanta(events, 'twitter_bootstrap3_translated') }}#}
{{ pagerfanta(materials, 'twitter_bootstrap3_translated', { routeName: routeName }) }}
</div>
{% endif %}
</div>
{% endblock %}
and here is the part of MaterialController which is working ok:
/**
* #Route("/materials", defaults={"page": "1"}, name="materials")
* #Route("/materials/page/{page}", requirements={"page": "[1-9]\d*"}, name="materials_paginated")
*
*/
public function allMaterials($page)
{
/** #var User $user */
$user = $this->getUser();
$userSpecialty = $user->getUserDetails()->getSpecialty();
// $allMaterials = $this->getDoctrine()->getRepository(FileUpload::class)->findBy([
// 'specialty' => $user->getUserDetails()->getSpecialty()
// ]);
$allMaterials = $this->getDoctrine()->getRepository(FileUpload::class)->findUserSpecialtyMaterials($page, $userSpecialty);
$routeName = 'materials_paginated';
return $this->render('material/materials.html.twig', [
'materials' => $allMaterials,
'routeName' => $routeName
]
);
}
/**
* #Route("/myMaterials", defaults={"page": "1"}, name="my_materials")
* #Route("/myMaterials/page/{page}", requirements={"page": "[1-9]\d*"}, name="my_materials_paginated")
*/
public function myMaterials($page)
{
/** #var User $user */
$user = $this->getUser();
// $myMaterials = $user->getFiles();
$myMaterials = $this->getDoctrine()->getRepository(FileUpload::class)->findUserMaterials($page, $user);
$routeName = 'my_materials_paginated';
return $this->render('material/materials.html.twig', [
'materials' => $myMaterials,
'routeName' => $routeName
]
);
}
but the below is not getting me anything:
/**
* #Route("/favoriteMaterials", defaults={"page": "1"}, name="favorite_materials")
* #Route("/favoriteMaterials/page/{page}", requirements={"page": "[1-9]\d*"}, name="favorite_materials_paginated")
*
*/
public function favoriteMaterials($page)
{
/** #var User $user */
$user = $this->getUser();
// $favoriteMaterials = $user->getFavoriteFiles();
$favoriteMaterials = $this->getDoctrine()->getRepository(User::class)->findUserFavoriteMaterials($page, $user->getId());
$routeName = 'favorite_materials_paginated';
return $this->render('material/materials.html.twig',[
'materials' => $favoriteMaterials,
'routeName' => $routeName
]
);
}
So how to use the same twig template for myMaterials, allMaterials, favoriteMaterials and get the paginate working ?

I have found the solution. Added these to FileUploadRepository
/**
* #param $user
* #return \Doctrine\ORM\Query
*/
public function findUserFavoriteMaterialsQuery($user)
{
return $this->createQueryBuilder('f')
->andWhere(':user MEMBER OF f.favoriteUsers')
->setParameter('user', $user)
->getQuery();
}
/**
* #param int $page
* #param $user
* #param int $perPage
* #return Pagerfanta
*/
public function findUserFavoriteMaterials($page = 1, $user, $perPage = FileUpload::FILES_PER_PAGE)
{
$paginator = new Pagerfanta(new DoctrineORMAdapter($this->findUserFavoriteMaterialsQuery($user)));
$paginator->setMaxPerPage($perPage);
$paginator->setCurrentPage($page);
return $paginator;
}
Then in my MaterialController I have used it like this:
/** #var User $user */
$user = $this->getUser();
$favoriteMaterials = $this->getDoctrine()->getRepository(FileUpload::class)->findUserFavoriteMaterials($page, $user);
$routeName = 'favorite_materials_paginated';
$title = 'Favorite materials';
return $this->render('material/materials.html.twig', [
'materials' => $favoriteMaterials,
'routeName' => $routeName,
'title' => $title
]
);

Related

failed to send activation message with Mythauth

I am using myth auth to signup my website, in localhost its work but when hosting, send activation to email always display error "failed to send activation message", can anyone help me?
do it like me
/**
* Resend activation account.
* #param AuthEntity $entity
*/
public
function sendActivateCodeViaEmail(AuthEntity $entity): void
{
if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_NOT_ACCEPTABLE);
$findUser = $this->userModel->where('email', $entity->email)
->where('active', 0)
->first();
if (is_null($findUser)) $this->httpException(lang('Auth.activationNoUser'), ResponseInterface::HTTP_CONFLICT);
$isSent = $this->email
->setTo($entity->email)
->setSubject(lang('Auth.activationSubject'))
->setMessage(view($this->authConfig->views['emailActivation'],
['hash' => $entity->toArray()['activate_hash']]))
->setMailType('html')->send();
if (!$isSent) {
$this->httpException(lang('Auth.unknownError'),
ResponseInterface::HTTP_BAD_REQUEST, $this->email->printDebugger(['headers']['headers'] ?? lang('Auth.unknownError')));
}
unset($entity->email);
if (!$this->userModel->update($findUser->id, $entity)) {
$this->httpException(lang('Shared.api.reject'), ResponseInterface::HTTP_BAD_REQUEST, serializeMessages($this->userModel->errors()));
}
}
email config
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
class Email extends BaseConfig
{
/**
* #var string
*/
public $fromEmail='admin#emaple.ir';
/**
* #var string
*/
public $fromName='admin';
/**
* #var string
*/
public $recipients;
/**
* The "user agent"
*
* #var string
*/
public $userAgent = 'CodeIgniter';
/**
* The mail sending protocol: mail, sendmail, smtp
*
* #var string
*/
public $protocol = 'smtp';
/**
* The server path to Sendmail.
*
* #var string
*/
public $mailPath = '/usr/sbin/sendmail';
/**
* SMTP Server Address
*
* #var string
*/
public $SMTPHost='mail.emaple.ir';
/**
* SMTP Username
*
* #var string
*/
public $SMTPUser='admin#emaile.ir';
/**
* SMTP Password
*
* #var string
*/
public $SMTPPass='X04r0U2ikd';
/**
* SMTP Port
*
* #var int
*/
public $SMTPPort = 25;
/**
* SMTP Timeout (in seconds)
*
* #var int
*/
public $SMTPTimeout = 5;
/**
* Enable persistent SMTP connections
*
* #var bool
*/
public $SMTPKeepAlive = false;
/**
* SMTP Encryption. Either tls or ssl
*
* #var string
*/
public $SMTPCrypto = '';
/**
* Enable word-wrap
*
* #var bool
*/
public $wordWrap = true;
/**
* Character count to wrap at
*
* #var int
*/
public $wrapChars = 76;
/**
* Type of mail, either 'text' or 'html'
*
* #var string
*/
public $mailType = 'text';
/**
* Character set (utf-8, iso-8859-1, etc.)
*
* #var string
*/
public $charset = 'UTF-8';
/**
* Whether to validate the email address
*
* #var bool
*/
public $validate = false;
/**
* Email Priority. 1 = highest. 5 = lowest. 3 = normal
*
* #var int
*/
public $priority = 3;
/**
* Newline character. (Use “\r\n” to comply with RFC 822)
*
* #var string
*/
public $CRLF = "\r\n";
/**
* Newline character. (Use “\r\n” to comply with RFC 822)
*
* #var string
*/
public $newline = "\r\n";
/**
* Enable BCC Batch Mode.
*
* #var bool
*/
public $BCCBatchMode = false;
/**
* Number of emails in each BCC batch
*
* #var int
*/
public $BCCBatchSize = 200;
/**
* Enable notify message from server
*
* #var bool
*/
public $DSN = false;
}

Call to a member function format() on string symfony 3.4

I'm trying to register a new appointment in my database, after sending an email, but it shows me an error: Call to a member function format() on string,
in vendor\doctrine\dbal\lib\Doctrine\DBAL\Types\DateTimeType.php
,
because in the booking entity, there is the date and time I need to register which are datetime types.
Here is the booking entity :
<?php
namespace Doctix\FrontBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Booking
*
* #ORM\Table(name="booking")
*
class Booking
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \DateTime
*
*#ORM\Column(name="date_rdv", type="datetime", nullable=true)
*/
private $dateRdv;
/**
* #var \DateTime
*
*#ORM\Column(name="heure_rdv", type="datetime", nullable=true)
*/
private $heureRdv;
/**
* #var bool
*
*#ORM\Column(name="valider_rdv", type="boolean", nullable=true)
*/
private $validerRdv;
/**
* #ORM\ManyToOne(targetEntity="Doctix\MedecinBundle\Entity\Medecin")
* #ORM\JoinColumn(nullable=true)
*/
private $medecin;
/**
* #ORM\ManyToOne(targetEntity="Doctix\PatientBundle\Entity\Patient")
* #ORM\JoinColumn(nullable=true)
*/
private $patient;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set dateRdv
*
* #param \DateTime $dateRdv
*
* #return Booking
*/
public function setDateRdv($dateRdv)
{
$this->dateRdv = $dateRdv;
return $this;
}
/**
* Get dateRdv
*
* #return \DateTime
*/
public function getDateRdv()
{
return $this->dateRdv;
}
/**
* Set heureRdv
*
* #param \DateTime $heureRdv
*
* #return Booking
*/
public function setHeureRdv($heureRdv)
{
$this->heureRdv = $heureRdv;
return $this;
}
/**
* Get heureRdv
*
* #return \DateTime
*/
public function getHeureRdv()
{
return $this->heureRdv;
}
/**
* Set validerRdv
*
* #param boolean $validerRdv
*
* #return Booking
*/
public function setValiderRdv($validerRdv)
{
$this->validerRdv = $validerRdv;
return $this;
}
/**
* Get validerRdv
*
* #return bool
*/
public function getValiderRdv()
{
return $this->validerRdv;
}
/**
* Set medecin
*
* #param \Doctix\MedecinBundle\Entity\Medecin $medecin
* #return Booking
*/
public function setMedecin(\Doctix\MedecinBundle\Entity\Medecin $medecin)
{
$this->medecin = $medecin;
return $this;
}
/**
* Get medecin
*
* #return \Doctix\MedecinBundle\Entity\Medecin
*/
public function getMedecin()
{
return $this->medecin;
}
/**
* Set patient
*
* #param \Doctix\PatientBundle\Entity\Patient $patient
* #return Booking
*/
public function setPatient(\Doctix\PatientBundle\Entity\Patient $patient)
{
$this->patient = $patient;
return $this;
}
/**
* Get patient
*
* #return \Doctix\PatientBundle\Entity\Patient
*/
public function getPatient()
{
return $this->patient;
}
}
Here is the controller:
public function patientHandleBookingAction(Request $request){
$id = $request->query->get('id');
$date = $request->query->get('date');
$time = $request->query->get('time');
// $user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$repoPatient = $em->getRepository('DoctixPatientBundle:Patient');
$patient = $repoPatient->findOneBy(array(
'user' => $this->getUser()
));
$repoMedecin = $em->getRepository('DoctixMedecinBundle:Medecin');
$medecin = $repoMedecin->findOneBy(array(
'id' => $request->query->get("idMedecin")));
$mailer = $this->get('mailer');
$message = (new \Swift_Message('Email de Confirmaton'))
->setFrom("medmamtest#gmail.com")
->setTo($patient->getUser()->getUsername())
->setBody(
$this->renderView(
// app/Resources/views/Emails/registration.html.twig
'Emails/registration.html.twig',
array('name' => 'mam')
),
'text/html'
);
$mailer->send($message);
if($mailer){
$booking = new Booking();
$booking->setMedecin($medecin);
$booking->setPatient($patient);
$booking->setDateRdv('date');
$booking->setHeureRdv('time');
$booking->setValiderRdv(0);
}
$em->persist($booking);
$em->flush();
// A remplacer par un contenu plus approprié
return $this->render('DoctixPatientBundle:Patient:confirm.html.twig',array(
'time' => $request->query->get("time"),
'date' => $request->query->get("date"),
'medecin' => $medecin,
'patient' => $patient,
// 'date' => $date,
// 'time' => $time
));
}
Thanks
This error is happening because you are trying to set the date and time as strings on your booking entity.
$booking->setDateRdv('date');
$booking->setHeureRdv('time');
Try to change it to:
$booking->setDateRdv(new \DateTime($date));
$booking->setHeureRdv(new \DateTime($time));

Symfony2 - Using controller security for user and category

I am trying to restrict user access from accessing the CRUD access in the controller.
I have a bi-directional OneToOne relationship with User and Category. It's setup to only allow 1 user to be able to access 1 blog.
I am testing this by logging in as another user that is not related to this category. And upon clicking on new, the form loads by-passing any security I have setup.
Speculating that the problem is with the $title parameter being passed in, (trying to pass this in as the route variable) as I don't think I'm setting this up correctly.
Can someone guide me on what I'm doing wrong?
Controller code
/**
* Post controller.
*
* #Route("/category")
*/
/**
* Creates a new Post entity.
*
* #Route("/", name="category_create")
* #Method("POST")
* #Template("AcmeDemoBundle:Page:new.html.twig")
*/
public function createAction(Request $request, $title)
{
// User security
$em = $this->getDoctrine()->getManager();
$categoryRepository = $em->getRepository('AcmeDemoBundle:Category');
$category = $categoryRepository->findOneBy(array(
'title' => '$title',
));
$owner = $category->getUser();
$currentUser = $this->get('security.context')->getToken()->getUser();
if ($owner != $currentUser) {
throw new AccessDeniedException('You do not have access for this');
}
// Form creation
$post = new Post();
$form = $this->createCreateForm($post);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($post);
$em->flush();
return $this->redirect($this->generateUrl('category_show', array('id' => $post->getId())));
}
return array(
'post' => $post,
'form' => $form->createView(),
);
}
Category entity
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #Gedmo\Slug(fields={"title"}, unique=false)
* #ORM\Column(length=255)
*/
private $catslug;
/**
* #ORM\OneToMany(targetEntity="Post", mappedBy="category")
*/
protected $posts;
/**
* #ORM\OneToOne(targetEntity="Acme\DemoBundle\Entity\User", inversedBy="cat")
* #ORM\JoinColumn(name="cat_id", referencedColumnName="id")
*/
protected $user;
User entity
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=255)
* #Assert\NotBlank(message="Field cannot be blank")
*/
private $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
/**
* #ORM\Column(type="string", length=255)
* #Assert\NotBlank()
*/
private $email;
/**
* #ORM\Column(type="json_array")
*/
private $roles = array();
/**
* #var bool
*
* #ORM\Column(type="boolean")
*/
private $isActive = true;
/**
* #Assert\NotBlank
* #Assert\Regex(
* pattern="/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s).*$/",
* message="Use 1 upper case letter, 1 lower case letter, and 1 number")
*/
private $plainPassword;
/**
* #ORM\OneToOne(targetEntity="Acme\DemoBundle\Entity\Category", mappedBy="user")
*/
private $cat;
You can try to create own Security Voter to check if user has a permission to this action. Sample code:
class CategoryVoter implements VoterInterface
{
const CREATE = 'create';
/**
* #param string $attribute
* #return bool
*/
public function supportsAttribute($attribute)
{
return in_array($attribute, [
self::CREATE
]);
}
/**
* #param string $class
* #return bool
*/
public function supportsClass($class)
{
$supportedClass = 'Acme\DemoBundle\Entity\Category';
return $supportedClass === $class || is_subclass_of($class, $supportedClass);
}
/**
* #param TokenInterface $token
* #param object $blog
* #param array $attributes
* #return int
*/
public function vote(TokenInterface $token, Category $category, array $attributes)
{
....
$attribute = $attributes[0];
$user = $token->getUser();
switch($attribute) {
case 'create':
if ($user->getId() === $category->getUser()->getId()) {
return VoterInterface::ACCESS_GRANTED;
}
break;
....
}
...
}
}
create action:
public function createAction(Request $request, $title)
{
$em = $this->getDoctrine()->getManager();
$categoryRepository = $em->getRepository('AcmeDemoBundle:Category');
$category = $categoryRepository->findOneBy([
'title' => '$title',
]);
...
if (false === $this->get('security.context')->isGranted('create', $category)) {
throw new AccessDeniedException('Unauthorised access!');
}
...
}

Symfony 2.3 Bad Credentials Custom provider

I'm completely lost at the moment, two days that I try to figure why I always obtain a "Bad Credential" response on my login form.
I've used the How to load Security Users from the Database tutorial.
Is there any way to know what he's comparing to get that "bad credentials" error ?
The dumped error :
exception 'Symfony\Component\Security\Core\Exception\BadCredentialsException' with message 'Bad credentials' in D:\dev\workspace\esig_grandprojet\vendor\symfony\symfony\src\Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider.php:89 Stack trace:
#0 D:\dev\workspace\esig_grandprojet\app\cache\dev\classes.php(107): session_start()
#1 D:\dev\workspace\esig_grandprojet\app\cache\dev\classes.php(184): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->start()
#2 D:\dev\workspace\esig_grandprojet\app\cache\dev\classes.php(482): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->getBag('attributes')
#3 D:\dev\workspace\esig_grandprojet\src\ESIG\BBC\ManagerCP2Bundle\Controller\SecurityController.php(45): Symfony\Component\HttpFoundation\Session\Session->get('_security.last_...')
#4 [internal function]: ESIG\BBC\ManagerCP2Bundle\Controller\SecurityController->loginAction()
#5 D:\dev\workspace\esig_grandprojet\app\bootstrap.php.cache(2844): call_user_func_array(Array, Array)
#6 D:\dev\workspace\esig_grandprojet\app\bootstrap.php.cache(2818): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#7 D:\dev\workspace\esig_grandprojet\app\bootstrap.php.cache(2947): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#8 D:\dev\workspace\esig_grandprojet\app\bootstrap.php.cache(2249): Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#9 D:\dev\workspace\esig_grandprojet\web\app_dev.php(28): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#10 {main}
Here are my files :
my security.yml :
security:
encoders:
ESIG\BBC\ManagerCP2Bundle\Entity\Utilisateur:
algorithm: sha512
encode_as_base64: true
iterations: 5000
providers:
users:
entity: { class: ESIGBBCManagerCP2Bundle:Utilisateur }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login$
security: false
main:
pattern: /.*
form_login:
# The user is redirected here when he needs to login
login_path: _security_login
#if true, forward the user to the login form instead of redirecting
use_forward: false
# submit the login form here
check_path: _security_check
# by default, the login form *must* be a POST, not a GET
post_only: true
# login success redirecting options
always_use_default_target_path: true
default_target_path: /
target_path_parameter: _target_path
use_referer: false
# login failure redirecting options
failure_path: null
failure_forward: false
# field names for the username and password fields
username_parameter: _username
password_parameter: _password
#csrf token options
csrf_parameter: _csrf_token
intention: authenticate
logout: true
security: true
anonymous: true
remember_me:
key: "%secret%"
lifetime: 3600
path: /
domain: ~ #Default to the current domain from $_SERVER
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /.*, roles: IS_AUTHENTICATED_REMEMBERED }
#- { path: ^/demo/secured/hello/admin/, roles: ROLE_ADMIN }
#- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
my user entity :
<?php
namespace ESIG\BBC\ManagerCP2Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* Utilisateur
*
* #ORM\Table(name="mcp2_utilisateur")
* #ORM\Entity(repositoryClass="ESIG\BBC\ManagerCP2Bundle\Entity\UtilisateurRepository")
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="uti_discr", type="string")
* #ORM\DiscriminatorMap({"utilisateur" = "Utilisateur", "pompier" = "Pompier"})
*
* #UniqueEntity(fields="username", message="error.input.unique.user")
* #UniqueEntity(fields="email", message="error.input.unique.mail")
*/
class Utilisateur implements AdvancedUserInterface, \Serializable
{
/**
* #var integer
*
* #ORM\Column(name="uti_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="uti_nom_utilisateur", type="string", length=50, unique=true)
* #Assert\NotBlank(message="error.input.blank")
*/
private $username;
/**
* #ORM\Column(name="uti_salt", type="string", length=255)
*/
private $salt;
/**
* #var string
*
* #ORM\Column(name="uti_mot_de_passe", type="string", length=255)
* #Assert\NotBlank(message="error.input.blank")
*/
private $password;
/**
* #var string
*
* #ORM\Column(name="uti_email", type="string", length=100, unique=true)
* #Assert\NotBlank(message="error.input.blank")
* #Assert\Email(message="error.input.invalid.mail")
*/
private $email;
/**
* #var boolean
*
* #ORM\Column(name="uti_is_active", type="boolean")
* #Assert\NotBlank(message="error.input.blank")
*/
private $isActive;
/**
* #var boolean
*
* #ORM\Column(name="uti_mot_de_passe_expire", type="boolean")
* #Assert\NotBlank(message="error.input.blank")
*/
private $motDePasseExpire;
/**
* #var string
*
* #ORM\Column(name="uti_nom", type="string", length=50)
* #Assert\NotBlank(message="error.input.blank")
*/
private $nom;
/**
* #var string
*
* #ORM\Column(name="uti_prenom", type="string", length=50)
* #Assert\NotBlank(message="error.input.blank")
*/
private $prenom;
/**
* #var string
*
* #ORM\Column(name="uti_adresse", type="text")
* #Assert\NotBlank(message="error.input.blank")
*/
private $adresse;
/**
* #var string
*
* #ORM\Column(name="uti_telephone", type="string", length=13)
* #Assert\NotBlank(message="error.input.blank")
*/
private $telephone;
/**
* #var boolean
*
* #ORM\Column(name="uti_date_derniere_connexion", type="boolean", nullable=true)
*/
private $dateDerniereConnexion;
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="GroupeAutorisation", inversedBy="utilisateurs")
* #ORM\JoinTable(name="mcp2_associe",
* joinColumns={#ORM\JoinColumn(name="ass_uti_id", referencedColumnName="uti_id")},
* inverseJoinColumns={#ORM\JoinColumn(name="ass_gra_id", referencedColumnName="gra_id")}
* )
*/
private $groupesAutorisation;
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="Notification", mappedBy="utilisateur", cascade={"persist", "remove"})
*/
private $notifications;
public function __construct() {
$this->isActive = True;
$this->salt = md5(uniqid(null, true));
$this->groupesAutorisation = new \Doctrine\Common\Collections\ArrayCollection();
$this->notifications = new \Doctrine\Common\Collections\ArrayCollection();
$this->motDePasseExpire = False;
}
/**
* Returns the username used to authenticate the user.
*
* #return string The username
*/
public function getUsername() {
return $this->username;
}
public function getSalt() {
//return $this->salt;
return null;
}
public function getPassword() {
$this->password;
}
public function getRoles() {
// special
//return $this->groupesAutorisation->toArray();
return array('ROLE_USER');
}
public function equals(UserInterface $user)
{
/*
if (!$account instanceof Account) {
return false;
}
if($this->password !== $user->getPassword()) {
return false;
}
if($this->getSalt() !== $user->getSalt()) {
return false;
}
if($this->getUsername() !== $user->getUsername()) {
return false;
}
return true; */
return md5($this->getUsername()) == md5($user->getUsername());
}
/**
* Removes sensitive data from the user.
*
* This is important if, at any given point, sensitive information like
* the plain-text password is stored on this object.
*/
public function eraseCredentials() {
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
return serialize(array(
$this->id,
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
) = unserialize($serialized);
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
* #return Utilisateur
*/
public function setUsername($nomUtilisateur)
{
$this->username = $nomUtilisateur;
return $this;
}
/**
* Set motDePasse
*
* #param string $motDePasse
* #return Utilisateur
*/
public function setPassword($motDePasse)
{
$this->password = $motDePasse;
return $this;
}
/**
* Set email
*
* #param string $email
* #return Utilisateur
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Get groupes
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getGroupes()
{
return $this->groupes;
}
/**
* Add notifications
*
* #param \ESIG\BBC\ManagerCP2Bundle\Entity\Notification $notifications
* #return Utilisateur
*/
public function addNotification(\ESIG\BBC\ManagerCP2Bundle\Entity\Notification $notifications)
{
$this->notifications[] = $notifications;
return $this;
}
/**
* Add groupesAutorisation
*
* #param \ESIG\BBC\ManagerCP2Bundle\Entity\GroupeAutorisation $groupesAutorisation
* #return Utilisateur
*/
public function addGroupesAutorisation(\ESIG\BBC\ManagerCP2Bundle\Entity\GroupeAutorisation $groupesAutorisation)
{
$this->groupesAutorisation[] = $groupesAutorisation;
return $this;
}
/**
* Remove groupesAutorisation
*
* #param \ESIG\BBC\ManagerCP2Bundle\Entity\GroupeAutorisation $groupesAutorisation
*/
public function removeGroupesAutorisation(\ESIG\BBC\ManagerCP2Bundle\Entity\GroupeAutorisation $groupesAutorisation)
{
$this->groupesAutorisation->removeElement($groupesAutorisation);
}
/**
* Get groupesAutorisation
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getGroupesAutorisation()
{
return $this->groupesAutorisation;
}
/**
* Set salt
*
* #param string $salt
* #return Utilisateur
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
/**
* Set isActive
*
* #param boolean $isActive
* #return Utilisateur
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
/**
* Get isActive
*
* #return boolean
*/
public function isActive()
{
return $this->isActive;
}
}
(The getSalt return "null" just to be sure he's not involved in my problem)
my user repository :
<?php
namespace ESIG\BBC\ManagerCP2Bundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NoResultException;
use ESIG\BBC\ManagerCP2Bundle\Entity\Notification;
/**
* UtilisateurRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class UtilisateurRepository extends EntityRepository implements UserProviderInterface
{
public function loadUserByUsername($username)
{
$q = $this
->createQueryBuilder('u')
->where('u.username = :username OR u.email = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery();
try {
// La méthode Query::getSingleResult() lance une exception
// s'il n'y a pas d'entrée correspondante aux critères
$user = $q->getSingleResult();
} catch (NoResultException $e) {
throw new UsernameNotFoundException(sprintf('Unable to find an active admin AcmeUserBundle:User object identified by "%s".', $username), 0, $e);
}
return $user;
}
public function refreshUser(UserInterface $user)
{
$class = get_class($user);
if (!$this->supportsClass($class)) {
throw new UnsupportedUserException(
sprintf(
'Instances of "%s" are not supported.',
$class
)
);
}
return $this->find($user->getId());
}
public function supportsClass($class)
{
return $this->getEntityName() === $class || is_subclass_of($class, $this->getEntityName());
}
}
my SecurityController :
<?php
namespace ESIG\BBC\ManagerCP2Bundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Security\Core\SecurityContext;
class SecurityController extends Controller
{
/**
* #Template("ESIGBBCManagerCP2Bundle::menu.html.twig")
*/
public function GenerateMenuAction()
{
return array();
}
/**
* #Route("/login", name="_security_login")
* #Template("ESIGBBCManagerCP2Bundle:Security:login.html.twig")
*/
public function loginAction()
{
$request = $this->getRequest();
$session = $request->getSession();
// Récupère l'erreur de login si il y en a une
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $session->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} else {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
return array(
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error
);
}
/**
* #Route("/login_check", name="_security_check")
* #Template("ESIGBBCManagerCP2Bundle:Security:login.html.twig")
*/
public function securityCheckAction()
{
}
/**
* #Route("/logout", name="_security_logout")
* #Template("ESIGBBCManagerCP2Bundle:Security:login.html.twig")
*/
public function logoutAction()
{
return array();
}
}
my loginform template :
{% extends "ESIGBBCManagerCP2Bundle::ManagerCP2.html.twig" %}
{% block right %}
{{ error }}
{% if error %}
<div>{{ error.message }}</div>
{% endif %}
{{ test }}
<form action="{{ path('_security_check') }}" method="post">
<label for="username">Login :</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" title="{{ "login.mail.title" | trans }}" /><br />
<label for="password" >Mot de passe :</label>
<input type="password" id="password" name="_password" title="{{ "login.password.title" | trans }}" /><br />
<input type="checkbox" id="remember_me" name="_remember_me" title="{{ "login.rememberme.title" | trans }}" checked /> <label for="remember_me" >Se souvenir de moi</label><br />
{#
Si vous voulez contrôler l'URL vers laquelle l'utilisateur est redirigé en cas de succès
(plus de détails ci-dessous)
<input type="hidden" name="_target_path" value="/account" />
#}
<button type="submit" name="login" title="{{ "login.submit.title" | trans }}">{{ "login.submit.value" | trans }}</button>
</form>
{% endblock %}
and finally : my fixture
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace ESIG\BBC\ManagerCP2Bundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use ESIG\BBC\ManagerCP2Bundle\Entity\Pompier;
use ESIG\BBC\ManagerCP2Bundle\Entity\Utilisateur;
use \Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
/**
* Description of LoadUserData
*
* #author noirv_000
*/
class LoadUserData implements FixtureInterface
{
public function load(ObjectManager $manager)
{
$pwd_encoder = new MessageDigestPasswordEncoder('sha512', true, 5000);
// Super Administrateur
$superAdmin = new Utilisateur();
$superAdmin->setNom("Admin")
->setPrenom("Super")
->setUsername("super.admin")
->setEmail("super#admin.foo")
->setPassword($pwd_encoder->encodePassword("12345678", $superAdmin->getSalt()))
->setAdresse("Chemin de l'administration")
->setTelephone("0041000000000");
$manager->persist($superAdmin);
// Enregistre toutes les nouvelles entrées
$manager->flush();
}
}
Please, save me T_T
First check how UserAuthenticationProvider tring encode your password and compare it with generated by datafixtures
Try this :
$pwd_encoder = new EncoderFactory(array('Symfony\Component\Security\Core\User\UserInterface' => new MessageDigestPasswordEncoder('sha1',true,500)));
// Super Administrateur
$superAdmin = new Utilisateur();
$superAdmin->setNom("Admin")
->setPrenom("Super")
->setUsername("super.admin")
->setEmail("super#admin.foo")
->setPassword($pwd_encoder->getEncoder($superAdmin)->encodePassword("12345678", $superAdmin->getSalt()))
->setAdresse("Chemin de l'administration")
->setTelephone("0041000000000");

symfony2 can't login “Bad credentials”

I am writing a website using the Symfony framework but for some reason, the login process is not working.
I always get message: Bad credentials
Here is my security.yml
# app/config/security.yml
jms_security_extra:
secure_all_services: false
expressions: true
security:
firewalls:
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: /login
check_path: /login_check
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
contant_manager: { password: manpass, roles: [ 'ROLE_CONTENT_MANAGER' ] }
admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
encoders:
Symfony\Component\Security\Core\User\User: plaintext
My User.php class
<?php
namespace YouMustKnowIt\NewsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Doctrine\Common\Collections\ArrayCollection;
use APY\DataGridBundle\Grid\Mapping as GRID;
/**
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="\YouMustKnowIt\NewsBundle\Entity\UserRepository")
*
* #GRID\Source(columns="id, username, email, role.name, isActive")
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*
* #GRID\Column(filterable=false)
*/
private $id;
/**
* #ORM\Column(type="string", length=25, unique=true)
*/
private $username;
/**
* #ORM\Column(type="string", length=32)
*/
private $salt;
/**
* #ORM\Column(type="string", length=100)
*/
private $password;
/**
* #ORM\Column(type="string", length=60, unique=true)
*/
private $email;
/**
* #ORM\ManyToMany(targetEntity="RolesList", inversedBy="users")
*
* #GRID\Column(field="roleslist.role", type="text", filter="select", title="role")
*/
private $role;
/**
* #ORM\OneToMany(targetEntity="NewsCatalog", mappedBy="user")
* #ORM\Column(name="created_news", nullable=true)
*/
private $createdNews;
/**
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
public function __construct()
{
$this->isActive = false;
$this->salt = md5(uniqid(null, true));
$this->role = new \Doctrine\Common\Collections\ArrayCollection();
$this->createdNews = new \Doctrine\Common\Collections\ArrayCollection();
}
public function __toString()
{
return $this->username;
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
/**
* #inheritDoc
*/
public function getRoles()
{
return $this->role->toArray();
}
/**
* #inheritDoc
*/
public function getUsername()
{
return $this->username;
}
/**
* #inheritDoc
*/
public function getSalt()
{
return $this->salt;
}
/**
* #inheritDoc
*/
public function getPassword()
{
return $this->password;
}
/**
* #inheritDoc
*/
public function getEmail()
{
return $this->email;
}
/**
* #inheritDoc
*/
public function eraseCredentials()
{
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
return serialize(array(
$this->id,
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
) = unserialize($serialized);
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Set salt
*
* #param string $salt
* #return User
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
/**
* Set password
*
* #param string $password
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set email
*
* #param string $email
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Set isActive
*
* #param boolean $isActive
* #return User
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
/**
* Get isActive
*
* #return boolean
*/
public function getIsActive()
{
return $this->isActive;
}
/**
* Add role
*
* #param \YouMustKnowIt\NewsBundle\Entity\RolesList $role
* #return User
*/
public function addRole(\YouMustKnowIt\NewsBundle\Entity\RolesList $role)
{
$this->role[] = $role;
return $this;
}
/**
* Remove role
*
* #param \YouMustKnowIt\NewsBundle\Entity\RolesList $role
*/
public function removeRole(\YouMustKnowIt\NewsBundle\Entity\RolesList $role)
{
$this->role->removeElement($role);
}
/**
* Add createdNews
*
* #param \YouMustKnowIt\NewsBundle\Entity\NewsCatalog $createdNews
* #return User
*/
public function addCreatedNews(\YouMustKnowIt\NewsBundle\Entity\NewsCatalog $createdNews)
{
$this->createdNews[] = $createdNews;
return $this;
}
/**
* Remove createdNews
*
* #param \YouMustKnowIt\NewsBundle\Entity\NewsCatalog $createdNews
*/
public function removeCreatedNews(\YouMustKnowIt\NewsBundle\Entity\NewsCatalog $createdNews)
{
$this->createdNews->removeElement($createdNews);
}
/**
* Get createdNews
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCreatedNews()
{
return $this->createdNews;
}
/**
* Get role
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getRole()
{
return $this->role;
}
}
My UserRepository.php class
<?php
namespace YouMustKnowIt\NewsBundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NoResultException;
class UserRepository extends EntityRepository implements UserProviderInterface
{
public function loadUserByUsername($username)
{
$q = $this
->createQueryBuilder('u')
->select('u, g')
->leftJoin('u.groups', 'g')
->where('u.username = :username OR u.email = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery();
try {
$user = $q->getSingleResult();
} catch (NoResultException $e) {
$message = sprintf(
'Unable to find an active admin User object identified by "%s".',
$username
);
throw new UsernameNotFoundException($message, 0, $e);
}
return $user;
}
public function refreshUser(UserInterface $user)
{
$class = get_class($user);
if (!$this->supportsClass($class)) {
throw new UnsupportedUserException(
sprintf(
'Instances of "%s" are not supported.',
$class
)
);
}
return $this->find($user->getId());
}
public function supportsClass($class)
{
return $this->getEntityName() === $class
|| is_subclass_of($class, $this->getEntityName());
}
public function findAll()
{
return $this->createQueryBuilder('u');
}
}
SecurityController.php
<?php
namespace YouMustKnowIt\NewsBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\SecurityContext;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use YouMustKnowIt\NewsBundle\Entity\User;
class SecurityController extends Controller
{
/**
* #Route("/login", name="login")
*/
public function loginAction()
{
$request = $this->getRequest();
$session = $request->getSession();
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(
SecurityContext::AUTHENTICATION_ERROR
);
} else {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
return $this->render(
'YouMustKnowItNewsBundle:User:login.html.twig',
array(
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
)
);
}
/**
* #Route("/login_check", name="login_check")
*/
public function loginCheckAction()
{
}
/**
* #Route("/logout", name="logout")
*/
public function logoutAction()
{
}
/**
* #Route("/recover_pass", name="recover_pass")
*/
public function recoverPasswordAction(Request $request)
{
$data = array();
$form = $this->createFormBuilder($data)
->add('email', 'email')
->getForm();
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$data = $form->getData();
$user = $this->getDoctrine()
->getRepository('YouMustKnowItNewsBundle:User')
->findOneByEmail($data['email']);
if (isset($user)) {
$this->createNewPassword($user);
return $this->redirect($this->generateUrl('homepage'));
} else {
$this->get('session')->getFlashbag()->add(
'error_message',
'The user with such email doesn\'t exist.'
);
}
}
}
return $this->render('YouMustKnowItNewsBundle:Default:recoverPass.html.twig', array(
'form' => $form->createView()
));
}
private function sendEmail(User $user)
{
$message = \Swift_Message::newInstance()
->setSubject('YouMustKnowIt! Password restoration.')
->setFrom('php.gr2#gmail.com')
->setTo($user->getEmail())
->setBody('Your new password: ' . $user->getPassword());
$this->get('mailer')->send($message);
}
private function generatePassword($length = 7)
{
$num = range(0, 9);
$alf = range('a', 'z');
$_alf = range('A', 'Z');
$symbols = array_merge($num, $alf, $_alf);
shuffle($symbols);
$code_array = array_slice($symbols, 0, $length);
$code = implode("", $code_array);
return $code;
}
private function encodePassword(User $user)
{
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$password = $encoder->encodePassword(
$user->getPassword(),
$user->getSalt()
);
return $password;
}
private function createNewPassword(User $user)
{
$password = $this->generatePassword();
$user->setPassword($password);
$this->sendEmail($user);
$encodedPassword = $this->encodePassword($user);
$user->setPassword($encodedPassword);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($user);
$em->flush();
$this->get('session')->getFlashbag()->add(
'success_message',
'On your email the new password was sent.'
);
}
}
and finally login.html.twig
{% extends '::base.html.twig' %}
{% block body %}
{% if error %}
<div>{{ error.message }}</div>
{% endif %}
<form action="{{ path('login_check') }}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" />
<label for="password">Password:</label>
<input type="password" id="password" name="_password" />
#<input type="hidden" name="_csrf_token" value="/" />
<input type="submit" name="login" />
</form>
{% endblock %}
If you are using an entity that is mapped to a database then your Provider: is missing the correct mapping.
providers:
users:
entity: { class: YouMustKnowItNewsBundle:User, property: username }

Resources