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

Draft: rough draft to add doctrine ODM support #179

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ phpunit.xml

# Tests
tests/.kernel/

.idea/
7 changes: 5 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
],
"require": {
"php": "^8.1",
"doctrine/doctrine-bundle": "^2.0.8",
"doctrine/orm": "^2.7.1",
"league/oauth2-server": "^8.3",
"nyholm/psr7": "^1.4",
"psr/http-factory": "^1.0",
Expand All @@ -31,6 +29,11 @@
"require-dev": {
"ext-pdo": "*",
"ext-pdo_sqlite": "*",
"ext-mongodb": "*",
"doctrine/doctrine-bundle": "^2.0.8",
"doctrine/mongodb-odm": "2.7.x-dev",
"doctrine/mongodb-odm-bundle": "4.7.x-dev",
"doctrine/orm": "^2.7.1",
"symfony/browser-kit": "^5.4|^6.2|^7.0",
"symfony/phpunit-bridge": "^5.4|^6.2|^7.0"
},
Expand Down
3 changes: 3 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ For implementation into Symfony projects, please see [bundle documentation](basi

# Table name prefix.
table_prefix: oauth2_
doctrine_odm:
document_manager: default
collection_prefix: oauth2_
in_memory: ~

# Set a custom prefix that replaces the default 'ROLE_OAUTH2_' role prefix
Expand Down
14 changes: 14 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,20 @@ private function createPersistenceNode(): NodeDefinition
->end()
->end()
->end()
->arrayNode('doctrine_odm')
->children()
->scalarNode('document_manager')
->info('Name of the document manager that you wish to use for managing clients and tokens.')
->cannotBeEmpty()
->defaultValue('default')
->end()
->scalarNode('collection_prefix')
->info('Collection name prefix.')
->cannotBeEmpty()
->defaultValue('oauth2_')
->end()
->end()
->end()
// In-memory persistence
->scalarNode('in_memory')
->end()
Expand Down
38 changes: 24 additions & 14 deletions src/DependencyInjection/LeagueOAuth2ServerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace League\Bundle\OAuth2ServerBundle\DependencyInjection;

use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
use Doctrine\Bundle\MongoDBBundle\DoctrineMongoDBBundle;
use League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantTypeInterface;
use League\Bundle\OAuth2ServerBundle\Command\CreateClientCommand;
use League\Bundle\OAuth2ServerBundle\DBAL\Type\Grant as GrantType;
Expand All @@ -16,7 +17,8 @@
use League\Bundle\OAuth2ServerBundle\Manager\Doctrine\RefreshTokenManager;
use League\Bundle\OAuth2ServerBundle\Manager\InMemory\AccessTokenManager as InMemoryAccessTokenManager;
use League\Bundle\OAuth2ServerBundle\Manager\ScopeManagerInterface;
use League\Bundle\OAuth2ServerBundle\Persistence\Mapping\Driver;
use League\Bundle\OAuth2ServerBundle\Persistence\Mapping\Doctrine\ODM\Driver as DoctrineODMDriver;
use League\Bundle\OAuth2ServerBundle\Persistence\Mapping\Doctrine\ORM\Driver as DoctrineORMDrive;
use League\Bundle\OAuth2ServerBundle\Security\Authenticator\OAuth2Authenticator;
use League\Bundle\OAuth2ServerBundle\Service\CredentialsRevoker\DoctrineCredentialsRevoker;
use League\Bundle\OAuth2ServerBundle\ValueObject\Scope as ScopeModel;
Expand Down Expand Up @@ -105,6 +107,7 @@ private function assertRequiredBundlesAreEnabled(ContainerBuilder $container): v
{
$requiredBundles = [
'doctrine' => DoctrineBundle::class,
'doctrine_mongodb' => DoctrineMongoDBBundle::class,
'security' => SecurityBundle::class,
];

Expand Down Expand Up @@ -227,55 +230,62 @@ private function configurePersistence(LoaderInterface $loader, ContainerBuilder
break;
case 'doctrine':
$loader->load('storage/doctrine.php');
$this->configureDoctrinePersistence($container, $config, $persistenceConfig);
$this->configureDoctrinePersistence($container, $config, $persistenceConfig, 'doctrine');
break;
case 'doctrine_odm':
$loader->load('storage/doctrine_odm.php');
$this->configureDoctrinePersistence($container, $config, $persistenceConfig, 'doctrine_odm');
break;
}
}

private function configureDoctrinePersistence(ContainerBuilder $container, array $config, array $persistenceConfig): void
private function configureDoctrinePersistence(ContainerBuilder $container, array $config, array $persistenceConfig, string $type): void
{
$entityManagerName = $persistenceConfig['entity_manager'];
$doctrineManager = $type === 'doctrine_odm' ? 'document_manager' : 'entity_manager';
$doctrineConfigPrefix = $type === 'doctrine_odm' ? 'doctrine_mongodb.odm' : 'doctrine.orm';

$objectManagerName = $persistenceConfig[$doctrineManager];

$entityManager = new Reference(
sprintf('doctrine.orm.%s_entity_manager', $entityManagerName)
$objectManager = new Reference(
sprintf('%s.%s_%s', $doctrineConfigPrefix, $objectManagerName, $doctrineManager)
);

$container
->findDefinition(AccessTokenManager::class)
->replaceArgument(0, $entityManager)
->replaceArgument(0, $objectManager)
->replaceArgument(1, $config['authorization_server']['persist_access_token'])
;

$container
->findDefinition(ClientManager::class)
->replaceArgument(0, $entityManager)
->replaceArgument(0, $objectManager)
->replaceArgument(2, $config['client']['classname'])
;

$container
->findDefinition(RefreshTokenManager::class)
->replaceArgument(0, $entityManager)
->replaceArgument(0, $objectManager)
;

$container
->findDefinition(AuthorizationCodeManager::class)
->replaceArgument(0, $entityManager)
->replaceArgument(0, $objectManager)
;

$container
->findDefinition(DoctrineCredentialsRevoker::class)
->replaceArgument(0, $entityManager)
->replaceArgument(0, $objectManager)
;

$container
->findDefinition(Driver::class)
->findDefinition($type === 'doctrine_odm'? DoctrineODMDriver::class : DoctrineORMDrive::class)
->replaceArgument(0, $config['client']['classname'])
->replaceArgument(1, $config['authorization_server']['persist_access_token'])
->replaceArgument(2, $persistenceConfig['table_prefix'])
;

$container->setParameter('league.oauth2_server.persistence.doctrine.enabled', true);
$container->setParameter('league.oauth2_server.persistence.doctrine.manager', $entityManagerName);
$container->setParameter("league.oauth2_server.persistence.$type.enabled", true);
$container->setParameter("league.oauth2_server.persistence.$type.manager", $objectManagerName);
}

private function configureInMemoryPersistence(ContainerBuilder $container, array $config): void
Expand Down
32 changes: 23 additions & 9 deletions src/LeagueOAuth2ServerBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
namespace League\Bundle\OAuth2ServerBundle;

use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\DoctrineMongoDBMappingsPass;
use League\Bundle\OAuth2ServerBundle\DependencyInjection\CompilerPass\EncryptionKeyPass;
use League\Bundle\OAuth2ServerBundle\DependencyInjection\LeagueOAuth2ServerExtension;
use League\Bundle\OAuth2ServerBundle\DependencyInjection\Security\OAuth2Factory;
use League\Bundle\OAuth2ServerBundle\Persistence\Mapping\Driver;
use League\Bundle\OAuth2ServerBundle\Persistence\Mapping\Doctrine\ODM\Driver as DoctrineODMDriver;
use League\Bundle\OAuth2ServerBundle\Persistence\Mapping\Doctrine\ORM\Driver as DoctrineORMDriver;
use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
Expand Down Expand Up @@ -56,14 +58,26 @@ private function configureSecurityExtension(ContainerBuilder $container): void

private function configureDoctrineExtension(ContainerBuilder $container): void
{
$container->addCompilerPass(
new DoctrineOrmMappingsPass(
new Reference(Driver::class),
['League\Bundle\OAuth2ServerBundle\Model'],
['league.oauth2_server.persistence.doctrine.manager'],
'league.oauth2_server.persistence.doctrine.enabled'
)
);
if (class_exists(DoctrineOrmMappingsPass::class)) {
$container->addCompilerPass(
new DoctrineOrmMappingsPass(
new Reference(DoctrineORMDriver::class),
['League\Bundle\OAuth2ServerBundle\Model'],
['league.oauth2_server.persistence.doctrine.manager'],
'league.oauth2_server.persistence.doctrine.enabled'
)
);
}
if (class_exists(DoctrineMongoDBMappingsPass::class)) {
$container->addCompilerPass(
new DoctrineMongoDBMappingsPass(
new Reference(DoctrineODMDriver::class),
['League\Bundle\OAuth2ServerBundle\Model'],
['league.oauth2_server.persistence.doctrine_odm.manager'],
'league.oauth2_server.persistence.doctrine_odm.enabled'
)
);
}

$container->addCompilerPass(new EncryptionKeyPass());
}
Expand Down
18 changes: 9 additions & 9 deletions src/Manager/Doctrine/AccessTokenManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@

namespace League\Bundle\OAuth2ServerBundle\Manager\Doctrine;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager;
use League\Bundle\OAuth2ServerBundle\Manager\AccessTokenManagerInterface;
use League\Bundle\OAuth2ServerBundle\Model\AccessToken;
use League\Bundle\OAuth2ServerBundle\Model\AccessTokenInterface;

final class AccessTokenManager implements AccessTokenManagerInterface
{
/**
* @var EntityManagerInterface
* @var ObjectManager
*/
private $entityManager;
private $objectManager;

/** @var bool */
private $persistAccessToken;

public function __construct(EntityManagerInterface $entityManager, bool $persistAccessToken)
public function __construct(ObjectManager $objectManager, bool $persistAccessToken)
{
$this->entityManager = $entityManager;
$this->objectManager = $objectManager;
$this->persistAccessToken = $persistAccessToken;
}

Expand All @@ -31,7 +31,7 @@ public function find(string $identifier): ?AccessTokenInterface
return null;
}

return $this->entityManager->find(AccessToken::class, $identifier);
return $this->objectManager->find(AccessToken::class, $identifier);
}

public function save(AccessTokenInterface $accessToken): void
Expand All @@ -40,8 +40,8 @@ public function save(AccessTokenInterface $accessToken): void
return;
}

$this->entityManager->persist($accessToken);
$this->entityManager->flush();
$this->objectManager->persist($accessToken);
$this->objectManager->flush();
}

