Autenticación y Manejo de Roles de Usuarios en Laravel 7

Claudio Vallejo
4 min readMar 26, 2020

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

Autenticación y Manejo de Roles de Usuarios

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 :)

--

--

Claudio Vallejo

Wine, programmer, diver & photographer lover. Agronomist Engineer. CEO/Founder of Intelvid.la — Cofounder Tradesfere.com More: cvallejo.me