Giter Club home page Giter Club logo

laravel-acl's Introduction

Kodeine/Laravel-ACL

Laravel Source Build Status License Total Downloads

Laravel ACL adds role based permissions to built in Auth System of Laravel 9.0+. ACL middleware protects routes and even crud controller methods.

Table of Contents

Requirements

  • Version 2.x of this package requires PHP 7.2+ and Laravel 6.0+
  • Version 1.x requires PHP 5.6+ and Laravel 5.0+

Getting Started

Install the package using composer

composer require kodeine/laravel-acl

If you need to support Laravel 5.x, make sure to install version 1.x

composer require kodeine/laravel-acl "^1.0"
  1. If you are using Laravel before version 5.4, manually register the service provider in your config/app.php file
'providers' => [
    'Illuminate\Foundation\Providers\ArtisanServiceProvider',
    'Illuminate\Auth\AuthServiceProvider',
    ...
    'Kodeine\Acl\AclServiceProvider',
],
  1. Publish the package configuartion files and add your own models to the list of ACL models"
$ php artisan vendor:publish --provider="Kodeine\Acl\AclServiceProvider"

Once you publish, it publishes the configuration file where you can:

  • Use your own models: Define your own models which should extend to Acl models.
  • Use your own guard: Define a guard other than laravel default for user recovery.
  1. Add the middleware to your app/Http/Kernel.php.
protected $routeMiddleware = [
    ....
    'acl' => 'Kodeine\Acl\Middleware\HasPermission',
];
  1. Add the HasRole trait to your User model.
use Kodeine\Acl\Traits\HasRole;

class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
    use Authenticatable, CanResetPassword, HasRole;
}
  1. Run the migrations to generate your roles and permissions tables

Please note that if you are upgrading to 6.0 from a previous version, the default column type for the id on the users table has changed. On certain databases foreign keys can only be defined with matching column types. As such, you will need to change the id column on your users table to bigInteger in to user this package.

php artisan migrate

Documentation

Follow along the Wiki to find out more.

Roadmap

Here's the TODO list for the next release.

  • Refactoring the source code.
  • Correct all issues.
  • Adding cache to final user permissions.

Change Logs

June 14 2022

  • Added support for different guard

September 14 2019

  • Updated the readme to reflect new major release

September 13, 2019

  • Added support for Laravel 6

September 22, 2016*

  • Added unit tests

September 20, 2016*

  • Added support for Laravel 5.3

September 19, 2016

  • Added cache support to Roles and Permissions.

June 14, 2015

March 28, 2015

  • Added Role Scope to get all users having a specific role. e.g User::role('admin')->get(); will list all users having admin role.

March 7, 2015

  • is() and can() methods now support comma for AND and pipe as OR operator. Or pass an operator as a second param. more information
  • You can bind multiple permissions together so they inherit ones permission. more information

Contribution Guidelines

Support follows PSR-2 PHP coding standards, and semantic versioning.

Please report any issue you find in the issues page. Pull requests are welcome.

laravel-acl's People

Contributors

ajoy39 avatar ajtrichards avatar alec-joy avatar alexsnowb avatar chris-doehring avatar chrisschaetzlein avatar codeigor avatar cptmeatball avatar damiandriscoll avatar fridzema avatar heukirne avatar ilyasavich avatar jshah4517 avatar khaledsmq avatar kodeine avatar lagg avatar mivale avatar peetersdiet avatar rafaelpv avatar rjackson avatar screencomuser avatar stygiansabyss avatar tolawho avatar tylerwiegand avatar uzegonemad avatar vanderson139 avatar vjandrea avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laravel-acl's Issues

Assing specific permissions to roles

Hi, is it possible to assign only specific permissions to roles?

According to the wiki it's possible to do this by following line:

$roleAdmin->assignPermission('user');

But in my case I want my roles to only have something like this:

$roleUser->assignPermission('view.user');
$roleModerator->assignPermission(['view.user', 'update.user']);
$roleAdmin->assignPermission('user');

So is this possible with the code above or is it a feature that has to be implemented?

Regards,
Stefan

Blade template

using
@ROLE('artist')
test
@Endrole

simply outputs the blade stuff as if it were text, i'm in Laravel 5.1 I have not tested in 5.0.x

Integrity constraint violation

When I try to run the first example in Create Permissions part, I get the following error:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`laravel5`.`permissions`, CONSTRAINT `permissions_inherit_id_foreign` FOREIGN KEY (`inherit_id`) REFERENCES `permissions` (`id`)) (SQL: insert into `permissions` (`name`, `slug`, `description`, `updated_at`, `created_at`) values (user, {"create":true,"view":true,"update":true,"view.phone":true,"delete":true}, manage user permissions, 2015-03-17 16:33:08, 2015-03-17 16:33:08))

I've migrated all tables of course.

Code is:

    $permission = new \Kodeine\Acl\Models\Eloquent\Permission();
    $permission->create([ 
        'name'        => 'user',
        'slug'        => [          // pass an array of permissions.
            'create'     => true,
            'view'       => true,
            'update'     => true,      
            'view.phone' => true,
            'delete'     => true   
        ],
        'description' => 'manage user permissions'
    ]);

Use middleware ?

Hi,

I've some issues with the middleware. You can see my seed:

<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class UsersTableSeeder extends Seeder {

    public function run()
    {
        DB::table('users')->truncate();

        $admin = new \App\User();
        $admin->email = "[email protected]";
        $admin->password = "admin";
        $admin->save();

        $editor = new \App\User();
        $editor->email = "[email protected]";
        $editor->password = "editor";
        $editor->save();

        $user = new \App\User();
        $user->email = "[email protected]";
        $user->password = "user";
        $user->save();
    }

}
<?php

use App\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Kodeine\Acl\Models\Eloquent\Permission;
use Kodeine\Acl\Models\Eloquent\Role;

class AclTableSeeder extends Seeder {

    public function run()
    {

        DB::table('roles')->truncate();
        DB::table('role_user')->truncate();
        DB::table('permissions')->truncate();
        DB::table('permission_role')->truncate();
        DB::table('permission_user')->truncate();

        $roleAdmin = new Role();
        $roleAdmin->name = 'Administrator';
        $roleAdmin->slug = 'admin';
        $roleAdmin->description = 'manage administration privileges';
        $roleAdmin->save();

        $roleEditor = new Role();
        $roleEditor = $roleEditor->create([
            'name' => 'Editor',
            'slug' => 'editor',
            'description' => 'manage editor privileges'
        ]);

        $roleUser = new Role();
        $roleUser = $roleUser->create([
            'name' => 'User',
            'slug' => 'user',
            'description' => 'manage user privileges'
        ]);


        $userAdmin = User::where('email', '=', '[email protected]')->first();
        $userAdmin->assignRole($roleAdmin);

        $userEditor = User::where('email', '=', '[email protected]')->first();
        $userEditor->assignRole($roleEditor);

        $userUser = User::where('email', '=', '[email protected]')->first();
        $userUser->assignRole($roleUser);


        $permissionRole = Permission::create([
            'name'        => 'role',
            'slug'        => [ // an array of permissions.
                'index' => true, // with or without it doesn't work
                'create' => true,
                'view'   => true,
                'update' => true,
                'delete' => true,
            ],
            'description' => 'manage role'
        ]);

        $permissionUser = Permission::create([
            'name'        => 'role.editor',
            'slug'        => [ // an array of permissions only for student
                'create' => false,
            ],
            // we use permission inheriting.
            'inherit_id' => $permissionRole->getKey(),
            'description' => 'user roles permissions'
        ]);

        $roleAdmin->assignPermission('role');
        $roleEditor->assignPermission('role.editor');
    }

}

If I'm logged as admin I see with $user->getPermissions():

"role" => array:4 [▼
    "create" => true
    "view" => true
    "update" => true
    "delete" => true
  ]

And as editor:

"role" => array:4 [▼
    "create" => false
    "view" => true
    "update" => true
    "delete" => true
  ]

And in my routes.php

Route::group( [
    'middleware' => ['auth', 'acl'],
    'is' => 'admin|editor',
    'can' => 'create.role',
    ], function () {

    Route::resource('roles', 'RolesController');

});

So, as admin it's working great, but as editor, if I try to go in /roles, I'm not authorized to see that page and I don't know what I'm doing wrong.

I would like to check if the user is admin or editor and check if he can create a role only. Editor is allowed to views the /roles pages.

The solution is to create each route for a resource but it's really heavy to write each RESTFUL resource like this:

Route::get('/roles', [
    'uses'        => 'RolesController@index',
    'middleware'   => ['auth', 'acl'],
    'is'           => 'admin|editor']);

Route::get('/roles/create', [
    'as' => 'roles.create',
    'uses'        => 'RolesController@create',
    'middleware'   => ['auth', 'acl'],
    'is'           => 'admin|editor',
    'can' => 'create.role']);

