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

Error in RefreshTokenManager - Support for doctrine/common +3.0 #200

Closed
HeiJon opened this issue Aug 26, 2020 · 25 comments
Closed

Error in RefreshTokenManager - Support for doctrine/common +3.0 #200

HeiJon opened this issue Aug 26, 2020 · 25 comments

Comments

@HeiJon
Copy link

HeiJon commented Aug 26, 2020

Since Doctrine Common 3.0, Common was split into smaller packages.

Actually in RefreshTokenManager you inject Doctrine\Common\Persistence\ObjectManager in constructor.

Since Doctrine Common 3.0, Doctrine\Common\Persistence\ObjectManager became Doctrine\Persistence\ObjectManager.

@byhaskell
Copy link

byhaskell commented Aug 27, 2020

Hello. Faced the same problem, my solution is:

    gesdinet.jwtrefreshtoken.refresh_token_manager:
        class: App\Doctrine\RefreshTokenManager
        public: true
        arguments: [ '@doctrine.orm.default_entity_manager', 'Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken']
<?php
namespace App\Doctrine;

use Doctrine\Persistence\ObjectManager;
use Doctrine\ORM\EntityManagerInterface;
use Gesdinet\JWTRefreshTokenBundle\Entity\RefreshTokenRepository;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManager as BaseRefreshTokenManager;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenInterface;

class RefreshTokenManager extends BaseRefreshTokenManager
{
    /**
     * @var EntityManagerInterface
     */
    protected $objectManager;
    
    /**
     * @var string
     */
    protected $class;
    
    /**
     * @var RefreshTokenRepository
     */
    protected $repository;
    
    /**
     * Constructor.
     *
     * @param ObjectManager $om
     * @param string        $class
     */
    public function __construct(ObjectManager $om, $class)
    {
        $this->objectManager = $om;
        $this->repository = $om->getRepository($class);
        $metadata = $om->getClassMetadata($class);
        $this->class = $metadata->getName();
    }
    
    /**
     * @param string $refreshToken
     *
     * @return RefreshTokenInterface
     */
    public function get($refreshToken)
    {
        return $this->repository->findOneBy(array('refreshToken' => $refreshToken));
    }
    
    /**
     * @param string $username
     *
     * @return RefreshTokenInterface
     */
    public function getLastFromUsername($username)
    {
        return $this->repository->findOneBy(array('username' => $username), array('valid' => 'DESC'));
    }
    
    /**
     * @param RefreshTokenInterface $refreshToken
     * @param bool|true             $andFlush
     */
    public function save(RefreshTokenInterface $refreshToken, $andFlush = true)
    {
        $this->objectManager->persist($refreshToken);
        
        if ($andFlush) {
            $this->objectManager->flush();
        }
    }
    
    /**
     * @param RefreshTokenInterface $refreshToken
     * @param bool                  $andFlush
     */
    public function delete(RefreshTokenInterface $refreshToken, $andFlush = true)
    {
        $this->objectManager->remove($refreshToken);
        
        if ($andFlush) {
            $this->objectManager->flush();
        }
    }
    
    /**
     * @param \DateTime $datetime
     * @param bool      $andFlush
     *
     * @return RefreshTokenInterface[]
     */
    public function revokeAllInvalid($datetime = null, $andFlush = true)
    {
        $invalidTokens = $this->repository->findInvalid($datetime);
        
        foreach ($invalidTokens as $invalidToken) {
            $this->objectManager->remove($invalidToken);
        }
        
        if ($andFlush) {
            $this->objectManager->flush();
        }
        
        return $invalidTokens;
    }
    
    /**
     * Returns the RefreshToken fully qualified class name.
     *
     * @return string
     */
    public function getClass()
    {
        return $this->class;
    }
}

@ciphrd
Copy link

ciphrd commented Aug 28, 2020

Adding the relevant error for the people coming from google:

