I
I
Igor2020-06-15 10:22:34
symfony
Igor, 2020-06-15 10:22:34

Groups and permissions, RBAC best practice in symfony?

Colleagues, welcome.
Give advice.

What's the best way to do it?

Store permissions per user?
Or for groups to which the user belongs?
I need best practice.

Internally, the perfectionist does not give rest.

For example.
Well type I get attributes from group in which the user consists.
Accordingly, if it is not a member of the group, then there are no permissions.

voter
<?php


namespace App\Security\Administrator\Voter;


use App\Entity\User;
use App\Entity\UserGroup;
use Exception;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;

/**
 * Class UserVoter
 * @package App\Security\Administrator\Voters
 */
class UserVoter extends Voter implements IVoter
{

    public const CREATE_USERS = 'create_users';
    public const EDIT_USERS = 'edit_users';
    public const DELETE_USERS = 'delete_users';
    public const VIEW_USERS = 'view_users';
    public const VIEW_CONTACTS = 'view_contacts';
    public const SET_PRIVILEGES_USERS = 'set_privileges_users';


    /**
     * @param string $attribute
     * @param mixed $subject
     * @return bool
     */
    protected function supports($attribute, $subject)
    {
        if (!in_array($attribute, $this->getAttributes())) {
            return false;
        }

        return true;
    }


    /**
     * @param string $attribute
     * @param mixed $subject
     * @param TokenInterface $token
     * @return bool
     */
    protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
    {
        $user = $token->getUser();

        if (!$user instanceof User) {
            return false;
        }

        $permissions = [];
        try {
            if (is_a($user->getGroup(), UserGroup::class)) {
                $permissions = $user->getGroup()->getPermissions();
            }

            foreach ($permissions as $permission) {
                if (in_array($permission, $this->getAttributes())) {
                    return true;
                }
            }

            return false;
        }catch (Exception $exception) {
            return false;
        }
    }


    /**
     * @return string[]
     */
    public function getAttributes()
    {
        return [
            self::CREATE_USERS,
            self::EDIT_USERS,
            self::DELETE_USERS,
            self::VIEW_USERS,
            self::VIEW_CONTACTS,
            self::SET_PRIVILEGES_USERS
        ];
    }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
Igor, 2020-06-17
@IgorPI

Colleagues, I decided to do the following.
Having a certain permission stack for something is not important, the main thing is that it be static.
What do I mean when I say "static stack"?
These are normal attributes that are declared beforehand.
Example

class UserVoter extends Voter implements IVoter
{

    public const CREATE_USERS = 'create_users';
    public const EDIT_USERS = 'edit_users';
    public const DELETE_USERS = 'delete_users';
    public const VIEW_USERS = 'view_users';
    public const VIEW_CONTACTS = 'view_contacts';
    public const SET_PRIVILEGES_USERS = 'set_privileges_users';
...

Further check in the voter
...
$permissions = [];
        try {
            if (is_a($user->getGroup(), UserGroup::class)) {
                $permissions = $user->getGroup()->getPermissions();
            }

            foreach ($permissions as $permission) {
                if (in_array($permission, $this->getAttributes())) {
                    return true;
                }
            }

            return false;
        }catch (Exception $exception) {
            return false;
        }
...

As a result, all permissions belong to a certain group, and this or that user already belongs to the group.
That's all.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question