Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FOSUserBundle login with email (Symfony2)

I have a question about the FOSUserBundle for Symfony 2.0.x. In there documentation you can find a way to change the login to work with either username and email. That works great! But I want to login to work with just the email. So I added a function in my CustomUserManager (extends from the original) that makes sure you just can logon with your email.

namespace Frontend\UserBundle\Model;

use FOS\UserBundle\Entity\UserManager;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;

class CustomUserManager extends UserManager
{
    public function loadUserByUsername($email)
    {
        /*$user = $this->findUserByUsernameOrEmail($username);

        if (!$user) {
            throw new UsernameNotFoundException(sprintf('No user with name "%s" was found.', $username));
        }

        return $user;*/

        //Change it to only email (Default calls loadUserByUsername -> we send it to our own loadUserByEmail)
        return $this->loadUserByEmail($email);
    }

    public function loadUserByEmail($email)
    {
        $user = $this->findUserByEmail($email);

        if (!$user) {
            throw new UsernameNotFoundException(sprintf('No user with email "%s" was found.', $email));
        }

        return $user;

    }
}

But now I have a problem that I need to control the values that are saved in the session. He saves my username in the session and when the system checks this there will be no email (Because he only checks on email) available.

So my question is how/where can you change the value that is stored inside the username variable.

Thanks!

like image 981
jeroenjoosen Avatar asked Apr 25 '12 11:04

jeroenjoosen


Video Answer


1 Answers

This can be done by overriding setters in the User entity:

<?php

namespace Acme\UserBundle\Entity;

use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * @ORM\Entity(repositoryClass="Acme\UserBundle\Entity\UserRepository")
 * @ORM\Table(name="users")
 */
class User extends BaseUser
{

    // ...

    // override methods for username and tie them with email field

    /**
     * Sets the email.
     *
     * @param string $email
     * @return User
     */
    public function setEmail($email)
    {
        $this->setUsername($email);

        return parent::setEmail($email);
    }

    /**
     * Set the canonical email.
     *
     * @param string $emailCanonical
     * @return User
     */
    public function setEmailCanonical($emailCanonical)
    {
        $this->setUsernameCanonical($emailCanonical);

        return parent::setEmailCanonical($emailCanonical);
    }

    // ...

}

It's not clear from your question, but from your namespaces I assume that you have your own child bundle that uses FOSUserBundle as its parent bundle (as per FOSUserBundle documentation, example "b").

If you do, you can then easily override Forms and templates in order to remove any username fields from the UI and replace them with email fields. Since you have overridden the email setters as per above, username property will be populated properly.

Although this works, it's not a very nice solution. The downside is that you will still have username and usernameCanonical columns in the database. We originally wanted to remove these altogether, but this would require too many changes in FOSUserBundle (the username attribute is required by \FOS\UserBundle\Model\UserInterface, and bundle code depends on it).

like image 152
MicE Avatar answered Oct 09 '22 03:10

MicE