Symfony2: SonataAdminBundle - How can i get the object representing the current user inside an admin class?
Asked Answered
U

3

9

I use the sonata-admin bundle. I have the relationship with the user (FOSUserBundle) in the PageEntity. I want to save the current user which create or change a page.

My guess is get the user object in postUpdate and postPersist methods of the admin class and this object transmit in setUser method.

But how to realize this?

On the google's group I saw

    public function setSecurityContext($securityContext) {
        $this->securityContext = $securityContext;
    }

    public function getSecurityContext() {
        return $this->securityContext;
    }

    public function prePersist($article) {
        $user = $this->getSecurityContext()->getToken()->getUser();

        $appunto->setOperatore($user->getUsername());
    }

but this doesn't work

Ube answered 27/2, 2014 at 13:10 Comment(5)
What do you mean by "doesn't work"? Were there any error message?Atlantes
How and where do you pass the current security context to your entity's setSecurityContext() method? You should probably create a listener/subscriber instead of using lifecycle events to perform such an operation btw.Ruyle
There is "FatalErrorException: Error: Call to a member function getToken() on a non-object"Ube
nifr, in the admin class also.Ube
nifr, thank, I have created listener/subscriber, the error message already doesn't display. But user dosn't save in the page entity. There aren't errors, but field for the user id is empty in the page table.Ube
A
27

In the admin class you can get the current logged in user like this:

$this->getConfigurationPool()->getContainer()->get('security.token_storage')->getToken()->getUser()

EDIT based on feedback

And you are doing it this? Because this should work.

 /**
     * {@inheritdoc}
     */
    public function prePersist($object)
    {

$user = $this->getConfigurationPool()->getContainer()->get('security.token_storage')->getToken()->getUser();
        $object->setUser($user);
    }

    /**
     * {@inheritdoc}
     */
    public function preUpdate($object)
    {
$user = $this->getConfigurationPool()->getContainer()->get('security.token_storage')->getToken()->getUser();
        $object->setUser($user);
    }
Attractive answered 27/2, 2014 at 13:50 Comment(10)
No errors, but don't save in the table also. My code $user = $this->getConfigurationPool()->getContainer()->get('security.context')->getToken()->getUser(); $object->setUser($user);Ube
yes, is the same. Probably, issue is in the user entity, therefore my code don't work...Ube
Right, I have decided my problem with the user now. Your code works.Ube
security.context component is deprecated since 2.6 and removed since 3.0, use security.token_storage instead.Marbut
@Marbut : strangely, the token is null when I try this.Agitator
@Agitator on what symfony version do you are? It's surely a cache issue, be sure that you use $this->getConfigurationPool()->getContainer()->get('security.token_storage')->getToken()->getUser() . See the corresponding changelog.Marbut
I'm using 2.8, and I got the issue in CI too, so probably not a cache issue, but I'll try clearing the cache locally tomorrow. Please note that I get a TokenStorage object, but the token inside is nullAgitator
@Marbut : I found a solution : inject the token storage properly, with the admin constructor. Otherwise, I think symfony does not "see" the dependency and does not build the service properly.Agitator
@Agitator Glad to hear that! For a lot of 3rd party bundles, this service has been configured through hacks In compiler passes and bundle extension in order to keep the compatibility with versions < 2.6, so it surely need to be explicitly set in your sonata+sf versionsMarbut
I posted an answer below (below for the moment ;) )Agitator
A
8

Starting with symfony 2.8, you should use security.token_storage instead of security.context to retrieve the user. Use constructor injection to get it in your admin:

public function __construct(
    $code,
    $class,
    $baseControllerName,
    TokenStorageInterface $tokenStorage
) {
    parent::__construct($code, $class, $baseControllerName);
    $this->tokenStorage = $tokenStorage;
}

admin.yml :

    arguments:
        - ~
        - Your\Entity
        - ~
        - '@security.token_storage'

then use $this->tokenStorage->getToken()->getUser() to get the current user.

Agitator answered 12/4, 2016 at 9:54 Comment(0)
P
1

I was dealing with this issue on the version 5.3.10 of symfony and 4.2 of sonata. The answer from greg0ire was really helpful, also this info from symfony docs, here is my approach:

In my case I was trying to set a custom query based on a property from User.

// ... 
use Symfony\Component\Security\Core\Security;

final class YourClassAdmin extends from AbstractAdmin {
    // ... 
    private $security;
    public function __construct($code, $class, $baseControllerName, Security $security)
    {
        parent::__construct($code, $class, $baseControllerName);
        // Avoid calling getUser() in the constructor: auth may not
        // be complete yet. Instead, store the entire Security object.
        $this->security = $security;
    }

    // customize the query used to generate the list
    protected function configureQuery(ProxyQueryInterface $query): ProxyQueryInterface 
    {
        $query = parent::configureQuery($query);
        $rootAlias = current($query->getRootAliases());
        // ..
        $user = $this->security->getUser();
        // ...    
        return $query;
    }

}
Pyromorphite answered 9/12, 2021 at 8:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.