1

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])
hakre
  • 193,403
  • 52
  • 435
  • 836
kosaidpo
  • 461
  • 1
  • 5
  • 14

3 Answers3

4

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 ; ]

kosaidpo
  • 461
  • 1
  • 5
  • 14
4

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.

Dmitry
  • 227
  • 3
  • 12
  • thanks for your reply but can you please be more explicit why i should not do `$this->password = null` thanks again – kosaidpo Feb 12 '12 at 21:24
  • [You can take a look at this](http://stackoverflow.com/questions/8455398/symfony-2-logout-userinterfaceerasecredentials) and, may be it will explain you something. In your case you was removing password (encrypted password) which is one of persisted fields from your entity file, that is why Doctrine was updating your user in database. It is how Doctrine works by default, it checks if something has changed in persisted fields and if it is so - updates the whole entity. And eraseCredentials() is that method which is called every time before Doctrine is checking what has changed in your entity. – Dmitry Feb 13 '12 at 19:12
  • thanks infact i did figure it why the psw set to null and now after readin that post you linked me too i got why i should not use that `$this->password = null in your eraseCredentials() ' thanks – kosaidpo Feb 13 '12 at 21:33
0

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...

Jovan Perovic
  • 19,846
  • 5
  • 44
  • 85
  • yeah true the password its not in the user object but ican't see why the user object get updated even its not the owner side plus its only unidirectional relation ; ] and your workaround its the same as mine (i tried it ) cus in the end i end up with user object with no password – kosaidpo Feb 05 '12 at 17:41
  • Hmmm that really should have worked, but since it didn't I going to take a wild guess. First, make sure that user object, being overwritten/emptied by earlier tries, now contains non-blank password? Try `print_r`0ing the content of a password field within the retrieved user object. Secondly, I would suggest logging out of application either by invoking `logout` route or deleting session id from browser and logging in again... – Jovan Perovic Feb 05 '12 at 20:28
  • none of em worked ;[ im sure that many people had the same thing as me in many kind of apps – kosaidpo Feb 05 '12 at 21:32
  • Can you update your question with `Job` entity and `JobType` form code? I'm sure we have overlooked something... – Jovan Perovic Feb 05 '12 at 21:37
  • i just added the log file where it says the password is updated ;] – kosaidpo Feb 07 '12 at 09:41