Symfony Gedmo Blameable not working - php

Did any one ever find an solution for this issue?
I'm having the same issue.
My config.yml:
# Doctrine Configuration
doctrine:
dbal:
driver: "%database_server%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
# e.g. database_path: "%kernel.root_dir%/data/data.db3"
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
# path: "%database_path%"
orm:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
#Gedmo Package extension for Symfony and Doctrine
mappings:
gedmo_tree:
type: annotation
prefix: Gedmo\Tree\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Tree/Entity"
alias: GedmoTree
is_bundle: false
gedmo_sortable:
type: annotation
prefix: Gedmo\Sortable\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Sortable/Entity"
alias: GedmoTree
is_bundle: false
[...]
stof_doctrine_extensions:
default_locale: "%locale%"
translation_fallback: true
orm:
default:
timestampable: true
blameable: true
My doctrine_extension.yml is included in the config file:
services:
extension.listener:
class: Omega\HomeBundle\Library\Listener\DoctrineExtensionListener
calls:
- [ setContainer, [#service_container]]
tags:
# loggable hooks user username if one is in security context
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
# Doctrine Extension listeners to handle behaviors
gedmo.listener.tree:
class: Gedmo\Tree\TreeListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
gedmo.listener.sortable:
class: Gedmo\Sortable\SortableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
gedmo.listener.timestampable:
class: Gedmo\Timestampable\TimestampableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
gedmo.listener.loggable:
class: Gedmo\Loggable\LoggableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
gedmo.listener.blameable:
class: Gedmo\Blameable\BlameableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
- [ setUserValue, [ #security.token_storage ] ]
I created myself an trait to handle the created, updated, updated_by and createdby fields:
namespace HomeBundle\Traits;
use Doctrine\ORM\Mapping as ORM;
use Omega\UserBundle\Entity\Users;
use Gedmo\Mapping\Annotation as Gedmo;
trait LogableTrait
{
/**
* #var Users
* #Gedmo\Blameable(on="create")
* #ORM\ManyToOne(targetEntity="UserBundle\Entity\Users")
* #ORM\JoinColumn(name="log_created_by", referencedColumnName="id")
*/
protected $CreatedBy;
/**
* #var Users
* #Gedmo\Blameable(on="update")
* #ORM\ManyToOne(targetEntity="UserBundle\Entity\Users")
* #ORM\JoinColumn(name="log_updated_by", referencedColumnName="id")
*/
protected $UpdatedBy;
/**
* #Gedmo\Timestampable(on="create")
* #ORM\Column(name="created", type="datetime")
* #var \DateTime
*/
protected $created;
/**
* #Gedmo\Timestampable(on="create")
* #ORM\Column(name="updated", type="datetime")
* #var \DateTime
*/
protected $updated;
/**
* #return Users
*/
public function getCreatedBy ()
{
return $this->CreatedBy;
}
/**
* #param Users $CreatedBy
*
* #return $this
*/
public function setCreatedBy (Users $CreatedBy )
{
$this->CreatedBy = $CreatedBy;
return $this;
}
/**
* #return Users
*/
public function getUpdatedBy ()
{
return $this->UpdatedBy;
}
/**
* #param Users $UpdatedBy
*
* #return $this
*/
public function setUpdatedBy (Users $UpdatedBy )
{
$this->UpdatedBy = $UpdatedBy;
return $this;
}
}
But everytime that I use this Bundle I get:
The class 'Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage' was not found in the chain configured namespaces Gedmo\Tree\Entity, Gedmo\Sortable\Entity, JMS\JobQueueBundle\Entity, AccountingBundle\Entity, DocumentsBundle\Entity, EavBundle\Entity, HomeBundle\Entity, UserBundle\Entity, CustomerBundle\Entity, Jns\Bundle\XhprofBundle\Entity
I hope some body can help me.

for any one that Is having th same issue like me that the blamable feature is not working:
My solution was to implement the BlamableListener with an different approach:
namespace HomeBundle\Library;
use Doctrine\Common\NotifyPropertyChanged;
use Gedmo\Exception\InvalidArgumentException;
use Gedmo\Timestampable\TimestampableListener;
use Gedmo\Blameable\Mapping\Event\BlameableAdapter;
use Gedmo\Blameable\Mapping\Driver\Annotation;
/**
* The Blameable listener handles the update of
* dates on creation and update.
*
* #author Gediminas Morkevicius <gediminas.morkevicius#gmail.com>
* #license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class BlameableListener extends TimestampableListener
{
protected $user;
/**
* Get the user value to set on a blameable field
*
* #param object $meta
* #param string $field
*
* #return mixed
*/
public function getUserValue($meta, $field)
{
if ($meta->hasAssociation($field)) {
if (null !== $this->user && ! is_object($this->user)) {
throw new InvalidArgumentException("Blame is reference, user must be an object");
}
$user = $this->user->getToken()->getUser();
if(!is_object($user))
{
return null;
}
return $user;
}
// ok so its not an association, then it is a string
if (is_object($this->user)) {
if (method_exists($this->user, 'getUsername')) {
return (string) $this->user->getUsername();
}
if (method_exists($this->user, '__toString')) {
return $this->user->__toString();
}
throw new InvalidArgumentException("Field expects string, user must be a string, or object should have method getUsername or __toString");
}
return $this->user;
}
/**
* Set a user value to return
*
* #param mixed $user
*/
public function setUserValue($user)
{
$this->user = $user;
}
/**
* {#inheritDoc}
*/
protected function getNamespace()
{
return __NAMESPACE__;
}
/**
* Updates a field
*
* #param object $object
* #param BlameableAdapter $ea
* #param $meta
* #param $field
*/
protected function updateField($object, $ea, $meta, $field)
{
$property = $meta->getReflectionProperty($field);
$oldValue = $property->getValue($object);
$newValue = $this->getUserValue($meta, $field);
//if blame is reference, persist object
if ($meta->hasAssociation($field) && $newValue) {
$ea->getObjectManager()->persist($newValue);
}
$property->setValue($object, $newValue);
if ($object instanceof NotifyPropertyChanged) {
$uow = $ea->getObjectManager()->getUnitOfWork();
$uow->propertyChanged($object, $field, $oldValue, $newValue);
}
}
}
adjust the service for the blamable:
gedmo.listener.blameable:
class: HomeBundle\Library\BlameableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
- [ setUserValue, [ #security.token_storage ] ]
you need to copy the mapping library to the same location as the listener itself. Adjust the namespaces and it works. It seems that some structures changed in symfony 2.7 so the plugin no longer works out of the box.

If you want to update the updated_by field, you must specify the field so that when you update it, do so in updated_by. For example:
/**
* #var \DateTime $updated
*
* #Gedmo\Timestampable(on="update")
* #ORM\Column(type="datetime", nullable=true)
*/
protected $updated;
/**
* #var string $updatedBy
*
* #Gedmo\Blameable(on="update", field="updated")
* #ORM\Column(type="string", nullable=true)
*/
protected $updatedBy;
Pay attention to field="updated"

Just create DoctrineExtensionSubscriber
Manually tag the listeners
Gedmo\Loggable\LoggableListener:
tags:
- { name: doctrine_mongodb.odm.event_subscriber }
Create DoctrineExtensionSubscriber
<?php
namespace App\EventSubscriber;
use Gedmo\Blameable\BlameableListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class DoctrineExtensionSubscriber implements EventSubscriberInterface
{
/**
* #var BlameableListener
*/
private $blameableListener;
/**
* #var TokenStorageInterface
*/
private $tokenStorage;
/**
* #var TranslatableListener
*/
private $translatableListener;
/**
* #var LoggableListener
*/
private $loggableListener;
public function __construct(
BlameableListener $blameableListener,
TokenStorageInterface $tokenStorage,
TranslatableListener $translatableListener,
LoggableListener $loggableListener
) {
$this->blameableListener = $blameableListener;
$this->tokenStorage = $tokenStorage;
$this->translatableListener = $translatableListener;
$this->loggableListener = $loggableListener;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => 'onKernelRequest',
KernelEvents::FINISH_REQUEST => 'onLateKernelRequest'
];
}
public function onKernelRequest(): void
{
if ($this->tokenStorage !== null &&
$this->tokenStorage->getToken() !== null &&
$this->tokenStorage->getToken()->isAuthenticated() === true
) {
$this->blameableListener->setUserValue($this->tokenStorage->getToken()->getUser());
}
}
public function onLateKernelRequest(FinishRequestEvent $event): void
{
$this->translatableListener->setTranslatableLocale($event->getRequest()->getLocale());
}
}

Related

Symfony 3 - How to authenticate a user from a password encrypted by bcrypt?

I have a User entity, with password encryption by bcrypt, in the database.
In fact, when a user is created, I generate a random password of 7 characters, and send him by mail. This password is encrypted using bcrypt and then in the database in the password attribute.
I would like that when my user connects from my login form, he can enter the password that I sent him by email to authenticate. But I do not understand how to do it. I can look at different sites, I do not see.
In addition, I think my code is a little mess ... My ultimate goal being to authenticate the user, so he has an open session, with a possibility to disconnect, and it is restricted to certain pages. But also to manage if the user is activated, and its expiration date.
I emphasize the fact that I am a beginner in symfony (I discovered it 2 weeks ago as part of my internship, and I knew very little PHP, so it's quite difficult for me)
I do not use the fosUserBundle bundle.
This is my code :
User.php :
<?php
namespace Site\PagesBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="Site\PagesBundle\Repository\UserRepository")
*/
class User implements UserInterface, \Serializable
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=255, nullable=true, unique=true)
*/
private $username;
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=255)
*/
private $nom;
/**
* #var string
*
* #ORM\Column(name="prenom", type="string", length=255)
*/
private $prenom;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=254, unique=true)
*/
private $email;
/**
* #Assert\Length(max=4096)
*/
private $plainPassword;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=64, nullable=true)
*/
private $password;
/**
* #var int
*
* #ORM\Column(name="nbTelechargementsAuto", type="integer", nullable=true)
*/
private $nbTelechargementsAuto;
/**
* #var bool
*
* #ORM\Column(name="isActif", type="boolean")
*/
private $isActif=0;
/**
* #ORM\Column(type="datetime", nullable=true)
*
* #var \DateTime
*/
private $createdAt;
/**
* #var bool
*
* #ORM\Column(name="isCreated", type="boolean")
*/
private $isCreated=0;
/**
* #ORM\Column(type="array")
*/
private $roles;
/**
* Set createdAt
*
* #param \DateTime $createdAt
*
* #return User
*/
public function setCreatedAt()
{
$this->createdAt = new \DateTimeImmutable();
return $this;
}
/**
* Get createdAt
*
* #return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set nom
*
* #param string $nom
*
* #return User
*/
public function setNom($nom)
{
$this->nom = $nom;
return $this;
}
/**
* Get nom
*
* #return string
*/
public function getNom()
{
return $this->nom;
}
/**
* Set nom
*
* #param string $username
*
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get nom
*
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set prenom
*
* #param string $prenom
*
* #return User
*/
public function setPrenom($prenom)
{
$this->prenom = $prenom;
return $this;
}
/**
* Get prenom
*
* #return string
*/
public function getPrenom()
{
return $this->prenom;
}
/**
* Set email
*
* #param string $email
*
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set password
*
* #param string $password
*
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set nbTelechargementsAuto
*
* #param integer $nbTelechargementsAuto
*
* #return User
*/
public function setNbTelechargementsAuto($nbTelechargementsAuto)
{
$this->nbTelechargementsAuto = $nbTelechargementsAuto;
return $this;
}
/**
* Get nbTelechargementsAuto
*
* #return int
*/
public function getNbTelechargementsAuto()
{
return $this->nbTelechargementsAuto;
}
/**
* Set isActif
*
* #param boolean $isActif
*
* #return User
*/
public function setIsActif($isActif)
{
$this->isActif = $isActif;
return $this;
}
/**
* Get isActif
*
* #return bool
*/
public function getIsActif()
{
return $this->isActif;
}
/**
* Set isCreated
*
* #param boolean $isCreated
*
* #return User
*/
public function setIsCreated($isCreated)
{
$this->isCreated = $isCreated;
return $this;
}
/**
* Get isCreated
*
* #return bool
*/
public function getIsCreated()
{
return $this->isCreated;
}
public function __construct()
{
$this->roles = ['ROLE_USER'];
}
public function getPlainPassword()
{
return $this->plainPassword;
}
public function setPlainPassword($password)
{
$this->plainPassword = $password;
}
public function getSalt()
{
// you *may* need a real salt depending on your encoder
// see section on salt below
return null;
}
public function getRoles()
{
return $this->roles;
}
public function eraseCredentials()
{
}
/** #see \Serializable::serialize() */
public function serialize()
{
return serialize([
$this->id,
$this->username,
$this->password,
$this->email,
$this->nbTelechargementsAuto,
$this->nom,
$this->prenom,
// see section on salt below
// $this->salt,
]);
}
/** #see \Serializable::unserialize() */
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
$this->email,
$this->nbTelechargementsAuto,
$this->nom,
$this->prenom,
// see section on salt below
// $this->salt
) = unserialize($serialized, ['allowed_classes' => false]);
}
/**
* Activation du compte
*/
public function activerCompte($nbPackages, $nbHomonymes)
{
if($this->getIsCreated() == 0)
{
$unUsername = $this->getNom();
$unUsername .= ".";
$unUsername .= $this->getPrenom();
$unUsername = strtolower($unUsername);
if($nbHomonymes > 0)
{
$nbHomonymes++;
$unUsername .= $nbHomonymes;
}
$this->setUsername(strtolower($unUsername));
$this->setNbTelechargementsAuto($nbPackages);
$this->setCreatedAt();
$this->setIsCreated(true);
}
$password = $this->generatePassword();
$this->setPlainPassword($password);
$this->setIsActif(true);
return $this;
}
public function constructionUsername()
{
$unUsername = $this->getNom();
$unUsername .= ".";
$unUsername .=$this->getPrenom();
return $unUsername;
}
/**
* Désactivation du compte
*/
public function desactiverCompte()
{
$this->setIsActif(false);
$this->setCreatedAt();
return $this;
}
public function registration()
{
// Passage Nom 1ère lettre Majuscule le reste minuscule
$leNom = $this->getNom();
$leNom = strtolower($leNom);
$leNom = ucfirst($leNom);
// Passage Nom 1ère lettre Majuscule le reste minuscule
$lePrenom = $this->getPrenom();
$lePrenom = strtolower($lePrenom);
$lePrenom = ucfirst($lePrenom);
$this->setNom($leNom);
$this->setPrenom($lePrenom);
$this->setCreatedAt();
}
/**
* Génération d'un mot de passe
* $nb_caractere = nombre de caractère du mdp
* Pas de caractère qui se ressemble (L minuscule, 1 et i majuscule, Zéro et la lettre o.)
* Sécurité supplémentaire avec : caractères speciaux: - + = $ % ! # #
* Pas d'espace pour éviter les erreurs
*/
function generatePassword($nb_caractere = 7)
{
$mot_de_passe = "";
$chaine = "abcdefghjkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ023456789#!$?&";
$longeur_chaine = strlen($chaine);
for($i = 1; $i <= $nb_caractere; $i++)
{
$place_aleatoire = mt_rand(0,($longeur_chaine-1));
$mot_de_passe .= $chaine[$place_aleatoire];
}
return $mot_de_passe;
}
}
config.php:
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: en
framework:
# ...
templating:
engines: ['twig']
#esi: ~
#translator: { fallbacks: ['%locale%'] }
secret: '%secret%'
router:
resource: '%kernel.project_dir%/app/config/routing.yml'
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
default_locale: '%locale%'
trusted_hosts: ~
session:
# https://symfony.com/doc/current/reference/configuration/framework.html#handler-id
handler_id: session.handler.native_file
save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
fragments: ~
http_method_override: true
assets: ~
php_errors:
log: true
# Twig Configuration
twig:
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
form_themes: ['bootstrap_4_layout.html.twig']
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
# e.g. database_path: '%kernel.project_dir%/var/data/data.sqlite'
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
#path: '%database_path%'
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
# Swiftmailer Configuration
swiftmailer:
transport: '%mailer_transport%'
host: '%mailer_host%'
username: '%mailer_user%'
password: '%mailer_password%'
spool: { type: memory }
sensio_framework_extra:
router:
annotations: false
assetic:
debug: "%kernel.debug%"
use_controller: false
bundles: [ ]
#java: /usr/bin/java
java: C:\Program Files\Java\jdk1.8.0_65\bin\java.exe
filters:
cssrewrite: ~
cssembed:
jar: "%kernel.root_dir%/Resources/java/cssembed.jar"
yui_js:
jar: "%kernel.root_dir%/Resources/java/yuicompressor.jar"
yui_css:
jar: "%kernel.root_dir%/Resources/java/yuicompressor.jar"
lessphp:
file: "%kernel.root_dir%/../vendor/oyejorge/less.php/lessc.inc.php"
apply_to: ".less$"
assets:
jquery_js:
inputs:
- "%kernel.root_dir%/../vendor/components/jquery/jquery.min.js"
filters: [?yui_js]
output: js/jquery.min.js
bootstrap_css:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/less/bootstrap.less"
filters:
- lessphp
- cssrewrite
output: css/bootstrap.css
bootstrap_js:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/affix.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/alert.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/button.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/carousel.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/collapse.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/dropdown.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/modal.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/tooltip.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/popover.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/scrollspy.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/tab.js"
- "%kernel.root_dir%/../vendor/twbs/bootstrap/js/transition.js"
filters: [?yui_js]
output: js/bootstrap.js
fonts_glyphicons_eot:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/fonts/glyphicons-halflings-regular.eot"
output: "fonts/glyphicons-halflings-regular.eot"
fonts_glyphicons_svg:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/fonts/glyphicons-halflings-regular.svg"
output: "fonts/glyphicons-halflings-regular.svg"
fonts_glyphicons_ttf:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/fonts/glyphicons-halflings-regular.ttf"
output: "fonts/glyphicons-halflings-regular.ttf"
fonts_glyphicons_woff:
inputs:
- "%kernel.root_dir%/../vendor/twbs/bootstrap/fonts/glyphicons-halflings-regular.woff"
output: "fonts/glyphicons-halflings-regular.woff"
stof_doctrine_extensions:
orm:
default:
sluggable: true
vich_uploader:
db_driver: orm
twig: true
storage: file_system
mappings:
paquet:
uri_prefix: fichiers/packages
upload_destination: '%kernel.root_dir%/../web/fichiers/packages/'
inject_on_load: true
delete_on_update: true
delete_on_remove: true
notice:
uri_prefix: fichiers/notices
upload_destination: '%kernel.root_dir%/../web/fichiers/notices/'
inject_on_load: false
delete_on_update: true
delete_on_remove: true
fos_ck_editor:
configs:
my_config:
toolbar: [ ["Source", "-", "Save"], "/", ["Anchor"], "/", ["Maximize"] ]
uiColor: "#000000"
Security.yml :
# To get started with security, check out the documentation:
# https://symfony.com/doc/current/security.html
security:
encoders:
Site\PagesBundle\Entity\User: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH ]
# https://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
providers:
in_memory: {memory: ~}
in_database:
entity:
class: Site\PagesBundle\Entity\User
property: username
our_db_provider:
entity:
class: Site\PagesBundle\Entity\User
property: username
# if you're using multiple entity managers
# manager_name: customer
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
provider: in_database
form_login:
login_path: security_login
check_path: security_login
logout:
path: security_logout
target: informations
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
#http_basic: ~
# https://symfony.com/doc/current/security/form_login_setup.html
#form_login: ~
And a part fo the controller that I use to manage what is relative to the navigation of the user, including its authentication
DefaultController.php :
<?php
namespace Site\PagesBundle\Controller;
use Site\PagesBundle\Entity\User;
use Site\PagesBundle\Entity\Paquet;
use Site\PagesBundle\Entity\TypeUser;
use Site\PagesBundle\Entity\Information;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Vich\UploaderBundle\Handler\DownloadHandler;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
/**
* Default controller.
*
* #Route("accueil")
*/
class DefaultController extends Controller
{
/**
* Accueil
*
* #Route("/", name="connexion_index")
* #Method({"GET", "POST"})
*/
public function indexAction(Request $request, UserPasswordEncoderInterface $passwordEncoder)
{
$em = $this->getDoctrine()->getManager(); //Récupération du manager
$listeInfos = $em->getRepository('PagesBundle:Information')->getInformationsZone("Zone 1"); //Récupération d'une liste d'informations
$user = new User(); //Initialisation de l'objet User
$form = $this->createForm('Site\PagesBundle\Form\ConnexionType', $user); //Formulaire de création
$form->handleRequest($request);
//Traitement si le formulaire est soumis ( Ajout du package dans la BDD )
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$password = $passwordEncoder->encodePassword($user, $user->getPlainPassword());
$valide = $this->getDoctrine()->getManager()->getRepository('PagesBundle:User')->authentifier($user->getUsername(),$password);
dump($valide);
dump($password);
if($valide == 1)
{
return $this->redirectToRoute('accueil');
}
else
{
return $this->render('#Pages/Default/connexion.html.twig',array(
'user' => $user,
'form' => $form->createView(),
'listeInfos' => $listeInfos,
));
}
// On ajoute un package, donc on offre un téléchargement supplémentaire aux utilisateurs concernés
$this->getDoctrine()->getManager()->getRepository('PagesBundle:User')->updateNbDDLAll("inc");
//return $this->redirectToRoute('paquets_index'); // Redirection page de gestion de packages
}
return $this->render('#Pages/Default/connexion.html.twig',array(
'user' => $user,
'form' => $form->createView(),
'listeInfos' => $listeInfos,
));
}
Thanks for your help !
EDIT:
My function :
/**
* Accueil
*
* #Route("/", name="connexion_index")
* #Method({"GET", "POST"})
*/
public function indexAction(Request $request, UserPasswordEncoderInterface $passwordEncoder)
{
$em = $this->getDoctrine()->getManager(); //Récupération du manager
$listeInfos = $em->getRepository('PagesBundle:Information')->getInformationsZone("Zone 1"); //Récupération d'une liste d'informations
$user = new User(); //Initialisation de l'objet User
$form = $this->createForm('Site\PagesBundle\Form\ConnexionType', $user); //Formulaire de création
$form->handleRequest($request);
//Traitement si le formulaire est soumis ( Ajout du package dans la BDD )
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$password = $passwordEncoder->encodePassword($user, $user->getPlainPassword());
$valide = $this->getDoctrine()->getManager()->getRepository('PagesBundle:User')->authentifier($user->getUsername(),$password);
dump($valide);
dump($password);
if($valide == 1)
{
return $this->redirectToRoute('accueil');
}
else
{
return $this->render('#Pages/Default/connexion.html.twig',array(
'user' => $user,
'form' => $form->createView(),
'listeInfos' => $listeInfos,
));
}
// On ajoute un package, donc on offre un téléchargement supplémentaire aux utilisateurs concernés
$this->getDoctrine()->getManager()->getRepository('PagesBundle:User')->updateNbDDLAll("inc");
//return $this->redirectToRoute('paquets_index'); // Redirection page de gestion de packages
}
I retrieve the password entered by the user in the login form.
I encrypt it. Then I run a check in my UserRepository with the username and password encrypted.
If the function returns true, there is someone who has the username entered and the encrypted password entered.
My UserRepository function :
public function authentifier($username, $password)
{
$queryBuilder = $this->createQueryBuilder("u")
->select("count(u.id)")
->where("u.username = :username")
->andWhere("u.password = :password")
->setParameter("username",$username)
->setParameter("password",$password);
return $queryBuilder->getQuery()->getSingleScalarResult();
}
}
However, what is the cost in the security.yml?
To check if the posted password on your login form match with the one in database, you just need to bcrypt it and check if it's the same as the one in db.
You get your User from db
you encode the posted password
You check if the posted encoded password is the same as the one sotred in your User
But in your Controller code, it seems you create a new user (you create a new User instrad of getting one from db, and you persist it) ?

