Adding many to many relationship into database Symfony - php

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.

Related

Symfony 3 : Check if I am logged in

I would like to check if I am logged in when I login with a form, but I can't find my anwser and I don't understand the tutorial on symfony website... I try to follow this : http://symfony.com/doc/current/security.html , but I don't want to do with a "HTTP basic authentication", but with my symfony form.
Here is my user class :
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* Player
*
* #ORM\Table(name="player")
* #ORM\Entity(repositoryClass="AppBundle\Repository\PlayerRepository")
*/
class Player implements UserInterface, \Serializable
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="pseudo", type="string", length=255, unique=true)
*/
private $pseudo;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255, unique=true)
*/
protected $email;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
*/
protected $password;
/**
* #var \DateTime
*
* #ORM\Column(name="date_log", type="datetime", nullable=true)
*/
private $dateLog;
/**
* #ORM\OneToMany(targetEntity="Characters", mappedBy="player")
*/
private $characters;
public function __construct(){
$this->characters = new ArrayCollection();
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set pseudo
*
* #param string $pseudo
*
* #return Player
*/
public function setPseudo($pseudo)
{
$this->pseudo = $pseudo;
return $this;
}
/**
* Get pseudo
*
* #return string
*/
public function getPseudo()
{
return $this->pseudo;
}
/**
* Set email
*
* #param string $email
*
* #return Player
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set password
*
* #param string $password
*
* #return Player
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set dateLog
*
* #param \DateTime $dateLog
*
* #return Player
*/
public function setDateLog($date_log)
{
$this->dateLog = $date_log;
return $this;
}
/**
* Get dateLog
*
* #return \DateTime
*/
public function getDateLog()
{
return $this->dateLog;
}
/**
* Set Characters
*
* #param array $characters
*
* #return Characters
*/
public function setCharacters($characters)
{
$this->characters = $characters;
return $this;
}
/**
* Get characters
*
* #return array
*/
public function getCharacters()
{
return $this->characters;
}
/**
* Add character
*
* #param \AppBundle\Entity\Characters $character
*
* #return Player
*/
public function addCharacter(\AppBundle\Entity\Characters $character)
{
$this->characters[] = $character;
return $this;
}
/**
* Remove character
*
* #param \AppBundle\Entity\Characters $character
*/
public function removeCharacter(\AppBundle\Entity\Characters $character)
{
$this->characters->removeElement($character);
}
public function getUsername()
{
return $this->pseudo;
}
public function getSalt()
{
// you *may* need a real salt depending on your encoder
// see section on salt below
return null;
}
public function getRoles()
{
return array('ROLE_USER');
}
public function eraseCredentials()
{
}
/** #see \Serializable::serialize() */
public function serialize()
{
return serialize(array(
$this->id,
$this->pseudo,
$this->password,
// see section on salt below
// $this->salt,
));
}
/** #see \Serializable::unserialize() */
public function unserialize($serialized)
{
list (
$this->id,
$this->pseudo,
$this->password,
// see section on salt below
// $this->salt
) = unserialize($serialized);
}
}
Then my login form (it work well, I am just not able to check if anybody is connected):
public function indexAction(Request $request)
{
$player = new Player;
$form = $this->createFormBuilder($player)
->add('email', TextType::class, array('label' => 'Email :'))
->add('password', PasswordType::class, array('label' => 'Mot de passe :'))
->add('login', SubmitType::class, array('label' => 'Login'))
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid())
{
$password = $form['password']->getData();
$email = $form['email']->getData();
$encoded_pass = sha1($form['password']->getData());
$date = date_create();
$player = $this->getDoctrine()
->getRepository('AppBundle:Player')
->findOneByEmail($email);
$pass_check = $this->getDoctrine()
->getRepository('AppBundle:Player')
->findByPassword($encoded_pass);
if(!$player)
{
//return $this->redirectToRoute('registration');
}
else
{
$pseudo = $this->getDoctrine()
->getRepository('AppBundle:Player')
->findOneByEmail($email)->getPseudo();
$player->setDateLog($date);
$em = $this->getDoctrine()->getManager();
$em->persist($player);
$em->flush(); // insère dans la BD
return $this->redirectToRoute('accueil', array('pseudo' => $pseudo));
}
}
return $this->render('Sko/menu.html.twig', array('form' => $form->createView()));
}
EDIT : I don't want to encode my password because I already do it (even if it is not 100% securised)
EDIT2 : Well I think I can't do that, when I saw the tutoriel, I saw that on their symfony toolbar, we can seethere is the role of the user instead of an anonymous user, but they didn't do this dynamically. Maybe I can't do it dynamically so I need to send user information each time I change page
EDIT3 : I will clarify my question : How to change the token class when I login?
You dont need to create your token, but encoder like described in this answer
After that you can log in programmatically with this code
$token = new UsernamePasswordToken($player, $player->getPassword(), "main");
$event = new InteractiveLoginEvent(new Request(), $token);
$this->container->get("event_dispatcher")->dispatch("security.interactive_login", $event);
$this->container->get("security.token_storage")->setToken($token);
Now you can use standard symfony security functionality to check if user logged in etc