Argument 1 passed to Gesdinet\\JWTRefreshTokenBundle\\Doctrine\\RefreshTokenManager::__construct() must be an instance of Doctrine\\Common\\Persistence\\ObjectManager, instance of Doctrine\\ORM\\EntityManager given, called in \getGesdinet_Jwtrefreshtoken_RefreshTokenManagerService.php on line 24

@adityacodes
Copy link

adityacodes commented Aug 31, 2020

Thank You @byhaskell . Added the config to services in config/services.yaml and it worked like a charm.

@ciphrd
Copy link

ciphrd commented Aug 31, 2020

I can confirm that the solution provided by @byhaskell works out of the box. Thanks !

@samikroon
Copy link

samikroon commented Sep 16, 2020

When will this be merged and released? @markitosgv

@prathje
Copy link

prathje commented Sep 22, 2020

I hope that this gets merged soon ;)
For the ones using PHPStan (based on @byhaskell):

<?php

declare(strict_types=1);

namespace App\Doctrine;

use Doctrine\Persistence\ObjectManager;
use Gesdinet\JWTRefreshTokenBundle\Entity\RefreshTokenRepository;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenInterface;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManager as BaseRefreshTokenManager;

/**
 * Class RefreshTokenManager.
 */
class RefreshTokenManager extends BaseRefreshTokenManager
{
    protected ObjectManager $objectManager;

    /**
     * @var class-string<mixed>
     */
    protected string $class;

    protected RefreshTokenRepository $repository;

    /**
     * Constructor.
     *
     * @param class-string<mixed> $class
     */
    public function __construct(ObjectManager $om, $class)
    {
        $this->objectManager = $om;

        $repo = $om->getRepository($class);
        assert($repo instanceof RefreshTokenRepository);
        $this->repository = $repo;

        $metadata = $om->getClassMetadata($class);

        /** @var class-string<mixed> $classString */
        $classString = $metadata->getName();
        $this->class = $classString;
    }

    /**
     * @param string $refreshToken
     *
     * @return ?RefreshTokenInterface
     */
    public function get($refreshToken): ?RefreshTokenInterface
    {
        $refreshToken = $this->repository->findOneBy(['refreshToken' => $refreshToken]);
        if ($refreshToken instanceof RefreshTokenInterface) {
            return $refreshToken;
        } else {
            return null;
        }
    }

    /**
     * @param string $username
     *
     * @return RefreshTokenInterface
     */
    public function getLastFromUsername($username): ?RefreshTokenInterface
    {
        $refreshToken = $this->repository->findOneBy(['username' => $username], ['valid' => 'DESC']);

        if ($refreshToken instanceof RefreshTokenInterface) {
            return $refreshToken;
        } else {
            return null;
        }
    }

    /**
     * @param bool|true $andFlush
     */
    public function save(RefreshTokenInterface $refreshToken, $andFlush = true): void
    {
        $this->objectManager->persist($refreshToken);

        if ($andFlush) {
            $this->objectManager->flush();
        }
    }

    /**
     * @param bool $andFlush
     */
    public function delete(RefreshTokenInterface $refreshToken, $andFlush = true): void
    {
        $this->objectManager->remove($refreshToken);

        if ($andFlush) {
            $this->objectManager->flush();
        }
    }

    /**
     * @param \DateTime $datetime
     * @param bool      $andFlush
     *
     * @return RefreshTokenInterface[]
     */
    public function revokeAllInvalid(?\DateTimeInterface $datetime = null, $andFlush = true)
    {
        /* @phpstan-ignore-next-line */
        $invalidTokens = $this->repository->findInvalid($datetime);

        foreach ($invalidTokens as $invalidToken) {
            $this->objectManager->remove($invalidToken);
        }

        if ($andFlush) {
            $this->objectManager->flush();
        }

        return $invalidTokens;
    }

    /**
     * Returns the RefreshToken fully qualified class name.
     *
     * @return string
     */
    public function getClass()
    {
        return $this->class;
    }
}

@shehi
Copy link

shehi commented Oct 1, 2020

Yea, stuck with this problem in doctrine/mongodb-odm.

