Skip to content
Advertisement

There is a way to load roles from a specific table in Symfony?

I have an app that manages all of its users inside one entity (USER), implementing the UserInterface, as recommended. Linked to it, I got the CUSTOMER and the EMPLOYEE entities: each one storing specific infos about the user.

You may ask why I’m doing like this: an EMPLOYEE can be a CUSTOMER in many WORKPLACES and may work in many WORKPLACES. In order to avoid repetition, the common info got centralized in USER and the attribute Roles in USER is always blank in db.

The goal here is to load my roles based on specific data stored in another entity (WORKPLACE) when an EMPLOYEE logs in.

My great question may live in the UserRepository: when symfony calls the repository looking for the user entered on the login form, doctrine delivers it with no roles. I put my roles and return the User to the Authenticator (the vanilla one, I havent touched it yet). After the end of every requery, Symfony checks for the user but then doctrine loads the ROLE_CLIENT (in other words – no privileges).

What I already tried and failed

The entities

class User implements UserInterface
{
    /**
     * @ORMId()
     */
    private $cpf;

    /**
     * @ORMColumn
     * 
     */
    private $email;

    /**
     * @ORMColumn
     */
    private $nome;

    /**
     * @var string
     *
     * @ORMColumn
     */
    private $telefone;

    /**
     * @var DateTime|null
     *
     * @ORMColumn
     */
    private $nascimento;

     /**
     * @var DateTime|null
     *
     * @ORMColumn
     */
    private $ultimoLogin;

    /**
     * @var string|null
     *
     * @ORMColumn
     */
    private $endereco;

    /**
     * @var string|null
     *
     * @ORMColumn
     */
    private $cidade;

    /**
     * @var string|null
     *
     * @ORMColumn
     */
    private $uf;

    /**
     * @var int|null
     *
     * @ORMColumn
     */
    private $cep;

    /**
     * @ORMColumn(name="Roles", type="json")
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORMColumn(name="password", type="string")
     */
    private $password;

//vanilla getters and setters

Workplace entity

The booleans store the privileges i want to get

class LocalTrabalho
{
    /**
     * @var Configuracao
     * 
     * @ORMManyToOne(targetEntity=Configuracao::class, inversedBy="localTrabalho")
     * @ORMJoinColumn(name="CNPJ", referencedColumnName="CNPJ", nullable=false)
     * @ORMId
     * the company unique code
     */
    private $cnpj;

    /**
     * @var Funcionario
     * 
     * @ORMManyToOne(targetEntity=Funcionario::class, inversedBy="localTrabalho")
     * @ORMJoinColumn(name="CPF_Funcionario", referencedColumnName="CPF", nullable=false)
     * @ORMId
     * the user-employee unique code
     */
    private $cpfFuncionario;

    /**
     * @var bool
     * 
     * @ORMColumn
     * is this employee is active?
     */
    private $ativo = 1;

    /**
     * @var bool
     * 
     * @ORMColumn
     */
    private $privilegioCaixa = 0;

    /**
     * @var bool
     * 
     * @ORMColumn
     */
    private $privilegioPrestador = 1;

    /**
     * @var bool
     * 
     * @ORMColumn
     */
    private $privilegioRecepcao = 0;

    /**
     * @var bool
     * 
     * @ORMColumn
     */
    private $privilegioAdministracao = 0;

Employee Entity

class Funcionario
{
    /**
     * @var int
     *
     * @ORMColumn
     * @ORMId
     * @ORMGeneratedValue(strategy="NONE")
     */
    private $cpf;

    /**
     * @var string|null
     *
     * @ORMColumn
     */
    private $ctps;

    /**
     * @var string|null
     *
     * @ORMColumn
     */
    private $foto;

An example USER tuple from db

# CodPFis, email, password, Roles, Nome, Telefone, Nascimento, Ultimo_login, Endereco, Cidade, UF, CEP
'89038252099', 'sophiejenniferteresinhaoliveira__sophiejenniferteresinhaoliveira@grupomozue.com.br', '$argon2id$v=19$m=65536,t=4,p=1$WEn7b64I9744kRJICEpaLA$jcYLDvh2bZsZPakMDGsncpbfIZwR6lN0QcgJOOSerK0', NULL, 'João da Silva', '', NULL, NULL, NULL, NULL, NULL, NULL

My last resource is asking here, after some long and wasted work hours, what should I do (or what i did wrong)?

I’ve seen some other threads asking similar questions, but they’re outdated (im using the version 5): Dynamic roles in symfony Symfony 2 – Loading roles from database Symfony2 – Dynamic Role Management How to update roles in security token in Symfony 4 without re-logging in Symfony User Logout After Role Change

PS: Someone tried this approach (https://github.com/symfony/symfony/issues/12025#issuecomment-562004005) and got success in symfony5?

Advertisement

Answer

Well, turns out that the best solution for my case was manipulate the User Repository. Doctrine uses them to operate the db so I just coded my rules inside and let the framework do the rest.

The algorithm is something like the shown below:

  • Find the user using the provided $id
  • If he/she works somewhere, load the ROLE constants into the User entity
  • If he/she does not have a job, load the profile as a common user
public function find($id, $lockmode=null, $lockversion = null){
        $us = $this->createQueryBuilder('u')
        ->andWhere('u.cpf = :cpf')
        ->setParameter('cpf', $id['cpf'])
        ->getQuery()->getOneOrNullResult();        
        $lt = $this->_em->createQuery(
            'SELECT t
            FROM AppEntityLocalTrabalho t
            WHERE t.cpfFuncionario = :cpf'
        )
        ->setParameters(['cpf' => $us->getCpf()])
        ->getResult();

        if (count($lt) > 0){
            $regras = ['ROLE_FUNCIONARIO'];
            if ($lt[0]->getPrivilegioCaixa()) $regras[] = 'ROLE_CAIXA';
            if ($lt[0]->getPrivilegioPrestador()) $regras[] = 'ROLE_PRESTADOR';
            if ($lt[0]->getPrivilegioRecepcao()) $regras[] = 'ROLE_RECEPCAO';
            
            if ($lt[0]->getPrivilegioAdministracao())
            {
                $regras = ['ROLE_ADMIN'];
            }
            $us->setRoles($regras);
        }
        return $us;
}
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement