Administrador en Laravel
Creación de un administrador en la aplicación Todo con Laravel
Habrá un administrador que podrá manejar todas las tareas almacenadas y ver todos los usuarios.
Conexión por ssh
ssh paco@alumnoportada.com.es cd todo
Crear el modelo y la migración
Abrir el fichero de migración de usuarios en database\migrations\2022_05_20_000000_create_users_table.php y añadirle la columna is_admin:
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->boolean('is_admin')->nullable(); $table->string('password'); $table->rememberToken(); $table->foreignId('current_team_id')->nullable(); $table->string('profile_photo_path', 2048)->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } };
añadir el campo is_admin a protected $fillable.
nano app/Models/User.php
<?php namespace App\Models; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Fortify\TwoFactorAuthenticatable; use Laravel\Jetstream\HasProfilePhoto; use Laravel\Sanctum\HasApiTokens; use App\Models\Task; class User extends Authenticatable implements MustVerifyEmail { use HasApiTokens; use HasFactory; use HasProfilePhoto; use Notifiable; use TwoFactorAuthenticatable; /** * The attributes that are mass assignable. * * @var string[] */ protected $fillable = [ 'name', 'email', 'password', 'is_admin' ]; /** * The attributes that should be hidden for serialization. * * @var array */ protected $hidden = [ 'password', 'remember_token', 'two_factor_recovery_codes', 'two_factor_secret', ]; /** * The attributes that should be cast to native types. * * @var array */ protected $casts = [ 'email_verified_at' => 'datetime', ]; /** * The accessors to append to the model's array form. * * @var array */ protected $appends = [ 'profile_photo_url', ]; public function tasks() { return $this->hasMany(Task::class); } }
Ejecutar la migración:
php artisan migrate
Crear el middleware isAdmin
php artisan make:middleware IsAdmin
modificar el fichero app/Http/middleware/IsAdmin.php
nano app/Http/middleware/IsAdmin.php
<?php namespace App\Http\Middleware; use Closure; class IsAdmin { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if(auth()->user()->is_admin == 1){ return $next($request); } return redirect('dashboard')->with('message',"Sorry, you don't have admin access."); } }
Añadir una línea en el fichero app/Http/Kernel.php para usar el middleware IsAdmin.
nano app/Http/Kernel.php
protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'is_admin' => \App\Http\Middleware\IsAdmin::class, ];
Rutas
nano routes/web.php
añadir el middleware ‘is_admin’ a las rutas de administración:
Route::prefix('admin')->middleware([ 'auth:sanctum', config('jetstream.auth_session'), 'verified', 'is_admin'
contenido del fichero routes/web.php:
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\TasksController; use App\Http\Controllers\AdminTasksController; use App\Http\Controllers\AdminUsersController; use App\Http\Controllers\EmailController; use Illuminate\Foundation\Auth\EmailVerificationRequest; use Illuminate\Http\Request; Route::get('/', function () { return view('welcome'); }); Route::middleware([ 'auth:sanctum', config('jetstream.auth_session'), 'verified' ])->group(function () { Route::get('/dashboard',[TasksController::class, 'index'])->name('dashboard'); Route::get('/admin/home', [HomeController::class, 'adminHome'])->name('admin.home')->middleware('is_admin'); Route::get('/task',[TasksController::class, 'add']); Route::post('/task',[TasksController::class, 'create']); Route::get('/task/{task}', [TasksController::class, 'edit']); Route::post('/task/{task}', [TasksController::class, 'update']); }); Route::prefix('admin')->middleware([ 'auth:sanctum', config('jetstream.auth_session'), 'verified', 'is_admin' ])->group(function () { Route::get('/', function () { return view('admin.dashboard'); }); Route::get('/tasks',[AdminTasksController::class, 'index'])->name('tasksdashboard'); Route::get('/task',[AdminTasksController::class, 'add']); Route::post('/task',[AdminTasksController::class, 'create']); Route::get('/task/{task}', [AdminTasksController::class, 'edit']); Route::post('/task/{task}', [AdminTasksController::class, 'update']); Route::get('/users',[AdminUsersController::class, 'index'])->name('usersdashboard'); });
Creación de controladores
nano app/Http/Controllers/AdminTasksController
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Task; class AdminTasksController extends Controller { public function index() { //$tasks = auth()->user()->tasks(); $tasks = Task::all(); return view('admin.tasks', compact('tasks')); } public function add() { return view('admin.add'); } public function create(Request $request) { $this->validate($request, [ 'description' => 'required' ]); $task = new Task(); $task->description = $request->description; $task->user_id = auth()->user()->id; $task->save(); return redirect('/admin'); } public function edit(Task $task) { if (auth()->user()->id == $task->user_id) { return view('admin.edit', compact('task')); } else { return redirect('/admin/tasks'); } } public function update(Request $request, Task $task) { if(isset($_POST['delete'])) { $task->delete(); return redirect('/admin/tasks'); } else { $this->validate($request, [ 'description' => 'required' ]); $task->description = $request->description; $task->save(); return redirect('/admin/tasks'); } } }
nano app/Http/Controllers/AdminUsersController
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\User; class AdminUsersController extends Controller { public function index() { $users = User::all(); return view('admin.users', compact('users')); } }
Creación de las vistas
Crearemos la carpeta admin para poner las vistas usadas.
mkdir resources/views/admin
Añadir al menú de navegación un enlace a la ruta de administración, si el usuario que hace login es administrador.
Añadir este contenido antes de <!– Settings Dropdown –>
@if ( Auth::user()->is_admin == 1) <span class="inline-flex rounded-md"> <button type="button" class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 bg-white hover:text-gray-700 focus:outline-none transition"> <x-jet-dropdown-link href="{{ url('/admin') }}"> {{ __('Administration') }} </x-jet-dropdown-link> </button> </span> @endif
Si el usuario es administrador, le aparecerá la opción de administración en el menú, al lado de su nombre.
nano resources/views/navigation-menu.blade
<nav x-data="{ open: false }" class="bg-white border-b border-gray-100"> <!-- Primary Navigation Menu --> <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div class="flex justify-between h-16"> <div class="flex"> <!-- Logo --> <div class="shrink-0 flex items-center"> <a href="{{ route('dashboard') }}"> <x-jet-application-mark class="block h-9 w-auto" /> </a> </div> <!-- Navigation Links --> <div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex"> <x-jet-nav-link href="{{ route('dashboard') }}" :active="request()->routeIs('dashboard')"> {{ __('Dashboard') }} </x-jet-nav-link> </div> </div> <div class="hidden sm:flex sm:items-center sm:ml-6"> <!-- Teams Dropdown --> @if (Laravel\Jetstream\Jetstream::hasTeamFeatures()) <div class="ml-3 relative"> <x-jet-dropdown align="right" width="60"> <x-slot name="trigger"> <span class="inline-flex rounded-md"> <button type="button" class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 bg-white hover:bg-gray-50 hover:text-gray-700 focus:outline-none focus:bg-gray-50 active:bg-gray-50 transition"> {{ Auth::user()->currentTeam->name }} <svg class="ml-2 -mr-0.5 h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"> <path fill-rule="evenodd" d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" /> </svg> </button> </span> </x-slot> <x-slot name="content"> <div class="w-60"> <!-- Team Management --> <div class="block px-4 py-2 text-xs text-gray-400"> {{ __('Manage Team') }} </div> <!-- Team Settings --> <x-jet-dropdown-link href="{{ route('teams.show', Auth::user()->currentTeam->id) }}"> {{ __('Team Settings') }} </x-jet-dropdown-link> @can('create', Laravel\Jetstream\Jetstream::newTeamModel()) <x-jet-dropdown-link href="{{ route('teams.create') }}"> {{ __('Create New Team') }} </x-jet-dropdown-link> @endcan <div class="border-t border-gray-100"></div> <!-- Team Switcher --> <div class="block px-4 py-2 text-xs text-gray-400"> {{ __('Switch Teams') }} </div> @foreach (Auth::user()->allTeams() as $team) <x-jet-switchable-team :team="$team" /> @endforeach </div> </x-slot> </x-jet-dropdown> </div> @endif @if ( Auth::user()->is_admin == 1) <span class="inline-flex rounded-md"> <button type="button" class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 bg-white hover:text-gray-700 focus:outline-none transition"> <x-jet-dropdown-link href="{{ url('/admin') }}"> {{ __('Administration') }} </x-jet-dropdown-link> </button> </span> @endif <!-- Settings Dropdown --> <div class="ml-3 relative"> <x-jet-dropdown align="right" width="48"> <x-slot name="trigger"> @if (Laravel\Jetstream\Jetstream::managesProfilePhotos()) <button class="flex text-sm border-2 border-transparent rounded-full focus:outline-none focus:border-gray-300 transition"> <img class="h-8 w-8 rounded-full object-cover" src="{{ Auth::user()->profile_photo_url }}" alt="{{ Auth::user()->name }}" /> </button> @else <span class="inline-flex rounded-md"> <button type="button" class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 bg-white hover:text-gray-700 focus:outline-none transition"> {{ Auth::user()->name }} <svg class="ml-2 -mr-0.5 h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"> <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" /> </svg> </button> </span> @endif </x-slot> <x-slot name="content"> <!-- Account Management --> <div class="block px-4 py-2 text-xs text-gray-400"> {{ __('Manage Account') }} </div> <x-jet-dropdown-link href="{{ route('profile.show') }}"> {{ __('Profile') }} </x-jet-dropdown-link> @if (Laravel\Jetstream\Jetstream::hasApiFeatures()) <x-jet-dropdown-link href="{{ route('api-tokens.index') }}"> {{ __('API Tokens') }} </x-jet-dropdown-link> @endif <div class="border-t border-gray-100"></div> <!-- Authentication --> <form method="POST" action="{{ route('logout') }}" x-data> @csrf <x-jet-dropdown-link href="{{ route('logout') }}" @click.prevent="$root.submit();"> {{ __('Log Out') }} </x-jet-dropdown-link> </form> </x-slot> </x-jet-dropdown> </div> </div> <!-- Hamburger --> <div class="-mr-2 flex items-center sm:hidden"> <button @click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition"> <svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24"> <path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" /> <path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> </svg> </button> </div> </div> </div> <!-- Responsive Navigation Menu --> <div :class="{'block': open, 'hidden': ! open}" class="hidden sm:hidden"> <div class="pt-2 pb-3 space-y-1"> <x-jet-responsive-nav-link href="{{ route('dashboard') }}" :active="request()->routeIs('dashboard')"> {{ __('Dashboard') }} </x-jet-responsive-nav-link> </div> <!-- Responsive Settings Options --> <div class="pt-4 pb-1 border-t border-gray-200"> <div class="flex items-center px-4"> @if (Laravel\Jetstream\Jetstream::managesProfilePhotos()) <div class="shrink-0 mr-3"> <img class="h-10 w-10 rounded-full object-cover" src="{{ Auth::user()->profile_photo_url }}" alt="{{ Auth::user()->name }}" /> </div> @endif <div> <div class="font-medium text-base text-gray-800">{{ Auth::user()->name }}</div> <div class="font-medium text-sm text-gray-500">{{ Auth::user()->email }}</div> </div> </div> <div class="mt-3 space-y-1"> <!-- Account Management --> <x-jet-responsive-nav-link href="{{ route('profile.show') }}" :active="request()->routeIs('profile.show')"> {{ __('Profile') }} </x-jet-responsive-nav-link> @if (Laravel\Jetstream\Jetstream::hasApiFeatures()) <x-jet-responsive-nav-link href="{{ route('api-tokens.index') }}" :active="request()->routeIs('api-tokens.index')"> {{ __('API Tokens') }} </x-jet-responsive-nav-link> @endif <!-- Authentication --> <form method="POST" action="{{ route('logout') }}" x-data> @csrf <x-jet-responsive-nav-link href="{{ route('logout') }}" @click.prevent="$root.submit();"> {{ __('Log Out') }} </x-jet-responsive-nav-link> </form> <!-- Team Management --> @if (Laravel\Jetstream\Jetstream::hasTeamFeatures()) <div class="border-t border-gray-200"></div> <div class="block px-4 py-2 text-xs text-gray-400"> {{ __('Manage Team') }} </div> <!-- Team Settings --> <x-jet-responsive-nav-link href="{{ route('teams.show', Auth::user()->currentTeam->id) }}" :active="request()->routeIs('teams.show')"> {{ __('Team Settings') }} </x-jet-responsive-nav-link> @can('create', Laravel\Jetstream\Jetstream::newTeamModel()) <x-jet-responsive-nav-link href="{{ route('teams.create') }}" :active="request()->routeIs('teams.create')"> {{ __('Create New Team') }} </x-jet-responsive-nav-link> @endcan <div class="border-t border-gray-200"></div> <!-- Team Switcher --> <div class="block px-4 py-2 text-xs text-gray-400"> {{ __('Switch Teams') }} </div> @foreach (Auth::user()->allTeams() as $team) <x-jet-switchable-team :team="$team" component="jet-responsive-nav-link" /> @endforeach @endif </div> </div> </div> </nav>
nano resources/views/admin/dashboard.blade.php
<x-app-layout> <x-slot name="header"> <h2 class="font-semibold text-xl text-gray-800 leading-tight"> {{ __('Dashboard') }} </h2> </x-slot> <div class="py-12"> <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-5"> <div class="flex"> <div class="flex-auto text-2xl mb-4 text-green-500">Dashboard Administration</div> </div> <div class="bg-gray-200 p-6 grid grid-rows-2"> <div class="m-2 p-6"> <a href="{{ url('/admin/tasks') }}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Administrar tareas</a> </div> <div class="m-2 p-6"> <a href="{{ url('/admin/users') }}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Ver usuarios</a> </div> </div> </div> </div> </div> </x-app-layout>
nano resources/views/admin/tasks.blade.php
<x-app-layout> <x-slot name="header"> <h2 class="font-semibold text-xl text-gray-800 leading-tight"> {{ __('Dashboard') }} </h2> </x-slot> <div class="py-12"> <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-5"> <div class="flex"> <div class="flex-auto text-2xl mb-4 text-green-500">Tasks Administration</div> <div class="flex-auto text-right mt-2"> <a href="/admin/task" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Add new Task</a> </div> </div> <table class="w-full text-md rounded mb-4"> <thead> <tr class="border-b"> <th class="text-left p-3 px-5">Task</th> <th class="text-left p-3 px-5">User Id</th> <th class="text-left p-3 px-5">Actions</th> <th></th> </tr> </thead> <tbody> @foreach($tasks as $task) <tr class="border-b hover:bg-orange-100"> <td class="p-3 px-5"> {{$task->description}} </td> <td class="p-3 px-5"> {{$task->user_id}} </td> <td class="p-3 px-5"> <a href="/admin/task/{{$task->id}}" name="edit" class="mr-3 text-sm bg-blue-500 hover:bg-blue-700 text-white py-1 px-2 rounded focus:outline-none focus:shadow-outline">Edit</a> <form action="/admin/task/{{$task->id}}" class="inline-block"> <button type="submit" name="delete" formmethod="POST" class="text-sm bg-red-500 hover:bg-red-700 text-white py-1 px-2 rounded focus:outline-none focus:shadow-outline">Delete</button> {{ csrf_field() }} </form> </td> </tr> @endforeach </tbody> </table> </div> </div> </div> </x-app-layout>
nano resources/views/admin/add.blade.php
<x-app-layout> <x-slot name="header"> <h2 class="font-semibold text-xl text-gray-800 leading-tight"> {{ __('Add Task') }} </h2> </x-slot> <div class="py-12"> <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-5"> <form method="POST" action="/admin/task"> <div class="form-group"> <textarea name="description" class="bg-gray-100 rounded border border-gray-400 leading-normal resize-none w-full h-20 py-2 px-3 font-medium placeholder-gray-700 focus:outline-none focus:bg-white" placeholder='Enter your task'></textarea> @if ($errors->has('description')) <span class="text-danger">{{ $errors->first('description') }}</span> @endif </div> <div class="form-group"> <button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Add Task</button> </div> {{ csrf_field() }} </form> </div> </div> </div> </x-app-layout>
nano resources/views/admin/edit.blade.php
<x-app-layout> <x-slot name="header"> <h2 class="font-semibold text-xl text-gray-800 leading-tight"> {{ __('Edit Task') }} </h2> </x-slot> <div class="py-12"> <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-5"> <form method="POST" action="/admin/task/{{ $task->id }}"> <div class="form-group"> <textarea name="description" class="bg-gray-100 rounded border border-gray-400 leading-normal resize-none w-full h-20 py-2 px-3 font-medium placeholder-gray-700 focus:outline-none focus:bg-white">{{$task->description }}</textarea> @if ($errors->has('description')) <span class="text-danger">{{ $errors->first('description') }}</span> @endif </div> <div class="form-group"> <button type="submit" name="update" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Update task</button> </div> {{ csrf_field() }} </form> </div> </div> </div> </x-app-layout>
nano resources/views/admin/users.blade.php
<x-app-layout> <x-slot name="header"> <h2 class="font-semibold text-xl text-gray-800 leading-tight"> {{ __('Dashboard') }} </h2> </x-slot> <div class="py-12"> <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-5"> <div class="flex"> <div class="flex-auto text-2xl mb-4 text-green-500">Users Administration</div> <div class="flex-auto text-right mt-2"> <a href="/admin" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Volver</a> </div> </div> <table class="w-full text-md rounded mb-4"> <thead> <tr class="border-b"> <th class="text-left p-3 px-5">Name</th> <th class="text-left p-3 px-5">Email</th> <th></th> </tr> </thead> <tbody> @foreach($users as $user) <tr class="border-b hover:bg-orange-100"> <td class="p-3 px-5"> {{$user->name}} </td> <td class="p-3 px-5"> {{$user->email}} </td> </tr> @endforeach </tbody> </table> </div> </div> </div> </x-app-layout>
nano resources/views/dashboard.blade.php
añadirle el mensaje de aviso si el usuario intenta acceder a la ruta de admin
@if(Session::has('message')) <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert"> <strong class="font-bold">{{ Session::get('message') }}</strong> <span class="absolute top-0 bottom-0 right-0 px-4 py-3"> <svg class="fill-current h-6 w-6 text-red-500" role="button" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><title>Close</title><path d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"/></svg> </span> </div> @endif
Más información: Alerts in Tailwindcss
<x-app-layout> <x-slot name="header"> <h2 class="font-semibold text-xl text-gray-800 leading-tight"> {{ __('Dashboard') }} </h2> </x-slot> <div class="py-12"> <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> <div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-5"> @if(Session::has('message')) <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert"> <strong class="font-bold">{{ Session::get('message') }}</strong> <span class="absolute top-0 bottom-0 right-0 px-4 py-3"> <svg class="fill-current h-6 w-6 text-red-500" role="button" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><title>Close</title><path d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"/></svg> </span> </div> @endif <div class="flex"> <div class="flex-auto text-2xl mb-4">Tasks List</div> <div class="flex-auto text-right mt-2"> <a href="/task" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Add new Task</a> </div> </div> <table class="w-full text-md rounded mb-4"> <thead> <tr class="border-b"> <th class="text-left p-3 px-5">Task</th> <th class="text-left p-3 px-5">Actions</th> <th></th> </tr> </thead> <tbody> @foreach(auth()->user()->tasks as $task) <tr class="border-b hover:bg-orange-100"> <td class="p-3 px-5"> {{$task->description}} </td> <td class="p-3 px-5"> <a href="/task/{{$task->id}}" name="edit" class="mr-3 text-sm bg-blue-500 hover:bg-blue-700 text-white py-1 px-2 rounded focus:outline-none focus:shadow-outline">Edit</a> <form action="/task/{{$task->id}}" class="inline-block"> <button type="submit" name="delete" formmethod="POST" class="text-sm bg-red-500 hover:bg-red-700 text-white py-1 px-2 rounded focus:outline-none focus:shadow-outline">Delete</button> {{ csrf_field() }} </form> </td> </tr> @endforeach </tbody> </table> </div> </div> </div> </x-app-layout>
Hacer administrador al usuario con email paco.portada@protonmail.com en la base de datos
mysql -u root -p
use todoDB; UPDATE users SET is_admin = 1 WHERE email = 'paco.portada@protonmail.com';
Más información:
Laravel 9 Multi Auth (Authentication) Tutorial with Example
Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.