# # Usage

First of all, use the `UsersTrait.php` on your `User` model:

    use Illuminate\Foundation\Auth\User as Authenticatable;
    use Junges\ACL\Traits\UsersTrait;

    class User extends Authenticatable
    {
        use UsersTrait;

        //
    }

You can add permissions to a user using the function below, using as parameter permissions slugs, permissions ids or instance of permissions model. Beside that, you can also combine this 3 ways, using a permission id, one instance of permission model and a permission slug too.

    //With permission slugs:
    $user->assignPermissions('permission-slug-1', 'permission-slug-2');

    //Using arrays:
    $user->assignPermissions(['permission-slug-1', 'permission-slug-2']);

    //With permission ids:
    $user->assignPermissions(1, 2, 3);

    //Using arrays:
    $user->assignPermissions([1, 2, 3]);

    //With instances of permission model:
    $user->assignPermissions(Permission::find(1), Permission::find(2));

    //Using arrays:
    $user->assignPermissions([Permission::find(1), Permission::find(2)]);

    //With the three ways above combined:
    $user->assignPermissions(1, 'permission-slug', Permission::find(1));

    //Using arrays:
    $user->assignPermissions([1, 'permission-slug', Permission::find(1)]);

Like as add permissions to user, you can add permissions to groups. To do this, you have the same method, and they can be used by the same way:

    //With permission slugs:
    $group->assignPermissions('permission-slug-1', 'permission-slug-2');

    //Using arrays:
    $group->assignPermissions(['permission-slug-1', 'permission-slug-2']);

    //With permission ids:
    $group->assignPermissions(1, 2, 3);

    //Using arrays:
    $group->assignPermissions([1, 2, 3]);

    //With instances of permission model:
    $group->assignPermissions(Permission::find(1), Permission::find(2));

    //Using arrays:
    $group->assignPermissions([Permission::find(1), Permission::find(2)]);

    //With the three ways above combined:
    $group->assignPermissions(1, 'permission-slug', Permission::find(1));

    //Using arrays:
    $group->assignPermissions([1, 'permission-slug', Permission::find(1)]);

After add permissions to a group, you may want/need to add a user to a group. This can be done in two different ways:

### # First way:

You can add a group to a user, and use 4 different types of parameters:

    //Assign a group to a user, using group slugs:
    $user->assignGroup('group-slug-1', 'group-slug-2');

    //Using arrays:
    $user->assignGroup(['group-slug-1', 'group-slug-2']);

    //Assign a group to a user, using group ids:
    $user->assignGroup(1, 2, 3);

    //Using arrays:
    $user->assignGroup([1, 2, 3]);

    //Assign a group to a user, with instance of group models:
    $user->assignGroup(Group::find(1), Group::find(2));

    //Using arrays:
    $user->assignGroup([Group::find(1), Group::find(2)]);

    //Assign group to a user, combining the three methods above:
    $user->assignGroup(Group::find(1), 'group-slug-2', 3);

    //Usign arrays:
    $user->assignGroup([Group::find(1), 'group-slug-2', 3]);

### # Second way:

You can add a user to a group, and use 4 different types of parameters:

    //Assign a user to a group, with user names:
    $group->assignUser('User one', 'User two');

    //Using arrays:
    $group->assignUser(['User one', 'User two']);

    //Assign a user to a group, user ids:
    $group->assignUser(1, 2, 3);

    //Using arrays:
    $group->assignUser([1, 2, 3]);

    //Assign a user to a group, with instance of User models:
    $group->assignUser(User::find(1), User::find(2));

    //Using arrays:
    $group->assignUser([User::find(1), User::find(2)]);

    //Assign a user to a group combining the three methods above:
    $group->assignUser(User::find(1), 'User name', 3);

    //Using arrays:
    $group->assignUser([User::find(1), 'User name', 3]);

## # Customize the `admin` permission

This package allows you to customize the name of your `admin` permission. All you have to do is publish the configuation file and change the `admin_permission` to the slug you want to use. If this key is no present in the `config/acl.php` file, the `admin` slug will be used:

    'admin_permission' => 'admin',

## # Revoke permissions

### # 1 - Revoke permissions from user

You can revoke a user permission using the method below:

    $user->revokePermissions('permission-slug', 2, Permission::find(3));

    //Or with arrays:
    $user->revokePermissions(['permission-slug', 2, Permission::find(3)]);

Like the methods to add or remove a group from a user, you can use as function parameter a the permission ids, permission slugs, instance of permission model, or, combine these three ways.

### # 2 - Revoke permissions from groups:

You can revoke a group permission using the method below:

    $group->revokePermissions('permission-slug', 2, Permission::find(3));

    //Or with arrays:
    $group->revokePermissions(['permission-slug', 2, Permission::find(3)]);

Like the methods to add or remove a group from a user, you can use as function parameter the permission ids, permission slugs, instance of permission model, or, combine these three ways.

### # 3 - Revoke a group from user:

You can remove a group from the user by using one of these methods:

    $user->revokeGroup('permission-slug', 2, Permission::find(3));
    $group->removeUser('User name', 2, User::find(3));

    //Or with arrays:
    $user->revokeGroup(['permission-slug', 2, Permission::find(3)]);
    $group->removeUser(['User name', 2, User::find(3)]);

Like the methods to add or remove a group from a user, you can use as function parameter a group/user ids, group/user slugs, instance of group/user model , or, combine these three ways.

## # Checking for permissions

### # Checking if user has permission:

You can check if a user has a permission using:

    //With permission slug:
    $user->hasPermission('permission-slug');

    //With permission id:
    $user->hasPermission(1);

    //With instance of permission model:
    $user->hasPermission(Permission::find(1));

If the user has the permissions passed, the function return `true` . Otherwise, returns `false` .

You can also check if the user has any permission:

    //With permission slugs:
    $user->hasAnyPermission('permission-slug-1', 'permission-slug-2');

    //With permission ids:
    $user->hasAnyPermission(1, 2, 3);

    //With instance of permission model:
    $user->hasAnyPermission(Permission::find(1), Permission::find(2), Permission::find(3));

    //With the three methods above combined:
    $user->hasAnyPermission(1, 'permission-slug' Permission::find(3));

If the user has any of the permissions passed, the function return `true` . Otherwise, returns `false` .

### # Checking if user has group:

To check if some user has a specific group, you can use the `hasGroup` method. This method accept a `Group` model, the group id or the group slug:

    // With group model:
    $user->hasGroup(Group::find(1));

    // With group id:
    $user->hasGroup(1);

    // With group slug:
    $user->hasGroup('some-group-slug');

### # Checking if user has permission trough group:

You can check if one user is associated with a group which has the required permission:

    //With permission id:
    $user->hasPermissionThroughGroup(1);

    //With instance of permission model:
    $user->hasPermissionThroughGroup(Permission::find(1));

    //With permission slug:
    $user->hasPermissionThroughGroup('admin');

### # Checking if user has permission direct assigned (not trough groups):

Sometimes you need to check if one of your users has a permission assigned directly, and not trough group. For example: the `$user` has the permission `$permission` assigned via group, but the `$permission2` is assigned directly. The `hasPermission` method returns `true` for both permissions. If you want to check for direct permissions, just use the `hasDirectPermission` method:

    // With permission model:
    $user->hasDirectPermission(Permission::find(1));

    // With permission slugs:
    $user->hasDirectPermission('some-permission-slug');

    // With permission ids:
    $user->hasDirectPermission(1);

### # Checking if group has permissions:

You can check if a group has a required permission with:

    //With permission id:
    $group->hasPermission(1);

    //With permission slug:
    $group->hasPermission('permission-slug');

    //With instance of permission model:
    $group->hasPermission(Permission::find(1));

### # Checking if a group has any permission:

In the same way as for users, you can check if a group has any of the required permissions:

    //With permission slugs:
    $group->hasAnyPermission('permission-slug-1', 'permission-slug-2');

    //With permission ids:
    $group->hasAnyPermission(1, 2, 3);

    //With instance of permission model:
    $group->hasAnyPermission(Permission::find(1), Permission::find(2), Permission::find(3));

    //With the three methods above combined:
    $group->hasAnyPermission(1, 'permission-slug' Permission::find(3));

## # Checking for permissions using wildcards

Sometimes, you want to know if the logged in user has any permission related to users, like `*.users` . It can easily be done with the `ACLWildcardsTrait` .

Add the `ACLWildcardsTrait` to your `user` model:

    use Illuminate\Foundation\Auth\User as Authenticatable;
    use Junges\ACL\Traits\UsersTrait;
    use Junges\ACL\Traits\ACLWildcardsTrait;

    class User extends Authenticatable
    {
        use UsersTrait;
        use ACLWildcardsTrait;

        //
    }

Then, you can check for wildcard permissions using the `hasPermissionWithWildcard` method:

    $user->hasPermissionWithWildcards('users.*');

You can also use this trait to check for group permissions using wildcards. The `ACLWildcardsTrait` is used by the Group model by default:

    $group->hasPermissionWithWildcards('users.*');

## # Syncing user permissions

The user permissions can synced with this method:

    //With permission id:
    $user->syncPermissions(1, 2, 4);

    //Using array:
    $user->syncPermissions([1, 2, 4]);

    //With permission slugs:
    $user->syncPermissions('permission-slug-1', 'permission-slug-2');

    //Using arrays:
    $user->syncPermissions(['permission-slug-1', 'permission-slug-2']);

    //With instance of permission model:
    $user->syncPermissions(Permission::find(1), Permission::find(2));

    //Using arrays:
    $user->syncPermissions([Permission::find(1), Permission::find(2)]);

    //Combining the three ways:
    $user->syncPermissions(1, 'permission-slug', Permission::find(3));

    //Using arrays:
    $user->syncPermissions([1, 'permission-slug', Permission::find(3)]);

## # Syncing user groups

The user groups can synced using this method:

    //With group ids:
    $user->syncGroups(1, 2, 3, 4);

    //Using array:
    $user->syncGroups([1, 2, 3, 4]);

    //Using group slugs:
    $user->syncGroups('group-1', 'group-2');

    //Using arrays of group slugs:
    $user->syncGroups(['group-1', 'group-2']);

    //Using group models:
    $user->syncGroups(Group::find(1), Group::find(2));

    //Using array of group models:
    $user->syncGroups([Group::find(1), Group::find(2)]);

    //Combining the three ways:
    $user->syncGroups(1, 'group-2', Group::find(3));

    //Or with arrays:
    $user->syncGroups([1, 'group-2', Group::find(3)]);

## # Syncing group permissions

The groups permissions can synced with this method:

    //With permission id:
    $group->syncPermissions(1, 2, 4);

    //Usign arrays:
    $group->syncPermissions([1, 2, 4]);

    //With permission slugs:
    $group->syncPermissions('permission-slug-1', 'permission-slug-2');

    //Using arrays:
    $group->syncPermissions(['permission-slug-1', 'permission-slug-2']);

    //With instance of permission model:
    $group->syncPermissions(Permission::find(1), Permission::find(2));

    //Using arrays:
    $group->syncPermissions([Permission::find(1), Permission::find(2)]);

    //Combining the three ways:
    $group->syncPermissions(1, 'permission-slug', Permission::find(3));

    //Using arrays:
    $group->syncPermissions([1, 'permission-slug', Permission::find(3)]);

## # Some "shortcuts"

The version `1.7.0` of this package provides some new methods to handle with groups and permissions. From now, you can use the `assignAllPermissions` method to assign all your system permissions to your users, instead of doing this manually. Similarly, the `revokeAllPermissions` , `assignAllGroups` and `revokeAllGroups` have similar functions. Here is some example:

    //If you want to remove all user permissions:
    $user->revokeAllPermissions();

    //If you want to grant all permissions for some user:
    $user->assignAllPermissions();

    //Remove all user groups:
    $user->revokeAllGroups();

    //Add all groups to the user:
    $user->assignAllGroups();

The `GroupsTrait` has some new methods as well:

    //To remove all group permissions:
    $group->revokeAllPermissions();

    //To add all permissions for some group:
    $group->assignAllPermissions();

    //Attach all users to a group:
    $group->attachAllUsers();

    //Detach all users from a group:
    $group->detachAllUsers();

## # Local scopes

### # The `group` scope

The `UserTrait.php` trait also adds a `group` scope to the query to certain groups or permissions:

    //Return only users with the group 'admin':
    $users = User::group('admin')->get();

The `group` scope can accept a `\Junges\ACL\Http\Models\Group::class` object or an `\Illuminate\Support\Collection` object.

### # The `permission` scope

The same trait also adds a scope to only get users who have a certain permission.

    //Return only users with the permission 'edit-post' (directly or via groups)
    $users = User::permission('edit-post')->get();

The `permission` scope can accept a string (permission slug), a `\Junges\ACL\Http\Models\Permission::class` or an `\Illuminate\Support\Collection` object.

### # The `user` scope (on `\Junges\ACL\Traits\PermissionsTrait` )

The `PermissionsTrait` adds a `user` scope to the query to certain users. With this scope, only permissions granted to the given user will be returned.

    //Return only permissions granted to the 'Test' user:
    $permissions = Permission::user('Test')->get();

### # The `user` scope (on `\Junges\ACL\Traits\GroupsTrait` )

The `GroupsTrait` adds a `user` scope to the query to certain users. With this scope, only groups granted to the given user will be returned.

    //Returns only groups granted to the 'Test' named user:
    $groups = Group::user('Test')->get();

The `user` scope can accept a string (user name, username, user email), a `App\User::class` instance or the user `id` .

## # Retrieving user permissions

If you want to get all user permissions (directly assigned), you can use the `permissions` method:

    $permissions = $user->permissions()->get();

To also get permission assigned to the user via a group, you can use the `getAllPermissions` method:

    $user->getAllPermissions();

## # Retrieving user groups

To get all user groups you just need to use the `groups` method:

    $groups = $user->groups()->get();

The `user` scope can accept a string (user name, username, user email), a `App\User::class` instance or the user `id` .

## # Blade and permissions

To check for permissions with this package, you can still using laravel built in `@can` blade directive and `can()` method:

    @can('edit-post')
        I can edit the post
    @endcan

    @if(auth()->user()->can('edit-post'))
        I can edit the post!
    @endcan

## # Using package custom blade directives

This package also adds Blade directives to verify whether the currently logged in user has a given list of groups/permissions.

The custom blade directives provided by this package are:

- @group
- @elsegroup
- @permission
- @elsepermission
- @allpermissions
- @allgroups
- @anypermission
- @anygroup

For groups:

    @group('admin')
        I have the admin group!
    @elsegroup('editor')
        I have the editor group, but not the admin!
    @endgroup

For permissions:

    @permission('admin')
        I have the admin permission!
    @elsepermission('writer')
        I have the writer permission, but not the admin!
    @endpermission

Check for all permissions:

    @allpermissions('permission-1', 'permission-2')
        I have permission 1 and permission 2!
    @endallpermissions

Check for any permission:

    @anypermission('permission-1', 'permission-2')
        I have at least one of these permissions!
    @endanypermission

Check for all groups:

    @allgroups('group-1', 'group-2')
        I have group 1 and group 2!
    @endallgroups

Check for any group:

    @anygroup('group-1', 'group-2')
        I have at least one of these groups!
    @endanygroup

NOTE: You can only use custom blade directives with group/permission id or slug.

# # Using a Middleware

If you want to use the middleware provided by this package ( `PermissionMiddleware` , `GroupMiddleware` , `HierarchicalPermissions` e `PermissionOrGroupMiddleware` ), you need to add them to the `app/Http/Kernel.php` file, inside the `routeMiddleware` array:

    protected $routeMiddleware = [
        'permissions' => \Junges\ACL\Middlewares\PermissionMiddleware::class,
        'groups' => \Junges\ACL\Middlewares\GroupMiddleware::class,
        'permissionOrGroup' => \Junges\ACL\Middlewares\PermissionOrGroupMiddleware::class,
        'hierarchical_permissions' => \Junges\ACL\Middlewares\HierarchicalPermissionsMiddleware::class
    ];

Then you can protect you routes using middleware rules:

    Route::get('/', function(){
        echo "Middlewares working!";
    })->middleware('permissions:admin');

    Route::get('/', function(){
        echo "Middlewares working!";
    })->middleware('permissionOrGroup:admin');

    Route::get('/', function(){
        echo "Middlewares working!";
    })->middleware('groups:admin');

    Route::get('/', function(){
        echo "Middlewares working!";
    })->middleware('hierarchical_permissions:user.auth.admin');

Alternatively, you can separate multiple groups or permissions with a `|` (pipe) character:

    Route::get('/', function(){
        echo "Middlewares working!";
    })->middleware('permissions:admin|manager');

    Route::get('/', function(){
        echo "Middlewares working!";
    })->middleware('permissionOrGroup:admin|manager');

    Route::get('/', function(){
        echo "Middlewares working!";
    })->middleware('groups:admin|manager');

    Route::get('/', function(){
        echo "Middlewares working!";
    })->middleware('hierarchical_permissions:user.auth.admin|user.manager.user.admin');

You can protect controller similarly, by setting desired middleware in the constructor:

    public function __construct()
    {
        $this->middleware(['groups:admin', 'permissions:edit']);
    }

    public function __construct()
    {
        $this->middleware('permissions:admin|manager');
    }

    public function __construct()
    {
        $this->middleware('hierarchical_permissions:user.auth.admin|user.manager.user.admin');
    }

The `groups` middleware will check if the current logged in user has any of the groups passed to the middleware.

The `permissions` middleware will check if the current logged in user has any of the required groups for a route.

