Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blameable listener need to use managed version of user in case of entity manager is cleared #373

Open
sam0delkin opened this issue Jul 16, 2018 · 7 comments

Comments

@sam0delkin
Copy link

Assume i have an entity:

namespace Some\Bundle\Entity\Post;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Some\Bundle\Entity\User;

/**
 * Post
 *
 * @ORM\Table(name="post")
 */
class Post
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    // ...

    /**
     * @var User
     *
     * @ORM\ManyToOne(targetEntity="Some\Bundle\Entity\User")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
     *
     * @Gedmo\Blameable(on="create")
     */
    protected $user;

and somehwere in code:

// here i have an IS_AUTHENTICATED_FULLY role.
$post1 = new Post();
$em->persist($post1);
$em->flush(); // <-- here post will be created successfully, and user relation will be set
$em->clear(); // user in token storage and in blameable listener becomes unmanaged
$post2 = new Post();
$em->persist($post2);
$em->flush(); // <-- here would be an exception listed below

Exception:

A new entity was found through the relationship 'Some\Bundle\Entity\Post#user' that was not configured to cascade persist operations for entity: Some User. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist  this association in the mapping for example @ManyToOne(..,cascade={"persist"})

Possible solution is to listen for onClear Doctrine event and do a $em->getReference() to get a managed version of the user.

Thanks in advance!

@BazylPL
Copy link

BazylPL commented Feb 11, 2019

Has anyone experienced this particular problem and successfully solved it? What should I exactly do in onClear listener? @sam0delkin ?
I can't use Blameable because of this :( Need to clear entity manager in order to use batch processing.

@sam0delkin
Copy link
Author

sam0delkin commented Feb 11, 2019

@BazylPL for a workaround i used the following:

$container->get('stof_doctrine_extensions.listener.blameable')->setUserValue($user);

note, that $user here is the updated (managed) value

@BazylPL
Copy link

BazylPL commented Feb 11, 2019

@sam0delkin where do you set that user value? Did you created some listener onClear and injected the container?
BTW, I have a subscriber for onClear doctrine Event and tokenStorage gives me logged user (as expected)

@sam0delkin
Copy link
Author

sam0delkin commented Feb 11, 2019

@BazylPL well, i'm using this on the queue consumer... So, maybe you're using this for different purposes. But yes, i think you can create some listener that listen to onClear event, and change the user in all places you can, as well, as you should change the token:

$token = new UsernamePasswordToken($user, '', 'default');
$tokenStorage->setToken($token);

@sam0delkin
Copy link
Author

@BazylPL but want to underline that it's a hack and workaround 😄

@BazylPL
Copy link

BazylPL commented Feb 11, 2019

Yeah, I know :( We need to go deeper :)

@sam0delkin
Copy link
Author

@BazylPL well, the best solution I see here is to:

  • Add an ability to TokenStorage to detach the user. And token storage or security component will dispatch some event that the user has been detached. Next, the bundle that provides a user functionality (such as FOSUserBundle), will listen to this event, reload user and map a new managed instance into token.

Another options are:

  1. FOSUserBundle (and other ones like this bundle) will listen to a onClear event and will replace the user in token manually.
  2. The most ugly and (i think) wrong way - to update user via clear even on any Doctrine extension (like Blameable)

So, with thought above, i think this issue should be closed and addresed to some other repo....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants