H
H
hbuser2014-02-22 09:51:50
Laravel
hbuser, 2014-02-22 09:51:50

Laravel. ACL. A snag with the logic of work?

I am writing for personal use an extension for Laravel to control access to the site.
Didn't use any ready-made solutions.
I am guided by logic.
First I will describe what I came up with, then - the question.
I doubted what to bind to: to the URL or to the methods in the controllers. Stopped on methods in controllers.
What actions may need to be protected: CRUD. Any actions on the site fall under this set. In some cases, not the entire set will be used, but nevertheless. For example.
51e3994e5d0e4219b5bf08c35dda7538.PNG
All actions that need to be protected will be stored in the permissions table. Records of the form ClassName.methodName are stored there. In order to be able to allow the user some protected actions, they need to be combined into roles. These roles are stored in the roles table. The Roles and Permissions tables have a many-to-many relationship. This will allow you to create both standard roles (admin, user, etc.) and personal ones if necessary (vasya, etc.). A user can only be assigned a role, but it must first be created. Because the extension is installed on the existing Laravel authorization / registration system, then by default each user will be assigned the only default role that initially exists, which will prohibit all actions for the user (or you can configure a number of common ones allowed for everyone). Those.,
Thus, the problem of blocking certain actions in the logic is solved.
In order to indicate that the performance of some action depends on the role, it is enough to call ACL::hasPermission() in the required RESTfull method. If the user does not have the right to act, then an error view will be displayed. If it does, then nothing will happen. You don't have to pass anything to the method. Because permissions in the permission table in the form of ClassName.methodName, then hasPermission will take __CLASS__, __METHOD__ will compare them with the roles in the current session (when the user authorizes, the roles will be added to the session so that they are not pulled from the database each time).
e2a61cc58b2647d4b9e11d81ccb9524f.PNGa81d012c5ee74aa3a728d05e2fd4abb8.PNG
Now the problem. There is one more thing left. It may be necessary, depending on the role, to change some parts of the view. Binding to role id or name is a bad option, because they are fickle. At any moment they can leave, change. But the permissions are relatively constant. What is the best way to shape content based on user permissions?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
K
kaluzhanin, 2014-11-20
@hbuser

I used the approach taken from the CanCan gem from RubyOnRails.
The idea is this: we define a trait Ability and add it to the User class. This trait itself has a can method that allows/denies a specific action:

<?php

trait Ability
{
    public function can($verb, $noun)
    {
        $class = is_string($noun) ? $noun : get_class($noun);
        if(is_callable([this, "canManage$class"]))
        {
            $this->{"canManage$class"}($verb, $noun);
        } else {
             $this->fallback($verb, $noun);
        }
    }

    public function canManageUser($verb, $noun)
    {
        switch($verb) {
            case 'create':
                return true;
            case 'edit':
                if ($this->isAdmin()) return true;
                if ($noun->id == $this->id)  return true;
                break;
            case 'delete':
            case 'destroy':
                if ($noun->id == $this->id) return false;
                break;
        }
        return $this->fallback($verb, $noun);
    }

    public function fallback($verb, $noun)
    {
        if ($this->isAdmin()) return true;
        return false;
    }

    public function isAdmin()
    {
        return $this->role == self::ADMIN;
    }
}

Thus, we isolate the semantics of roles in one specific place, and define permissions not at the level of the Entity class, but at the level of a specific entity, which is much more flexible.
As for using it in a view, no problem:
@if(Auth::user() && Auth::user()->can('edit', $page))
<form></form>
@endif
@if(Auth::user() && Auth::user()->can('create', 'Page'))
<a href="#">Добавить страницу</a>
@endif

A
Anatoly60, 2014-02-22
@anatoly60

How did you draw the diagrams? Look very cute

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question