Or If I want to use resource I need to update your middleware and it's working otherwise I'm never in the condition. I need to update my database to add "store": true for role and "store": false for role.editor and of course in routes.php I have 'can' => 'store.role':

if ( $this->protectMethods() ) {
    return $next($request);
}

I think it's because of last(array_keys($crud)) . '.' . $this->parseAlias(); You get the last key:

When I'm on /roles/create route:

$crud = array_where($methods, function ($k, $v) use ($called) {
    return in_array($called, $v);
});
dd($crud);

array:2 [▼
  "create" => array:2 [▼
    0 => "create"
    1 => "store"
  ]
  "store" => array:2 [▼
    0 => "create"
    1 => "store"
  ]
]

$permission = last(array_keys($crud)) . '.' . $this->parseAlias();
dd($permission);

'store.role'

It looks we can't never check the create method because of that.

Thx.

Specified role id does not exists

Hi,

Decide to give you package a run as it seems to fit the bill :)

/*$role = new \App\Modules\Base\Models\Role();

$roleAdmin = $role->create([
    'name' => 'Administrator',
    'slug' => 'administrator',
    'description'=>'manage administration privileges'
]);*/

$user = \App\User::find(1);

// assign role by just a slug
$user->assignRole('administrator');

dd($user);

The assignRole fails with...

InvalidArgumentException in HasRole.php line 158: Specified role id does not exists.

Any ideas @kodeine ?

Thanks.

Middleware constructor

Hi,

Not sure if this possible or not or im going about this the wrong way.

$this->middleware('acl', ['is' => 'admin']);

It never sees the "is"

Thanks

Permission based on resource owner ?

How can I implement permission that only owner of resource can make changes to his/her entity.

I have a post table with user_id column.
if post.user_id == current_user_id then he/she can edit

permission based on ownership of entity

Advise for validating permission

Hi Kodeine,
i can't figure out witch is the best way to validate user permission. All my controllers will extends an base controller, where i want to check if user has permission to access the specific methods...
Here is my code:
...
class BaseController extends Controller {

protected $user;

public function __construct(Route $route){

    //set middlewares
    $this->middleware('auth');
    $this->middleware('acl');

    //get loggedin user
    $this->user = Auth::user();

    //get current method
    $permission = $route->getActionName(); 

   /*here is my issue: i dont know how to validate permission based on your provided examples: Auth::user->can('view.user');
 */

    //validate current permission
    if (!$this->user->can($permission)) abort(403);        

}

Is this scenario wrong? Please help me with your advise!
Thank you!

Class 'Role' not found in eval()'d code on line 1

Hello,

i think i make an failure on installation.

on php artisan tinker i try do add a role but get the following error.

$roleAdmin = new Role();
PHP Fatal error: Class 'Role' not found in eval()'d code on line 1

Please help me. I am very new on laravel.

Adding created_by and updated_by column

Hello,

I added 2 columns "created_by" and "updated_by" in the tables "permissions" and "permission_user", how to fill this columns in this two tables when I call the function $user->addPermissions('user') or $user->assignPermission('user').

I figured it out for the table permission by changing the addPermission method like that

public function addPermission($name, $permission = true)
{
$slugs = $this->permissions->keyBy('name');
list($slug, $name) = $this->extractAlias($name);
$created_by="6";
$updated_by="6";

    if ( $slugs->has($name) && is_null($slug) && ! is_array($permission) ) {
        return true;
    }

    if ( ! $slugs->has($name) && is_null($slug) ) {
        return $this->addPermissionCrud($name);
    }

    $slug = is_array($permission)
        ? $permission : [$slug => (bool) $permission];

    // if alias doesn't exist, create permission
    if ( ! $slugs->has($name) )
    {
        $new = $this->permissions()->create(compact('name', 'slug','created_by'));
        $this->permissions->push($new);

        return $new;
    }

    // update slug
    return $slugs[$name]->update(compact('slug','updated_by'));
}

It works fine for me, but I still don't know how to fill it in the permission_user table.

Regards,

assignPermission with object argument

Following the wiki instruction:

$roleAdmin = Role::first(); // administrator
$roleAdmin->assignPermission($permUser);

I got

InvalidArgumentException in HasPermission.php line 157:
Specified permission name does not exists.

Function assignPermission works well when assign by id or name

Question not and issue.

This is more a question then a issue.

When implementing the acl. How would you go about managing this. If I make a admin page that manages the permissions. How would the database know witch permissions have been implemented into the routes file, and for that matter in the code?

Also if I make use of Roles in routes, then how are these roles translated into actual permission sets in the database?

In my mind if I implement either a role or a user permission in the routes file or anywhere else, this should some how be available to me in the interface, so that it is not necessary to implement the roles "by memory". Would this some how be possible?

Laravel 5.0 and 5.1 compatibility issue with lists()

I'm currently working with Laravel v.5.0, and I have an error in the HasRole.php since this 8e5bcd4 update.

FatalErrorException in HasRole.php line 35: Call to a member function all() on array

The lists() method still returns an array in v.5.0 whilst it no longer returns an array in v.5.1.

Could you make it compatible?

Question: Permission inheritance?

Hi Kodeine,

I'm trying to get a handle on this as a Laravel 5 replacement for Entrust. The route protection seems especially useful, and your presence here suggests that this might be a lot better maintained than Entrust seems to be. 👍

However, I'm not sure if either my scenario or my understanding fits the correct workflow here, as I can't see any form of permission inheritance.

I have set up three roles: webdev, admin, manager and viewer (the latter is probably redundant, but here for completeness)

I can create a permission for managing clients:

Permission::create([
                'name'        => 'client',
                'slug'        => [
                    'create'  => true,
                    'view'    => true,
                    'update'  => true,
                    'delete'  => false
                ],
                'description' => 'Manage client permissions'
            ]);

However, I would only want to assign those particular permissions to one role, say admin, so as far as I can see in order to make this work I'll need a new permission per role:

Permission::create([
                'name'        => 'client.as.admin',
                'slug'        => [
                    'create'  => true,
                    'view'    => true,
                    'update'  => true,
                    'delete'  => false
                ],
                'description' => 'Manage client permissions as admin'
            ]);

and I'd attach it to admin with:

