Problem with users in the BD

0

I have a basic Symfony 3.3 structure (version 3.4 does not work and 4 is very different) with two entities: User , for users and Role for the roles. Several users may have a role (ManyToOne), and a role may be assigned to several users (OneToMany). Also, I have two users created in configuration. The security.yml file includes:

security:
#Como encoder usamos bcrypt para las contraseñas.
    encoders:
        Symfony\Component\Security\Core\User\User:
            algorithm: bcrypt
            cost: 10
        AppBundle\Entity\User:
            algorithm: bcrypt
            cost: 10

#Como provider de usuarios definimos en memoria y en base de datos.
    providers:
        chain_provider:
            chain:
                providers: [in_memory, user_db]
        in_memory:
            memory:
                users:
                    user:
                        password: $2y$10$gMoT8xcqB5OK/zBWyqeSqOrQnAqTz/8yxQrmhVhflvs7qw6r65xpC
                        roles: 'ROLE_USER'
                    admin:
                        password: $2y$10$pzphAl3SnvP.UvRmMxKKiuGOoMQghTw7GQ/dZ1s3Kjlm8K0JP73hW
                        roles: 'ROLE_ROOT_ADMIN'
        user_db:
            entity: {class: AppBundle\Entity\User, property: username}

The AppBundle \ Entity \ User looks like this:

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * User
 */

/**
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 */

class User implements UserInterface
{
    /**
     * @var int
     */
    private $id;

    /**
     * @var string
     */
    private $firstName;

    /**
     * @var string
     */
    private $familyName;

    /**
     * @var string
     */
    private $username;

    /**
     * @var string
     */
    private $password;

    /**
     * @var string
     */
    private $email;

    /**
     * @var string
     */
    private $language;

    /**
     * @var string
     */
    private $image;

    /**
     * @var string
     */
    private $active;

    /**
     * @var int
     */
    private $role;


    /**
     * Get id.
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set firstName.
     *
     * @param string $firstName
     *
     * @return User
     */
    public function setFirstName($firstName)
    {
        $this->firstName = $firstName;

        return $this;
    }

    /**
     * Get firstName.
     *
     * @return string
     */
    public function getFirstName()
    {
        return $this->firstName;
    }

    /**
     * Set familyName.
     *
     * @param string $familyName
     *
     * @return User
     */
    public function setFamilyName($familyName)
    {
        $this->familyName = $familyName;

        return $this;
    }

    /**
     * Get familyName.
     *
     * @return string
     */
    public function getFamilyName()
    {
        return $this->familyName;
    }

    /**
     * Set username.
     *
     * @param string $username
     *
     * @return User
     */
    public function setUsername($username)
    {
        $this->username = $username;

        return $this;
    }

    /**
     * Get username.
     *
     * @return string
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * 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 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 language.
     *
     * @param string $language
     *
     * @return User
     */
    public function setLanguage($language)
    {
        $this->language = $language;

        return $this;
    }

    /**
     * Get language.
     *
     * @return string
     */
    public function getLanguage()
    {
        return $this->language;
    }

    /**
     * Set image.
     *
     * @param string $image
     *
     * @return User
     */
    public function setImage($image)
    {
        $this->image = $image;

        return $this;
    }

    /**
     * Get image.
     *
     * @return string
     */
    public function getImage()
    {
        return $this->image;
    }

    /**
     * Set active.
     *
     * @param string $active
     *
     * @return User
     */
    public function setActive($active)
    {
        $this->active = $active;

        return $this;
    }

    /**
     * Get active.
     *
     * @return string
     */
    public function getActive()
    {
        return $this->active;
    }

    /**
     * Set role.
     *
     * @param int $role
     *
     * @return User
     */
    public function setRole($role)
    {
        $this->role = $role;

        return $this;
    }

    /**
     * Get role.
     *
     * @return int
     */
    public function getRole()
    {
        return $this->role;
    }

    public function __construct($role)
    {
        $this->setRole($role);
    }

    public function getRoles()
    {
        // TODO: Implement getRoles() method.
    }
    public function getSalt()
    {
        // TODO: Implement getSalt() method.
    }
    public function eraseCredentials()
    {
        // TODO: Implement eraseCredentials() method.
    }
}

The AppBundle / Entity / Role is like this:

<?php

namespace AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\User as User;


/**
 * Role
 */
class Role
{
    /**
     * @var int
     */
    private $id;

    /**
     * @var string
     */
    private $role;


    /**
     * Get id.
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set role.
     *
     * @param string $role
     *
     * @return Role
     */
    public function setRole($role)
    {
        $this->role = $role;

        return $this;
    }

    /**
     * Get role.
     *
     * @return string
     */
    public function getRole()
    {
        return $this->role;
    }

    private $users;