@kayobruno
Copy link

Same problem :(

@djpremier
Copy link

djpremier commented Oct 18, 2020

Cannot autowire service "App\Doctrine\RefreshTokenManager": argument "$om" of method "__construct()" references interface "Doctrine\Persistence\ObjectManager" but no such service exists. 
You should maybe alias this interface to the existing "doctrine.orm.default_entity_manager" service.

@Ischci
Copy link

Ischci commented Oct 18, 2020

Any idea when this will be fixed?

lukasluecke added a commit to whatwedo/JWTRefreshTokenBundle that referenced this issue Oct 24, 2020
Add doctrine/common 3+ support, close markitosgv#200.
@acasademont
Copy link
Contributor

acasademont commented Nov 5, 2020

A simpler approach until this is fixed upstream:

override the service:

    gesdinet.jwtrefreshtoken.refresh_token_manager:
      class:  App\Doctrine\RefreshTokenManager
      public: true
      arguments: [ '@gesdinet.jwtrefreshtoken.object_manager', '%gesdinet.jwtrefreshtoken.refresh_token.class%' ]

and on the class just override the contructor

<?php

namespace App\Doctrine;

use Doctrine\Persistence\ObjectManager;

class RefreshTokenManager extends \Gesdinet\JWTRefreshTokenBundle\Doctrine\RefreshTokenManager
{
    public function __construct(ObjectManager $om, $class)
    {
        $this->objectManager = $om;
        $this->repository = $om->getRepository($class);
        $metadata = $om->getClassMetadata($class);
        $this->class = $metadata->getName();
    }
}

@MrMitch
Copy link

MrMitch commented Nov 6, 2020

@acasademont if you do that, be careful to use the right namespace in the class property of your YAML definition.

In your example, the class of you YAML is App\Doctrine\RefreshTokenManager and the FQDN of the PHP class you provide is App\Infrastructure\Share\Doctrine\RefreshTokenManager.

Those 2 values should match.

@acasademont
Copy link
Contributor

acasademont commented Nov 6, 2020 via email

@MarlonAEC
Copy link

@byhaskell yeah, excellent that worked for me, thanks!!... I hope the team merges this soon!! Regards!!!

@Bogro
Copy link

Bogro commented Nov 27, 2020

I had the same problem and I confirm that @byhaskell solution is the right one. Thank you!

@c7nj7n
Copy link

c7nj7n commented Nov 27, 2020

@acasademont your shorter solution works like charm, thanks and kudos!

@terox
Copy link

terox commented Dec 1, 2020

The @acasademont solution works perfectly. Thank you

Waiting the merge :)

@fd6130
Copy link
Contributor

fd6130 commented Dec 2, 2020

Thx for the solution. I hope the PR will get merge as soon as possible.

@lyrixx
Copy link
Contributor

lyrixx commented Dec 2, 2020

Hello @markitosgv

There are 5 PR to address this issue:

Could you merge one of theses please ?


And if you don't have time for this, this not a big deal. But Could you give write permissions to someone else? 🙏🏼

Have a nice day

@richard-keller
Copy link

Thank you @byhaskell. Worked perfectly.

@johnnydi
Copy link

johnnydi commented Dec 17, 2020

EDIT : got it. you need to place the new RefreshTokenManager class in the right place. in my case : src/Doctrine/RefreshTokenManager/RefreshTokenManager.php . You can see in the service.yaml that its loaded and placed in the right path. Thanks @ all it now works for me

Hi, first of all thank you all for your insights.
I tried the solutions in this thread but got the following ClassNotFound exception in var/cache/dev/ContainerDCJtw8v/getGesdinet_Jwtrefreshtoken_RefreshTokenManagerService.php (line 20):

* * @return \App\Doctrine\RefreshTokenManager */ public static function do($container, $lazyLoad = true) { return $container->services['gesdinet.jwtrefreshtoken.refresh_token_manager'] = new \App\Doctrine\RefreshTokenManager(($container->services['doctrine.orm.default_entity_manager'] ?? $container->getDoctrine_Orm_DefaultEntityManagerService()), 'Gesdinet\\JWTRefreshTokenBundle\\Entity\\RefreshToken'); }}