            $roleAdmin->assignPermission('client.as.admin');

So now for 5 models and 5 controllers using 4 roles I have 20 named permissions and 80 'can' permissions (can('view.client.as.admin') etc.). To use this in a blade file to determine whether a menu item should be displayed or not I think I need:

@if (Auth::user()->can('view.client.as.manager|view.client.as.admin|view.client.as.webdev'))

Might this be better if we could use some form of inheritance, or some form of shortened syntax such as

@if (Auth::user()->can('view.client'))

Further, your Permissions based on Role section says:

$admin = Role::first(); // administrator
$admin->can('view.user');
$admin->canViewUser();  // using method.

I read this as the view boolean on a single user permission, but unless there is just one set of user permissions for all roles, I can''t see how view.user could be different for any role other than no role at all. Am I missing something?

__call() default value causes an error with Mockery

I'm attempting to mock a class with User Eloquent model which has the HasRole traits. When I run my test suite I get this error:

ErrorException: Declaration of Kodeine\Acl\Traits\HasRole::__call() should be compatible with Illuminate\Database\Eloquent\Model::__call($method, $parameters)

After a little bit of research, I found keenlabs/KeenClient-PHP#52 could be related to this issue. It suggests __call()'s $args parameter is required and will always be present as an array and adding a default value can cause problems. It also references mockery/mockery#263 which seems the same as mine.

Question: How does $request->user get the user?

This acl package looks amazing and so I've started implementing it in a project I'm working on.. my problem is that I want to use it a bit differently because I don't want to attach the roles and permissions to my App\User Model. The reason for this is because in my application a user can authenticate using their user, but they have a different profile for each "company" that they register under.

In other words I have another model called Gamer, that essentially works as my user model once a person is logged in to a certain company.

I've gotten all of this to work properly using your package other then the Middleware. When it calls $request->user() I get a null value and I'm not sure how it is trying to get that.

this type of stuff works fine for me

$gamer->getRoles()
$gamer->is('admin');

etc... but the middleware doesn't try and get the correct user model... is there a place I can override that?

I always get this error because user is null:

BadMethodCallException in HasPermission.php line 69:
Call to a member function is() on a non-object (NULL)

here is how I created my Model for Role (and permission) to override the users() function and use my gamers model

<?php namespace App;

use Kodeine\Acl\Models\Eloquent\Role as AclRole;

class Role extends AclRole
{


    /**
     * alias for gamers()
     *
     * @return Gamer
     */
    public function users()
    {
        return $this->gamers();
    }

