1
votes

this methodi use it to add a new job but when i add a job the password of the that current user get its password set to empty cus the user object that i retrieve has no password and symfony behaves like so for to secure the password any help would be much appreciated ` public function addJobAction(){

    if(false === $this->get('security.context')
        ->isGranted('ROLE_ANNOUNCER') 
    )
    {           
        throw new AccessDeniedException();          
    }

    $job = new Job() ;
    $jobForm = $this->createForm( new JobType() ,$job) ;
    $request = $this->getRequest();

    if( $request->getMethod() == 'GET'){
        return
        $this->render('MyJobBundle:Job:addJob.html.twig' ,
            array('form'=> $jobForm->createView() )
        ) ;
    }

    if( $request->getMethod() == 'POST'){
        $jobForm->bindRequest($request);
        if( $jobForm->isValid() ){
            $user = $this->get('security.context')->getToken()
                    ->getUser();

            $job->setAnnouncer($user);
            $em = $this->getDoctrine()->getEntityManager();
            $em->persist($job) ;
            $em->flush() ;              
            return
            $this->redirect($this->generateUrl('show_job' ,
                array('id'=> $job->getId() ) ) 
            );              
        }else{
            return
            new Response('no');
        }       
    }       
}

heres my job entity

namespace My\JobBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use My\UserBundle\Entity\User ;
use Symfony\Component\Validator\Constraints as Assert;


/**
 * My\JobBundle\Entity\Job
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="My\JobBundle\Entity\JobRepository")
 */
 class Job
 {
/**
 * @var integer $id
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string $title
 * 
 * 
 * @ORM\Column(name="title", type="string", length=255)
 */
private $title;

/**
 * @var string $content
 * 
 * 
 * @ORM\Column(name="content", type="text")
 */
private $content;



/**
 * @var string $city
 *
 * @ORM\Column(name="city", type="string", length=255)
 * 
 */
private $city; 


/**
 * @var datetime $created_at
 *
 * @ORM\Column(name="created_at", type="datetime")
 */
private $created_at;

/**
 * @var string $salary
 *
 * @ORM\Column(name="salary", type="string", length=255)
 * 
 * 
 */
private $salary;


 /**
  * @ORM\ManyToOne(targetEntity="My\UserBundle\Entity\User")
  */
   private $announcer ;

  /**
   *  link a job to a user
   */
   public function setAnnouncer(User $a)
   {
    $this->announcer = $a;
   }   

 /**
  * return a user from a job  object
  */    
  public function getAnnouncer()
  {
    return $this->announcer;
  }


/**
 * Get id
 *
 * @return integer 
 */
public function getId()
{
    return $this->id;
}

/**
 * Set title
 *
 * @param string $title
 */
public function setTitle($title)
{
    $this->title = $title;
}

/**
 * Get title
 *
 * @return string 
 */
public function getTitle()
{
    return $this->title;
}

/**
 * Set content
 *
 * @param string $content
 */
public function setContent($content)
{
    $this->content = $content;
}

/**
 * Get content
 *
 * @return string 
 */
public function getContent()
{
    return $this->content;
}

/**
 * Set created_at
 *
 * @param datetime $createdAt
 */
public function setCreatedAt($createdAt)
{
    $this->created_at = $createdAt;
}

/**
 * Get created_at
 *
 * @return datetime 
 */
public function getCreatedAt()
{
    return $this->created_at;
}

/**
 * Set salary
 *
 * @param string $salary
 */
public function setSalary($salary)
{
    $this->salary = $salary;
}

/**
 * Get salary
 *
 * @return string 
 */
public function getSalary()
{
    return $this->salary;
}




public function setCity($c)
{
    $this->city = $c;
}

public function getCity()
{
    return $this->city ;
}


public function __construct(){

    $this->created_at = new \DateTime() ;
}

}

heres my jobType

namespace My\JobBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;

class JobType extends AbstractType
{
  public function buildForm(FormBuilder $builder, array $options)
 {
    $builder
        ->add('title')
        ->add('content','textarea' )
        //->add('created_at')
        ->add('salary')
        ->add('city')
        //->add('announcer')
    ;
}

public function getName()
{
    return 'my_jobbundle_jobtype';
}

}

and heres my log where i see the password updated

    INSERT INTO Job (title, content, city, created_at, salary, announcer_id) VALUES (?, ?, ?, ?, ?, ?) ({"1":"lfdgdfl;","2":";lkl;fdlgkdfl;","3":"lklkl;;l","4":{"date":"2012-02-05 23:39:16","timezone_type":3,"timezone":"Europe\/Paris"},"5":"333","6":1})
    UPDATE User SET password = ? WHERE id = ? ([null,1])
3

3 Answers

4
votes

well i found the issue it was caused by that eraseCredential method of the UserInterface in my User entity

<?php 
public function eraseCredential(){    
 $this->password = null ;
}

i just had to empty it as it was doin to my password by commenting that line ; ]

4
votes

2 kosaidpo

Your solution works because eraseCredentials() method is used to clear user sensitive data (means NOT secret, but the one that can be restored, the sense is like __sleep()) when serializing user object or saving it to database (that is what manual says). So when you attach user to job object and call #flush(), doctrine will check for changes in all objects connected with job and find that user object has changed because eraseCredentials() has erased password. That is why your user gets updated.

There is one more solution which could help you:

The Solution:

Change Tracking Policies from Doctrine documentation.

In short, you can add @ChangeTrackingPolicy("DEFERRED_EXPLICIT") annotation (as I did, because I'm using annotations. Captain Obvious =) ) to UserInterface implementation (in my case I'm using User class) and this will tell Doctrine not to check all 'connected' to job objects.

In this case doctrine will not check user object and save it with erased password, unless you will force it to do it with calling #persist(User object) manually.

But anyway, you should not do $this->password = null in your eraseCredentials() method.

0
votes

It does seem strange, but you could always retrieve User object prior to binding it to a newly created job:

$token = $this->get('security.context')->getToken();
$user_repo = $this->getDoctrine()->getRepository('**NAMESPACE**:User');
$user = $user_repo->find($token->getUser()->getId());

$job->setAnnouncer($user);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($job) ;
$em->flush();

Also, I'm not really sure but I read somewhere that token isn't supposed to carry password due to it's security nature.... maybe that is your problem...