my services.yaml looks like this-

`
services:
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

App\:
    resource: '../src/'
    exclude:
        - '../src/DependencyInjection/'
        - '../src/Entity/'
        - '../src/Kernel.php'
        - '../src/Tests/'

# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
    resource: '../src/Controller/'
    tags: ['controller.service_arguments']

# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones

gesdinet.jwtrefreshtoken.refresh_token_manager:
    class: App\Doctrine\RefreshTokenManager
    public: true
    arguments: [ '@doctrine.orm.default_entity_manager', 'Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken' ]

`

And i created the folders "App/Doctrine" and added the class with the following code in this folder

`<?php
namespace App\Doctrine;

use Doctrine\Persistence\ObjectManager;
use Doctrine\ORM\EntityManagerInterface;
use Gesdinet\JWTRefreshTokenBundle\Entity\RefreshTokenRepository;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManager as BaseRefreshTokenManager;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenInterface;

class RefreshTokenManager extends BaseRefreshTokenManager
{
/**
* @var EntityManagerInterface
*/
protected $objectManager;

/**
 * @var string
 */
protected $class;

/**
 * @var RefreshTokenRepository
 */
protected $repository;

/**
 * Constructor.
 *
 * @param ObjectManager $om
 * @param string        $class
 */
public function __construct(ObjectManager $om, $class)
{
    $this->objectManager = $om;
    $this->repository = $om->getRepository($class);
    $metadata = $om->getClassMetadata($class);
    $this->class = $metadata->getName();
}

/**
 * @param string $refreshToken
 *
 * @return RefreshTokenInterface
 */
public function get($refreshToken)
{
    return $this->repository->findOneBy(array('refreshToken' => $refreshToken));
}

/**
 * @param string $username
 *
 * @return RefreshTokenInterface
 */
public function getLastFromUsername($username)
{
    return $this->repository->findOneBy(array('username' => $username), array('valid' => 'DESC'));
}

/**
 * @param RefreshTokenInterface $refreshToken
 * @param bool|true             $andFlush
 */
public function save(RefreshTokenInterface $refreshToken, $andFlush = true)
{
    $this->objectManager->persist($refreshToken);

    if ($andFlush) {
        $this->objectManager->flush();
    }
}

/**
 * @param RefreshTokenInterface $refreshToken
 * @param bool                  $andFlush
 */
public function delete(RefreshTokenInterface $refreshToken, $andFlush = true)
{
    $this->objectManager->remove($refreshToken);

    if ($andFlush) {
        $this->objectManager->flush();
    }
}

/**
 * @param \DateTime $datetime
 * @param bool      $andFlush
 *
 * @return RefreshTokenInterface[]
 */
public function revokeAllInvalid($datetime = null, $andFlush = true)
{
    $invalidTokens = $this->repository->findInvalid($datetime);

    foreach ($invalidTokens as $invalidToken) {
        $this->objectManager->remove($invalidToken);
    }

    if ($andFlush) {
        $this->objectManager->flush();
    }

    return $invalidTokens;
}

/**
 * Returns the RefreshToken fully qualified class name.
 *
 * @return string
 */
public function getClass()
{
    return $this->class;
}

}
`
Any ideas? Thank you in Advance

@samikroon
Copy link

@johnnydi clear the cache should fix that, otherwise remove the contents of the cache folder.

@markitosgv
Copy link
Owner

Solved in v0.10.0, please confirm that!

@lyrixx
Copy link
Contributor

lyrixx commented Dec 28, 2020

Hello @markitosgv
Thanks for taking time to fix this issue.
I confirm the latest release fixed our CI with Symfony 5.2

@acasademont
Copy link
Contributor

I can also confirm the issue has been fixed, thanks @markitosgv! I believe this issue could be closed

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

Successfully merging a pull request may close this issue.