The class 'App\Document\User' was not found in the chain configured namespaces

I have just put in place mongodb with symfony4.1.
When I want to persist a simple User in the database, I got this error (title) :
Uncaught PHP Exception Doctrine\Common\Persistence\Mapping\MappingException: "The class 'App\Document\User' was not found in the chain configured namespaces
Here my controller :
/**
* #Route("/mongoTest")
* #Method("GET")
* #param DocumentManager $dm
* #return JsonResponse
*/
public function mongoTest(DocumentManager $dm)
{
$user = new User();
$user->setEmail("hello#medium.com");
$user->setFirstname("Matt");
$user->setLastname("Matt");
$user->setPassword(md5("123456"));
$dm->persist($user);
$dm->flush();
return new JsonResponse(array('Status' => 'OK'));
}
Config :
doctrine_mongodb:
connections:
default:
server: "%mongodb_server%"
options: {}
default_database: "%mongodb_database_name%"
document_managers:
default:
auto_mapping: true
default_commit_options: ~
Here my Document :
<?php
namespace App\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/**
* #MongoDB\Document
*/
class User
{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\Field(type="string")
*/
protected $firstname;
/**
* #MongoDB\Field(type="string")
*/
protected $lastname;
/**
* #MongoDB\Field(type="string")
*/
protected $email;
/**
* #MongoDB\Field(type="string")
*/
protected $password;
/**
* #MongoDB\Field(type="date")
*/
protected $create_date;
// ...
}
Does anyone have an idea ?
Thanks a lot !!
I found the answer :
I do not use bundles.
doctrine_mongodb:
connections:
default:
server: "%mongodb_server%"
options: {}
default_database: "%mongodb_database_name%"
document_managers:
default:
mappings:
# ...
App:
type: annotation
dir: "%kernel.root_dir%/../src/Document"
is_bundle: false
prefix: App\Document
alias: App
default_commit_options: ~