    public function __construct()
    {
        $this->users = new ArrayCollection();
    }

    public function __toString()
    {
        return $this->role;
    }

    /**
     * Add user.
     *
     * @param \AppBundle\Entity\User $user
     *
     * @return Role
     */
    public function addUser(User $user)
    {
        $this->users[] = $user;

        return $this;
    }

    /**
     * Remove user.
     *
     * @param \AppBundle\Entity\User $user
     *
     * @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
     */
    public function removeUser(User $user)
    {
        return $this->users->removeElement($user);
    }

    /**
     * Get users.
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getUsers()
    {
        return $this->users;
    }
}

Also, I have the relationships defined in yml. The AppBundle / Resources / config / doctrine / User.orm.yml is like this:

AppBundle\Entity\User:
    type: entity
    table: null
    repositoryClass: AppBundle\Repository\UserRepository
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    fields:
        firstName:
            type: string
            length: '100'
            column: first_name
        familyName:
            type: string
            length: '100'
            column: family_name
        username:
            type: string
            length: '50'
            unique: true
        password:
            type: string
            length: '100'
        email:
            type: string
            length: '100'
            unique: true
        language:
            type: string
            length: '2'
        image:
            type: string
            length: '100'
        active:
            type: string
            length: '1'
    manyToOne:
        role:
            type: integer
            targetEntity: AppBundle\Entity\Role
            inversedBy: users
            joinColumn:
                name: role
                referencedColumnName: id
    lifecycleCallbacks: {  }

And the AppBundle / Resources / config / doctrine / Role.orm.yml is like this:

AppBundle\Entity\Role:
    type: entity
    table: null
    repositoryClass: AppBundle\Repository\RoleRepository
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    fields:
        role:
            type: string
            length: '25'
            unique: true
    oneToMany:
        users:
            targetEntity: AppBundle\Entity\User
            mappedBy: role
    lifecycleCallbacks: {  }

Access is through a page with an integrated form, like this:

{% extends 'base.html.twig' %}
{% block body %}
    Página principal de la aplicación
    <br><br>

    {% if error %}
        <div>{{ error.messageKey|trans(error.messageData, 'security') }}</div>
    {% endif %}

    <form action="{{ path('entry_point') }}" method="post">
        <label for="username">Nombre de usuario o correo electrónico:</label>
        <input type="text" id="username" name="username" value="{{ last_username }}" />

        <label for="password">Contraseña:</label>
        <input type="password" id="password" name="password" />

        <button type="submit">login</button>
    </form>
{% endblock %}

The controller (adapted from one copied from the document) is like this:

<?php

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;

class DefaultController extends Controller
{
    public function indexAction(Request $request, AuthenticationUtils $authUtils)
    {
        // get the login error if there is one
        $error = $authUtils->getLastAuthenticationError();

        // last username entered by the user
        $lastUsername = $authUtils->getLastUsername();

        if ($this->getUser() === null) {
            return $this->render('AppBundle::main_app.html.twig', [
                'last_username' => $lastUsername,
                'error'         => $error,
            ]);
        }

        $userRol = $this->getUser()->getRoles()[0];
        if ($userRol == 'ROLE_ADMIN' || $userRol == 'ROLE_SUPER_ADMIN' || $userRol == 'ROLE_ROOT_ADMIN') {
            $destination = 'admin_index';
        } elseif ($userRol == 'ROLE_USER') {
            $destination = 'user_index';
        } else {
            return $this->render('AppBundle::main_app.html.twig', [
                'last_username' => $lastUsername,
                'error'         => $error,
            ]);
        }

        return $this->redirectToRoute($destination);
    }
}

When I access users who are in_memory there is no problem. He identifies me, and redirects me correctly. However, if I try to access with a user of the BD, it throws the following exception: Type error: Argument 4 passed to Symfony \ Component \ Security \ Core \ Authentication \ Token \ UsernamePasswordToken :: __ construct () must be of the type array, given null, called in C: \ xampp \ htdocs \ base_project_dark_q \ vendor \ symfony \ symfony \ src \ Symfony \ Component \ Security \ Core \ Authentication \ Provider \ UserAuthenticationProvider.php online 94

As he only mentions files that are from Symfony itself, which are not the ones I created, I do not know where to start looking. It is supposed that the user should read, read his role (for relations between entities) and redirect me.

Does anyone know what I'm doing wrong? I'm a rookie at Symfony and any help will be appreciated.

    
asked by Chefito 06.04.2018 в 20:01
source

1 answer

1

I suspect it is because you have not implemented a method of UserInterface :

public function getRoles()
{
    // TODO: Implement getRoles() method.
}

You have to return an array of roles, hence the null that marks you.

Greetings

    
answered by 17.04.2018 / 12:45
source