The `permissionOrGroup` will check if the current logged in user has any of the required permissions or groups necessary to access a route.

The `hierarchical_permissions` middleware will check if the current logged in user has any of the "sub-permissions" in the passed string. The `user.manager.user.admin` matches with all the following:

    user
    user.manager
    user.manager.user
    user.manager.user.admin

If the user has any of the above permissions, the access is granted.

In positive case, both middleware guarantee access to the route.

# # Handling group and permission exceptions

If you want to override the default `403` response, you can catch the `Unauthorized` exception using the laravel exception handler:

        public function render($request, Exception $exception)
        {
            if ($exception instanceof \Junges\ACL\Exceptions\UnauthorizedException) {
                // Your code here
            }

            return parent::render($request, $exception);
        }

When trying to create an existing Permission, the `Junges\ACL\Exceptions\PermissionAlreadyExistsExeption` will be throw. You can catch the exception using default laravel handler:

        public function render($request, Exception $exception)
        {
            if ($exception instanceof \Junges\ACL\Exceptions\PermissionAlreadyExistsException) {
                // Your code here
            }

            return parent::render($request, $exception);
        }

The same is valid for the `Junges\ACL\Exceptions\PermissionAlreadyExistsException` :

        public function render($request, Exception $exception)
        {
            if ($exception instanceof \Junges\ACL\Exceptions\GroupAlreadyExistsException) {

            }

            return parent::render($request, $exception);
        }

The same is valid for `PermissionDoesNotExistException` , `GroupDoesNotExistException` and `UserDoesNotExistException.`

# # Using artisan commands

You can create a group or a permission from a console with artisan commands:

    php artisan group:create name slug description

    php artisan permission:create name slug description

You can also use artisan commands to display user and groups permissions:

The following command display all permissions stored on the database:

    php artisan permission:show

The above command with `--group` option display all permissions of the specified group. You can use the `group slug` or the `group id` as option value, just like this:

    php artisan permission:show --group 1

Or

    php artisan permission:show --group admin

Likewise, you can display user permissions, using de `user:permissions` artisan command, with the `user id` , the user's `username` , the user `email` or the user `Name` as argument:

With the username:

    php artisan user:permissions username

With the user id:

    php artisan user:permissions 1

With user Name:

    php artisan user:permissions "User Name"

and with the user's email:

    php artisan user:permissions "email@domain.com"

# # Extending and replacing models

If you need to EXTEND the existing `Group` or `Permission` models note that:

- Your `Group` model needs to extend the `\Junges\ACL\Http\Models\Group` model
- Your `Permission` model needs to extend the `\Junges\ACL\Http\Models\Permission` model

If you need to REPLACE the existing `Group` or `Permission` models you need to keep the following things in mind:

- Your `Group` model needs to use the `\Junges\ACL\Traits\GroupTrait` trait
- Your `Permission` model needs to implement the `\Junges\ACL\Traits\PermissionTrait` trait

In both cases, whether extending or replacing, you will need to specify your new models in the configuration.

To do this you must update the `models.group` and `models.permission` values in the configuration file.

# # Route model key

If you would like model binding to use a database column other than id when retrieving a given model class, you may override the getRouteKeyName method on the Eloquent model with yours. The default key used for route model binding in this package is the `slug` database column. You can modify it by changing the `route_model_binding_keys` configuration, in `config/acl.php` file:

    'route_model_binding_keys' => [
        'group_model' => 'slug',
        'permission_model' => 'slug'
    ],

# # Basic form templates

This package provides form to add a group or permission to the user, and permissions to groups. Just include the view on you form:

    <form action="" method="">
        @include('acl::_forms.groups.group')
    </form>

    <form action="" method="">
        @include('acl::_forms.users.add-group')
    </form>

    <form action="" method="">
        @include('acl::_forms.users.add-permission')
    </form>

# # Translations

This package also provides translations for some messages. To use them is easy:

- Change your `config/app.php` file locale for your corresponding locale, like `en` or `pt-br` .
- Publish the translation files with

    php artisan vendor:publish --provider="Junges\ACL\ACLServiceProvider" --tag="acl-translations"

# # Ignition Solutions

This package ships with a lot of useful Ignition Solutions
out of the box. To use it, you just need to change the `offer_solutions` flag, within the `config/acl.php` file to `true`.

After changing the `offer_solutions` flag to `true`, you need to install the `facade/ignition` package as a dev dependency:

    composer require facade/ignition --dev

> Remember to set the `APP_DEBUG` environment variable to `false`, when in production environment.