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

后端 未结 2 1570
一向
一向 2020-12-20 06:21

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

相关标签:
2条回答
  • 2020-12-20 06:45

    It depends how you want to implement this.

    One approach:

    Implement the UserProviderInterface to loadByUsername (this is where you load the roles and permissions) an implementation of a UserInterface (your User).

    Then Implement the VoterInterface. Register this as a service tagged with security.voter and specify it as a provider in security.yml. Override the vote function to assess the User you loaded for permissions (and maybe roles too) from TokenInterface which is the first argument of that function.

    0 讨论(0)
  • 2020-12-20 07:04

    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: EventListenerBundle\EventListener\TokenListener
            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.

    0 讨论(0)
提交回复
热议问题