FpOpenIdBundle implement interface error - php

I am working on an authentication with FpOpenIdBundle but i get this error
Catchable Fatal Error: Argument 1 passed to Fp\OpenIdBundle\Model\UserIdentity::setUser() must implement interface Symfony\Component\Security\Core\User\UserInterface, instance of Doctrine\ODM\MongoDB\DocumentRepository given, called in C:\xampp\htdocs\project\src\AppBundle\Security\User\OpenIdUserManager.php on line 64 and defined
I followed the doc (https://github.com/formapro/FpOpenIdBundle/blob/master/Resources/doc/configure_user_manager.md)
I have made a manager
namespace AppBundle\Security\User;
use AppBundle\Document\User;
use AppBundle\Document\OpenIdIdentity;
use Doctrine\ODM\MongoDB\DocumentManager;
use Fp\OpenIdBundle\Model\UserManager;
use Fp\OpenIdBundle\Model\IdentityManagerInterface;
class OpenIdUserManager extends UserManager
{
/**
* #var DocumentManager
*/
private $documentManager;
/**
* OpenIdUserManager constructor.
*
* #param IdentityManagerInterface $identityManager
* #param DocumentManager $documentManager
*/
public function __construct(IdentityManagerInterface $identityManager, DocumentManager $documentManager)
{
parent::__construct($identityManager);
$this->documentManager = $documentManager;
}
/**
* #param string $identity
* #param array $attributes
*
* #return \Doctrine\ODM\MongoDB\DocumentRepository
*/
public function createUserFromIdentity($identity, array $attributes = array())
{
$user = $this->documentManager->getRepository('AppBundle:User');
$openIdIdentity = new OpenIdIdentity();
$openIdIdentity->setIdentity($identity);
$openIdIdentity->setAttributes($attributes);
$openIdIdentity->setUser($user);
$this->documentManager->persist($openIdIdentity);
$this->documentManager->flush();
return $user;
}
}
The error is returned because of this line
$openIdIdentity->setUser($user);
I use this manager as the service like this
services:
fp_openid.manager:
class: AppBundle\Security\User\OpenIdUserManager
arguments: [ '#fp_openid.identity_manager', '#doctrine.odm.mongodb.document_manager' ]
Who's called by my security.yml
security:
firewalls:
main:
fp_openid:
create_user_if_not_exists: true
provider: openid_user_manager
providers:
openid_user_manager:
id: fp_openid.manager
main:
entity:
{ class: AppBundle:User, property: personaName }
I finally made a MongoDB document as they said
namespace AppBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use Symfony\Component\Security\Core\User\UserInterface;
use Fp\OpenIdBundle\Document\UserIdentity as BaseUserIdentity;
/**
* #MongoDB\Document(collection="openid_identities")
*/
class OpenIdIdentity extends BaseUserIdentity
{
/**
* #MongoDB\Id(strategy="auto")
*/
protected $id;
/**
* {#inheritdoc}
* #MongoDB\String
*/
protected $identity;
/**
* {#inheritdoc}
* #MongoDB\Hash
*/
protected $attributes;
/**
* #var UserInterface
*
* #MongoDB\ReferenceOne(targetDocument="AppBundle\Document\User", simple=true)
*/
protected $user;
public function __construct()
{
parent::__construct();
}
}
Everythings is working well except this problem, i don't understand why this is not working whereas i do the same as the doc said. I must implement UserInterface instead of instance of DocumentRepository but they use their user document instead.
Does some already use this bundle and had this issue ?
Thanks for helping

Please carefully read the doc again, in the doc it's:
$user = $this->entityManager->getRepository('AcmeDemoBundle:User')->findOneBy(array(
'email' => $attributes['contact/email']
));

Related

Symfony4 extends controller with route annotation

I'm building a webapp with Symfony and since now I had to repeat a specific pattern for each new controller I built.
For example I have this AdminController :
/**
* #Route("/pro/{uniqid}")
* #ParamConverter("company", options={"mapping":{"uniqid" = "uniqid"}})
* #Security("is_granted(constant('App\\Security\\Voter\\CompanyVoter::VIEW'), company)")
* #package App\Controller
*/
class AdminController extends Controller
{
/**
* #Route("/admin/users/", name="users")
* #return \Symfony\Component\HttpFoundation\Response
*/
public function users(Company $company){}
}
So, each controller must redefine #Route, #ParamConverter and #Security that is extremely redundant.
I tried to create a LoggedController that define every annotation, then make Controller extends that LoggedController, but that does not work.
Is there a solution or should I continue to copy/paste these Annotation each time I create a new Controller that needs to implement it ?
EDIT :
I add the declaration of Company entity :
/**
* #ORM\Entity(repositoryClass="App\Repository\CompanyRepository")
*/
class Company
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
Long story short, you can but it will be a lot easier to duplicate your annotations in every controller.
But if you wan't to do this anyway, here are some solutions.
Routing
This is the easy one. You can define a global prefix in the config/routes/annotations.yaml file.
If you're using the default config, you can try something like this:
# Default controllers
controllers:
resource: ../../src/Controller/
type: annotation
# Company controllers
company_controllers:
resource: ../../src/Controller/Company/
type: annotation
prefix: /pro/{uniqid}
All your routes will now start with /pro/{uniqid} and you can remove the #Route annotation from your controller.
ParamConverter
You can create your own ParamConverter. Everytime you'll use a Company type in an action method, it'll be converted to the matching entity using the uniqid attribute.
Something like this:
// src/ParamConverter/CompanyConverter.php
<?php
namespace App\ParamConverter;
use App\Entity\Company;
use Doctrine\ORM\EntityManagerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
use Symfony\Component\HttpFoundation\Request;
class CompanyConverter implements ParamConverterInterface
{
const CONVERTER_ATTRIBUTE = 'uniqid';
/**
* #var EntityManagerInterface
*/
private $entityManager;
/**
* CompanyConverter constructor.
*
* #param EntityManagerInterface $entityManager
*/
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* #inheritdoc
*/
public function apply(Request $request, ParamConverter $configuration)
{
$uniqid = $request->attributes->get(self::CONVERTER_ATTRIBUTE);
$company = $this->entityManager->getRepository(Company::class)->findOneBy(['uniqid' => $uniqid]);
$request->attributes->set($configuration->getName(), $company);
}
/**
* #inheritdoc
*/
function supports(ParamConverter $configuration)
{
return $configuration->getClass() === Company::class;
}
}
With this, you can remove the #ParamConverter annotation from your controller.
Security
You can't use the access_control section of the security.yaml file since custom functions are not yet supported.
Otherwise, something like this could have been nice:
security:
...
access_control:
-
path: ^/pro
allow_if: "is_granted(constant('App\\Security\\Voter\\CompanyVoter::VIEW'), company)"
(Note: It was fixed in Symfony 4.1 but i don't know yet how it will work).
Instead, you can use a subscriber listening on the kernel.request kernel event:
<?php
namespace App\Subscriber;
use App\Entity\Company;
use App\Security\CompanyVoter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
class SecurityListener implements EventSubscriberInterface
{
/**
* #var AuthorizationCheckerInterface
*/
private $authorizationChecker;
/**
* #var EntityManagerInterface
*/
private $entityManager;
/**
* #param AuthorizationCheckerInterface $authorizationChecker
* #param EntityManagerInterface $entityManagerInterface
*/
public function __construct(AuthorizationCheckerInterface $authorizationChecker, EntityManagerInterface $entityManager)
{
$this->authorizationChecker = $authorizationChecker;
$this->entityManager = $entityManager;
}
/**
* #param GetResponseEvent $event
*/
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if (!$uniqid = $request->attributes->get('uniqid')) {
return;
}
$company = $this->entityManager->getRepository(Company::class)->findOneBy(['titre' => $uniqid]);
if (!$this->authorizationChecker->isGranted(CompanyVoter::VIEW, $company)) {
throw new AccessDeniedHttpException();
}
}
/**
* #return array
*/
public static function getSubscribedEvents()
{
return array(
KernelEvents::REQUEST => 'onKernelRequest',
);
}
}

How to create custom endpoint in API Platform and add it to the documentation?

I want to create not mapped with entity endpoint like /api/v1/me that returns information (User object) about currently authenticated user and add it to my documentation. In the plans I also want to add endpoints like /api/v1/account/recover and /api/v1/account/verify-email.
I have an action:
namespace AppBundle\Action\Me;
use AppBundle\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class MeView
{
/**
* #var TokenStorageInterface
*/
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
/**
* #Security("is_authenticated()")
*
* #Route(
* name="me_view",
* path="/me",
* methods={"GET"}
* )
*
* #return User
*/
public function __invoke()
{
return $this->tokenStorage->getToken()->getUser();
}
}
But when I try to access it, it returns an exception:
The controller must return a response (Object(AppBundle\Entity\User) given). (500 Internal Server Error)
Same action, but mapped with entity, works well:
namespace AppBundle\Action\City;
use AppBundle\Entity\City;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\Routing\Annotation\Route;
class CityView
{
/**
* #Security("is_authenticated()")
*
* #Route(
* name="city_view",
* path="/cities/{id}",
* methods={"GET"},
* defaults={"_api_resource_class"=City::class, "_api_item_operation_name"="view"}
* )
*
* #param City $city
* #return City
*/
public function __invoke(City $city)
{
return $city;
}
}
What should I do to make my custom action work and how to add it to auto-generated Swagger documentation?
Controller:
class MyUserController extends Controller
{
public function fn_me()
{
return $this->getUser();
}
}
Entity:
* #ApiResource(
* collectionOperations={
* "get","post",
* "collName_api_me"={"route_name"="api_me"}
* }
* )
*/
class User implements UserInterface, \Serializable
routes.yaml
api_me:
path: '/api/me'
methods: ['GET']
defaults:
_controller: '\App\Controller\MyUserController::fn_me'
_api_resource_class: 'App\Entity\User'
_api_collection_operation_name: 'collName_api_me'