    /**
     * Roles can belong to many gamers.
     *
     * @return Gamer
     */
    public function gamers()
    {
        return $this->belongsToMany('App\Gamer')->withTimestamps();
    }

}

I also updated the migrations etc.. so the only thing I can't figure out is the middleware.

Call to a member function keyBy() on null

Hello,

I created a new laravel project with new database, I did exactly what you did in the wiki, I hard coded a new user in the database, and then I tried to add a user permission like what you did

$user = User::first();
$user->addPermission('user');

And I get this error:

FatalErrorException in HasUserPermission.php line 17: Call to a member function keyBy() on null

Can you help please ?

Middleware inside resource controller

I've tried to do this inside my resource controller:

public function __construct(){
    $this->middleware('auth');
    $this->middleware('acl', ['protect_alias' => 'salon']);
}

but it doesn't work, why?

Permissions based on relationships

It's possible to have permission based on relationships automatically?
For example, if i have two tables: users and posts.
Can i assign a permission to user A that allow him to see only own posts?
Or i need to do it manually?

Reduce number of query and prevent duplicates

Hi,
I'm testing your package and I have followed you guide.

In a controller I have used this:

dump($this->logged->can('view.user'));
dump($this->logged->can('create.user'));
dump($this->logged->can('update.user'));
dump($this->logged->can('delete.user'));
dump($this->logged->can('view.post'));
dump($this->logged->can('create.post'));
dump($this->logged->can('update.post'));
dump($this->logged->can('delete.post'));

and I notice that it produce a lot of query which increase according to the number of check I do.
Most of this query are duplicated.

schermata 2015-05-08 alle 09 48 34

I think it's important to reduce the number of query and prevent any duplicate.
Do you have any idea why this happens?

Error when using as Global Middleware.

Hi Devs,

Thanks for your wonderful contribution.

I've been using your module smoothly so far, up to when I use it as a "Global Middleware", placing it in the Kernel.php's $middleware array.

The $this->request->route() returns NULL when HasPermission.php is being called during the pipeline.

If this is trivial to fix please kindly help, since it would be very useful to have all routes going through ACL while only exempting a few for public use, especially for some internal system use cases.

Thanks very much.

-Godric

BadMethodCallException in HasPermission.php line 162: Call to a member function getAction() on a non-object (NULL)

    in HasPermission.php line 162
    at HasPermission->getAction('is') in HasPermission.php line 45
    at HasPermission->handle(object(Request), object(Pipeline::getInitialSlice;1764878495)) in Pipeline.php line 125
    at {closure}(object(Request)) in VerifyCsrfToken.php line 43
    at VerifyCsrfToken->handle(object(Request), object(Pipeline::getSlice;1764878495)) in VerifyCsrfToken.php line 17
    at VerifyCsrfToken->handle(object(Request), object(Pipeline::getSlice;1764878495)) in Pipeline.php line 125
    at {closure}(object(Request)) in ShareErrorsFromSession.php line 55
    at ShareErrorsFromSession->handle(object(Request), object(Pipeline::getSlice;1764878495)) in Pipeline.php line 125
    at {closure}(object(Request)) in StartSession.php line 61
    at StartSession->handle(object(Request), object(Pipeline::getSlice;1764878495)) in Pipeline.php line 125
    at {closure}(object(Request)) in AddQueuedCookiesToResponse.php line 36
    at AddQueuedCookiesToResponse->handle(object(Request), object(Pipeline::getSlice;1764878495)) in Pipeline.php line 125
    at {closure}(object(Request)) in EncryptCookies.php line 40
    at EncryptCookies->handle(object(Request), object(Pipeline::getSlice;1764878495)) in Pipeline.php line 125
    at {closure}(object(Request)) in CheckForMaintenanceMode.php line 42
    at CheckForMaintenanceMode->handle(object(Request), object(Pipeline::getSlice;1764878495)) in Pipeline.php line 125
    at {closure}(object(Request))
    at call_user_func(object(Pipeline::getSlice;1764878495), object(Request)) in Pipeline.php line 101
    at Pipeline->then(object(Kernel::dispatchToRouter;1047617302)) in Kernel.php line 115
    at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 84
    at Kernel->handle(object(Request)) in index.php line 53

$role->getUsers();

Hello,

is the an function to get all Users where have the role like

$role->getUsers();

Thanks.

Bug with HasPermissionInheritance

So i have the following situation:

$genericUser=Permission::create([
            'name' => 'users',
            'slug' => [
                'create' => false,
                'view' => true,
                'view.specific' =>true,
                'edit' => false,
                'approve' => false,
                'delete' => false,
            ],
            'description' => 'generic permission regarding users'
        ]);
        $secretaryUser = Permission::create([
            'name' => 'users.secretary',
            'slug' => [
                'create' => true,
                'edit' => true,
                'approve' => true,
                'delete' => true,
            ],
            'inherit_id' => $genericUser->getKey(),
            'description' => 'secretary permission regarding users'
        ]);
$secretary->assignRole('users.secretary');
$generic->assignRole('users');

$genericYear=Permission::create([
            'name' => 'schoolyears',
            'slug' => [
                'create' => false,
                'view' => true,
                'view.specific' =>true,
                'edit' => false,
                'approve' => false,
                'delete' => false,
            ],
            'description' => 'generic permission regarding school years'
        ]);
        $secretaryYear = Permission::create([
            'name' => 'schoolyears.secretary',
            'slug' => [
                'create' => true,
                'edit' => true,
                'approve' => true,
                'delete' => true,
            ],
            'inherit_id' => $genericYear->getKey(),
            'description' => 'secretary permission regarding school years'
        ]);
$secretary->assignPermission('schoolyears.secretary');
$generic->assignPermission('schoolyears');

The problem is that when i call

$secretary.>getPermissions()
//I only get as result
array:1 [▼
  "schoolyears" => array:6 [▶]
]

I looked into the class HasPermissionInheritance and i think i found the bug in the method
getPermissionsInherited()
In fact you call $rights = array_replace_recursive($inherited, $merge); and since $inherited and $merge are permission-specific, rights gets overriden everytime and we only get the latest set of permissions.

To solve this i suggest declaring rights as a local variabile into the foreach, and in the end of every iteration merge it with a global array

Permission with empty slug

  1. Get a user
  2. Add new permission, e.g. update.user
  3. Remove permission update.user

Actual: permission "user" with empty slug
Expect: remove whole permission, as we have for role's permission

Validating Role using operator vs pipe inconsistency

Auth::user()->is('manager'); // TRUE
Auth::user()->is('admin|manager'); // TRUE
Auth::user()->is(['admin','manager'], 'or'); // FALSE

First 2 cases are correct - The user is assigned the manager role.
Shouldn't the 3rd case be returning TRUE as well?

Create Permissions

Hello,

When I want to create a new permission with the example in the wiki, I'm getting this error:
ErrorException in helpers.php line 686:
preg_replace(): Parameter mismatch, pattern is a string while replacement is an array.

Is this my mistake or an issue in the code?

Thanks!

Example:
$permission = new Permission();
$permUser = $permission->create([
'name' => 'user',
'slug' => [
'create' => true,
'view' => true,
'update' => true,
'delete' => true,
'view.phone' => true
],
'description' => 'manage user permissions'
]);

Multiple groups in routes

How to add multiple groups like I do in Sentry with filters?

Sentry:

'before' => 'inGroup:administrator,editor|hasAccess:users.show'

so this works?

...
'is' => 'administrator,editor',
'can' => 'create.user, delete.user'], 

thanks

is() fails on Laravel 5.1

At first I had to put ->all() onto the end of the getRoles() call to fix the in_array() issue, which worked. Decided to try updating to see if it was fixed, and it wasn't 100% fixed.

Dumping getRoles() returns this:

2015-06-13_15-02-24

I had to fix it by doing: $roles = array_values($this->getRoles())[0];. This works, however now all my is() calls are broken because of the above screenshotted issue.

This seems to fix the issue entirely, within hasRoles():

array_values((array)$this->roles->lists('slug'))[0]

I'd make a pull request but I don't know how, or even if this fix is ideal.

Wrong permission for user without role

Get a user without any role, for example

$testUser = User::find(4);

add permission to him

$testUser->addPermission('create.user');

$testUser->can('create.user') returns false

But if I assign him to any role, even which this roles doesnt relate to that permission, I get right answer.

Please check.

About get user permissions

In Wiki i found the following rules about user permissions

  1. getPermissions : Get permissions assigned to a user, all user permissions along with its role permissions.
  2. user permissions override role ones.

But I dont get them as result. Please refer this image

http://snag.gy/Eyc6Y.jpg

Please check.

User Model Primary Key

Hi,

Having trouble with user model havent a different primary key.

// User.php
protected $primaryKey = 'employee_id';
User::find(9969);

select 
    * 
from `users` 
where `users`.`employee_id` = '9969' 
limit 1
dd( $this->auth->user()->getRoles() ); // returns empty because of the query

SELECT 
    `roles`.*, 
    `role_user`.`user_id` AS `pivot_user_id`, 
    `role_user`.`role_id` AS `pivot_role_id`, 
    `role_user`.`created_at` AS `pivot_created_at`, 
    `role_user`.`updated_at` AS `pivot_updated_at` 