No entity manager defined for class

I am trying to just display a list. My Supplier and Property list were displaying until I implemented the product list :(
Now I get this error with the Supplier and Property lists but not for the newly added product list:
Here is my app/config.yml:
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
parameters:
sylius.locale: "%locale%"
framework:
#esi: ~
translator: { fallbacks: ["%locale%"] }
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
templating:
engines: ['twig']
#assets_version: SomeVersionScheme
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
storage_id: session.storage.php_bridge
# handler_id set to null will use default session handler from php.ini
handler_id: ~
fragments: ~
http_method_override: true
# Twig Configuration
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
form:
resources:
- 'SonataCoreBundle:Form:datepicker.html.twig'
# Assetic Configuration
assetic:
debug: "%kernel.debug%"
use_controller: false
#java: /usr/bin/java
node: /usr/bin/node
node_paths: [ /usr/lib/node_modules, %kernel.root_dir%/../node_modules ]
filters:
autoprefixer:
bin: %kernel.root_dir%/../node_modules/autoprefixer/autoprefixer
cssrewrite: ~
less:
apply_to: "\.less$"
bin: %kernel.root_dir%/../node_modules/less
uglifycss:
bin: %kernel.root_dir%/../node_modules/uglifycss
uglifyjs:
bin: %kernel.root_dir%/../node_modules/uglifyjs
#closure:
# jar: "%kernel.root_dir%/Resources/java/compiler.jar"
#yui_css:
# jar: "%kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar"
# Doctrine Configuration
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
mapping_types:
enum: string
orm:
auto_generate_proxy_classes: "%kernel.debug%"
entity_managers:
default:
connection: default
auto_mapping: true
dql:
string_functions:
HS_CONCAT_ADDRESS: AppBundle\DQL\HSConcatAddress
# Swiftmailer Configuration
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool: { type: memory }
# FOS UserBundle Configuration
fos_user:
registration:
form:
type: hs_user_registration
db_driver: orm
firewall_name: main
user_class: AppBundle\Entity\User
service:
user_manager: app.security.user_manager
# Doctrine migration bundle Configuration
doctrine_migrations:
dir_name: %kernel.root_dir%/DoctrineMigrations
namespace: Application\Migrations
table_name: migration_versions
name: Application Migrations
# Sonata Admin Configuration
sonata_admin:
options:
use_select2: false # disable select2
title: App
title_logo: bundles/sonataadmin/logo_title.png
# Override default template
templates:
show: AppBundle:Admin/Backend:show.html.twig
edit: AppBundle:Admin/Backend:edit.html.twig
layout: AppBundle:Common/Admin:standard_layout.html.twig
security:
# handler: sonata.admin.security.handler.role
#sonata_intl:
# timezone:
# locales:
# en_GB: Europe/London
# default: Europe/London
# Sonata Block Configuration
sonata_block:
default_contexts: [cms]
blocks:
sonata.user.block.menu: # used to display the menu in profile pages
sonata.user.block.account: # used to display menu option (login option)
sonata.admin.block.admin_list:
contexts: [admin]
sonata.admin.block.search_result:
contexts: [admin]
knp_menu:
# use "twig: false" to disable the Twig extension and the TwigRenderer
twig:
template: knp_menu.html.twig
# if true, enables the helper for PHP templates
templating: false
# the renderer to use, list is also available by default
default_renderer: twig
# STOF Doctrine Extensions Configuration
stof_doctrine_extensions:
default_locale: %locale%
orm:
default:
translatable: true
sluggable: true
timestampable: true
a2lix_translation_form:
locale_provider: default # [1]
locales: ["%locale%"] # [1-a]
default_locale: "%locale%" # [1-b]
manager_registry: doctrine # [2]
# Sylius Archetype
sylius_archetype:
classes:
product:
subject: Sylius\Component\Product\Model\Product
attribute: Sylius\Component\Product\Model\Attribute
option: Sylius\Component\Product\Model\Option
archetype:
model: Sylius\Component\Product\Model\Archetype
repository: Sylius\Bundle\ResourceBundle\Doctrine\ORM\TranslatableEntityRepository
translatable:
targetEntity: Sylius\Component\Product\Model\ArchetypeTranslation
archetype_translation:
model: Sylius\Component\Product\Model\ArchetypeTranslation
sylius_product:
driver: doctrine/orm
classes:
product:
model: AppBundle\Entity\Product
controller: AppBundle\Controller\Backend\ProductController
form:
default: AppBundle\Form\Type\ProductType
translatable:
targetEntity: AppBundle\Entity\ProductTranslation
product_translation:
model: AppBundle\Entity\ProductTranslation
form:
default: AppBundle\Form\Type\ProductTranslationType
#sylius_resource:
# resources:
# app.backend:
# driver: doctrine/orm
# object_manager: default
# classes:
# controller: AppBundle\Controller\Backend\ResourceController
# model: AppBundle\Entity\Product
# Sylius Attribute
sylius_attribute:
driver: doctrine/orm
# Sylius Locale
sylius_locale:
driver: doctrine/orm
# Sylius Translation
sylius_translation:
default_mapping:
translatable:
field: translations
currentLocale: currentLocale
fallbackLocale: fallbackLocale
translation:
field: translatable
locale: locale
# Sylius Variation
sylius_variation:
driver: doctrine/orm
classes:
product:
variant:
model: AppBundle\Entity\ProductVariant
form: AppBundle\Form\Type\ProductVariantType
My admin class:
namespace AppBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\EventDispatcher\Event;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Sonata\AdminBundle\Admin\AdminInterface;
use Sonata\AdminBundle\Route\RouteCollection;
use Sonata\AdminBundle\Form\Type;
use Sonata\AdminBundle\Validator\ErrorElement;
use AppBundle\Entity\Suppliers as Suppliers;
use AppBundle\Form\Type\CreateSupplierForm;
use Symfony\Component\DependencyInjection\ContainerInterface;
class SupplierAdmin extends Admin
{
/**
* {#inheritdoc}
*/
protected $baseRouteName = 'Admin\SupplierAdmin';
/**
* {#inheritdoc}
*/
protected $baseRoutePattern = 'supplier';
/**
* #var ContainerInterface
*/
private $container;
public function setContainer (ContainerInterface $container)
{
$this->container = $container;
}
/**
* #param \Sonata\AdminBundle\Show\ShowMapper $showMapper
*
* #return void
*/
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper
->with('Supplier Details')
->add('id')
->add('name')
->add('created')
->end();
if ($this->getSubject()->getType() == 'LPE') {
$showMapper->with('Property Expert')
->add('LpeFirstName', null, array('label' => 'First Name'))
->add('LpeLastName', null, array('label' => 'Last Name'))
->add('LpeEmail', null, array('label' => 'Email'))
->add('ContractType', null, array('label' => 'Type'))
->add('regions', 'entity', array(
'class' => 'AppBundle:Regions',
"multiple" => true,
'label' => 'Regions Covered'
))
->end();
}
}
/**
* #param \Sonata\AdminBundle\Datagrid\ListMapper $listMapper
*
* #return void
*/
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->add('id')
->add('Type')
->addIdentifier('name')
->add('created', 'date', array(
'pattern' => 'dd/MM/Y # H:m',
'locale' => 'en_GB',
'timezone' => 'Europe/London',
))
// add custom action links
->add('_action', 'actions', array(
'actions' => array(
'show' => array(),
'delete' => array()
)
));
}
/**
* #param \Sonata\AdminBundle\Datagrid\DatagridMapper $datagridMapper
*
* #return void
*/
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('type', null, array(),
'choice',
array('choices' => Suppliers::getTypes()))
->add('name');
}
protected function configureRoutes(RouteCollection $collection)
{
parent::configureRoutes($collection);
$collection->add('create', 'create', array(
'_controller' => 'AppBundle:Backend/SupplierAdmin:createSupplier'
)
);
$collection->add('show', $this->getRouterIdParameter() . '/show', array(
'_controller' => 'AppBundle:Backend/SupplierAdmin:show',
)
);
$collection->add('delete', $this->getRouterIdParameter() . '/delete', array(
'_controller' => 'AppBundle:Backend/SupplierAdmin:delete',
)
);
}
/**
* #return array
*/
public function getBatchActions()
{
// Disable all batch actions for now
$actions = array();
return $actions;
}
/**
* {#inheritdoc}
*/
public function createQuery($context = 'list')
{
$query = parent::createQuery($context);
// Default Alias is "o"
$query->orderBy('o.id', 'DESC');
$query->setSortOrder('DESC');
return $query;
}
public function preUpdate($supplier)
{
$supplier->setDeleted(0);
return $supplier;
}
public function preCreate($supplier)
{
$supplier->setDeleted(0);
return $supplier;
}
}
And lastly my Supplier entity:
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Suppliers
*
* #ORM\Table(
* name="suppliers",
* indexes={
* #ORM\Index(
* name="supplier_name", columns={"name"}
* )
* })
* #ORM\Entity
* #ORM\HasLifecycleCallbacks()
*/
class Suppliers
{
const TYPE_INTERNAL = 'internal';
const TYPE_EXTERNAL = 'external';
const TYPE_LPE = 'lpe';
protected static $types = array(
self::TYPE_INTERNAL => 'Internal',
self::TYPE_EXTERNAL => 'External',
self::TYPE_LPE => 'LPE'
);
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false, options={"unsigned":true})
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #Assert\NotNull()
* #ORM\Column(name="type", type="string", nullable=false, options={"default":"lpe"})
*/
private $type;
/**
* #var string
*
* #Assert\NotNull()
* #ORM\Column(name="name", type="string", nullable=false)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="created", type="datetime")
*/
private $created;
/**
* #var string
*
* #ORM\Column(name="updated", nullable=true, type="datetime")
*/
private $updated;
/**
* #var string
*
* #ORM\Column(name="deleted", type="boolean", options={"default":0})
*/
private $deleted;
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Regions")
* #ORM\JoinTable(name="supplier_regions",
* joinColumns={
* #ORM\JoinColumn(
* name="supplier_id",
* referencedColumnName="id"
* )
* },
* inverseJoinColumns={
* #ORM\JoinColumn(
* name="region_id",
* referencedColumnName="postcode"
* )
* }
* )
*/
private $regions;
private $lpe;
public function __construct()
{
$this->regions = new ArrayCollection();
}
public function getRegions()
{
return $this->regions;
}
public function setRegions($regions)
{
$this->regions = $regions;
return $this;
}
public function getLpe()
{
return $this->lpe;
}
public function setLpe($lpe)
{
$this->lpe = $lpe;
return $this;
}
/**
* #return string
*/
public function getLpeFirstName()
{
return $this->lpe->getUser()->getFirstName();
}
/**
* #return string
*/
public function getLpeLastName()
{
return $this->lpe->getUser()->getLastName();
}
/**
* #return string
*/
public function getLpeEmail()
{
return $this->lpe->getUser()->getEmail();
}
public function getContractType()
{
return $this->lpe->getContractType();
}
public function getUser()
{
return $this->lpe->getUser();
}
public function setUser($user)
{
$this->lpe->setUser($user);
return $this;
}
public function setFirstName($name)
{
$this->user->setFirstName($name);
return $this;
}
public function getFirstName()
{
return $this->user->getFirstName();
}
public function setLastName($name)
{
$this->user->setLastName($name);
return $this;
}
public function getLastName()
{
return $this->getUser()->getLastName();
}
public function setEmail($email)
{
$this->getUser()->setEmail($email);
return $this;
}
public function getEmail()
{
return $this->getUser()->getEmail();
}
/**
* #var string
*/
private $entityName;
/**
* Get id
*
* #return integer
*/
public function nullId()
{
return $this->id =null;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set type
*
* #param string $type
* #return User
*/
public function setType($type)
{
$this->type = strtolower($type);
return $this;
}
/**
* Get type
*
* #return string
*/
public function getType()
{
if ($this->type == 'lpe') {
return strtoupper($this->type);
}
return ucwords($this->type);
}
/**
* Set name
*
* #param string $name
* #return User
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set created
*
* #param string $created
* #return $this
*/
public function setCreated($created)
{
if (!empty($created)) {
$this->created = $created;
} else {
$this->created = new \DateTime("now");
}
return $this;
}
/**
* Get created
*
* #return string
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* #param string $updated
* #return User
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* Get updated
*
* #return string
*/
public function getUpdated()
{
return $this->updated;
}
/**
* Set deleted
*
* #param boolean $deleted
* #return User
*/
public function setDeleted($deleted)
{
$this->deleted = $deleted;
return $this;
}
/**
* Get deleted
*
* #return boolean
*/
public function getDeleted()
{
return $this->deleted;
}
/**
* #ORM\PrePersist()
*/
public function onPrePersist()
{
$this->created = new \DateTime();
$this->updated = new \DateTime();
if ($this->deleted === null) {
$this->deleted = 0;
}
if ($this->type === null) {
$this->type = 'lpe';
}
if ($this->name === null) {
$this->name = '';
}
}
/**
* #ORM\PreUpdate()
*/
public function onPreUpdate()
{
$this->created = new \DateTime();
$this->updated = new \DateTime();
if ($this->deleted === null) {
$this->deleted = 0;
}
}
/**
* #return array
*/
public static function getTypes()
{
return self::$types;
}
/**
* Set entityName
*
* #param string $name
* #return User
*/
public function setEntityName($name)
{
$this->entityName = $name;
return $this;
}
public function __toString()
{
if ($this->getUser() === null) {
return 'Supplier' . ($this->id !== null ? ' #' . $this->id.'' : '' );
}
return (string) ($this->id !== null ? '#' . $this->id.' ' : '' ) . $this->getUser()->getEmail();
}
}
Any suggestions? :)
I think it is in your configuration file
doctrine:
[...]
orm:
[...]
mappings:
AppBundle:
type: ~
dir: "Entity"
prefix: "AppBundle\Entity"
is_bundle: ~
If it is not working, look over your namespaces, I think (but not sure) it should be like PROJECT\BUNDLE\Entity and not just BUNDLE\Entity (for both namespace and use statements)
You have to set your doctrine configuration to add your bundle to the ORM :
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
charset: UTF8
orm:
auto_generate_proxy_classes: '%kernel.debug%'
entity_managers:
default:
mappings:
ApplicationSonataUserBundle: ~
SonataUserBundle: ~
FOSUserBundle: ~
**YourBundleNameBundle**: ~