Invalid argument key "nameOfTheArgument" found symfony3 (Extending an abstract service)

I'm getting the error invalid argument key "articleBuilder", when I launch a console command from symfony3.
I have extended an abstract service, and I'm including the configurations and the classes code that I have used.
Given as the configuration of my parent class service:
app.service.user.access_controller:
abstract: true
class: '%app.service.user.access_controller.class%'
arguments:
currentUser: "#=service('security.token_storage').getToken().getUser()"
userRoleProvider: '#app.repository.user.user_role_repository'
Where this is the parent service class:
<?php
namespace AppBundle\Service\User;
use AppBundle\Exception\User\AccessControlException;
use AppBundle\ModelInterface\User\OwnableInterface;
use AppBundle\ModelInterface\User\UserInterface;
use AppBundle\ServiceInterface\User\UserRoleProviderInterface;
/**
* Class AccessController
* #package AppBundle\Service\User
*/
abstract class AccessController
{
/** #var UserInterface */
protected $currentUser;
/** #var UserRoleProviderInterface */
protected $userRoleProvider;
/**
* AccessControlledService constructor.
* #param UserInterface $currentUser
* #param UserRoleProviderInterface $userRoleProvider
*/
public function __construct(UserInterface $currentUser, UserRoleProviderInterface $userRoleProvider)
{
$this->currentUser = $currentUser;
$this->userRoleProvider = $userRoleProvider;
}
And where this is my child service definition:
app.controller.article.article_json_api_controller:
class: '%app.controller.article.article_json_api_controller.class%'
parent: 'app.service.user.access_controller'
arguments:
articleBuilder: '#app.service.article.doctrine_orm.article_entity.builder'
articlePersister: '#app.service.article.doctrine_orm.article_entity.persister'
articleProvider: '#app.repository.article.article_repository'
articleUpdater: '#app.service.article.updater'
articleDestroyer: '#app.service.article.doctrine_orm.article_entity.destroyer'
languageProvider: '#app.repository.language.language_repository'
sectionBuilder: '#app.service.article.doctrine_orm.article_section_entity.builder'
sectionUpdater: '#app.service.article.article_section.updater'
And this is my child service class:
class ArticleJsonApiController extends AccessController
{
/** #var UserInterface */
private $currentUser;
/** #var ArticleBuilderInterface */
private $articleBuilder;
/** #var ArticlePeristerInterface */
private $articlePersister;
/** #var ArticleProviderInterface */
private $articleProvider;
/** #var ArticleUpdaterInterface */
private $articleUpdater;
/** #var ArticleDestroyerInterface */
private $articleDestroyer;
/** #var LanguageProviderInterface */
private $languageProvider;
/** #var ArticleSectionBuilderInterface */
private $sectionBuilder;
/** #var ArticleSectionUpdaterInterface */
private $sectionUpdater;
/**
* ArticleJsonApiController constructor.
*
* #param UserInterface $currentUser
* #param UserRoleProviderInterface $userRoleProvider
* #param ArticleBuilderInterface $articleBuilder
* #param ArticlePeristerInterface $articlePersister
* #param ArticleProviderInterface $articleProvider
* #param ArticleUpdaterInterface $articleUpdater
* #param ArticleDestroyerInterface $articleDestroyer
* #param LanguageProviderInterface $languageProvider
* #param ArticleSectionBuilderInterface $sectionBuilder
* #param ArticleSectionUpdaterInterface $sectionUpdater
*/
public function __construct(
UserInterface $currentUser,
UserRoleProviderInterface $userRoleProvider,
ArticleBuilderInterface $articleBuilder,
ArticlePeristerInterface $articlePersister,
ArticleProviderInterface $articleProvider,
ArticleUpdaterInterface $articleUpdater,
ArticleDestroyerInterface $articleDestroyer,
LanguageProviderInterface $languageProvider,
ArticleSectionBuilderInterface $sectionBuilder,
ArticleSectionUpdaterInterface $sectionUpdater
) {
parent::__construct($currentUser, $userRoleProvider);
I believe the problem does not lie with articleBuilder itself, but rather with your intention to define the arguments as an associative array.
If I am not mistaken, when dealing with parent services, you have at your disposal a special index_N key which serves to override the value of some argument already defined in your parent service. Therefor, I think, you need to define your argument in way that looks like this:
app.controller.article.article_json_api_controller:
class: '%app.controller.article.article_json_api_controller.class%'
parent: 'app.service.user.access_controller'
arguments:
- '#app.service.article.doctrine_orm.article_entity.builder'
- '#app.service.article.doctrine_orm.article_entity.persister'
- '#app.repository.article.article_repository'
- '#app.service.article.updater'
- '#app.service.article.doctrine_orm.article_entity.destroyer'
- '#app.repository.language.language_repository'
- '#app.service.article.doctrine_orm.article_section_entity.builder'
- '#app.service.article.article_section.updater'
Hope this helps a bit...
I think you misunderstood what parent services are. AFAIK you're trying to map 1-to-1 your parent abstract class as an abstract service, but parent services are used differently in Symfony, i.e. to manage common dependencies for several classes.
Reference: How to Manage Common Dependencies with Parent Services - Symfony docs

How to override bundled Doctrine repository in Symfony

I have an independent Symfony bundle (installed with Composer) with entities and repositories to share between my applications that connect same database.
Entities are attached to every applications using configuration (yml shown):
doctrine:
orm:
mappings:
acme:
type: annotation
dir: %kernel.root_dir%/../vendor/acme/entities/src/Entities
prefix: Acme\Entities
alias: Acme
Well, it was the easiest way to include external entities in application, but looks a bit ugly.
Whenever I get repository from entity manager:
$entityManager->getRepository('Acme:User');
I get either preconfigured repository (in entity configuration) or default Doctrine\ORM\EntityRepository.
Now I want to override bundled (or default) repository class for a single entity. Is there any chance to do it with some configuration/extension/etc?
I think, the best looking way is something like:
doctrine:
orm:
....:
Acme\Entities\User:
repositoryClass: My\Super\Repository
Or with tags:
my.super.repository:
class: My\Super\Repository
tags:
- { name: doctrine.custom.repository, entity: Acme\Entities\User }
You can use LoadClassMetadata event:
class LoadClassMetadataSubscriber implements EventSubscriber
{
/**
* #inheritdoc
*/
public function getSubscribedEvents()
{
return [
Events::loadClassMetadata
];
}
/**
* #param LoadClassMetadataEventArgs $eventArgs
*/
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
/**
* #var \Doctrine\ORM\Mapping\ClassMetadata $classMetadata
*/
$classMetadata = $eventArgs->getClassMetadata();
if ($classMetadata->getName() !== 'Acme\Entities\User') {
return;
}
$classMetadata->customRepositoryClassName = 'My\Super\Repository';
}
}
Doctrine Events
Entities are attached to every applications using configuration (yml shown):
Well, it was the easiest way to include external entities in application, but looks a bit ugly.
You can enable auto_mapping
Works for Doctrine versions <2.5
In addition to Artur Vesker answer I've found another way: override global repository_factory.
config.yml:
doctrine:
orm:
repository_factory: new.doctrine.repository_factory
services.yml:
new.doctrine.repository_factory:
class: My\Super\RepositoryFactory
Repository Factory:
namespace My\Super;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Repository\DefaultRepositoryFactory;
class RepositoryFactory extends DefaultRepositoryFactory
{
/**
* #inheritdoc
*/
protected function createRepository(EntityManagerInterface $entityManager, $entityName)
{
if ($entityName === Acme\Entities\User::class) {
$metadata = $entityManager->getClassMetadata($entityName);
return new ApplicationRepository($entityManager, $metadata);
}
return parent::createRepository($entityManager, $entityName);
}
}
No doubt implementing LoadClassMetadataSubscriber is a better way.
With current symfony 5.3 and doctrine 2.9.5
In your configuration define the service and doctrine.orm.repository_factory:
doctrine:
orm:
#Replace repository factory
repository_factory: 'MyBundle\Factory\RepositoryFactory'
services:
MyBundle\Factory\RepositoryFactory:
arguments: [ '#router', '#translator', '%kernel.secret%' ]
Add you MyBundle/Factory/RepositoryFactory.php file:
<?php declare(strict_types=1);
namespace MyBundle\Factory;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Repository\RepositoryFactory as RepositoryFactoryInterface;
use Doctrine\Persistence\ObjectRepository;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* This factory is used to create default repository objects for entities at runtime.
*/
final class RepositoryFactory implements RepositoryFactoryInterface {
/**
* The list of EntityRepository instances
*
* #var ObjectRepository[]
*/
private $repositoryList = [];
/**
* The kernel secret
*
* #var string
*/
private $secret;
/**
* The RouterInterface instance
*
* #var RouterInterface
*/
private $router;
/**
* The TranslatorInterface instance
*
* #var TranslatorInterface
*/
private $translator;
/**
* Initializes a new RepositoryFactory instance
*
* #param RouterInterface $router The router instance
* #param TranslatorInterface $translator The TranslatorInterface instance
* #param string $secret The kernel secret
*/
public function __construct(RouterInterface $router, TranslatorInterface $translator, string $secret) {
//Set router
$this->router = $router;
//Set secret
$this->secret = $secret;
//Set translator
$this->translator = $translator;
}
/**
* {#inheritdoc}
*/
public function getRepository(EntityManagerInterface $entityManager, $entityName): ObjectRepository {
//Set repository hash
$repositoryHash = $entityManager->getClassMetadata($entityName)->getName() . spl_object_hash($entityManager);
//With entity repository instance
if (isset($this->repositoryList[$repositoryHash])) {
//Return existing entity repository instance
return $this->repositoryList[$repositoryHash];
}
//Store and return created entity repository instance
return $this->repositoryList[$repositoryHash] = $this->createRepository($entityManager, $entityName);
}
/**
* Create a new repository instance for an entity class
*
* #param EntityManagerInterface $entityManager The EntityManager instance.
* #param string $entityName The name of the entity.
*/
private function createRepository(EntityManagerInterface $entityManager, string $entityName): ObjectRepository {
//Get class metadata
$metadata = $entityManager->getClassMetadata($entityName);
//Get repository class
$repositoryClass = $metadata->customRepositoryClassName ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName();
//Return repository class instance
//XXX: router, translator and secret arguments will be ignored by default
return new $repositoryClass($entityManager, $metadata, $this->router, $this->translator, $this->secret);
}
}
Then define your MyBundle/Repository/EntityRepository.php:
<?php declare(strict_types=1);
namespace MyBundle\Repository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository as BaseEntityRepository;
use Doctrine\ORM\Mapping\ClassMetadata;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* EntityRepository
*
* {#inheritdoc}
*/
class EntityRepository extends BaseEntityRepository {
/**
* The RouterInterface instance
*
* #var RouterInterface
*/
protected RouterInterface $router;
/**
* The table keys array
*
* #var array
*/
protected array $tableKeys;
/**
* The table values array
*
* #var array
*/
protected array $tableValues;
/**
* The TranslatorInterface instance
*
* #var TranslatorInterface
*/
protected TranslatorInterface $translator;
/**
* The kernel secret
*
* #var string
*/
protected string $secret;
/**
* Initializes a new LocationRepository instance
*
* #param EntityManagerInterface $manager The EntityManagerInterface instance
* #param ClassMetadata $class The ClassMetadata instance
* #param RouterInterface $router The router instance
* #param TranslatorInterface $translator The TranslatorInterface instance
* #param string $secret The kernel secret
*/
public function __construct(EntityManagerInterface $manager, ClassMetadata $class, RouterInterface $router, TranslatorInterface $translator, string $secret) {
//Call parent constructor
parent::__construct($manager, $class);
//Set secret
$this->secret = $secret;
//Set router
$this->router = $router;
//Set slugger
$this->slugger = $slugger;
//Set translator
$this->translator = $translator;
//Get quote strategy
$qs = $manager->getConfiguration()->getQuoteStrategy();
$dp = $manager->getConnection()->getDatabasePlatform();
//Set quoted table names
//XXX: remember to place longer prefix before shorter to avoid strange replacings
$tables = [
'MyBundle:UserGroup' => $qs->getJoinTableName($manager->getClassMetadata('MyBundle:User')->getAssociationMapping('groups'), $manager->getClassMetadata('MyBundle:User'), $dp),
'MyBundle:Group' => $qs->getTableName($manager->getClassMetadata('MyBundle:Group'), $dp),
'MyBundle:User' => $qs->getTableName($manager->getClassMetadata('MyBundle:User'), $dp),
//XXX: Set limit used to workaround mariadb subselect optimization
':limit' => PHP_INT_MAX,
"\t" => '',
"\n" => ' '
];
//Set quoted table name keys
$this->tableKeys = array_keys($tables);
//Set quoted table name values
$this->tableValues = array_values($tables);
}
}
Then simply extend it in MyBundle/Repository/UserRepository.php:
<?php declare(strict_types=1);
namespace MyBundle\Repository;
/**
* UserRepository
*/
class UserRepository extends EntityRepository {
}

Extend UserProvider forSymfony 2 FOS UserBundle

Iam using FOS User bundle to login in my site. For a requirement I need to make changes in the Fos user bundle user provider(
FOS\UserBundle\Security\UserProvider).
I have created a userProvider that extends the original userProvider in
FOS and have overridden the loadUserByUsername method to make my changes. It is given below
<?php
/*
* This file is part of the FOSUserBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Common\UtilityBundle\Security;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface as SecurityUserInterface;
use FOS\UserBundle\Model\User;
use FOS\UserBundle\Model\UserInterface;
use FOS\UserBundle\Model\UserManagerInterface;
use FOS\UserBundle\Propel\User as PropelUser;
use FOS\UserBundle\Security\UserProvider as FOSProvider;
use Symfony\Component\DependencyInjection\ContainerInterface;
class UserProvider extends FOSProvider
{
/**
*
* #var ContainerInterface
*/
protected $container;
protected $userManager;
public function __construct(UserManagerInterface $userManager, ContainerInterface $container) {
$this->userManager = $userManager;
$this->container = $container;
}
/**
* {#inheritDoc}
*/
public function loadUserByUsername($username)
{
$user = $this->findUserUsername($username);
if (!$user) {
throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
}
return $user;
}
/**
* {#inheritDoc}
*/
public function refreshUser(SecurityUserInterface $user)
{
if (!$user instanceof User && !$user instanceof PropelUser) {
throw new UnsupportedUserException(sprintf('Expected an instance of FOS\UserBundle\Model\User, but got "%s".', get_class($user)));
}
if (!$this->supportsClass(get_class($user))) {
throw new UnsupportedUserException(sprintf('Expected an instance of %s, but got "%s".', $this->userManager->getClass(), get_class($user)));
}
if (null === $reloadedUser = $this->userManager->findUserBy(array('id' => $user->getId()))) {
throw new UsernameNotFoundException(sprintf('User with ID "%d" could not be reloaded.', $user->getId()));
}
return $reloadedUser;
}
/**
* {#inheritDoc}
*/
public function supportsClass($class)
{
$userClass = $this->userManager->getClass();
return $userClass === $class || is_subclass_of($class, $userClass);
}
/**
* Finds a user by username.
*
* This method is meant to be an extension point for child classes.
*
* #param string $username
*
* #return UserInterface|null
*/
protected function findUserUsername($username)
{
return $this->userManager->findUserByUsername($username);
}
/**
* Finds a user by username.
*
* This method is meant to be an extension point for child classes.
*
* #param string $username
*
* #return UserInterface|null
*/
protected function findUserClub($username, $club)
{
return $this->userManager->findUserByClub($club, $username);
}
}
I have configured the service with the following.
fg.security.authentication.userprovider:
class: %Common_utility.security.user_provider.class%
arguments:
- #fos_user.user_manager
- #service_container
My security.yml looks like this:
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
providers:
fg_security_userprovider:
id: fg.security.authentication.userprovider
In my parameter.yml, I set the argument as:
Common_utility.security.user_provider.class: Common\UtilityBundle\Security\UserProvider
But all the time Iam getting the error like below:
Uncaught exception
'Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException'
with message 'The service "security.authentication.manager" has a
dependency on a non-existent service
"security.user.provider.concrete.fos_userbundle".' in
/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php:59
Does anybody know how to get this working?

Categories