FROM `roles` 
INNER JOIN `role_user` 
    ON `roles`.`id` = `role_user`.`role_id` 
WHERE `role_user`.`user_id` = '9969'

// should be below based on the ID of the employee_id
WHERE `role_user`.`user_id` = '1' 

How to get around this?

Thanks

[Suggestion]Soft deletes on pivot tables

First of all thanks for this awesome repo.
I'd like to use this system to create a webapp dedicated to the management of a school.
The key is that many users will have temporary roles, and i should be able to keep track of them.

To do so, the most logic way is to introduce soft deletes on the pivot tables users_roles and user_permissions, so that, by using created_at and deleted_at you can detect how much an user has been in charge of a given role.

It'd be awesome if you could implement that since not all roles are persistent.

ErrorException in HasPermissionInheritance.php line 51: array_replace_recursive(): Argument #3 is not an array

As well as the error highlighted in issue #56 by @camiant, upgrading to L5.1 also gave the following error:

ErrorException in HasPermissionInheritance.php line 51: array_replace_recursive(): Argument #3 is not an array

This is also fixed using ->toArray() on line 48:

            $merge = $permissions->where('name', $row->name)->lists('slug', 'name')->toArray();

            // replace and merge permissions
            $rights = array_replace_recursive($rights, $inherited, $merge);

Question

I'm not sure if I missed this but what does "Prefix" do in protecting routes?

Basically I'm trying to figure out why I'm getting 404 with it and getting the page/authorisation error once that is removed.

Thanks

assigning Permission to user issue

Hello,

I found an issue, that if you assign a permission to a user that already have that permission, it will retrun an exception said:
UnexpectedValueException in compiled.php line 14223: The Response content must be a string or object implementing __toString(), "boolean" given.

I think it's because of the "return false;" that you add in the last of the function assignPermission in HasPermission trait.

[Possible bug] Problem with multiple roles

Problem

I have just noticed something that doesn't look quite right to me, i have the following situation:
An user has two roles: student and secretary both have a different kind of permission regarding users obtained via permission inheritance:

$genericUser=Permission::create([
            'name' => 'users',
            'slug' => [
                'create' => false,
                'view' => true,
                'update' => false,
                'approve' => false,
                'delete' => false,
            ],
            'description' => 'generic permission regarding users'
        ]);
        $secretaryUser = Permission::create([
            'name' => 'users.secretary',
            'slug' => [
                'create' => true,
                'edit' => true,
                'approve' => true,
                'delete' => true,
            ],
            'inherit_id' => $genericUser->getKey(),
            'description' => 'secretary permission regarding users'
        ]);

Since the user has both roles, it has both the permission users and users.secretary.
The problem is that when i call can('edit.users') it returns false, if i call $user->getPermissions() i get the permissions of the last role assigned to the user (if i assign the generic first, i get the permissions of the secretary and vice versa).

Where the issue is

I think that depends on the fact that the method 'can' in 'HasPermission' trait calls the method 'getPermissions' which uses an array_replace_recursive, which replaces the permission set with the latest extracted from the database and not the higher in clearance

Proposal

When the user has more roles, each one with a different permission regarding the same thing, they should be merged granting the highest level of clearence, for example

User has role1 and role2
role1 has permission1:
'name' => 'generic'
 'slug' => [
                'create' => true,
                'edit' => false,
            ],
role2 has permission2:
'name' => 'generic'
 'slug' => [
                'create' => false,
                'edit' => true,
            ],

Calling getPermissions() on him should return

"users"=>array:2[
"create"=>"true"
"edit"=>"true"
]

Workaround

array_replace_recursive overwrites everything previously existing, even if this means loosing some clearence, to avoid that we need to check for every key that it's value is higher than the one we currently have, i can't find any fancy function in PHP to do this:

foreach($this->roles as $role){
  foreach($role->getPermissions() as $slug=>$array){
    if(array_key_exists($slug,$permissions){
      foreach($array as $clearence=>$value){
       !$value?:$permissions[$slug][$clearance]=true;
     }
   }else{
      $permissions = array_merge($permissions,array($slug => $array));
   }
 }
}

It's quite an ugly piece of code and i'm sorry for that, maybe you can come up with something better.
Sorry for my horrible english

Suggestion with getPermissions()

Imagine the following in the admin area. I want to edit a role's permissions, and when I use getPermission() helper function, I get all the permissions listed in arrays (rendered to list items here):

Administrator
create - 1
view - 1
update - 1
view.phone - 1
delete - 1
create - 1
update - 1
status - 1
delete - 1
edit - 1

as you see, because the function doesn't tell me what is the permission name, only the slugs are visible, how to decide to change for example the article's create permission to 0, and not the user's permission ?
What if the getPermissions() can give back a bit complex array, starting with the permission name?
If you say no, then what is the purpose adding the name for a permission?

So, in theory:

['users'] => [
    'create' => 1,
    'edit' => 1,
    '...' => ...
],
['articles'] => [
    'create => 0,
    'edit' => 1,
    '...' => ...
]

Can't understand how to use protect_methods

Hello, i have a really stupid question, but i can't understand how this works
I have seen you can protect methods based on permission in this way:
['protect_alias' => 'user',
'protect_methods' => [
'create' => ['someMethod', 'anotherMethod'],
'read' => ['readMethod', 'showMethod'],
'view' => ['readMethod', 'showMethod'], // its same as read.
'update' => ['editMethod'],
'delete' => ['destroyMethod']
]];
But i cannot understand where i should put this array, it would make sense to put it into the controller i want to protect but it should be assigned to a variable. Assigning it to a single route doesn't make sense to me, is it specific for a route::resource?
Thanks a lot

Question: Entrust

Greetings,

Just wonder. Reading the specs for Entrust and for me as a beginner it actually looks quite similar with laravel-acl. I also saw your comments on "If package is still alive" issue for Entrust. so it seems you just wanted to create something for yourself instead of waiting for compatibility with L5 👍

I mean I just try to find what is different and what are the killer features for laravel-acl as I would really like to use this one. Probably you can just share some thoughts you had while creating yours?

Cheers,
Roman.

Example of using this package with Laravel buil-in Auth system.

I am beginner of Laravel 5 even in Laravel too. So can you please give an example tutorial to working with laravel built-in Auth and registration system. i have modified the registration system of laravel and i install and cofigure your ACL package. but do not understand how i can add a role and permission.

NTFS / Permission inheritance

Greetings and thanks for your work on this package.

I just spent the last couple hours trying to figure out why the permissions inheritance was not working as per your example in the wiki. Alas, it was the 'ntfs' setting in the config file.

I suggested an edit on the Wiki page to inform the reader that the example will not work as expected if the default value of true is left unchanged.

Do you believe it is a more common desire to have the default behavior of "more permissive wins"? I would think not, but I have not implemented many ACL systems, so perhaps this is my ignorance.

Question: Protect Methods

Hi @kodeine,

Is there a way to globally change the Protect Methods, or do we have to feed a modified array in via each route?

Your Protect Methods are currently set up as

[
   'create' => ['store'],    // protects store() method on create.user (create.alias)
   'view'   => ['index', 'create', 'show', 'edit'],     // protects index(), create(), show(), edit() methods on view.user permission.
   'update' => ['update'],
   'delete' => ['destroy']
]

However, these mean that users who are denied the permission to store and update can still access the Create New Resource and Update Resource pages, as their permissions for create and edit routes are bundled under view. I'd like to use the following:

[
   'create' => ['create', 'store'],    // can create a new resource
   'view'   => ['index'],              // can see the resource
   'update' => ['edit', 'update'],     // can edit an existing resource
   'delete' => ['show', 'destroy']     // can delete a resource
]

Your Middleware class HasPermission has protected $crud; is there any chance this could be overridden via a resources array in config?

Help: Solution for segmented group of roles

Hello! I'm developing one ERP and I'm looking a solution for:

  • Users can control more than one companies.
  • Users have different permissions for the company branches.

Example: John Doe is employee from two companies A and B on A he have permission to delete users on B not.

So he need to have two different roles and permission on the same user.

What's the best way to solve this?

Thanks!

Advice for creating role class

Hi

excuse for my ignorance, but how shall I create role ? do i have to create app/role.php like this..

<?php namespace App;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

use Kodeine\Acl\Traits\HasRole;

class Role extends Model {

$role = new Role();
$roleAdmin = $role->create([
    'name' => 'Administrator',
    'slug' => 'administrator',
    'description'=>'manage administration privileges'
]);

$role = new Role();
$roleModerator = $role->create([
    'name' => 'Moderator',
    'slug' => 'moderator',
    'description'=>'manage moderator privileges'
]);
}

How do I check that roles and permissions are created ?

and simliarly must I create app/permission.php ?

I already have one user and which can login with default auth...
How should I pass role and permission as admin to this existing user?

advice pls :)
Thank you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.