mark-villudo/laravel-user-management

Laravel 5.1 及以上版本的权限处理

1 2018-11-05 08:41 UTC

This package is auto-updated.

Last update: 2024-09-29 05:09:17 UTC


README

Latest Version on Packagist Build Status Quality Score StyleCI Total Downloads

此包允许在数据库中保存权限和角色。它建立在 Laravel 的授权功能 之上,该功能是在版本 5.1.11 中 引入的

安装后,您可以执行如下操作

// Assign role to specific user
$user->assignRole('writer');

您可以使用特定的权限和模块名称测试用户是否有权限。

$user->canAccess('View','Users');

许可

您可以使用此包(它采用 MIT 许可),但如果它进入您的生产环境,我们非常感谢您给我们发送消息。

安装

您可以通过 Composer 安装此包

composer require mark-villudo/laravel-user-management

现在将服务提供者添加到 config/app.php 文件中

'providers' => [
    // ...
    MarkVilludo\Permission\PermissionServiceProvider::class,
];

您可以使用以下命令发布迁移

php artisan vendor:publish --provider="MarkVilludo\Permission\PermissionServiceProvider" --tag="migrations"

此包假设您的用户表名为 "users"。如果不是这种情况,您应该手动编辑已发布的迁移以使用自定义表名。

迁移发布后,您可以通过运行迁移来创建角色和权限表

$ php artisan migrate

您可以将初始权限种子发布,然后根据您的需求更新其内容。

php artisan vendor:publish --provider="MarkVilludo\Permission\PermissionServiceProvider" --tag="seeder"

您可以使用以下命令发布配置文件

php artisan vendor:publish --provider="MarkVilludo\Permission\PermissionServiceProvider" --tag="config"

这是已发布 config/laravel-permission.php 配置文件的内容

return [

    'models' => [

        /*
         * When using the "HasRoles" trait from this package, we need to know which
         * Eloquent model should be used to retrieve your permissions. Of course, it
         * is often just the "Permission" model but you may use whatever you like.
         *
         * The model you want to use as a Permission model needs to implement the
         * `MarkVilludo\Permission\Contracts\Permission` contract.
         */

        'permission' => MarkVilludo\Permission\Models\Permission::class,

        /*
         * When using the "HasRoles" trait from this package, we need to know which
         * Eloquent model should be used to retrieve your roles. Of course, it
         * is often just the "Role" model but you may use whatever you like.
         *
         * The model you want to use as a Role model needs to implement the
         * `MarkVilludo\Permission\Contracts\Role` contract.
         */

        'role' => MarkVilludo\Permission\Models\Role::class,

    ],

    'table_names' => [

        /*
         * The table that your application uses for users. This table's model will
         * be using the "HasRoles" and "HasPermissions" traits.
         */

        'users' => 'users',

        /*
         * When using the "HasRoles" trait from this package, we need to know which
         * table should be used to retrieve your roles. We have chosen a basic
         * default value but you may easily change it to any table you like.
         */

        'roles' => 'roles',

        /*
         * When using the "HasRoles" trait from this package, we need to know which
         * table should be used to retrieve your permissions. We have chosen a basic
         * default value but you may easily change it to any table you like.
         */

        'permissions' => 'permissions',

        /*
         * When using the "HasRoles" trait from this package, we need to know which
         * table should be used to retrieve your users permissions. We have chosen a
         * basic default value but you may easily change it to any table you like.
         */

        'user_has_permissions' => 'user_has_permissions',

        /*
         * When using the "HasRoles" trait from this package, we need to know which
         * table should be used to retrieve your users roles. We have chosen a
         * basic default value but you may easily change it to any table you like.
         */

        'user_has_roles' => 'user_has_roles',

        /*
         * When using the "HasRoles" trait from this package, we need to know which
         * table should be used to retrieve your roles permissions. We have chosen a
         * basic default value but you may easily change it to any table you like.
         */

        'role_has_permissions' => 'role_has_permissions',
    ],

    'foreign_keys' => [
        
        /*
         * The name of the foreign key to the users table.
         */
        'users' => 'user_id',
    ],

    /*
     *
     * By default we'll make an entry in the application log when the permissions
     * could not be loaded. Normally this only occurs while installing the packages.
     *
     * If for some reason you want to disable that logging, set this value to false.
     */

    'log_registration_exception' => true,
];

您可以使用以下命令发布视图

php artisan vendor:publish --provider="MarkVilludo\Permission\PermissionServiceProvider" --tag="views"

您可以使用以下命令发布公共资产

php artisan vendor:publish --provider="MarkVilludo\Permission\PermissionServiceProvider" --tag="assets"

用法

首先将 MarkVilludo\Permission\Traits\HasRoles 特性添加到您的用户模型中,然后粘贴以下代码。

<?php

namespace App;


use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use MarkVilludo\Permission\Traits\HasRoles;
use MarkVilludo\Permission\Models\Permission;
use MarkVilludo\Permission\Models\RoleHasPermission;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;
    use HasRoles;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'first_name', 'last_name', 'email', 'password', 'is_expire_access', 'expiration_date',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];


    public function scopeFilterByName($query, $key)
    {
        return $query->where('first_name', 'like', '%' . $key . '%')
            ->orWhere('last_name', 'like', '%' . $key . '%')
            ->orWhere('email', 'like', '%' . $key . '%');
    }

    //get by roles
    public function scopeFilterByRole($query, $role)
    {
        if ($role) {
            return  $query->withAndWhereHas('roles', function ($query) use ($role) {
                    $query->where('id', $role);
            });
        }
    }

    //for withandwherehas
    public function scopeWithAndWhereHas($query, $relation, $constraint)
    {
        return $query->whereHas($relation, $constraint)->with([$relation => $constraint]);
    }
    
    public static function checkAccess($permissionName, $moduleName)
    {
        // return $permissionName.'-'.$moduleName;
        $roleIds = auth()->user()->roles->pluck('id');
        //get permission id base on permission and module name
        $permissionData = Permission::where('name', $permissionName)
                                        ->where('module', $moduleName)
                                        ->first();
        if ($permissionData) {
            $checkIfHasPermission = RoleHasPermission::whereIn('role_id', $roleIds)
                                        ->where('permission_id', $permissionData->id)
                                        ->first();

            if ($checkIfHasPermission) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
}

设置 env

我们在添加新用户时发送密码。因此,我们需要定义每个邮件驱动程序、用户名、密码、加密和邮件发送地址。

MAIL_DRIVER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USERNAME=apikey
MAIL_PASSWORD=SG.QSaTRD4xQkSULUbbZbF1yg.oDr7zwINfMbaLtvNHFToUYj35ZXxqq6l-SXUN1TpBFs123
MAIL_ENCRYPTION=tls
MAIL_FROM=mark.villudo@synergy88digital.com

设置用户资源:php artisan make: resource UserResource

定义从用户表返回的每个数据。

  return 
        [
            'id' => $this->id,
            'first_name' => $this->first_name,
            'last_name' => $this->last_name,
            'email' => $this->email,
	    'type' => $this->type, //nullable for special purposes.
            'expiration_date' => date('M d, Y', strtotime($this->expiration_date)),
            'email_verified_at' => $this->email_verified_at,
            'is_expire_access' => $this->is_expire_access,
            'created_at' => $this->created_at->format('M d, Y') .' / '.$this->created_at->format('h:i a'),
            'roles' => $this->roles->pluck('name')
        ];

设置角色资源:php artisan make: resource RoleResource

定义从角色表返回的每个数据及其权限。

  return 
        [
            'id' => $this->id,
            'name' => $this->name,
            'permissions' => $this->permissions
        ];

访问用户管理页面

要通过在前面放置另一个 \ 来访问包控制器,您告诉 Laravel 在根命名空间中开始搜索。


//include this part in your routes/web.php
Route::group(['middleware' => 'auth'], function() {

	Route::resource('users', '\MarkVilludo\Permission\Controllers\UserController');
	Route::resource('roles', '\MarkVilludo\Permission\Controllers\RoleController');
	Route::resource('permissions', '\MarkVilludo\Permission\Controllers\PermissionController');
});

此包允许将用户与角色关联。权限可以与角色关联。一个 Role 和一个 Permission 是常规的 Eloquent 模型。角色可以有一个名称,可以像这样创建

use MarkVilludo\Permission\Models\Role;

$role = Role::create(['name' => 'writer']);

HasRoles 为您的模型添加 Eloquent 关系,可以直接访问或用作基础查询

$permissions = $user->permissions;
$roles = $user->roles()->pluck('name'); // Returns a collection

HasRoles 还为您的模型添加了一个作用域,以将查询范围到某些角色

$users = User::role('writer')->get(); // Only returns users with the role 'writer'

此作用域可以接受一个字符串、一个 MarkVilludo\Permission\Models\Role 对象或一个 \Illuminate\Support\Collection 对象。

使用权限检查是否可以在 Users 模块中的特定权限 添加 访问。

$user->canAccess('Add','Users');

使用角色和权限

可以将角色分配给用户

$user->assignRole('writer');

// You can also assign multiple roles at once
$user->assignRole('writer', 'admin');
$user->assignRole(['writer', 'admin']);

可以从用户中删除角色

$user->removeRole('writer');

角色也可以同步

// All current roles will be removed from the user and replace by the array given
$user->syncRoles(['writer', 'admin']);

您还可以确定用户是否具有特定角色

$user->hasRole('writer');

您还可以确定用户是否具有给定列表中的任何角色

$user->hasAnyRole(Role::all());

您还可以确定用户是否具有给定列表中的所有角色

$user->hasAllRoles(Role::all());

assignRolehasRolehasAnyRolehasAllRolesremoveRole 函数可以接受一个字符串、一个 MarkVilludo\Permission\Models\Role 对象或一个 \Illuminate\Support\Collection 对象。

可以将权限赋予一个角色

$role->givePermissionTo('edit articles');

可以判断一个角色是否拥有特定的权限

$role->hasPermissionTo('edit articles');

可以撤销一个角色的权限

$role->revokePermissionTo('edit articles');

可以列出所有这些权限

// Direct permissions
$user->getDirectPermissions() // Or $user->permissions;

// Permissions inherited from user's roles
$user->getPermissionsViaRoles();

// All permissions which apply on the user
$user->getAllPermissions();

所有这些响应都是 Spatie\Permission\Models\Permission 对象的集合。

如果我们遵循前面的例子,第一个响应将是一个包含 '删除文章' 权限的集合,第二个将是一个包含 '编辑文章' 权限的集合,第三个将包含两者。

使用 Blade 指令

此包还添加了 Blade 指令,用于验证当前登录用户是否拥有给定的角色列表中的所有或任何角色。

@role('writer')
    I'm a writer!
@else
    I'm not a writer...
@endrole
@hasrole('writer')
    I'm a writer!
@else
    I'm not a writer...
@endhasrole
@hasanyrole(Role::all())
    I have one or more of these roles!
@else
    I have none of these roles...
@endhasanyrole
@hasallroles(Role::all())
    I have all of these roles!
@else
    I don't have all of these roles...
@endhasallroles
@if(auth()->user()->checkAccess('View', 'Users'))
    <button class="btn btn-success btn-custom waves-effect w-md waves-light m-b-5 pull-left">View User</button>
@endif

您可以使用 Laravel 的原生 @can 指令来检查用户是否具有特定的权限。

使用中间件

此包不包含用于检查权限的中间件,但添加此功能非常简单

$ php artisan make:middleware RoleMiddleware

这将为您创建一个 app/Http/Middleware/RoleMiddleware.php 文件,您可以在此文件中处理您的角色和权限检查

use Auth;

// ...

public function handle($request, Closure $next, $role, $permission)
{
    if (Auth::guest()) {
        return redirect($urlOfYourLoginPage);
    }

    if (! $request->user()->hasRole($role)) {
       abort(403);
    }
    
    return $next($request);
}

别忘了将路由中间件添加到 app/Http/Kernel.php 文件中

protected $routeMiddleware = [
    // ...
    'role' => \App\Http\Middleware\RoleMiddleware::class,
    // ...
];

现在您可以使用刚刚设置的中间件来保护您的路由

Route::group(['middleware' => ['role:admin,access_backend']], function () {
    //
});

扩展

如果您需要扩展或替换现有的 RolePermission 模型,您只需记住以下几点

  • 您的 Role 模型需要实现 MarkVilludo\Permission\Contracts\Role 接口
  • 您的 Permission 模型需要实现 MarkVilludo\Permission\Contracts\Permission 接口
  • 您必须使用以下命令发布配置
    $ php artisan vendor:publish --provider="MarkVilludo\Permission\PermissionServiceProvider" --tag="config"
    并且更新 models.rolemodels.permission 的值

变更日志

有关最近更改的更多信息,请参阅 CHANGELOG

测试

composer test

贡献

有关详细信息,请参阅 CONTRIBUTING

安全

如果您发现任何与安全相关的问题,请发送电子邮件至 [mark.villudo@synergy88digital.com]

鸣谢

此包在很大程度上基于 Jeffrey Way 的优秀 Laracasts 课程 角色和权限。他的原始代码可以在 GitHub 上的 此仓库 中找到。

替代方案

许可

MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件