Autenticación y Manejo de Roles de Usuarios en Laravel 7
He vuelto con la actualización de la versión anterior que he escrito sobre este tema que puedes leer en mi post anterior: Autenticación de Usuarios y Roles en Laravel 5.8
1. Crear un proyecto nuevo
Lo inicial es crear un proyecto nuevo incorporando el flag --auth
con el objeto que se cree automáticamente con las vistas y lógica.
laravel new roles-laravel7 --auth
Recuerda en este punto abrir tu proyecto y configurar las variables de entorno en tu archivo
.env
de tu base de datos.
2. Crear el modelo y la migración
Para esto Laravel provee un flag que crea automáticamente el modelo y la migración -m
. En este caso crearemos un modelo llamado Role y su correspondiente migración:
php artisan make:model Role -m
Ahora debemos agregar los campos que llevará la nueva tabla que crearemos en nuestra base de datos llamada roles
a través del archivo de migración recién creado app/database/migrations/xxxx_xx_xx_create_roles_table.php
public function up()
{
Schema::create('roles', function (Blueprint $table) {
$table->id(); $table->string('name');
$table->string('description');
$table->timestamps();
});
}
3. Crear las relaciones y migración de la tabla pivot
Para que este nuevo modelo pueda ser utilizado, debemos crear una relación ente él y el modelo User, el tipo de relación en este caso es many-to-many puesto que un usuario puede tener uno o más roles.
Abrimos el modelo app/User.php
y agregamos el método que indica la relación:
<?phpnamespace App;use App\Role;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;class User extends Authenticatable
{
use Notifiable; protected $fillable = [
'name', 'email', 'password',
]; protected $hidden = [
'password', 'remember_token',
]; protected $casts = [
'email_verified_at' => 'datetime',
]; public function roles()
{
return $this->belongsToMany(Role::class)->withTimestamps();
}
}
Ahora debemos hacer lo mismo pero con el modelo app/Role.php
puesto que también necesitaremos saber cuáles usuarios poseen qué roles. Para ello hay que escribir el método:
<?phpnamespace App;use App\User;
use Illuminate\Database\Eloquent\Model;class Role extends Model
{
public function users()
{
return $this->belongsToMany(User::class)->withTimestamps();
}
}
Es momento de crear la migración correspondiente a la tabla pivot para las relaciones creadas. Para ello utilizaremos la convención de escribir las tablas en singular y en orden alfabético:
php artisan make:migration create_role_user_table
Ingresamos al archivo de migración recién creado en app/database/migration/xxx_xx_xx_create_role_user_table.php
y agregamos:
public function up()
{
Schema::create('role_user', function (Blueprint $table) {
$table->id(); $table->unsignedBigInteger('role_id');
$table->unsignedBigInteger('user_id'); $table->timestamps(); $table->foreign('role_id')
->references('id')
->on('roles')
->onDelete('cascade'); $table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
});
}
Es importante notar que hemos agregado en esta tabla los “foreign constraint” para roles y usuarios que se pueden ver al final del archivo.
4. Agregar un seeder para poblar la tabla roles
Para poder tener acceso a todos los roles que se necesitan es importante anexarlos a un seeder.
php artisan make:seeder RoleTableSeeder
Se necesita ahora editar el archivo app/database/seeds/RoleTableSeeder.php
agregando el siguiente código al método run()
.
En este archivo es posible agregar todos los roles y descripciones que necesites incorporar en tu proyecto y por ende almacenar en tu base de datos.
<?phpuse App\Role;
use Illuminate\Database\Seeder;class RoleTableSeeder extends Seeder
{ public function run()
{
$role = new Role();
$role->name = 'admin';
$role->description = 'Administrator';
$role->save(); $role = new Role();
$role->name = 'user';
$role->description = 'User';
$role->save();
}
}
Debemos editar el archivo app/database/seeds/DatabaseSeeder.php
agregándole el siguiente código al método run()
:
public function run()
{
$this->call(RoleTableSeeder::class);
}
5. Ejecutar las migraciones
Solo unos pocos pasos más… casi todo está listo. Es momento de correr las migraciones y generar el contenido:
php artisan migrate:refresh --seed
6. Adicionar métodos al modelo User
Abrir el modelo app/User.php
y agregar los siguientes tres métodos:
public function authorizeRoles($roles)
{
abort_unless($this->hasAnyRole($roles), 401);
return true;
} public function hasAnyRole($roles)
{
if (is_array($roles)) {
foreach ($roles as $role) {
if ($this->hasRole($role)) {
return true;
}
}
} else {
if ($this->hasRole($roles)) {
return true;
}
}
return false;
}
public function hasRole($role)
{
if ($this->roles()->where('name', $role)->first()) {
return true;
}
return false;
}
7. Anexar un rol al registrar un usuario
Hay que editar el archivo app/Http/Controllers/Auth/RegisterController.php
y cambiar el método create()
para definir por defecto el Role para los nuevos usuarios.
En este caso añadiremos el Role ‘user’ al usuario creado.
<?phpnamespace App\Http\Controllers\Auth;use App\Role;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use App\Providers\RouteServiceProvider;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;class RegisterController extends Controller
{
... protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]); $user->roles()->attach(Role::where('name', 'user')->first()); return $user;
}
}
Por último el paso final. Ahora, todo lo que se necesita es llamar al método authorizeRoles() dentro de la acciones del controlador y pasar el array con los roles de usuario y el nivel de acceso que se desee.
Editar el archivo app/Http/Controllers/HomeController.php
y agregar el siguiente código:
Con esto se logra que solo los usuarios con role de ‘user’ o ‘admin’ puedan ingresar en esa vista.
<?phpnamespace App\Http\Controllers;use Illuminate\Http\Request;class HomeController extends Controller
{ public function __construct()
{
$this->middleware('auth');
} public function index(Request $request)
{
$request->user()->authorizeRoles(['user', 'admin']); return view('home');
}
}
Gracias por tu lectura.
Si te ha gustado, podrías darme un aplauso y seguirme :)