public function clearExpired(): int
Expand All @@ -51,7 +51,7 @@ public function clearExpired(): int
}

/** @var int */
return $this->entityManager->createQueryBuilder()
return $this->objectManager->createQueryBuilder()
->delete(AccessToken::class, 'at')
->where('at.expiry < :expiry')
->setParameter('expiry', new \DateTimeImmutable(), 'datetime_immutable')
Expand Down
18 changes: 9 additions & 9 deletions src/Manager/Doctrine/AuthorizationCodeManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,38 @@

namespace League\Bundle\OAuth2ServerBundle\Manager\Doctrine;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager;
use League\Bundle\OAuth2ServerBundle\Manager\AuthorizationCodeManagerInterface;
use League\Bundle\OAuth2ServerBundle\Model\AuthorizationCode;
use League\Bundle\OAuth2ServerBundle\Model\AuthorizationCodeInterface;

final class AuthorizationCodeManager implements AuthorizationCodeManagerInterface
{
/**
* @var EntityManagerInterface
* @var ObjectManager
*/
private $entityManager;
private $objectManager;

public function __construct(EntityManagerInterface $entityManager)
public function __construct(ObjectManager $objectManager)
{
$this->entityManager = $entityManager;
$this->objectManager = $objectManager;
}

public function find(string $identifier): ?AuthorizationCodeInterface
{
return $this->entityManager->find(AuthorizationCode::class, $identifier);
return $this->objectManager->find(AuthorizationCode::class, $identifier);
}

public function save(AuthorizationCodeInterface $authCode): void
{
$this->entityManager->persist($authCode);
$this->entityManager->flush();
$this->objectManager->persist($authCode);
$this->objectManager->flush();
}

public function clearExpired(): int
{
/** @var int */
return $this->entityManager->createQueryBuilder()
return $this->objectManager->createQueryBuilder()
->delete(AuthorizationCode::class, 'ac')
->where('ac.expiry < :expiry')
->setParameter('expiry', new \DateTimeImmutable(), 'datetime_immutable')
Expand Down
25 changes: 13 additions & 12 deletions src/Manager/Doctrine/ClientManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace League\Bundle\OAuth2ServerBundle\Manager\Doctrine;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager;
use League\Bundle\OAuth2ServerBundle\Event\PreSaveClientEvent;
use League\Bundle\OAuth2ServerBundle\Manager\ClientFilter;
use League\Bundle\OAuth2ServerBundle\Manager\ClientManagerInterface;
Expand All @@ -19,9 +19,9 @@
final class ClientManager implements ClientManagerInterface
{
/**
* @var EntityManagerInterface
* @var ObjectManager
*/
private $entityManager;
private $objectManager;

/**
* @var class-string<AbstractClient>
Expand All @@ -37,18 +37,19 @@ final class ClientManager implements ClientManagerInterface
* @param class-string<AbstractClient> $clientFqcn
*/
public function __construct(
EntityManagerInterface $entityManager,
ObjectManager $objectManager,
EventDispatcherInterface $dispatcher,
string $clientFqcn
) {
$this->entityManager = $entityManager;
)
{
$this->objectManager = $objectManager;
$this->dispatcher = $dispatcher;
$this->clientFqcn = $clientFqcn;
}

public function find(string $identifier): ?ClientInterface
{
$repository = $this->entityManager->getRepository($this->clientFqcn);
$repository = $this->objectManager->getRepository($this->clientFqcn);

return $repository->findOneBy(['identifier' => $identifier]);
}
Expand All @@ -58,22 +59,22 @@ public function save(ClientInterface $client): void
$event = $this->dispatcher->dispatch(new PreSaveClientEvent($client), OAuth2Events::PRE_SAVE_CLIENT);
$client = $event->getClient();

$this->entityManager->persist($client);
$this->entityManager->flush();
$this->objectManager->persist($client);
$this->objectManager->flush();
}

public function remove(ClientInterface $client): void
{
$this->entityManager->remove($client);
$this->entityManager->flush();
$this->objectManager->remove($client);
$this->objectManager->flush();
}

/**
* @return list<AbstractClient>
*/
public function list(?ClientFilter $clientFilter): array
{
$repository = $this->entityManager->getRepository($this->clientFqcn);
$repository = $this->objectManager->getRepository($this->clientFqcn);
$criteria = self::filterToCriteria($clientFilter);

/** @var list<AbstractClient> */
Expand Down
Loading