I get this error 'Must implement UserProviderInterface'
when trying to using the symfony login features. I'm referencing the repository * #ORM\Entity(repositoryClass="Login\LogBundle\Entity\Repository\UserRepository") . Does anyone have any ideas.
Entity
<?php
namespace Login\LogBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
/**
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="Login\LogBundle\Entity\Repository\UserRepository")
* #ORM\HasLifecycleCallbacks()
*/
class User implements UserInterface, \Serializable
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $password;
/**
* #var string
*/
private $name;
/**
* #var string
*/
private $username;
/**
* #ORM\Column(type="string", length=32)
*/
private $salt;
/**
* #ORM\Column(type="string", length=60, unique=true)
*/
private $email;
/**
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
/**
* #OneToMany(targetEntity="userapidetails", mappedBy="user")
*/
public $userapidetails;
public function __construct()
{
$this->userapidetails = new ArrayCollection();
$this->isActive = true;
$this->salt = md5(uniqid(null, true));
}
public function getUserapidetails() {
return $this->userapidetails;
}
// public function setUserapidetails($userapidetails) {
// $this->userapi=$userapidetails;
// return $this;
// }
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set password
*
* #param string $password
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set name
*
* #param string $name
* #return User
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set username
*
* #param string $username
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* #var string
*/
private $isactive;
/**
* Set email
*
* #param string $email
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set salt
*
* #param string $salt
* #return User
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
/**
* Get salt
*
* #return string
*/
public function getSalt()
{
return $this->salt;
}
/**
* Set isactive
*
* #param string $isactive
* #return User
*/
public function setIsactive($isactive)
{
$this->isactive = $isactive;
return $this;
}
/**
* Get isactive
*
* #return string
*/
public function getIsactive()
{
return $this->isactive;
}
/**
* #inheritDoc
*/
public function getRoles()
{
return array('ROLE_USER');
}
/**
* #inheritDoc
*/
public function eraseCredentials()
{
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->salt,
$this->password,
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->salt,
$this->password,
) = unserialize($serialized);
}
}
Repository
// src/Acme/UserBundle/Entity/UserRepository.php
namespace Login\LogBundle\Entity;
use Doctrine\ORM\EntityRepository;
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\NoResultException;
class UserRepository 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 {
// The Query::getSingleResult() method throws an exception
// if there is no record matching the criteria.
$user = $q->getSingleResult();
} catch (NoResultException $e) {
$message = sprintf(
'Unable to find an active admin AcmeUserBundle: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());
}
}
Check the app/config/security.yml file with something like this:
# app/config/security.yml
security:
providers:
main:
entity:
class: Acme\UserBundle\Entity\User
property: username
And path to repositoryClass UserRepository is wrong, maybe you mean this:
#ORM\Entity(repositoryClass="Login\LogBundle\Entity\UserRepository")
becouse you use namespace \Login\LogBundle\Entity\UserRepository.
To load user from Repository, you should omit the { property: username } from security.yml.
Related
i have a big problem implementing JWT Tokens on symfony.
I already make work the JWT token, but i need to add to the token info the User roles too. i am doing this using a Listener (JWTCreatedListener):
public function onJWTCreated(JWTCreatedEvent $event)
{
$request = $this->requestStack->getCurrentRequest();
$payload = $event->getData();
$payload['ip'] = $request->getClientIp();
$payload['roles'] = $event->getUser()->getRoles();
$event->setData($payload);
}
I implemented the Role.php (AppBundle/Entity/Role.php) on this way:
<?php
namespace AppBundle\Entity;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="acme_role")
* #ORM\Entity()
*/
class Role implements RoleInterface
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="name", type="string", length=30)
*/
private $name;
/**
* #ORM\Column(name="role", type="string", length=20, unique=true)
*/
private $role;
/**
* #ORM\ManyToMany(targetEntity="User", mappedBy="roles")
*/
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
/**
* #see RoleInterface
*/
public function getRole()
{
return $this->role;
}
// ... getters and setters for each property
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Role
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set role
*
* #param string $role
*
* #return Role
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* Add user
*
* #param \AppBundle\Entity\User $user
*
* #return Role
*/
public function addUser(\AppBundle\Entity\User $user)
{
$this->users[] = $user;
return $this;
}
/**
* Remove user
*
* #param \AppBundle\Entity\User $user
*/
public function removeUser(\AppBundle\Entity\User $user)
{
$this->users->removeElement($user);
}
/**
* Get users
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUsers()
{
return $this->users;
}
}
And my User class:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Table(name="users")
* #ORM\Entity
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=25, unique=true)
*/
private $username;
/**
* #ORM\Column(type="string", length=500)
*/
private $password;
/**
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* #ORM\ManyToMany(targetEntity="Role", inversedBy="users")
*
*/
private $roles;
public function __construct($username)
{
$this->isActive = true;
$this->username = $username;
$this->roles = new ArrayCollection();
}
public function getUsername()
{
return $this->username;
}
public function getSalt()
{
return null;
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
$this->password = $password;
}
public function getRoles()
{
return $this->roles->toArray();
}
public function eraseCredentials()
{
}
/**
* 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 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 \AppBundle\Entity\Role $role
*
* #return User
*/
public function addRole(\AppBundle\Entity\Role $role)
{
$this->roles[] = $role;
return $this;
}
/**
* Remove role
*
* #param \AppBundle\Entity\Role $role
*/
public function removeRole(\AppBundle\Entity\Role $role)
{
$this->roles->removeElement($role);
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
// serialize and unserialize must be updated - see below
public function serialize()
{
return serialize(array(
// ...
$this->isActive
));
}
public function unserialize($serialized)
{
list (
// ...
$this->isActive
) = unserialize($serialized);
}
}
The problem is that this method getRole() always returns empty.
This is my db data:
[users]
id username password is_active
1 abriceno $2y$13$NW6uNOKJGUQTSXirej4HKOwIa6mWzYqFxzz1ppWQjyp... 1
[acme_role]
id name role
1 admin ROLE_ADMIN
[user_role]
user_id user_role
1 1
Also, i try to call the data from a controller test using doctrine:
public function indexAction(Request $request)
{
$repository = $this->getDoctrine()->getRepository('AppBundle:User');
$user = $repository->findOneByusername('abriceno');
$username = $user->getUsername();
$roles = $user->getRoles();
$arr = array(
'username' => $user->getUsername(),
'password' => $user->getPassword(),
'roles' => $user->getRoles()
);
return new JsonResponse($arr);
this returns:
{"username":"abriceno","password":"$2y$13$NW6uNOKJGUQTSXirej4HKOwIa6mWzYqFxzz1ppWQjypQJLIgUGJ.m","roles":[{}]}
I am so desperate... thanks for all the help that you can provide to me.
UPDATE 1
If i do print_r($role) this prints a huuuuuge list of values:
array(1) { [0]=> object(AppBundle\Entity\Role)#624 (4) { ["id":"AppBundle\Entity\Role":private]=> int(1) ["name":"AppBundle\Entity\Role":private]=> string(5) "admin" ["role":"AppBundle\Entity\Role":private]=> string(10) "ROLE_ADMIN" ["users":"AppBundle\Entity\Role":private]=> object(Doctrine\ORM\PersistentCollection)#626 (9) { ["snapshot":"Doctrine\ORM\PersistentCollection":private]=> array(0) { } ["owner":"Doctrine\ORM\PersistentCollection":private]=> *RECURSION*
... and keeps going... very strange!!
Seems that the join table is not handled directly by doctrine, so you need do specify to doctrine howto map the referenced fied with the JoinTable annotation (See the default mapping section.)
In your case, try to modify the roles relation definition in the User entity as follow:
/**
* #ORM\ManyToMany(targetEntity="Role", inversedBy="users")
* #ORM\JoinTable(name="user_role",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="user_role", referencedColumnName="id")})
*
*/
private $roles;
Hope this help
Finally i fix this with this code:
// Work of roles
$roles = $event->getUser()->getRoles();
$role_length = count($roles);
$role_list = array();
for ($i=0; $i <$role_length ; $i++) {
array_push($role_list,$roles[$i]->getRole());
}
$payload = $event->getData();
$payload['ip'] = $request->getClientIp();
$payload['roles'] = $role_list;
The problem (i guess) is on the ->getRoles(); code. This returns a array of Entity\Role class, not an array of roles.
Now the dump is:
{
"token": "eyJhbGciOiJSUzI1NiJ9.....",
"data": {
"roles": [
"ROLE_ADMIN"
]
}
}
Welcome,
I have some problem with user Authentication. My security.yml file:
security:
firewalls:
default:
anonymous: ~
http_basic: ~
provider: our_db_provider
logout:
path: /logout
providers:
our_db_provider:
entity:
class: CmsUserBundle:User
property: username
encoders:
Cms\UserBundle\Entity\User: plaintext
My user entity:
<?php
namespace Cms\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\HasLifecycleCallbacks()
* #ORM\Entity(repositoryClass="Cms\UserBundle\Entity\UserRepository")
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=64)
*/
private $username;
/**
* #ORM\Column(type="string", length= 64)
*/
private $email;
/**
* #ORM\Column(type="string", length=64)
*/
private $password;
/**
* #ORM\Column(type="date", length=128)
*/
private $dateOfBirthday;
/**
* #ORM\Column(type="text")
*/
private $about;
/**
* #ORM\Column(type="string", length=64)
*/
private $salt;
/**
* #ORM\ManyToOne(targetEntity="Cms\UserBundle\Entity\Role")
* #ORM\JoinColumn(name="role_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $roles;
/**
* #ORM\Column(type="string", length=255)
*/
private $eraseCredentials;
/**
* #ORM\Column(name="is_active", type="boolean", options={"default": 0})
*/
private $isActive;
/**
* #ORM\Column(type="string", nullable=true)
* #Assert\Image()
*/
private $profilePicturePath;
/**
* #ORM\Column(type="string", nullable=true)
*/
private $activatedHash;
public function __construct()
{
$this->setActivatedHash(bin2hex(random_bytes(36)));
}
public function getSalt()
{
return $this->salt;
}
public function getPassword()
{
return $this->password;
}
public function getRoles()
{
return array($this->roles);
}
public function eraseCredentials()
{
}
public function getUsername()
{
return $this->username;
}
/**
* Get eraseCredentials
*
* #return string
*/
public function getEraseCredentials()
{
return $this->eraseCredentials;
}
/**
* 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;
}
/**
* Set email
*
* #param string $email
*
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* 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 password
*
* #param string $password
*
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set dateOfBirthday
*
* #param \DateTime $dateOfBirthday
*
* #return User
*/
public function setDateOfBirthday($dateOfBirthday)
{
$this->dateOfBirthday = $dateOfBirthday;
return $this;
}
/**
* Get dateOfBirthday
*
* #return \DateTime
*/
public function getDateOfBirthday()
{
return $this->dateOfBirthday;
}
/**
* Set about
*
* #param string $about
*
* #return User
*/
public function setAbout($about)
{
$this->about = $about;
return $this;
}
/**
* Get about
*
* #return string
*/
public function getAbout()
{
return $this->about;
}
/**
* Set salt
*
* #param string $salt
*
* #return User
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
/**
* Set eraseCredentials
*
* #param string $eraseCredentials
*
* #return User
*/
public function setEraseCredentials($eraseCredentials)
{
$this->eraseCredentials = $eraseCredentials;
return $this;
}
/**
* Set roles
*
* #param \Cms\UserBundle\Entity\Role $roles
*
* #return User
*/
public function setRoles(\Cms\UserBundle\Entity\Role $roles = null)
{
$this->roles = $roles;
return $this;
}
/**
* Set profilePicturePath
*
* #param string $profilePicturePath
*
* #return User
*/
public function setProfilePicturePath($profilePicturePath)
{
$this->profilePicturePath = $profilePicturePath;
return $this;
}
/**
* Get profilePicturePath
*
* #return string
*/
public function getProfilePicturePath()
{
return $this->profilePicturePath;
}
/**
* Serialization is required to FileUploader
* #return string
*/
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->salt,
$this->password,
$this->roles,
$this->isActive
));
}
/**
* #param string $serialized
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->salt,
$this->password,
$this->roles,
$this->isActive
) = unserialize($serialized);
}
/**
* Set activatedHash
*
* #param string $activatedHash
*
* #return User
*/
public function setActivatedHash($activatedHash)
{
$this->activatedHash = $activatedHash;
return $this;
}
/**
* Get activatedHash
*
* #return string
*/
public function getActivatedHash()
{
return $this->activatedHash;
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->getIsActive();
}
}
And in my Controller:
$token = new UsernamePasswordToken($foundUser, $foundUser->getPassword(), 'default', array($role->getRole()) );
$this->get('security.token_storage')->setToken($token);
My problem is that every time user is success Authenticated, even if my isEnabled() function return false. Thanks for help.
I'm trying to add new user with ManyToMany relationship with group, but only user is saving in database
this is my
User.php
/**
* Acme\UserBundle\Entity\User
*
* #ORM\Table(name="User")
* #ORM\Entity(repositoryClass="Acme\UserBundle\Entity\UserRepository")
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="username", type="string", length=25, unique=true)
*/
private $username;
/**
* #ORM\Column(name="salt", type="string", length=40)
*/
private $salt;
/**
* #ORM\Column(name="password", type="string", length=40)
*/
private $password;
/**
* #ORM\Column(name="email", type="string", length=60, unique=true)
*/
private $email;
/**
* #ORM\Column(name="isActive", type="boolean")
*/
private $isActive;
/**
* #ORM\ManyToMany(targetEntity="Group", inversedBy="users")
*
* #ORM\JoinTable(name="user_group",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*
*/
private $groups;
public function __construct()
{
$this->isActive = true;
$this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
$this->groups = new ArrayCollection();
}
/**
* #inheritDoc
*/
public function getRoles()
{
$roles = array();
foreach ($this->groups as $role) {
$roles[] = $role->getRole();
}
return $roles;
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
/*
* ! Don't serialize $roles field !
*/
return \json_encode(array(
$this->id,
$this->username,
$this->email,
$this->salt,
$this->password,
$this->isActive
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->email,
$this->salt,
$this->password,
$this->isActive
) = \json_decode($serialized);
}
public function eraseCredentials()
{
}
public function getUsername()
{
return $this->username;
}
public function getSalt()
{
return $this->salt;
}
public function getPassword()
{
return $this->password;
}
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 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;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* 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 groups
*
* #param \Acme\UserBundle\Entity\Group $groups
* #return User
*/
public function addGroup(\Acme\UserBundle\Entity\Group $groups)
{
$groups->addUser($this);
$this->groups -> add($groups);
return $this->groups;
}
/**
* Remove groups
*
* #param \Acme\UserBundle\Entity\Group $groups
*/
public function removeGroup(\Acme\UserBundle\Entity\Group $groups)
{
$this->groups->removeElement($groups);
}
/**
* Get groups
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getGroups()
{
return $this->groups;
}
}
my Group.php
<?php
namespace Acme\UserBundle\Entity;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="groups")
* #ORM\Entity
*/
class Group implements RoleInterface, \Serializable
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/** #ORM\Column(name="name", type="string", length=30) */
private $name;
/** #ORM\Column(name="role", type="string", length=20, unique=true) */
private $role;
/** #ORM\ManyToMany(targetEntity="User", mappedBy="groups",cascade={"persist"}) */
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
// ... getters and setters for each property
/** #see RoleInterface */
public function getRole()
{
return $this->role;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
/*
* ! Don't serialize $users field !
*/
return \json_encode(array(
$this->id,
$this->role
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list(
$this->id,
$this->role
) = \json_decode($serialized);
}
/**
* Set name
*
* #param string $name
* #return Group
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set role
*
* #param string $role
* #return Group
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* Add users
*
* #param \Acme\UserBundle\Entity\User $users
* #return Group
*/
public function addUser(\Acme\UserBundle\Entity\User $users)
{
$this->users[] = $users;
return $this;
}
/**
* Remove users
*
* #param \Acme\UserBundle\Entity\User $users
*/
public function removeUser(\Acme\UserBundle\Entity\User $users)
{
$this->users->removeElement($users);
}
/**
* Get users
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUsers()
{
return $this->users;
}
}
and fragment from my controller
public function newAction(Request $request)
{
$user = new User();
$form = $this->createFormBuilder($user)
->add('username', 'text')
->add('password', 'text')
->add('email', 'email')
->add('submit','submit')
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
$user=$form->getData();
$group=new Group();
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$user->setSalt(md5(time()));
$pass = $encoder->encodePassword($form->getData()->getPassword(), $user->getSalt());
$user->setPassword($pass);
$group->setRole('ROLE_USER');
$user->addGroup($group);
$em = $this->getDoctrine()->getManager();
$em->merge($user);
$em->flush();
return $this->redirect($this->generateUrl('login'));
}
return $this->render('AcmeUserBundle:User:new.html.twig', array(
'form' => $form->createView(),
));
in database i have 3 table : User, Group and user_group (user_id, group_id)
everything generated from entities. I can register new user but it isnt saving in user_group.
Thanks for any help.
Ps.Sorry for my poor english
From what i can tell, you're not saving your group. So because you're not saving it, there is no user_group to save, because your group doesn't exist in the database. However you'll have another problem once you do this because you have a unique constraint on the role field for your group, so you'll get a database error saying you have a duplicate once you try to register more than one person. You'll need to pull the group from the db instead of making a new one every time.
$group = $this->em->getRepository('Group')->findOneByRole('ROLE_USER');
$user->addGroup($group);
$em->persist($group);
$em->persist($user);
$em->flush();
Update your controller to contain:
$group = $em->getRepository('AcmeUserBundle:Group')->findOne(array('role' => 'ROLE_USER'));
$user->addGroup($group);
$em->persist($user);
$em->persist($group);
$em->flush();
You forgot to persist the Group entity in your code, so it didn't save any data.
By the way, I suggest using a UserService that handles all that logic instead of putting it all in your controllers.
Also, in your User.php, you can just do:
/**
* #ORM\ManyToMany(targetEntity="Group", inversedBy="user")
*/
protected $groups;
The #JoinColumn annotation is not required. If it is not specified the attributes name and referencedColumnName are inferred from the table and primary key names.
I am getting above error when login. With property option in security.yml it is working. I have added the #ORM\Entity(repositoryClass="versionR\userBundle\Entity\UserRepository") line on my entity class, dobule checked path, cleared cache but no luck.
User entity class
<?php
namespace versionR\userBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
//use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="versionR\userBundle\Entity\UserRepository")
*/
class User implements UserInterface, \Serializable
{
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=40, nullable=false)
*/
private $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255, nullable=false)
*/
private $password;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255, nullable=false)
*/
private $email;
/**
* #var string
*
* #ORM\Column(name="address", type="string", length=255, nullable=false)
*/
private $address;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var \Doctrine\Common\Collections\Collection
*
* #ORM\ManyToMany(targetEntity="versionR\userBundle\Entity\Role", inversedBy="user")
* #ORM\JoinTable(name="user_role",
* joinColumns={
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="role_id", referencedColumnName="id")
* }
* )
*/
private $role;
/**
* Constructor
*/
public function __construct()
{
$this->role = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #param string $address
*/
public function setAddress($address)
{
$this->address = $address;
}
/**
* #return string
*/
public function getAddress()
{
return $this->address;
}
/**
* #param string $email
*/
public function setEmail($email)
{
$this->email = $email;
}
/**
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* #param int $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param string $password
*/
public function setPassword($password)
{
$this->password = $password;
}
/**
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* #param string $username
*/
public function setUsername($username)
{
$this->username = $username;
}
/**
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* #param \Doctrine\Common\Collections\Collection $role
*/
public function setRole($role)
{
$this->role->add($role);
}
/**
* #return \Doctrine\Common\Collections\Collection
*/
public function getRole()
{
return $this->role;
}
/**
*/
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password,
// see section on salt below
// $this->salt,
));
}
/**
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
// see section on salt below
// $this->salt
) = unserialize($serialized);
}
/**
* Returns the roles granted to the user.
*/
public function getRoles()
{
return $this->role->toArray();
}
/**
*/
public function getSalt()
{
return null;
}
/**
*/
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
}
User repository class
<?php
namespace versionR\userBundle\Entity;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
/**
* UserRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class UserRepository extends EntityRepository implements UserProviderInterface
{
/**
* #param string $username
* #return \versionR\userBundle\Entity\User
*/
public function loadUserByUsername($username)
{
return $this->findOneBy(array('username' => $username));
}
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());
}
}
Both classes are in Entity directory. Any suggestions to solve this problem. I am using symfony 2.5.2
I am using FOSUserBundle but I wanted to rename the roles field column name to user_roles for legacy database,
By referring to
https://github.com/FriendsOfSymfony/FOSUserBundle/issues/338
and
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/doctrine.md#replacing-the-mapping-of-the-bundle
I am trying to overwrite the existing FOS\UserBundle\Model\User with my AcmeDemoBundle:User entity by mapping all fields again.
This is my Class,
PLEASE NOTE I AM EXTENDING ENTITY DIRECTLY FROM "FOS\UserBundle\Model\User"
namespace Acme\SecurityBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Acme\CommonBundle\Util\Url as Url;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="Acme\SecurityBundle\Entity\UserRepository")
*/
Class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
* #ORM\Column(name="username", type="string", length=255)
*/
protected $username;
/**
* #var string
* #ORM\Column(name="username_canonical", type="string", length=255, unique=true)
*/
protected $usernameCanonical;
/**
* #var string
* #ORM\Column(name="email", type="string", length=255)
*/
protected $email;
/**
* #var string
* #ORM\Column(name="email_canonical", type="string", length=255, unique=true)
*/
protected $emailCanonical;
/**
* #var boolean
* #ORM\Column(name="enabled", type="boolean")
*/
protected $enabled;
/**
* The salt to use for hashing
*
* #var string
* #ORM\Column(name="salt", type="string")
*/
protected $salt;
/**
* Encrypted password. Must be persisted.
*
* #var string
* #ORM\Column(name="password", type="string")
*/
protected $password;
/**
* Plain password. Used for model validation. Must not be persisted.
*
* #var string
*/
protected $plainPassword;
/**
* #var \DateTime
* #ORM\Column(name="last_login", type="datetime", nullable=true)
*/
protected $lastLogin;
/**
* Random string sent to the user email address in order to verify it
*
* #var string
* #ORM\Column(name="confirmation_token", type="string", nullable=true)
*/
protected $confirmationToken;
/**
* #var \DateTime
* #ORM\Column(name="password_requested_at", type="datetime", nullable=true)
*/
protected $passwordRequestedAt;
/**
* #var Collection
*/
protected $groups;
/**
* #var boolean
* #ORM\Column(name="locked", type="boolean")
*/
protected $locked;
/**
* #var boolean
* #ORM\Column(name="expired", type="boolean")
*/
protected $expired;
/**
* #var \DateTime
* #ORM\Column(name="expires_at", type="datetime", nullable=true)
*/
protected $expiresAt;
/**
* #var array
* #ORM\Column(name="fos_roles", type="array", nullable=true)
*/
protected $roles;
/**
* #var boolean
* #ORM\Column(name="credentials_expired", type="boolean")
*/
protected $credentialsExpired;
/**
* #var \DateTime
* #ORM\Column(name="credentials_expire_at", type="datetime", nullable=true)
*/
protected $credentialsExpireAt;
public function __construct()
{
parent::__construct();
$this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
$this->enabled = false;
$this->locked = false;
$this->expired = false;
$this->roles = array();
$this->credentialsExpired = false;
//$this->setEmailHash();
}
public function addRole($role)
{
$role = strtoupper($role);
if ($role === static::ROLE_DEFAULT) {
return $this;
}
if (!in_array($role, $this->roles, true)) {
$this->roles[] = $role;
}
return $this;
}
/**
* Serializes the user.
*
* The serialized data have to contain the fields used by the equals method and the username.
*
* #return string
*/
public function serialize()
{
return serialize(array(
$this->password,
$this->salt,
$this->usernameCanonical,
$this->username,
$this->expired,
$this->locked,
$this->credentialsExpired,
$this->enabled,
$this->id,
));
}
/**
* Unserializes the user.
*
* #param string $serialized
*/
public function unserialize($serialized)
{
$data = unserialize($serialized);
// add a few extra elements in the array to ensure that we have enough keys when unserializing
// older data which does not include all properties.
$data = array_merge($data, array_fill(0, 2, null));
list(
$this->password,
$this->salt,
$this->usernameCanonical,
$this->username,
$this->expired,
$this->locked,
$this->credentialsExpired,
$this->enabled,
$this->id
) = $data;
}
/**
* Removes sensitive data from the user.
*/
public function eraseCredentials()
{
$this->plainPassword = null;
}
/**
* Returns the user unique id.
*
* #return mixed
*/
public function getId()
{
return $this->id;
}
public function getUsername()
{
return $this->username;
}
public function getUsernameCanonical()
{
return $this->usernameCanonical;
}
public function getSalt()
{
return $this->salt;
}
public function getEmail()
{
return $this->email;
}
public function getEmailCanonical()
{
return $this->emailCanonical;
}
/**
* Gets the encrypted password.
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
public function getPlainPassword()
{
return $this->plainPassword;
}
/**
* Gets the last login time.
*
* #return \DateTime
*/
public function getLastLogin()
{
return $this->lastLogin;
}
public function getConfirmationToken()
{
return $this->confirmationToken;
}
/**
* Returns the user roles
*
* #return array The roles
*/
public function getRoles()
{
$roles = $this->roles;
foreach ($this->getGroups() as $group) {
$roles = array_merge($roles, $group->getRoles());
}
// we need to make sure to have at least one role
$roles[] = static::ROLE_DEFAULT;
return array_unique($roles);
}
/**
* Never use this to check if this user has access to anything!
*
* Use the SecurityContext, or an implementation of AccessDecisionManager
* instead, e.g.
*
* $securityContext->isGranted('ROLE_USER');
*
* #param string $role
*
* #return boolean
*/
public function hasRole($role)
{
return in_array(strtoupper($role), $this->getRoles(), true);
}
public function isAccountNonExpired()
{
if (true === $this->expired) {
return false;
}
if (null !== $this->expiresAt && $this->expiresAt->getTimestamp() < time()) {
return false;
}
return true;
}
public function isAccountNonLocked()
{
return !$this->locked;
}
public function isCredentialsNonExpired()
{
if (true === $this->credentialsExpired) {
return false;
}
if (null !== $this->credentialsExpireAt && $this->credentialsExpireAt->getTimestamp() < time()) {
return false;
}
return true;
}
public function isCredentialsExpired()
{
return !$this->isCredentialsNonExpired();
}
public function isEnabled()
{
return $this->enabled;
}
public function isExpired()
{
return !$this->isAccountNonExpired();
}
public function isLocked()
{
return !$this->isAccountNonLocked();
}
public function isSuperAdmin()
{
return $this->hasRole(static::ROLE_SUPER_ADMIN);
}
public function isUser(\FOS\UserBundle\Model\UserInterface $user = null)
{
return null !== $user && $this->getId() === $user->getId();
}
public function removeRole($role)
{
if (false !== $key = array_search(strtoupper($role), $this->roles, true)) {
unset($this->roles[$key]);
$this->roles = array_values($this->roles);
}
return $this;
}
public function setUsername($username)
{
$this->username = $username;
return $this;
}
public function setUsernameCanonical($usernameCanonical)
{
$this->usernameCanonical = $usernameCanonical;
return $this;
}
/**
* #param \DateTime $date
*
* #return User
*/
public function setCredentialsExpireAt(\DateTime $date = null)
{
$this->credentialsExpireAt = $date;
return $this;
}
/**
* #param boolean $boolean
*
* #return User
*/
public function setCredentialsExpired($boolean)
{
$this->credentialsExpired = $boolean;
return $this;
}
public function setEmail($email)
{
$this->email = $email;
return $this;
}
public function setEmailCanonical($emailCanonical)
{
$this->emailCanonical = $emailCanonical;
return $this;
}
public function setEnabled($boolean)
{
$this->enabled = (Boolean) $boolean;
return $this;
}
/**
* Sets this user to expired.
*
* #param Boolean $boolean
*
* #return User
*/
public function setExpired($boolean)
{
$this->expired = (Boolean) $boolean;
return $this;
}
/**
* #param \DateTime $date
*
* #return User
*/
public function setExpiresAt(\DateTime $date = null)
{
$this->expiresAt = $date;
return $this;
}
public function setPassword($password)
{
$this->password = $password;
return $this;
}
public function setSuperAdmin($boolean)
{
if (true === $boolean) {
$this->addRole(static::ROLE_SUPER_ADMIN);
} else {
$this->removeRole(static::ROLE_SUPER_ADMIN);
}
return $this;
}
public function setPlainPassword($password)
{
$this->plainPassword = $password;
return $this;
}
public function setLastLogin(\DateTime $time = null)
{
$this->lastLogin = $time;
return $this;
}
public function setLocked($boolean)
{
$this->locked = $boolean;
return $this;
}
public function setConfirmationToken($confirmationToken)
{
$this->confirmationToken = $confirmationToken;
return $this;
}
public function setPasswordRequestedAt(\DateTime $date = null)
{
$this->passwordRequestedAt = $date;
return $this;
}
/**
* Gets the timestamp that the user requested a password reset.
*
* #return null|\DateTime
*/
public function getPasswordRequestedAt()
{
return $this->passwordRequestedAt;
}
public function isPasswordRequestNonExpired($ttl)
{
return $this->getPasswordRequestedAt() instanceof \DateTime &&
$this->getPasswordRequestedAt()->getTimestamp() + $ttl > time();
}
public function setRoles(array $roles)
{
$this->roles = array();
foreach ($roles as $role) {
$this->addRole($role);
}
return $this;
}
/**
* Gets the groups granted to the user.
*
* #return Collection
*/
public function getGroups()
{
return $this->groups ? : $this->groups = new ArrayCollection();
}
public function getGroupNames()
{
$names = array();
foreach ($this->getGroups() as $group) {
$names[] = $group->getName();
}
return $names;
}
public function hasGroup($name)
{
return in_array($name, $this->getGroupNames());
}
public function addGroup(\FOS\UserBundle\Model\GroupInterface $group)
{
if (!$this->getGroups()->contains($group)) {
$this->getGroups()->add($group);
}
return $this;
}
public function removeGroup(\FOS\UserBundle\Model\GroupInterface $group)
{
if ($this->getGroups()->contains($group)) {
$this->getGroups()->removeElement($group);
}
return $this;
}
public function __toString()
{
return (string) $this->getUsername();
}
}
If I remove extends BaseUser (FOS\UserBundle\Model\User), it gives error "The user provider must return a UserInterface object."
Then I tried adding "implements UserInterface, GroupableInterface" but it still gives "There is no user provider for user "Acme\SecurityBundle\Entity\User".
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Model/User.php
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/config/doctrine/model/User.orm.xml
The property username is already defined in FOS\UserBundle\Model\User. Its metadata is in their resources config. So you are defining that column twice essentially.
We dont need to overwrite all fields to rename the field in database, I could achieve this by using AttributeOverride
/**
* #ORM\Entity
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="Acme\SecurityBundle\Entity\UserRepository")
* #ORM\AttributeOverrides({
* #ORM\AttributeOverride(name="roles",
* column=#ORM\Column(
* name = "user_roles",
* type = "array"
* )
* )
* })
*/
Class User extends BaseUser
{
...
}
#Fosculus: what about the property id? It's also defined in FOS\UserBundle\Model\User. Why doesn't it give any problem?