Let's say, I have many models: user, group, complex, house, flat.
I want to assign different permissions to different users.
For example, users in group1 can have these permissions (self explanatory): "complex.show", "complex.edit"
Users in group2: "house.show", "flat.show", "flat.edit"
Users in group3: "house.show", "house.edit.1", "house.edit.3" (these users can see all houses and can edit house with id 1&3)
Migration
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');
}
}
User model
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]);
}
}
Also I want to store all revisions of permissions (when administrator changes user's permissions) this way (not production code):
\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();
});
And here is 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
would contain current
permissions' ids (like this 10|35|42
) and revisions
table would contain history of permissions.
Is it good way to do it?
via Chebli Mohamed
Aucun commentaire:
Enregistrer un commentaire