Symfony2 gedmo SortablePosition annotation does not exist

I want to implement a sortable behavior in a doctrine entity using Gedmo Extensions.
My config:
services:
# KernelRequest listener
extension.listener:
class: {Bundle Name}\Listener\DoctrineExtensionListener
calls:
- [ setContainer, [ #service_container ] ]
tags:
# translatable sets locale after router processing
- { name: kernel.event_listener, event: kernel.request, method: onLateKernelRequest, priority: -10 }
# loggable hooks user username if one is in security context
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
gedmo.listener.tree:
class: Gedmo\Tree\TreeListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
gedmo.listener.translatable:
class: Gedmo\Translatable\TranslatableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
# - [ setDefaultLocale, [ %locale% ] ]
# - [ setTranslationFallback, [ false ] ]
gedmo.listener.timestampable:
class: Gedmo\Timestampable\TimestampableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
gedmo.listener.sluggable:
class: Gedmo\Sluggable\SluggableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
gedmo.listener.sortable:
class: Gedmo\Sortable\SortableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
gedmo.listener.loggable:
class: Gedmo\Loggable\LoggableListener
tags:
- { name: doctrine.event_subscriber, connection: default }
calls:
- [ setAnnotationReader, [ #annotation_reader ] ]
Entity:
namespace Stenik\FooterLinkBundle\Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
// use Gedmo\Translatable\TranslationInterface as Translatable;
// use Gedmo\Mapping\Annotation\SortablePosition as SortablePosition;
/**
* #ORM\Table(name="footer_link")
* #ORM\Entity(repositoryClass="Gedmo\Sortable\Entity\Repository\SortableRepository")
* #Gedmo\Loggable
*/
class FooterLink
{
use \A2lix\TranslationFormBundle\Util\Gedmo\GedmoTranslatable;
/**
* #Gedmo\SortablePosition
* #ORM\Column(name="position", type="integer")
*/
private $position;
/** #ORM\Id #ORM\GeneratedValue #ORM\Column(type="integer") */
protected $id;
/**
* #Gedmo\Translatable
* #ORM\Column(name="title", type="string", length=255)
*/
protected $title;
/**
* #ORM\Column(name="link", type="string", length=255)
*/
protected $link;
/**
* #ORM\Column(name="target", type="string", length=255)
*/
protected $target = '_self';
/**
* #ORM\Column(name="is_hidden", type="boolean", options={"default" = 0})
*/
protected $is_hidden;
/**
* #Gedmo\Timestampable(on="create")
* #ORM\Column(name="created_at", type="datetime")
*/
protected $created_at;
/**
* #Gedmo\Timestampable(on="update")
* #ORM\Column(name="updated_at", type="datetime")
*/
protected $updated_at;
/**
* #ORM\OneToMany(targetEntity="Stenik\FooterLinkBundle\Entity\FooterLinkTranslation", mappedBy="object", cascade={"persist", "remove"}, indexBy="locale")
*/
protected $translations;
public function __construct()
{
$this->translations = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function getTitle()
{
return $this->title;
}
public function setTitle($value)
{
$this->title = $value;
}
public function getLink()
{
return $this->link;
}
public function setLink($value)
{
$this->link = $value;
}
public function getTarget()
{
return $this->target;
}
public function setTarget($value)
{
$this->target = $value;
}
public function getIsHidden()
{
return $this->is_hidden;
}
public function setIsHidden($is_hidden)
{
$this->is_hidden = $is_hidden;
}
public function getCreatedAt()
{
return $this->created_at;
}
public function setCreatedAt($created_at)
{
$this->created_at = $created_at;
}
public function getUpdatedAt()
{
return $this->updated_at;
}
public function setUpdatedAt($updated_at)
{
$this->updated_at = $updated_at;
}
public function __toString()
{
return $this->getTitle() ?: 'n/a';
}
}
I also have added the service as a subscriber in the bundle class:
public function boot(){
// get the doctrine 2 entity manager
$em = $this->container->get('doctrine.orm.default_entity_manager');
// get the event manager
$evm = $em->getEventManager();
$sortableListener = new \Gedmo\Sortable\SortableListener;
$evm->addEventSubscriber($sortableListener);
}
But when I try to update the schema I get the following error:
[Doctrine\Common\Annotations\AnnotationException]
[Semantical Error] The annotation "#Gedmo\Mapping\Annotation\SortablePosition" in property Stenik\FooterLinkBundle\Entity\FooterLink::$position does not exist, or could not be auto-loaded.
After quite the struggle, it turns out that the doctrine extensions version that I am using has some changes(wip-2.4.0) and there are no longer SortablePosition and SortableGroup annotations but only Sortable. That fixed it.

Symfony2 Authenticating Someone with a Custom Entity Provider ERROR

I faced a problem when trying to implement the Custom Entity Provider for user authentication. I got the Mapping Exception that my entity is not a valid or mapped super class. Here is my Actual Error:
------------- Exception/Error Start --------------
1/1 MappingException: Class MunichInnovationGroup\PatentBundle\Entity\UmUsers is not a valid entity or mapped super class.
in C:\wamp\www\idp\vendor\doctrine\lib\Doctrine\ORM\Mapping\MappingException.php line 142
at MappingException::classIsNotAValidEntityOrMappedSuperClass() in C:\wamp\www\idp\vendor\doctrine\lib\Doctrine\ORM\Mapping\Driver\DriverChain.php line 80
at DriverChain->loadMetadataForClass() in C:\wamp\www\idp\vendor\doctrine\lib\Doctrine\ORM\Mapping\ClassMetadataFactory.php line 281
at ClassMetadataFactory->loadMetadata() in C:\wamp\www\idp\vendor\doctrine\lib\Doctrine\ORM\Mapping\ClassMetadataFactory.php line 170
at ClassMetadataFactory->getMetadataFor() in C:\wamp\www\idp\vendor\doctrine\lib\Doctrine\ORM\EntityManager.php line 257
at EntityManager->getClassMetadata() in C:\wamp\www\idp\vendor\doctrine\lib\Doctrine\ORM\EntityManager.php line 573
at EntityManager->getRepository() in C:\wamp\www\idp\vendor\symfony\src\Symfony\Bridge\Doctrine\Security\User\EntityUserProvider.php line 42
at EntityUserProvider->__construct() in C:\wamp\www\idp\app\cache\dev\appDevDebugProjectContainer.php line 2191
at appDevDebugProjectContainer->getSecurity_User_Provider_Concrete_UserDbService() in C:\wamp\www\idp\app\bootstrap.php.cache line 190
at Container->get() in C:\wamp\www\idp\app\cache\dev\appDevDebugProjectContainer.php line 2174
at appDevDebugProjectContainer->getSecurity_User_Provider_Concrete_ChainProviderService() in C:\wamp\www\idp\app\bootstrap.php.cache line 190
at Container->get() in C:\wamp\www\idp\app\cache\dev\appDevDebugProjectContainer.php line 2140
at appDevDebugProjectContainer->getSecurity_Authentication_ManagerService() in C:\wamp\www\idp\app\bootstrap.php.cache line 190
at Container->get() in C:\wamp\www\idp\app\cache\dev\appDevDebugProjectContainer.php line 1304
at appDevDebugProjectContainer->getSecurity_ContextService() in C:\wamp\www\idp\app\bootstrap.php.cache line 190
at Container->get() in C:\wamp\www\idp\app\cache\dev\appDevDebugProjectContainer.php line 1178
at appDevDebugProjectContainer->getProfilerService() in C:\wamp\www\idp\app\bootstrap.php.cache line 190
at Container->get() in C:\wamp\www\idp\app\cache\dev\appDevDebugProjectContainer.php line 1195
at appDevDebugProjectContainer->getProfilerListenerService() in C:\wamp\www\idp\app\bootstrap.php.cache line 190
at Container->get() in C:\wamp\www\idp\app\cache\dev\classes.php line 4779
at ContainerAwareEventDispatcher->lazyLoad() in C:\wamp\www\idp\app\cache\dev\classes.php line 4768
at ContainerAwareEventDispatcher->dispatch() in C:\wamp\www\idp\app\cache\dev\classes.php line 3916
at HttpKernel->handleException() in C:\wamp\www\idp\app\cache\dev\classes.php line 3855
at HttpKernel->handle() in C:\wamp\www\idp\app\cache\dev\classes.php line 4828
at HttpKernel->handle() in C:\wamp\www\idp\app\bootstrap.php.cache line 547
at Kernel->handle() in C:\wamp\www\idp\web\app_dev.php line 20
**------------- Exception/Error End --------------**
Lets describe my application
I have three databases DB-A, DB-B, DB-C and make three database connections in config.yml file which are default: DB-A, DB_B: DB-B, DB_C: DB-C
default connection is configured with default_entity_manager ORM, other entity managers DB_B uses connection DB_B and mapping with MIGPatBundle, DB_C uses connection DB_C and also mapping with MIGPatBundle.
My UmUsers entity resides in MIGPatBundle and we need to validate it in DB-B database.
I explain these elaborately because if i change the default_entity_manager ORM from default to DB_B then it works fine.
Here is my files
------------- config.yml Start --------------
**Doctrine Configuration**
doctrine:
dbal:
default_connection: default
connections:
default:
driver: "%db_driver_DB-A%"
host: "%db_host_DB-A%"
port: "%db_port_DB-A%"
dbname: "%db_name_DB-A%"
user: "%db_user_DB-A%"
password: "%db_password_DB-A%"
charset: UTF8
DB_B:
driver: "%db_driver_DB-B%"
host: "%db_host_DB-B%"
port: "%db_port_DB-B%"
dbname: "%db_name_DB-B%"
user: "%db_user_DB-B%"
password: "%db_password_DB-B%"
charset: UTF8
DB_C:
driver: "%db_driver_DB-C%"
host: "%db_host_DB-C%"
port: "%db_port_DB-C%"
dbname: "%db_name_DB-C%"
user: "%db_user_DB-C%"
password: "%db_password_DB-C%"
charset: UTF8
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
MIGBundle: ~
DB_B:
connection: DB_B
mappings:
MIGPatBundle: ~
DB_C:
connection: DB_C
mappings:
MIGPatBundle: ~
------------- config.yml End --------------
------------- security.yml Start ------------
security:
encoders:
MIG\PatBundle\Entity\UmUsers:
algorithm: sha512
encode-as-base64: true
iterations: 10
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
chain_provider:
providers: [user_db]
user_db:
entity: { class: MIG\PatBundle\Entity\UmUsers }
firewalls:
secured_area:
pattern: ^/
anonymous: ~
logout:
target: /
form_login:
provider: chain_provider
check_path: /security/login_check
default_target_path: /
login_path: /security/login
access_control:
- { path: ^/account, roles: ROLE_USER }
- { path: ^/management, roles: ROLE_ADMIN }
- { path: ^/portfolio, roles: ROLE_USER }
- { path: ^/portfoliogroup, roles: ROLE_USER }
- { path: ^/security, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/userpatent, roles: ROLE_USER }
- { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
access_denied_url: /security/forbidden
------------- security.yml End --------------
------------- User Entity Start --------------
<?php
namespace MIG\PatBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Security\Core\User\UserInterface;
/**
*MIG\PatBundle\Entity\UmUsers
*
*#ORM\Entity(repositoryClass="MIG\PatBundle\Entity\UserRepository")
*#ORM\Table(name = "um_users")
*/
class UmUsers implements UserInterface
{
/**
#var string $id
#ORM\Column(name="id", type="string", length=36, nullable=false)
#ORM\Id
#ORM\GeneratedValue(strategy="UUID")
*/
private $id;
/**
* #ORM\Column(name="user_name", type="string", length=50, nullable=true)
*
* #var string $userName
*/
private $userName;
/**
* #var string $email
*
* #ORM\Column(name="email", type="string", length=100, nullable=false)
*/
private $email;
/**
* #ORM\Column(name="password", type="string", length=100, nullable=false)
*
* #Assert\MinLength(
* limit = 6,
* message = "The password must contain at least {{ limit }} characters."
* )
* #var string $password
*/
private $password;
/**
* #var string $salt
*
* #ORM\Column(name="salt", type="string", length=255, nullable=false)
*/
private $salt;
/**
* #var string $activationCode
*
* #ORM\Column(name="activation_code", type="string", length=255, nullable=false)
*/
private $activationCode;
/**
* #var boolean $activated
*
* #ORM\Column(name="activated", type="boolean", nullable=true)
*/
private $activated;
/**
* #var UmRoles
*
* #ORM\ManyToMany(targetEntity="UmRoles", inversedBy="user")
* #ORM\JoinTable(name="um_usersinroles",
* joinColumns={
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="role_id", referencedColumnName="id")
* }
* )
*/
private $role;
public function __construct()
{
$this->role = new \Doctrine\Common\Collections\ArrayCollection();
$this->createdAt = new \DateTime();
$this->lastLoginAt = new \DateTime();
$this->lastUpdatedDate = new \DateTime();
$this->lastLoginDate = new \DateTime();
$this->lastPasswordChangedDate = new \DateTime();
}
/**
* Get id
*
* #return string
*/
public function getId()
{
return $this->id;
}
/**
* Set userName
*
* #param string $userName
*/
public function setUserName($userName)
{
$this->userName = $userName;
}
/**
* Get userName
*
* #return string
*/
public function getUserName()
{
return $this->userName;
}
/**
* Set email
*
* #param string $email
*/
public function setEmail($email)
{
$this->email = $email;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set password
*
* #param string $password
*/
public function setPassword($password)
{
$this->password = $password;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set salt
*
* #param string $salt
*/
public function setSalt($salt)
{
$this->salt = $salt;
}
/**
* Get salt
*
* #return string
*/
public function getSalt()
{
return $this->salt;
}
/**
* Set activationCode
*
* #param string $activationCode
*/
public function setActivationCode($activationCode)
{
$this->activationCode = $activationCode;
}
/**
* Get activationCode
*
* #return string
*/
public function getActivationCode()
{
return $this->activationCode;
}
/**
* Set activated
*
* #param boolean $activated
*/
public function setActivated($activated)
{
$this->activated = $activated;
}
/**
* Get activated
*
* #return boolean
*/
public function getActivated()
{
return $this->activated;
}
/**
* Add role
*
* #param MIG\PatBundle\Entity\UmRoles $role
*/
public function addUmRoles(\MIG\PatBundle\Entity\UmRoles $role)
{
$this->role[] = $role;
}
/**
* Get role
*
* #return Doctrine\Common\Collections\Collection
*/
public function getRole()
{
return $this->role;
}
/**
* Gets an array of roles.
*
* #return array An array of Role objects
*/
public function getRoles()
{
return $this->getRole()->toArray();
}
/**
* Erases the user credentials.
*/
public function eraseCredentials()
{
}
/**
* Compares this user to another to determine if they are the same.
*
* #param UserInterface $user The user
* #return booleanean True if equal, false othwerwise.
*/
public function equals(UserInterface $user)
{
return md5($this->getUsername()) == md5($user->getUsername());
}
}
------------- User Entity End --------------
------------- UserRepository Entity Start--------------
namespace MIG\PatBundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NoResultException;
class UserRepository extends EntityRepository implements UserProviderInterface
{
public function loadUserByUsername($username)
{
$q = $this
->createQueryBuilder('u')
->where('u.userName = :username OR u.email = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery()
;
try {
// The Query::getSingleResult() method throws an exception
// if there is no record matching the criteria.
$user = $q->getSingleResult();
} catch (NoResultException $e) {
throw new UsernameNotFoundException(sprintf('Unable to find an active admin MunichInnovationGroup\PatentBundle\Entity\UmUsers object identified by "%s".', $username), null, 0, $e);
}
return $user;
}
public function refreshUser(UserInterface $user)
{
$class = get_class($user);
if (!$this->supportsClass($class)) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $class));
}
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return $this->getEntityName() === $class || is_subclass_of($class, $this->getEntityName());
}
}
------------- UserRepository Entity End--------------
Actually i have a deadline to complete this task. I will be very much glade to you if someone can give me the solution.
Regards,
Zaif
If you have a look at vendor/symfony/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml, you'll see this:
<service id="security.user.provider.entity" class="%security.user.provider.entity.class%" abstract="true" public="false" >
<argument type="service" id="security.user.entity_manager" />
</service>
<service id="security.user.entity_manager" alias="doctrine.orm.entity_manager" public="false" />
I think you need to override the security.user.entity_manager , but I am not sure how (maybe adding some lines in security.yml will do the trick), and since it is not public, I am not sure whether you can.
If this does not work, maybe you could report an issue about this.

Categories