Could not determine access type for property "roles"

I'm getting the following error when trying to submit the following form
I figured the error must be from the fact that the property for roles within User is userRoles and not roles. I'd like to know if there is a way to map the EntityType field to a property in Users I looked at this Answer but it does not seem to be the proper way to solve this problem, it is more of a work around.
class UserEditType extends AbstractType{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('roles', EntityType::class, array('multiple'=> true, 'class' => 'AuthBundle:Role', 'choice_label' => 'slug','attr' => array('class'=>'form-control')))
->add('email', EmailType::class, array('attr' => array('class'=>'form-control')))
->add('username', TextType::class, array('attr' => array('class'=>'form-control')))
->add('active', CheckboxType::class, array('attr' => array('class'=>'checkbox')));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => User::class,
));
}
}
The User Class
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;
/**
* #Assert\Length(max=4096)
* #Assert\Length(min=8)
*/
private $plainPassword;
/**
* #ORM\Column(type="string", length=64)
*/
private $password;
/**
* #ORM\Column(type="string", length=240, nullable=true)
*/
private $profilePicture;
/**
* #ORM\Column(type="string", length=180, unique=true, options={"default" : "default.png"})
*/
private $email;
/**
* #ORM\Column(name="is_active", type="boolean", options={"default" : 0})
*/
private $isActive;
/**
* #ORM\ManyToMany(targetEntity="Role")
* #ORM\JoinTable(name="user_role",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="role_id", referencedColumnName="id")}
* )
*
* #var ArrayCollection $userRoles
*/
protected $userRoles;
public function __construct()
{
$this->userRoles = new ArrayCollection();
}
public function getUsername()
{
return $this->username;
}
//deprecated bcrypt does not require salt
public function getSalt()
{
// you *may* need a real salt depending on your encoder
// see section on salt below
return null;
}
public function isActive()
{
return $this->isActive;
}
public function getPassword()
{
return $this->password;
}
public function getplainPassword()
{
return $this->plainPassword;
}
public function getPicture()
{
return $this->profilePicture;
}
public function getRoles()
{
return $this->getUserRoles()->toArray();
}
public function eraseCredentials()
{
}
/** #see \Serializable::serialize() */
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password,
$this->isActive,
// see section on salt below
// $this->salt,
));
}
/** #see \Serializable::unserialize() */
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
$this->isActive,
// see section on salt below
// $this->salt
) = 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 password
*
* #param string $password
*
* #return User
*/
public function setPlainPassword($password)
{
$this->plainPassword = $password;
return $this;
}
/**
* Set password
*
* #param string $password
*
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set profilePicture
*
* #param string $profilePicture
*
* #return User
*/
public function setProfilePicture($profilePicture)
{
$this->profilePicture = $profilePicture;
return $this;
}
/**
* Get profilePicture
*
* #return string
*/
public function getProfilePicture()
{
return $this->profilePicture;
}
/**
* 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;
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
/**
* Add userRole
*
* #param \AuthBundle\Entity\Role $userRole
*
* #return User
*/
public function addUserRole(\AuthBundle\Entity\Role $userRole)
{
$this->userRoles[] = $userRole;
return $this;
}
/**
* Remove userRole
*
* #param \AuthBundle\Entity\Role $userRole
*/
public function removeUserRole(\AuthBundle\Entity\Role $userRole)
{
$this->userRoles->removeElement($userRole);
}
/**
* Get userRoles
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUserRoles()
{
return $this->userRoles;
}
}
The Role Class
class Role implements RoleInterface
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
* #var integer $id
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
*
* #var string $name
*/
protected $name;
/**
* #ORM\Column(type="string", length=255)
*
* #var string $slug
*/
protected $slug;
/**
* #ORM\Column(type="datetime", name="created_at")
*
* #var DateTime $createdAt
*/
protected $createdAt;
/**
* #ORM\ManyToMany(targetEntity="AuthBundle\Entity\User")
*/
protected $users;
/**
*
*/
public function __construct()
{
$this->users = new ArrayCollection();
$this->createdAt = new \DateTime();
}
/**
*
*
* #return integer The id.
*/
public function getId()
{
return $this->id;
}
/**
*
*
* #return string The name.
*/
public function getName()
{
return $this->name;
}
/**
*
*
* #param string $value The name.
*/
public function setName($value)
{
$this->name = $value;
}
/**
*
*
* #return string The name.
*/
public function getSlug()
{
return $this->slug;
}
/**
*
*
* #param string $value The name.
*/
public function setSlug($value)
{
$this->slug = $value;
}
/**
*
*
* #return DateTime A DateTime object.
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* RoleInterface.
*
* #return string The role.
*/
public function getRole()
{
return $this->getName();
}
/**
* Set createdAt
*
* #param \DateTime $createdAt
*
* #return Role
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Add user
*
* #param \AuthBundle\Entity\User $user
*
* #return Role
*/
public function addUser(\AuthBundle\Entity\User $user)
{
$this->users[] = $user;
return $this;
}
/**
* Remove user
*
* #param \AuthBundle\Entity\User $user
*/
public function removeUser(\AuthBundle\Entity\User $user)
{
$this->users->removeElement($user);
}
/**
* Get users
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUsers()
{
return $this->users;
}
}

getRole() form RoleInterface returns empty on symfony

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"
]
}
}

Symfony Security AdvancedUserInterface

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.

unexpected behaviour following changing entity relationships

my nightmare of a day continues.....
after implimenting a successful solution in an earlier thread where I need to alter my inter-entity relationships I am now getting this error when I try to log a user into the app:
CRITICAL - Uncaught PHP Exception Symfony\Component\Debug\Exception\UndefinedMethodException: "Attempted to call method "getRole" on class "Closure"." at C:\Dropbox\xampp\htdocs\etrack3\src\Ampisoft\Bundle\etrackBundle\Entity\Users.php line 234
I changed from a manyToMany relationship, to a manyToOne/OneToMany between a Users/Roles entity.
Ive read that serialize could cause the issue but Ive taken it out and it didnt make any difference. The remnants of the serialize required methods are still in there so please ignore (unless they are the issue).
Please could someone tell me what Ive done wrong? Im wondering if its best to scrap all the database tables and start again!!!!
here is the entity class.
/**
* user
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="Ampisoft\Bundle\etrackBundle\Entity\UsersRepository")
*/
class Users implements UserInterface
{
/**
* #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=25, unique=true)
*/
private $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=64)
*/
private $password;
/**
* #ORM\Column(name="firstname", type="string", length=25)
*/
private $firstname;
/**
* #ORM\Column(name="surname", type="string", length=25)
*/
private $lastname;
/**
* #var boolean
*
* #ORM\Column(name="isActive", type="boolean")
*/
private $isActive = 1;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255, unique=true)
*/
private $email;
/**
* #var \DateTime
*
* #ORM\Column(name="lastLogged", type="string")
*/
private $lastLogged = '-0001-11-30 00:00:00';
/**
* #var string;
*
* #ORM\Column(name="salt", type="string", length=255)
*/
private $salt;
/**
* #ORM\ManyToOne(targetEntity="Roles", inversedBy="users")
*
*/
private $roles;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set Id
*
* #return integer
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* 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;
}
/**
* 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 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;
}
/**
* Set lastLogged
*
* #param \DateTime $lastLogged
* #return user
*/
public function setLastLogged($lastLogged)
{
$this->lastLogged = $lastLogged;
return $this;
}
/**
* Get lastLogged
*
* #return \DateTime
*/
public function getLastLogged()
{
return $this->lastLogged;
}
public function __construct()
{
$this->roles = new ArrayCollection();
$this->isActive = true;
}
/**
* #inheritDoc
*/
public function getRoles()
{
$roles = array();
foreach ($this->roles as $role) {
$roles[] = $role->getRole();
}
return $roles;
}
/**
* #param $roles
* #return $this
*/
public function setRoles($roles)
{
$this->roles = $roles;
return $this;
}
/**
* #inheritDoc
*/
public function eraseCredentials()
{
}
/**
* #inheritDoc
*/
public function getSalt()
{
return $this->salt;
}
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
/**
* Add roles
*
* #param \Ampisoft\Bundle\etrackBundle\Entity\Roles $roles
* #return users
*/
public function addRoles(Roles $roles)
{
$this->roles[] = $roles;
return $this;
}
/**
* Remove roles
*
* #param \Ampisoft\Bundle\etrackBundle\Entity\Roles $roles
*/
public function removeRoles(Roles $roles)
{
$this->roles->removeElement($roles);
}
/**
* Set firstname
*
* #param string $firstname
* #return users
*/
public function setFirstname($firstname)
{
$this->firstname = $firstname;
return $this;
}
/**
* Get firstname
*
* #return string
*/
public function getFirstname()
{
return $this->firstname;
}
/**
* Set lastname
*
* #param string $lastname
* #return users
*/
public function setLastname($lastname)
{
$this->lastname = $lastname;
return $this;
}
/**
* Get lastname
*
* #return string
*/
public function getLastname()
{
return $this->lastname;
}
/**
* #see \Serializable::serialize()
*/
/**
* Serializes the content of the current User object
* #return string
*/
public function serialize()
{
return \json_encode(
array($this->username, $this->password, $this->salt,
$this->roles, $this->id));
}
/**
* Unserializes the given string in the current User object
* #param serialized
*/
public function unserialize($serialized)
{
list($this->username, $this->password, $this->salt,
$this->roles, $this->id) = \json_decode(
$serialized);
}
}
update 1
this has worked but produced a new error Im going to move it to a new question when the post timer lets me.
Catchable Fatal Error: Argument 4 passed to Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken::__construct() must be of the type array, object given, called in C:\Dropbox\xampp\htdocs\etrack3\vendor\symfony\symfony\src\Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider.php on line 96 and defined
HI I think what you want is not this
public function getRoles()
{
$roles = array();
foreach ($this->roles as $role) {
$roles[] = $role->getRole();
}
return $roles;
}
but this
public function getRoles()
{
return $this->roles;
}
Roles should be an ArrayCollection already, so calling getRole on the ( I assume ) Role class seems to be possible the issue.
If you are using an IDE such as Eclipse then the class is Doctrine\Common\Collections\ArrayCollection; this should be your collection of Roles, I would suggest also is you are using an IDE to do something like this ( for type hinting )
//... at the top of the class file before the class deceleration
use Doctrine\Common\Collections\ArrayCollection;
/**
* #param ArrayCollection $roles
*/
public function setRoles(ArrayCollection $roles)
{
//.. type cast the input to allow only use of ArrayCollection class
$this->roles = $roles;
}
/**
* #return ArrayCollection
*/
public function getRoles()
{
return $this->roles;
}
Also there is a good chance you are setting $this->roles to be a standard array at some point. You should always type cast your input to a specific class if it can only accept that type of class to rule out errors such as using a plain array.
Last thing, is generally protected for the properties are preferred because latter you can extend the class, it's not accessible outside the class much like private, but unlike private it is accessible in inheriting classes.

Categories