feat(authorization): add roles and permissions models, migration, and tests
This commit is contained in:
parent
ace3f136e4
commit
a674bcfabc
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Domains\Authorization\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
class Permission extends Model
|
||||
{
|
||||
protected $table = 'permisos';
|
||||
|
||||
protected $fillable = [
|
||||
'codigo',
|
||||
'nombre',
|
||||
'descripcion',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<Role, $this>
|
||||
*/
|
||||
public function roles(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(
|
||||
Role::class,
|
||||
'roles_permisos',
|
||||
'codigo_permiso',
|
||||
'rol_codigo',
|
||||
'codigo',
|
||||
'codigo'
|
||||
)->withTimestamps();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Domains\Authorization\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
class Role extends Model
|
||||
{
|
||||
protected $table = 'roles';
|
||||
|
||||
protected $fillable = [
|
||||
'codigo',
|
||||
'nombre',
|
||||
'descripcion',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<Permission, $this>
|
||||
*/
|
||||
public function permissions(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(
|
||||
Permission::class,
|
||||
'roles_permisos',
|
||||
'rol_codigo',
|
||||
'codigo_permiso',
|
||||
'codigo',
|
||||
'codigo'
|
||||
)->withTimestamps();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Domains\Authorization\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class RolePermission extends Model
|
||||
{
|
||||
protected $table = 'roles_permisos';
|
||||
|
||||
protected $fillable = [
|
||||
'codigo_permiso',
|
||||
'rol_codigo',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Permission, $this>
|
||||
*/
|
||||
public function permission(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Permission::class, 'codigo_permiso', 'codigo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Role, $this>
|
||||
*/
|
||||
public function role(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Role::class, 'rol_codigo', 'codigo');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('permisos', function (Blueprint $table): void {
|
||||
$table->id();
|
||||
$table->string('codigo')->unique();
|
||||
$table->string('nombre');
|
||||
$table->text('descripcion')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('roles', function (Blueprint $table): void {
|
||||
$table->id();
|
||||
$table->string('codigo')->unique();
|
||||
$table->string('nombre');
|
||||
$table->text('descripcion')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('roles_permisos', function (Blueprint $table): void {
|
||||
$table->id();
|
||||
$table->string('codigo_permiso');
|
||||
$table->string('rol_codigo');
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('codigo_permiso')
|
||||
->references('codigo')
|
||||
->on('permisos')
|
||||
->cascadeOnUpdate()
|
||||
->cascadeOnDelete();
|
||||
$table->foreign('rol_codigo')
|
||||
->references('codigo')
|
||||
->on('roles')
|
||||
->cascadeOnUpdate()
|
||||
->cascadeOnDelete();
|
||||
$table->unique(['rol_codigo', 'codigo_permiso']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('roles_permisos');
|
||||
Schema::dropIfExists('roles');
|
||||
Schema::dropIfExists('permisos');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature\Authorization;
|
||||
|
||||
use App\Domains\Authorization\Models\Permission;
|
||||
use App\Domains\Authorization\Models\Role;
|
||||
use App\Domains\Authorization\Models\RolePermission;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Tests\TestCase;
|
||||
|
||||
class RolePermissionModelTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_authorization_tables_have_the_expected_columns(): void
|
||||
{
|
||||
$this->assertEqualsCanonicalizing([
|
||||
'id',
|
||||
'codigo',
|
||||
'nombre',
|
||||
'descripcion',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
], Schema::getColumnListing('permisos'));
|
||||
|
||||
$this->assertEqualsCanonicalizing([
|
||||
'id',
|
||||
'codigo',
|
||||
'nombre',
|
||||
'descripcion',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
], Schema::getColumnListing('roles'));
|
||||
|
||||
$this->assertEqualsCanonicalizing([
|
||||
'id',
|
||||
'codigo_permiso',
|
||||
'rol_codigo',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
], Schema::getColumnListing('roles_permisos'));
|
||||
}
|
||||
|
||||
public function test_a_role_and_permission_can_be_related_by_their_codes(): void
|
||||
{
|
||||
$role = Role::query()->create([
|
||||
'codigo' => 'administrador',
|
||||
'nombre' => 'Administrador',
|
||||
'descripcion' => 'Administra la tienda.',
|
||||
]);
|
||||
$permission = Permission::query()->create([
|
||||
'codigo' => 'catalogo.editar',
|
||||
'nombre' => 'Editar catálogo',
|
||||
]);
|
||||
|
||||
$role->permissions()->attach($permission->codigo);
|
||||
|
||||
$this->assertTrue($role->permissions()->firstOrFail()->is($permission));
|
||||
$this->assertTrue($permission->roles()->firstOrFail()->is($role));
|
||||
$this->assertDatabaseHas('roles_permisos', [
|
||||
'rol_codigo' => $role->codigo,
|
||||
'codigo_permiso' => $permission->codigo,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_the_pivot_model_exposes_its_role_and_permission(): void
|
||||
{
|
||||
$role = Role::query()->create([
|
||||
'codigo' => 'editor',
|
||||
'nombre' => 'Editor',
|
||||
]);
|
||||
$permission = Permission::query()->create([
|
||||
'codigo' => 'catalogo.editar',
|
||||
'nombre' => 'Editar catálogo',
|
||||
]);
|
||||
$assignment = RolePermission::query()->create([
|
||||
'rol_codigo' => $role->codigo,
|
||||
'codigo_permiso' => $permission->codigo,
|
||||
]);
|
||||
|
||||
$this->assertTrue($assignment->role->is($role));
|
||||
$this->assertTrue($assignment->permission->is($permission));
|
||||
}
|
||||
|
||||
public function test_a_permission_cannot_be_assigned_twice_to_the_same_role(): void
|
||||
{
|
||||
$role = Role::query()->create([
|
||||
'codigo' => 'editor',
|
||||
'nombre' => 'Editor',
|
||||
]);
|
||||
$permission = Permission::query()->create([
|
||||
'codigo' => 'catalogo.editar',
|
||||
'nombre' => 'Editar catálogo',
|
||||
]);
|
||||
$role->permissions()->attach($permission->codigo);
|
||||
|
||||
$this->expectException(QueryException::class);
|
||||
|
||||
$role->permissions()->attach($permission->codigo);
|
||||
}
|
||||
|
||||
public function test_deleting_a_role_removes_its_permission_assignments(): void
|
||||
{
|
||||
$role = Role::query()->create([
|
||||
'codigo' => 'editor',
|
||||
'nombre' => 'Editor',
|
||||
]);
|
||||
$permission = Permission::query()->create([
|
||||
'codigo' => 'catalogo.editar',
|
||||
'nombre' => 'Editar catálogo',
|
||||
]);
|
||||
$role->permissions()->attach($permission->codigo);
|
||||
|
||||
$role->delete();
|
||||
|
||||
$this->assertDatabaseMissing('roles_permisos', [
|
||||
'rol_codigo' => $role->codigo,
|
||||
'codigo_permiso' => $permission->codigo,
|
||||
]);
|
||||
$this->assertDatabaseHas('permisos', [
|
||||
'codigo' => $permission->codigo,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue