Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Security] Why RoleInterface will be removed on 4.0 release? #24043

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
merorafael opened this issue Aug 30, 2017 · 13 comments
Closed

[Security] Why RoleInterface will be removed on 4.0 release? #24043

merorafael opened this issue Aug 30, 2017 · 13 comments
Labels

Comments

@merorafael
Copy link

merorafael commented Aug 30, 2017

Q A
Bug report? no
Feature request? yes
BC Break report? yes
RFC? no
Symfony version 3.3.8

Why the RoleInterface is deprecated and will be removed on 4.0 release?

The super class Role is a poor implementation, because the old projects entities can have a super class. The change(RoleInterface to super class Role) does not appear to have a technical justification.

@xabbuh
Copy link
Member

xabbuh commented Aug 31, 2017

The goal is to move away from the Role class itself (see also #22048) and completely rely on roles just being simple strings. Thus having a RoleInterface does not make much sense either then.

@wilcorrea
Copy link

Is there any way of maintaining compatibility with the previous stream? How can we migrate to this new structure a paper system that is saved in a database, for example?

@xabbuh
Copy link
Member

xabbuh commented Aug 31, 2017

I am not sure I understand your question. What do you mean with "paper system"? And how does it depend on your roles to be custom classes?

@merorafael
Copy link
Author

@xabbuh My question is this: if my application have a Role entity with an attribute that represents the role. Today using 3.x version I create using the example below:

class Group implements RoleInterface
{
    use IdTrait;

    /**
     * @var string Name
     *
     * @ORM\Column(type="string", length=30)
     */
    protected $name;

    /**
     * @var string Role identifier
     *
     * @ORM\Column(type="string", length=20, unique=true)
     */
    protected $role;

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

Note that I use one trait in above example. I could have use a superclass and not a trait(IdTrait).

The change made in Symfony 4.0, you changed the interface RoleInterface to superclass Role with the same method(getRole). I need change my class to example below:

class Group extends Role
{
    use IdTrait;

    /**
     * @var string Name
     *
     * @ORM\Column(type="string", length=30)
     */
    protected $name;

    /**
     * @var string Role identifier
     *
     * @ORM\Column(type="string", length=20, unique=true)
     */
    protected $role;
}

Using my examples, I don't need work on many changes, but the old projects may have an old entity equal to example below:

class Group extends AbstractEntity implements RoleInterface
{
    /**
     * @var string Name
     *
     * @ORM\Column(type="string", length=30)
     */
    protected $name;

    /**
     * @var string Role identifier
     *
     * @ORM\Column(type="string", length=20, unique=true)
     */
    protected $role;

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

On this last example, I have an superclass AbstractEntity and the interface RoleInterface implemented. I need work to change my code to change from superclass "AbstractEntity" to superclass "Role" and this can create a more fails in my code.

Resume
The Symfony users can work to big code changes to move from interface "RoleInterface" to superclass "Role", and don't have any technical justification, using the follow argument:

  • I can test variable type using interface, equals a superclass;
$group instanceof Role == $group instanceof RoleInterface
  • Not have any change on "Role" superclass that justified this change, both interface and superclass have a same method and nothing more;

  • If the intention is to implement new features in superclass, the ideal would be to use a trait in conjunction with an interface, as it is done ok in "ContainerAwareInterface" and "ContainerAwareTrait" today.

Sorry for my bad english rs

@xabbuh
Copy link
Member

xabbuh commented Aug 31, 2017

I see two possible solutions depending on what you need:

  1. Do not let your role entities extend any Symfony class anymore and inside your user class the getRoles() class will simply return the string representation of your role entities.

  2. Implement a custom voter that would work directly on your role objects (that again would not extend any Symfony class). This can be useful if you need to check a bit more than just the name of your role objects.

@nicolas-grekas
Copy link
Member

Closing as this has been answered.

@delboy1978uk
Copy link
Contributor

I don't see the harm in having the RoleInterface define a method getRole() to return a string?
If Symfony is moving their roles to be just strings, then fine, but so what? It's not your concern how I generate that string, and having the interface provides the contract that ensures I will deliver that string. This is a poor decision imo. In theory the concrete class should be the one being deprecated.
@merorafael you could create a HasRoleTrait, which contains a private $role with a getter and setter. Pretty lame, but it should work.

@xabbuh
Copy link
Member

xabbuh commented Dec 5, 2017

@delboy1978uk The concrete class will be deprecated in the future too. We just didn't manage to finish the PR for 3.4/4.0.

@delboy1978uk
Copy link
Contributor

I have no problems with concrete implementations being deprecated and removed, I just thought removing a contractual interface guaranteeing a string from a getRole() method was a very strange design decision indeed

@fsmeier
Copy link

fsmeier commented Apr 17, 2018

+1 on this issue. Would be nice to link to the discussion where the decision was made to understand the thought behind this.

@emkookmer
Copy link

emkookmer commented May 11, 2018

@xabbuh if a pull request wasn't finished, it show that this was a bad choice to remove the interface too early

@valepu
Copy link

valepu commented May 30, 2019

I have discovered this deprecation in the latest changelog, and i don't understand this change at all.
I moved from FOSUserBundle to the default authentication features provided by Symfony because it better supported roles as a Object (so that i could make my entity with its own table in the DB) rather than saving them in a serialized array on the DB
Now i have to go back into manually handling the roles system again. I can't find the discussion about this deprecation so i'd like to know what are the advantages of using only strings rather than letting people chose from string or objects?

@johnpancoast
Copy link

johnpancoast commented Feb 7, 2020

Coming back to Symfony after a little time away, I came across some of these same considerations too.

You can still use Role entities. You can handle roles however you want really. The only real security requirement that I can see is from the UserInterface::getRoles() method. Your User::getRoles() method must return an array of roles as strings but you do not have to store roles as a JSON string like the default User entity setup. You can change that.

For example, you can instead change things to be a ManyToMany relationship between a User and Role entity and then just change the logic of User::getRoles() to loop the related Role entities, get the role names as strings, and return those as an array. Everything else will still work as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants