Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
441 views
in Technique[技术] by (71.8m points)

php - How to dynamic handle roles|permissions in Symfony2 at database level: CRUD operations over them

I am working in a Symfony 2.8 project and I have a doubt regarding users/groups/roles|permissions. There are a few ways to handle users and groups as for example SonataUser on top of SonataAdmin and lately EasyAdmin but all of them lacks ROLE|permissions management and this is exactly my doubt: what's the proper way to handle them? Yes, I know I need to write them at security.yml but I don't know if I can store then in DB (somewhere) and then read from there. I have research about this and found ACL, Voters and so on but instead of clear my mind the research is confusing me a lot so I need some push from people here. Then:

  • How would you handle this?
  • Any example at code level? (I prefer to see something other than words to get the whole point)
  • Are ROLES sames as permissions?

Update: improve question

What I want to have is a ManyToMany relationship between users and roles and possibly groups and roles. I think that as SonataUserBundle handle this is by creating a column roles in user table and assign a lot of roles to each user, even create new ones if I'm not mistaken but what about if I want to create as much roles as I can without assign them to a user and later add many roles to a user even to a group?

How would you do that?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can add new roles in the FOSUserBundle on the go. There is no need for you to initially add it in the security.yml file.

To do this you can do something like this:

$user = new User();
$user->addRole('ROLE_NEWUSER'); //Role Name should begin with 'ROLE_'

or in your controller you can get current or any user

$this->getUser();
$user->addRole('ROLE_NEWUSER'); //Role Name should begin with 'ROLE_'

This answers your first and second part.

For the third part, Roles can be used as permissions. I have implemented a structure previously where I was restricting access to pages based on the user role also restricting what data they can change based on their role.

UPDATE I implemented an Event Listener for this which would listen to all the kernel requests which is called onKernelRequest. I have partially done the access management on the SQL side since I have my roles stored in SQL side as well but one can do the same on the Server side. My Event Listener looked like this: (This is a trimmed down version of what I have)

class TokenListener
{
    protected $em;
    protected $token_storage;
    protected $templating;
    protected $router;
    protected $resolver;
    public function __construct($em,TokenStorageInterface $token_storage, TwigEngine $templating, Router $router, ControllerResolver $resolver)
    {
        $this->em = $em;
        $this->token_storage = $token_storage;
        $this->templating = $templating;
        $this->router = $router;
        $this->resolver = $resolver;
    }


    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        $route  = $request->attributes->get('_route');
        $routeArr = array('fos_js_routing_js', 'fos_user_security_login', '_wdt'); //These are excluded routes. These are always allowed. Required for login page
        if(!is_int(array_search($route, $routeArr)) && false)
        {
            $userRoles = $this->token_storage->getToken()->getUser()->getRoles();
            if(!in_array('ROLE_NEWUSER', $userRoles))
            {
                $event->setResponse(new RedirectResponse($this->router->generate('user_management_unauthorized_user', array())));
            }
        }
    }
}

My services.yml looks like this

services:
    app.tokens.action_listener:
        class: EventListenerBundleEventListenerTokenListener
        arguments:
            entityManager: "@doctrine.orm.entity_manager"
            token_storage: "@security.token_storage"
            templating: "@templating"
            router: "@router"
            resolver: "@controller_resolver"
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

UPDATE To answer your update part of the question, what you can do is have another roles entity and you could populate the roles you want in advance and then have a one to many relationship with the original User table. You can then have something like prePersist or preUpdate Doctrine Lifecycle Events to check when adding a new if the role already exists in your roles entity. That should precisely solve your problem. All this will involve a little tweaking though. There is no straight way to do this.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...