laravel 中如何设计多重权限?

问题描述 投票:0回答:1

比方说,我有很多模型:用户、团体、综合体、房屋、公寓。

我想为不同的用户分配不同的权限。

例如,group1 中的用户可以拥有以下权限(不言自明):“complex.show”、“complex.edit”

组 2 中的用户:“house.show”、“flat.show”、“flat.edit”

group3中的用户:“house.show”、“house.edit.1”、“house.edit.3”(这些用户可以查看所有房屋并可以编辑id为1&3的房屋)

迁移

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    public function up()
    {
        Schema::create('app_users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('email')->unique();
            $table->string('first_name');
            $table->string('last_name');
            $table->string('password');
            $table->rememberToken();
            $table->boolean('active')->default(0);
            $table->string('timezone')->default('Europe/Moscow');
            $table->timestamp('created_at')->useCurrent();
            $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
        });

        Schema::create('app_permissions', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->string('description')->default('');
            $table->timestamp('created_at')->useCurrent();
            $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
        });

        Schema::create('app_groups', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->string('description')->default('');
            $table->timestamp('created_at')->useCurrent();
            $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
        });

        Schema::create('app_group_users', function (Blueprint $table) {
            $table->integer('user_id')->unsigned();
            $table->foreign('user_id')->references('id')->on('app_users');
            $table->integer('group_id')->unsigned();
            $table->foreign('group_id')->references('id')->on('app_groups');
            $table->timestamp('created_at')->useCurrent();
            $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
        });

        Schema::create('app_group_permissions', function (Blueprint $table) {
            $table->integer('group_id')->unsigned();
            $table->foreign('group_id')->references('id')->on('app_groups');
            $table->integer('permission_id')->unsigned();
            $table->foreign('permission_id')->references('id')->on('app_permissions');
            $table->timestamp('created_at')->useCurrent();
            $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
        });
    }

    public function down()
    {
        Schema::dropIfExists('app_group_permissions');
        Schema::dropIfExists('app_group_users');
        Schema::dropIfExists('app_groups');
        Schema::dropIfExists('app_permissions');
        Schema::dropIfExists('app_users');
    }
}

用户模型

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    protected $table = 'app_users';

    protected $fillable = [
        'name', 'email', 'password', 'first_name', 'last_name'
    ];

    protected $visible = [
        'id', 'email', 'first_name', 'last_name', 'created_at', 'updated_at', 'timezone'
    ];

    public function groups() {
        return $this->belongsToMany('App\Group', 'app_group_users');
    }

    protected static $_PERMISSIONS_CACHE = [];

    public function permissions() {
        if(isset(self::$_PERMISSIONS_CACHE[$this->id])) {
            return self::$_PERMISSIONS_CACHE[$this->id];
        }
        $groups = $this->groups()->get();
        $_permissions = GroupPermission::whereIn('group_id', $groups)
        ->join('app_permissions', 'app_permissions.id', '=', 'app_group_permissions.permission_id')
        ->select('app_permissions.title', 'app_permissions.description')->get()->toArray();
        $permissions = [];
        foreach($_permissions as $_permission) {
            $permissions[$_permission['title']] = [
                'description' => $_permission['description']
            ];
        }
        self::$_PERMISSIONS_CACHE[$this->id] = $permissions;
        return $permissions;
    }

    protected static $_AVAILABLE_PERMISSIONS = [
        'show' => 'show', 'add' => 'add', 'edit' => 'edit', 'delete' => 'delete'
    ];
    protected static $_AVAILABLE_ENTITIES = [
        'user' => 'user', 'group' => 'group',
        'complex' => 'complex', 'house' => 'house', 'flat' => 'flat',
        'property' => 'property'
    ];

    public function has_permission($entity_permission, $id = null) {
        list($entity, $permission) = explode('.', $entity_permission);

        if(!isset(self::$_AVAILABLE_ENTITIES[$entity])) {
            throw new \InvalidArgumentException("Wrong enity '" . $entity . "'");
        }
        if(!isset(self::$_AVAILABLE_PERMISSIONS[$permission])) {
            throw new \InvalidArgumentException("Wrong permission '" . $permission . "'");
        }

        if($id !== null) {
            $entity_permission = $entity_permission . '.' . $id;
        }

        return isset($this->permissions()[$entity_permission]);
    }
}

我还想以这种方式存储所有权限修订(当管理员更改用户的权限时)(不是生产代码):

\DB::transaction(function() {
    $g = App\Group::find(Input::get('group_id'));
    $p = App\Permission::find(Input::get('permission_id'));
    $permissions = $g->permissions()->lockForUpdate()->get()->pluck('id')->toArray();
    $new_permissions = array_merge($permissions, [$p->id]);
    $g->permissions()->sync($new_permissions);
    $permissions_revision = App\GroupPermissionRevision::firstOrNew(['group_id' => $g->id]);
    $permissions_revision->value = implode('|', $new_permissions);
    $permissions_revision->save();
});

这是 GroupPermissionRevision

namespace App;

use Illuminate\Database\Eloquent\Model;

class GroupPermissionRevision extends Model
{
    protected $table = 'app_group_permissions_revisions';

    use \Venturecraft\Revisionable\RevisionableTrait;

    protected $keepRevisionOf = ['value'];

    protected $fillable = ['group_id', 'value'];

}

$value
将包含
current
权限的 ID(像这样
10|35|42
),而
revisions
表将包含权限历史记录。

有好的方法吗?

php mysql laravel laravel-5
1个回答
0
投票

使用授权服务是最好的方法:https://laravel.com/docs/5.3/authorization

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.