有没有一种方法可以从Symfony中的特定表加载角色?

时间:2020-09-25 21:05:28

标签: php symfony

我有一个应用程序可以管理一个实体(USER)内的所有用户,并根据建议实施UserInterface。 链接到它,我得到了CUSTOMER和EMPLOYEE实体:每个实体都存储有关用户的特定信息。

您可能会问我为什么要这样做:员工可以在许多工作场所担任客户,并且可以在许多工作场所工作。为了避免重复,常用信息集中在USER中,而USER中的属性Roles在db中始终为空。

这里的目标是在EMPLOYEE登录时根据存储在另一个实体(WORKPLACE)中的特定数据加载我的角色。

我的大问题可能存在于UserRepository中:当symfony调用存储库以查找在登录表单上输入的用户时,主义不提供任何角色。我摆上了角色,并将User返回给Authenticator(香草的,我还没有碰过)。每次重新查询结束后,Symfony都会检查用户,但然后说教义会加载ROLE_CLIENT(换句话说,没有特权)。

我已经尝试过的事情失败了

实体

class User implements UserInterface
{
    /**
     * @ORM\Id()
     */
    private $cpf;

    /**
     * @ORM\Column
     * 
     */
    private $email;

    /**
     * @ORM\Column
     */
    private $nome;

    /**
     * @var string
     *
     * @ORM\Column
     */
    private $telefone;

    /**
     * @var \DateTime|null
     *
     * @ORM\Column
     */
    private $nascimento;

     /**
     * @var \DateTime|null
     *
     * @ORM\Column
     */
    private $ultimoLogin;

    /**
     * @var string|null
     *
     * @ORM\Column
     */
    private $endereco;

    /**
     * @var string|null
     *
     * @ORM\Column
     */
    private $cidade;

    /**
     * @var string|null
     *
     * @ORM\Column
     */
    private $uf;

    /**
     * @var int|null
     *
     * @ORM\Column
     */
    private $cep;

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

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

//vanilla getters and setters

工作场所实体

布尔值存储我想获得的特权

class LocalTrabalho
{
    /**
     * @var Configuracao
     * 
     * @ORM\ManyToOne(targetEntity=Configuracao::class, inversedBy="localTrabalho")
     * @ORM\JoinColumn(name="CNPJ", referencedColumnName="CNPJ", nullable=false)
     * @ORM\Id
     * the company unique code
     */
    private $cnpj;

    /**
     * @var Funcionario
     * 
     * @ORM\ManyToOne(targetEntity=Funcionario::class, inversedBy="localTrabalho")
     * @ORM\JoinColumn(name="CPF_Funcionario", referencedColumnName="CPF", nullable=false)
     * @ORM\Id
     * the user-employee unique code
     */
    private $cpfFuncionario;

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

    /**
     * @var bool
     * 
     * @ORM\Column
     */
    private $privilegioCaixa = 0;

    /**
     * @var bool
     * 
     * @ORM\Column
     */
    private $privilegioPrestador = 1;

    /**
     * @var bool
     * 
     * @ORM\Column
     */
    private $privilegioRecepcao = 0;

    /**
     * @var bool
     * 
     * @ORM\Column
     */
    private $privilegioAdministracao = 0;

员工实体

class Funcionario
{
    /**
     * @var int
     *
     * @ORM\Column
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $cpf;

    /**
     * @var string|null
     *
     * @ORM\Column
     */
    private $ctps;

    /**
     * @var string|null
     *
     * @ORM\Column
     */
    private $foto;

来自db的USER元组示例

# 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

我的最后一个资源是在这里,在漫长而浪费的工作时间后,我该怎么办(或我做错了什么)?

我已经看到其他一些线程在问类似的问题,但是它们已经过时了(使用版本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:有人尝试过这种方法(https://github.com/symfony/symfony/issues/12025#issuecomment-562004005)并在symfony5中获得成功吗?

1 个答案:

答案 0 :(得分:0)

嗯,事实证明,对于我的案例来说,最好的解决方案是操作 User 存储库。 Doctrine 使用它们来操作数据库,所以我只是在里面编写了我的规则,让框架来完成剩下的工作。

算法如下图所示:

  • 使用提供的 $id
  • 查找用户
  • 如果他/她在某处工作,请将 ROLE 常量加载到 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 App\Entity\LocalTrabalho 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;
}