Rollen für Langutor: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
| Zeile 170: | Zeile 170: | ||
'users' => UserController::class, | 'users' => UserController::class, | ||
]); | ]); | ||
</pre> | |||
== Controller für Role und Resources == | |||
<pre> | |||
php artisan make:controller RoleController --resource | |||
php artisan make:controller UserController --resource | |||
</pre> | |||
* app/http/Controllers/RoleController: | |||
<pre> | |||
<?php | |||
namespace App\Http\Controllers; | |||
use App\Http\Requests\StoreRoleRequest; | |||
use App\Http\Requests\UpdateRoleRequest; | |||
use Spatie\Permission\Models\Role; | |||
use Spatie\Permission\Models\Permission; | |||
use Illuminate\View\View; | |||
use Illuminate\Http\RedirectResponse; | |||
use DB; | |||
class RoleController extends Controller | |||
{ | |||
public function __construct() | |||
{ | |||
$this->middleware('auth'); | |||
$this->middleware('permission:create-role|edit-role|delete-role', ['only' => ['index', 'show']]); | |||
$this->middleware('permission:create-role', ['only' => ['create', 'store']]); | |||
$this->middleware('permission:edit-role', ['only' => ['edit', 'update']]); | |||
$this->middleware('permission:delete-role', ['only' => ['destroy']]); | |||
} | |||
/** | |||
* Display a listing of the resource. | |||
*/ | |||
public function index(): View | |||
{ | |||
return view('roles.index', [ | |||
'roles' => Role::orderBy('id', 'DESC')->paginate(3) | |||
]); | |||
} | |||
/** | |||
* Show the form for creating a new resource. | |||
*/ | |||
public function create(): View | |||
{ | |||
return view('roles.create', [ | |||
'permissions' => Permission::get() | |||
]); | |||
} | |||
/** | |||
* Store a newly created resource in storage. | |||
*/ | |||
public function store(StoreRoleRequest $request): RedirectResponse | |||
{ | |||
$role = Role::create(['name' => $request->name]); | |||
$role->syncPermissions($request->permissions); | |||
return redirect()->route('roles.index') | |||
->withSuccess('New role is added successfully.'); | |||
} | |||
/** | |||
* Display the specified resource. | |||
*/ | |||
public function show(Role $role): View | |||
{ | |||
$rolePermissions = Permission::join("role_has_permissions", "permission_id", "=", "id") | |||
->where("role_id", $role->id) | |||
->select('name') | |||
->get(); | |||
return view('roles.show', [ | |||
'role' => $role, | |||
'rolePermissions' => $rolePermissions | |||
]); | |||
} | |||
/** | |||
* Show the form for editing the specified resource. | |||
*/ | |||
public function edit(Role $role): View | |||
{ | |||
if ($role->name == 'Super Admin') { | |||
abort(403, 'SUPER ADMIN ROLE CAN NOT BE EDITED'); | |||
} | |||
$rolePermissions = DB::table("role_has_permissions")->where("role_id", $role->id) | |||
->pluck('permission_id') | |||
->all(); | |||
return view('roles.edit', [ | |||
'role' => $role, | |||
'permissions' => Permission::get(), | |||
'rolePermissions' => $rolePermissions | |||
]); | |||
} | |||
/** | |||
* Update the specified resource in storage. | |||
*/ | |||
public function update(UpdateRoleRequest $request, Role $role): RedirectResponse | |||
{ | |||
$input = $request->only('name'); | |||
$role->update($input); | |||
$role->syncPermissions($request->permissions); | |||
return redirect()->back() | |||
->withSuccess('Role is updated successfully.'); | |||
} | |||
/** | |||
* Remove the specified resource from storage. | |||
*/ | |||
public function destroy(Role $role): RedirectResponse | |||
{ | |||
if ($role->name == 'Super Admin') { | |||
abort(403, 'SUPER ADMIN ROLE CAN NOT BE DELETED'); | |||
} | |||
if (auth()->user()->hasRole($role->name)) { | |||
abort(403, 'CAN NOT DELETE SELF ASSIGNED ROLE'); | |||
} | |||
$role->delete(); | |||
return redirect()->route('roles.index') | |||
->withSuccess('Role is deleted successfully.'); | |||
} | |||
} | |||
</pre> | |||
* App/http/Controllers/UserController | |||
<pre> | |||
<?php | |||
namespace App\Http\Controllers; | |||
use App\Models\User; | |||
use App\Http\Requests\StoreUserRequest; | |||
use App\Http\Requests\UpdateUserRequest; | |||
use Illuminate\View\View; | |||
use Illuminate\Http\RedirectResponse; | |||
use Spatie\Permission\Models\Role; | |||
use Illuminate\Support\Facades\Hash; | |||
class UserController extends Controller | |||
{ | |||
/** | |||
* Instantiate a new UserController instance. | |||
*/ | |||
public function __construct() | |||
{ | |||
$this->middleware('auth'); | |||
$this->middleware('permission:create-user|edit-user|delete-user', ['only' => ['index','show']]); | |||
$this->middleware('permission:create-user', ['only' => ['create','store']]); | |||
$this->middleware('permission:edit-user', ['only' => ['edit','update']]); | |||
$this->middleware('permission:delete-user', ['only' => ['destroy']]); | |||
} | |||
/** | |||
* Display a listing of the resource. | |||
*/ | |||
public function index(): View | |||
{ | |||
return view('users.index', [ | |||
'users' => User::latest('id')->paginate(3) | |||
]); | |||
} | |||
/** | |||
* Show the form for creating a new resource. | |||
*/ | |||
public function create(): View | |||
{ | |||
return view('users.create', [ | |||
'roles' => Role::pluck('name')->all() | |||
]); | |||
} | |||
/** | |||
* Store a newly created resource in storage. | |||
*/ | |||
public function store(StoreUserRequest $request): RedirectResponse | |||
{ | |||
$input = $request->all(); | |||
$input['password'] = Hash::make($request->password); | |||
$user = User::create($input); | |||
$user->assignRole($request->roles); | |||
return redirect()->route('users.index') | |||
->withSuccess('New user is added successfully.'); | |||
} | |||
/** | |||
* Display the specified resource. | |||
*/ | |||
public function show(User $user): View | |||
{ | |||
return view('users.show', [ | |||
'user' => $user | |||
]); | |||
} | |||
/** | |||
* Show the form for editing the specified resource. | |||
*/ | |||
public function edit(User $user): View | |||
{ | |||
// Check Only Super Admin can update his own Profile | |||
if ($user->hasRole('Super Admin')){ | |||
if($user->id != auth()->user()->id){ | |||
abort(403, 'USER DOES NOT HAVE THE RIGHT PERMISSIONS'); | |||
} | |||
} | |||
return view('users.edit', [ | |||
'user' => $user, | |||
'roles' => Role::pluck('name')->all(), | |||
'userRoles' => $user->roles->pluck('name')->all() | |||
]); | |||
} | |||
/** | |||
* Update the specified resource in storage. | |||
*/ | |||
public function update(UpdateUserRequest $request, User $user): RedirectResponse | |||
{ | |||
$input = $request->all(); | |||
if(!empty($request->password)){ | |||
$input['password'] = Hash::make($request->password); | |||
}else{ | |||
$input = $request->except('password'); | |||
} | |||
$user->update($input); | |||
$user->syncRoles($request->roles); | |||
return redirect()->back() | |||
->withSuccess('User is updated successfully.'); | |||
} | |||
/** | |||
* Remove the specified resource from storage. | |||
*/ | |||
public function destroy(User $user): RedirectResponse | |||
{ | |||
// About if user is Super Admin or User ID belongs to Auth User | |||
if ($user->hasRole('Super Admin') || $user->id == auth()->user()->id) | |||
{ | |||
abort(403, 'USER DOES NOT HAVE THE RIGHT PERMISSIONS'); | |||
} | |||
$user->syncRoles([]); | |||
$user->delete(); | |||
return redirect()->route('users.index') | |||
->withSuccess('User is deleted successfully.'); | |||
} | |||
} | |||
</pre> | |||
== Requests für User und Role == | |||
<pre> | |||
php artisan make:request StoreRoleRequest | |||
php artisan make:request UpdateRoleRequest | |||
php artisan make:request StoreUserRequest | |||
php artisan make:request UpdateUserRequest | |||
</pre> | |||
=== app/Http/Requests/StoreRoleRequest.php === | |||
<pre> | |||
<?php | |||
namespace App\Http\Requests; | |||
use Illuminate\Foundation\Http\FormRequest; | |||
class StoreRoleRequest extends FormRequest | |||
{ | |||
/** | |||
* Determine if the user is authorized to make this request. | |||
*/ | |||
public function authorize(): bool | |||
{ | |||
return true; | |||
} | |||
/** | |||
* Get the validation rules that apply to the request. | |||
* | |||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string> | |||
*/ | |||
public function rules(): array | |||
{ | |||
return [ | |||
'name' => 'required|string|max:250|unique:roles,name', | |||
'permissions' => 'required', | |||
]; | |||
} | |||
} | |||
</pre> | |||
=== app/Http/Requests/UpdateRoleRequest.php === | |||
<pre> | |||
<?php | |||
namespace App\Http\Requests; | |||
use Illuminate\Foundation\Http\FormRequest; | |||
class UpdateRoleRequest extends FormRequest | |||
{ | |||
/** | |||
* Determine if the user is authorized to make this request. | |||
*/ | |||
public function authorize(): bool | |||
{ | |||
return true; | |||
} | |||
/** | |||
* Get the validation rules that apply to the request. | |||
* | |||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string> | |||
*/ | |||
public function rules(): array | |||
{ | |||
return [ | |||
'name' => 'required|string|max:250|unique:roles,name,'.$this->role->id, | |||
'permissions' => 'required', | |||
]; | |||
} | |||
} | |||
</pre> | |||
=== app/Http/Requests/StoreUserRequest.php === | |||
<pre> | |||
<?php | |||
namespace App\Http\Requests; | |||
use Illuminate\Foundation\Http\FormRequest; | |||
class StoreUserRequest extends FormRequest | |||
{ | |||
/** | |||
* Determine if the user is authorized to make this request. | |||
*/ | |||
public function authorize(): bool | |||
{ | |||
return true; | |||
} | |||
/** | |||
* Get the validation rules that apply to the request. | |||
* | |||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string> | |||
*/ | |||
public function rules(): array | |||
{ | |||
return [ | |||
'name' => 'required|string|max:250', | |||
'email' => 'required|string|email:rfc,dns|max:250|unique:users,email', | |||
'password' => 'required|string|min:8|confirmed', | |||
'roles' => 'required' | |||
]; | |||
} | |||
} | |||
</pre> | |||
=== app/Http/Requests/UpdateUserRequest.php === | |||
<pre> | |||
<?php | |||
namespace App\Http\Requests; | |||
use Illuminate\Foundation\Http\FormRequest; | |||
class UpdateUserRequest extends FormRequest | |||
{ | |||
/** | |||
* Determine if the user is authorized to make this request. | |||
*/ | |||
public function authorize(): bool | |||
{ | |||
return true; | |||
} | |||
/** | |||
* Get the validation rules that apply to the request. | |||
* | |||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string> | |||
*/ | |||
public function rules(): array | |||
{ | |||
return [ | |||
'name' => 'required|string|max:250', | |||
'email' => 'required|string|email:rfc,dns|max:250|unique:users,email,'.$this->user->id, | |||
'password' => 'nullable|string|min:8|confirmed', | |||
'roles' => 'required' | |||
]; | |||
} | |||
} | |||
</pre> | |||
== Views für Role und User == | |||
<pre> | |||
php artisan make:view users.index | |||
php artisan make:view users.create | |||
php artisan make:view users.edit | |||
php artisan make:view users.show | |||
php artisan make:view roles.index | |||
php artisan make:view roles.create | |||
php artisan make:view roles.edit | |||
php artisan make:view roles.show | |||
</pre> | |||
=== resources/views/roles/index.blade.php === | |||
<pre> | |||
@extends('layouts.app') | |||
@section('content') | |||
<div class="card"> | |||
<div class="card-header">Manage Roles</div> | |||
<div class="card-body"> | |||
@can('create-role') | |||
<a href="{{ route('roles.create') }}" class="btn btn-success btn-sm my-2"><i class="bi bi-plus-circle"></i> Add New Role</a> | |||
@endcan | |||
<table class="table table-striped table-bordered"> | |||
<thead> | |||
<tr> | |||
<th scope="col">S#</th> | |||
<th scope="col">Name</th> | |||
<th scope="col" style="width: 250px;">Action</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
@forelse ($roles as $role) | |||
<tr> | |||
<th scope="row">{{ $loop->iteration }}</th> | |||
<td>{{ $role->name }}</td> | |||
<td> | |||
<form action="{{ route('roles.destroy', $role->id) }}" method="post"> | |||
@csrf | |||
@method('DELETE') | |||
<a href="{{ route('roles.show', $role->id) }}" class="btn btn-warning btn-sm"><i class="bi bi-eye"></i> Show</a> | |||
@if ($role->name!='Super Admin') | |||
@can('edit-role') | |||
<a href="{{ route('roles.edit', $role->id) }}" class="btn btn-primary btn-sm"><i class="bi bi-pencil-square"></i> Edit</a> | |||
@endcan | |||
@can('delete-role') | |||
@if ($role->name!=Auth::user()->hasRole($role->name)) | |||
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Do you want to delete this role?');"><i class="bi bi-trash"></i> Delete</button> | |||
@endif | |||
@endcan | |||
@endif | |||
</form> | |||
</td> | |||
</tr> | |||
@empty | |||
<td colspan="3"> | |||
<span class="text-danger"> | |||
<strong>No Role Found!</strong> | |||
</span> | |||
</td> | |||
@endforelse | |||
</tbody> | |||
</table> | |||
{{ $roles->links() }} | |||
</div> | |||
</div> | |||
@endsection | |||
</pre> | |||
=== resources/views/roles/create.blade.php === | |||
<pre> | |||
@extends('layouts.app') | |||
@section('content') | |||
<div class="row justify-content-center"> | |||
<div class="col-md-8"> | |||
<div class="card"> | |||
<div class="card-header"> | |||
<div class="float-start"> | |||
Add New Role | |||
</div> | |||
<div class="float-end"> | |||
<a href="{{ route('roles.index') }}" class="btn btn-primary btn-sm">← Back</a> | |||
</div> | |||
</div> | |||
<div class="card-body"> | |||
<form action="{{ route('roles.store') }}" method="post"> | |||
@csrf | |||
<div class="mb-3 row"> | |||
<label for="name" class="col-md-4 col-form-label text-md-end text-start">Name</label> | |||
<div class="col-md-6"> | |||
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" name="name" value="{{ old('name') }}"> | |||
@if ($errors->has('name')) | |||
<span class="text-danger">{{ $errors->first('name') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="permissions" class="col-md-4 col-form-label text-md-end text-start">Permissions</label> | |||
<div class="col-md-6"> | |||
<select class="form-select @error('permissions') is-invalid @enderror" multiple aria-label="Permissions" id="permissions" name="permissions[]" style="height: 210px;"> | |||
@forelse ($permissions as $permission) | |||
<option value="{{ $permission->id }}" {{ in_array($permission->id, old('permissions') ?? []) ? 'selected' : '' }}> | |||
{{ $permission->name }} | |||
</option> | |||
@empty | |||
@endforelse | |||
</select> | |||
@if ($errors->has('permissions')) | |||
<span class="text-danger">{{ $errors->first('permissions') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<input type="submit" class="col-md-3 offset-md-5 btn btn-primary" value="Add Role"> | |||
</div> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@endsection | |||
</pre> | |||
=== resources/views/roles/edit.blade.php === | |||
<pre> | |||
@extends('layouts.app') | |||
@section('content') | |||
<div class="row justify-content-center"> | |||
<div class="col-md-8"> | |||
<div class="card"> | |||
<div class="card-header"> | |||
<div class="float-start"> | |||
Edit Role | |||
</div> | |||
<div class="float-end"> | |||
<a href="{{ route('roles.index') }}" class="btn btn-primary btn-sm">← Back</a> | |||
</div> | |||
</div> | |||
<div class="card-body"> | |||
<form action="{{ route('roles.update', $role->id) }}" method="post"> | |||
@csrf | |||
@method("PUT") | |||
<div class="mb-3 row"> | |||
<label for="name" class="col-md-4 col-form-label text-md-end text-start">Name</label> | |||
<div class="col-md-6"> | |||
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" name="name" value="{{ $role->name }}"> | |||
@if ($errors->has('name')) | |||
<span class="text-danger">{{ $errors->first('name') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="permissions" class="col-md-4 col-form-label text-md-end text-start">Permissions</label> | |||
<div class="col-md-6"> | |||
<select class="form-select @error('permissions') is-invalid @enderror" multiple aria-label="Permissions" id="permissions" name="permissions[]" style="height: 210px;"> | |||
@forelse ($permissions as $permission) | |||
<option value="{{ $permission->id }}" {{ in_array($permission->id, $rolePermissions ?? []) ? 'selected' : '' }}> | |||
{{ $permission->name }} | |||
</option> | |||
@empty | |||
@endforelse | |||
</select> | |||
@if ($errors->has('permissions')) | |||
<span class="text-danger">{{ $errors->first('permissions') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<input type="submit" class="col-md-3 offset-md-5 btn btn-primary" value="Update Role"> | |||
</div> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@endsection | |||
</pre> | |||
=== resources/views/roles/show.blade.php === | |||
<pre> | |||
@extends('layouts.app') | |||
@section('content') | |||
<div class="row justify-content-center"> | |||
<div class="col-md-8"> | |||
<div class="card"> | |||
<div class="card-header"> | |||
<div class="float-start"> | |||
Role Information | |||
</div> | |||
<div class="float-end"> | |||
<a href="{{ route('roles.index') }}" class="btn btn-primary btn-sm">← Back</a> | |||
</div> | |||
</div> | |||
<div class="card-body"> | |||
<div class="mb-3 row"> | |||
<label for="name" class="col-md-4 col-form-label text-md-end text-start"><strong>Name:</strong></label> | |||
<div class="col-md-6" style="line-height: 35px;"> | |||
{{ $role->name }} | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="roles" class="col-md-4 col-form-label text-md-end text-start"><strong>Permissions:</strong></label> | |||
<div class="col-md-6" style="line-height: 35px;"> | |||
@if ($role->name=='Super Admin') | |||
<span class="badge bg-primary">All</span> | |||
@else | |||
@forelse ($rolePermissions as $permission) | |||
<span class="badge bg-primary">{{ $permission->name }}</span> | |||
@empty | |||
@endforelse | |||
@endif | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@endsection | |||
</pre> | |||
=== resources/views/users/index.blade.php === | |||
<pre> | |||
@extends('layouts.app') | |||
@section('content') | |||
<div class="card"> | |||
<div class="card-header">Manage Users</div> | |||
<div class="card-body"> | |||
@can('create-user') | |||
<a href="{{ route('users.create') }}" class="btn btn-success btn-sm my-2"><i class="bi bi-plus-circle"></i> Add New User</a> | |||
@endcan | |||
<table class="table table-striped table-bordered"> | |||
<thead> | |||
<tr> | |||
<th scope="col">S#</th> | |||
<th scope="col">Name</th> | |||
<th scope="col">Email</th> | |||
<th scope="col">Roles</th> | |||
<th scope="col">Action</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
@forelse ($users as $user) | |||
<tr> | |||
<th scope="row">{{ $loop->iteration }}</th> | |||
<td>{{ $user->name }}</td> | |||
<td>{{ $user->email }}</td> | |||
<td> | |||
@forelse ($user->getRoleNames() as $role) | |||
<span class="badge bg-primary">{{ $role }}</span> | |||
@empty | |||
@endforelse | |||
</td> | |||
<td> | |||
<form action="{{ route('users.destroy', $user->id) }}" method="post"> | |||
@csrf | |||
@method('DELETE') | |||
<a href="{{ route('users.show', $user->id) }}" class="btn btn-warning btn-sm"><i class="bi bi-eye"></i> Show</a> | |||
@if (in_array('Super Admin', $user->getRoleNames()->toArray() ?? []) ) | |||
@if (Auth::user()->hasRole('Super Admin')) | |||
<a href="{{ route('users.edit', $user->id) }}" class="btn btn-primary btn-sm"><i class="bi bi-pencil-square"></i> Edit</a> | |||
@endif | |||
@else | |||
@can('edit-user') | |||
<a href="{{ route('users.edit', $user->id) }}" class="btn btn-primary btn-sm"><i class="bi bi-pencil-square"></i> Edit</a> | |||
@endcan | |||
@can('delete-user') | |||
@if (Auth::user()->id!=$user->id) | |||
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Do you want to delete this user?');"><i class="bi bi-trash"></i> Delete</button> | |||
@endif | |||
@endcan | |||
@endif | |||
</form> | |||
</td> | |||
</tr> | |||
@empty | |||
<td colspan="5"> | |||
<span class="text-danger"> | |||
<strong>No User Found!</strong> | |||
</span> | |||
</td> | |||
@endforelse | |||
</tbody> | |||
</table> | |||
{{ $users->links() }} | |||
</div> | |||
</div> | |||
@endsection | |||
</pre> | |||
=== resources/views/users/create.blade.php === | |||
<pre> | |||
@extends('layouts.app') | |||
@section('content') | |||
<div class="row justify-content-center"> | |||
<div class="col-md-8"> | |||
<div class="card"> | |||
<div class="card-header"> | |||
<div class="float-start"> | |||
Add New User | |||
</div> | |||
<div class="float-end"> | |||
<a href="{{ route('users.index') }}" class="btn btn-primary btn-sm">← Back</a> | |||
</div> | |||
</div> | |||
<div class="card-body"> | |||
<form action="{{ route('users.store') }}" method="post"> | |||
@csrf | |||
<div class="mb-3 row"> | |||
<label for="name" class="col-md-4 col-form-label text-md-end text-start">Name</label> | |||
<div class="col-md-6"> | |||
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" name="name" value="{{ old('name') }}"> | |||
@if ($errors->has('name')) | |||
<span class="text-danger">{{ $errors->first('name') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="email" class="col-md-4 col-form-label text-md-end text-start">Email Address</label> | |||
<div class="col-md-6"> | |||
<input type="email" class="form-control @error('email') is-invalid @enderror" id="email" name="email" value="{{ old('email') }}"> | |||
@if ($errors->has('email')) | |||
<span class="text-danger">{{ $errors->first('email') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="password" class="col-md-4 col-form-label text-md-end text-start">Password</label> | |||
<div class="col-md-6"> | |||
<input type="password" class="form-control @error('password') is-invalid @enderror" id="password" name="password"> | |||
@if ($errors->has('password')) | |||
<span class="text-danger">{{ $errors->first('password') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="password_confirmation" class="col-md-4 col-form-label text-md-end text-start">Confirm Password</label> | |||
<div class="col-md-6"> | |||
<input type="password" class="form-control" id="password_confirmation" name="password_confirmation"> | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="roles" class="col-md-4 col-form-label text-md-end text-start">Roles</label> | |||
<div class="col-md-6"> | |||
<select class="form-select @error('roles') is-invalid @enderror" multiple aria-label="Roles" id="roles" name="roles[]"> | |||
@forelse ($roles as $role) | |||
@if ($role!='Super Admin') | |||
<option value="{{ $role }}" {{ in_array($role, old('roles') ?? []) ? 'selected' : '' }}> | |||
{{ $role }} | |||
</option> | |||
@else | |||
@if (Auth::user()->hasRole('Super Admin')) | |||
<option value="{{ $role }}" {{ in_array($role, old('roles') ?? []) ? 'selected' : '' }}> | |||
{{ $role }} | |||
</option> | |||
@endif | |||
@endif | |||
@empty | |||
@endforelse | |||
</select> | |||
@if ($errors->has('roles')) | |||
<span class="text-danger">{{ $errors->first('roles') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<input type="submit" class="col-md-3 offset-md-5 btn btn-primary" value="Add User"> | |||
</div> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@endsection | |||
</pre> | |||
=== resources/views/users/edit.blade.php === | |||
<pre> | |||
@extends('layouts.app') | |||
@section('content') | |||
<div class="row justify-content-center"> | |||
<div class="col-md-8"> | |||
<div class="card"> | |||
<div class="card-header"> | |||
<div class="float-start"> | |||
Edit User | |||
</div> | |||
<div class="float-end"> | |||
<a href="{{ route('users.index') }}" class="btn btn-primary btn-sm">← Back</a> | |||
</div> | |||
</div> | |||
<div class="card-body"> | |||
<form action="{{ route('users.update', $user->id) }}" method="post"> | |||
@csrf | |||
@method("PUT") | |||
<div class="mb-3 row"> | |||
<label for="name" class="col-md-4 col-form-label text-md-end text-start">Name</label> | |||
<div class="col-md-6"> | |||
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" name="name" value="{{ $user->name }}"> | |||
@if ($errors->has('name')) | |||
<span class="text-danger">{{ $errors->first('name') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="email" class="col-md-4 col-form-label text-md-end text-start">Email Address</label> | |||
<div class="col-md-6"> | |||
<input type="email" class="form-control @error('email') is-invalid @enderror" id="email" name="email" value="{{ $user->email }}"> | |||
@if ($errors->has('email')) | |||
<span class="text-danger">{{ $errors->first('email') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="password" class="col-md-4 col-form-label text-md-end text-start">Password</label> | |||
<div class="col-md-6"> | |||
<input type="password" class="form-control @error('password') is-invalid @enderror" id="password" name="password"> | |||
@if ($errors->has('password')) | |||
<span class="text-danger">{{ $errors->first('password') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="password_confirmation" class="col-md-4 col-form-label text-md-end text-start">Confirm Password</label> | |||
<div class="col-md-6"> | |||
<input type="password" class="form-control" id="password_confirmation" name="password_confirmation"> | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="roles" class="col-md-4 col-form-label text-md-end text-start">Roles</label> | |||
<div class="col-md-6"> | |||
<select class="form-select @error('roles') is-invalid @enderror" multiple aria-label="Roles" id="roles" name="roles[]"> | |||
@forelse ($roles as $role) | |||
@if ($role!='Super Admin') | |||
<option value="{{ $role }}" {{ in_array($role, $userRoles ?? []) ? 'selected' : '' }}> | |||
{{ $role }} | |||
</option> | |||
@else | |||
@if (Auth::user()->hasRole('Super Admin')) | |||
<option value="{{ $role }}" {{ in_array($role, $userRoles ?? []) ? 'selected' : '' }}> | |||
{{ $role }} | |||
</option> | |||
@endif | |||
@endif | |||
@empty | |||
@endforelse | |||
</select> | |||
@if ($errors->has('roles')) | |||
<span class="text-danger">{{ $errors->first('roles') }}</span> | |||
@endif | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<input type="submit" class="col-md-3 offset-md-5 btn btn-primary" value="Update User"> | |||
</div> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@endsection | |||
</pre> | |||
=== resources/views/users/show.blade.php === | |||
<pre> | |||
@extends('layouts.app') | |||
@section('content') | |||
<div class="row justify-content-center"> | |||
<div class="col-md-8"> | |||
<div class="card"> | |||
<div class="card-header"> | |||
<div class="float-start"> | |||
User Information | |||
</div> | |||
<div class="float-end"> | |||
<a href="{{ route('users.index') }}" class="btn btn-primary btn-sm">← Back</a> | |||
</div> | |||
</div> | |||
<div class="card-body"> | |||
<div class="mb-3 row"> | |||
<label for="name" class="col-md-4 col-form-label text-md-end text-start"><strong>Name:</strong></label> | |||
<div class="col-md-6" style="line-height: 35px;"> | |||
{{ $user->name }} | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="email" class="col-md-4 col-form-label text-md-end text-start"><strong>Email Address:</strong></label> | |||
<div class="col-md-6" style="line-height: 35px;"> | |||
{{ $user->email }} | |||
</div> | |||
</div> | |||
<div class="mb-3 row"> | |||
<label for="roles" class="col-md-4 col-form-label text-md-end text-start"><strong>Roles:</strong></label> | |||
<div class="col-md-6" style="line-height: 35px;"> | |||
@forelse ($user->getRoleNames() as $role) | |||
<span class="badge bg-primary">{{ $role }}</span> | |||
@empty | |||
@endforelse | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@endsection | |||
</pre> | |||
== resources/views/layhouts/app.blade.php == | |||
<pre> | |||
<!doctype html> | |||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> | |||
<head> | |||
<meta charset="utf-8"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1"> | |||
<!-- CSRF Token --> | |||
<meta name="csrf-token" content="{{ csrf_token() }}"> | |||
<title>Simple Laravel 10 User Roles and Permissions - AllPHPTricks.com</title> | |||
<!-- Fonts --> | |||
<link rel="dns-prefetch" href="//fonts.bunny.net"> | |||
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet"> | |||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css"> | |||
<!-- Scripts --> | |||
@vite(['resources/sass/app.scss', 'resources/js/app.js']) | |||
</head> | |||
<body> | |||
<div id="app"> | |||
<nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm"> | |||
<div class="container"> | |||
<a class="navbar-brand" href="{{ url('/') }}"> | |||
AllPHPTricks.com | |||
</a> | |||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}"> | |||
<span class="navbar-toggler-icon"></span> | |||
</button> | |||
<div class="collapse navbar-collapse" id="navbarSupportedContent"> | |||
<!-- Left Side Of Navbar --> | |||
<ul class="navbar-nav me-auto"> | |||
</ul> | |||
<!-- Right Side Of Navbar --> | |||
<ul class="navbar-nav ms-auto"> | |||
<!-- Authentication Links --> | |||
@guest | |||
@if (Route::has('login')) | |||
<li class="nav-item"> | |||
<a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a> | |||
</li> | |||
@endif | |||
@if (Route::has('register')) | |||
<li class="nav-item"> | |||
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a> | |||
</li> | |||
@endif | |||
@else | |||
@canany(['create-role', 'edit-role', 'delete-role']) | |||
<li><a class="nav-link" href="{{ route('roles.index') }}">Manage Roles</a></li> | |||
@endcanany | |||
@canany(['create-user', 'edit-user', 'delete-user']) | |||
<li><a class="nav-link" href="{{ route('users.index') }}">Manage Users</a></li> | |||
@endcanany | |||
@canany(['create-product', 'edit-product', 'delete-product']) | |||
<li><a class="nav-link" href="{{ route('products.index') }}">Manage Products</a></li> | |||
@endcanany | |||
<li class="nav-item dropdown"> | |||
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> | |||
{{ Auth::user()->name }} | |||
</a> | |||
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown"> | |||
<a class="dropdown-item" href="{{ route('logout') }}" | |||
onclick="event.preventDefault(); | |||
document.getElementById('logout-form').submit();"> | |||
{{ __('Logout') }} | |||
</a> | |||
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none"> | |||
@csrf | |||
</form> | |||
</div> | |||
</li> | |||
@endguest | |||
</ul> | |||
</div> | |||
</div> | |||
</nav> | |||
<main class="py-4"> | |||
<div class="container"> | |||
<div class="row justify-content-center mt-3"> | |||
<div class="col-md-12"> | |||
@if ($message = Session::get('success')) | |||
<div class="alert alert-success text-center" role="alert"> | |||
{{ $message }} | |||
</div> | |||
@endif | |||
<h3 class="text-center mt-3 mb-3">Simple Laravel 10 User Roles and Permissions - <a href="https://www.allphptricks.com/">AllPHPTricks.com</a></h3> | |||
@yield('content') | |||
<div class="row justify-content-center text-center mt-3"> | |||
<div class="col-md-12"> | |||
<p>Back to Tutorial: | |||
<a href="https://www.allphptricks.com/simple-laravel-10-user-roles-and-permissions/"><strong>Tutorial Link</strong></a> | |||
</p> | |||
<p> | |||
For More Web Development Tutorials Visit: <a href="https://www.allphptricks.com/"><strong>AllPHPTricks.com</strong></a> | |||
</p> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</main> | |||
</div> | |||
</body> | |||
</html> | |||
</pre> | |||
== resources/views/home.blade.php == | |||
<pre> | |||
@extends('layouts.app') | |||
@section('content') | |||
<div class="container"> | |||
<div class="row justify-content-center"> | |||
<div class="col-md-12"> | |||
<div class="card"> | |||
<div class="card-header">{{ __('Dashboard') }}</div> | |||
<div class="card-body"> | |||
@if (session('status')) | |||
<div class="alert alert-success" role="alert"> | |||
{{ session('status') }} | |||
</div> | |||
@endif | |||
{{ __('You are logged in!') }} | |||
<p>This is your application dashboard.</p> | |||
@canany(['create-role', 'edit-role', 'delete-role']) | |||
<a class="btn btn-primary" href="{{ route('roles.index') }}"> | |||
<i class="bi bi-person-fill-gear"></i> Manage Roles</a> | |||
@endcanany | |||
@canany(['create-user', 'edit-user', 'delete-user']) | |||
<a class="btn btn-success" href="{{ route('users.index') }}"> | |||
<i class="bi bi-people"></i> Manage Users</a> | |||
@endcanany | |||
@canany(['create-product', 'edit-product', 'delete-product']) | |||
<a class="btn btn-warning" href="{{ route('products.index') }}"> | |||
<i class="bi bi-bag"></i> Manage Products</a> | |||
@endcanany | |||
<p> </p> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@endsection | |||
</pre> | </pre> | ||
Aktuelle Version vom 24. Oktober 2023, 15:08 Uhr
Links
Zielsetzung
Es soll ein Rollen-/Rechtesystem mittels des Paketes spatie/laravel-permission eingerichtet werden.
Vorgehen
composer require spatie/laravel-permission
app/Http/Kernel.php
protected $middlewareAliases = [
....
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];
app\Models\User.php
... use HasApiTokens, HasFactory, Notifiable, HasRoles; ...
php artisan make:seeder PermissionSeeder php artisan make:seeder RoleSeeder php artisan make:seeder SuperAdminSeeder
- database\seeders\PermissionSeeder.php
use Spatie\Permission\Models\Permission;
...
public function run(): void
{
$permissions = [
'create-role',
'edit-role',
'delete-role',
'create-user',
'edit-user',
'delete-user',
'create-data',
'edit-data',
'delete-data'
];
// Looping and Inserting Array's Permissions into Permission Table
foreach ($permissions as $permission) {
Permission::create(['name' => $permission]);
}
}
database\seeders\RoleSeeder.php
use Spatie\Permission\Models\Role;
...
public function run(): void
{
Role::create(['name' => 'Super Admin']);
$admin = Role::create(['name' => 'Admin']);
$manager = Role::create(['name' => 'Manager']);
$student = Role::create(['name' => 'Student']);
$admin->givePermissionTo([
'create-user',
'edit-user',
'delete-user',
'create-product',
'edit-product',
'delete-product',
'create-data',
'edit-data',
'delete-data'
]);
$manager->givePermissionTo([
'create-data',
'edit-data',
'delete-data'
]);
$student->givePermissionTo([
'create-data',
'edit-data'
]);
}
database\seeders\SuperAdminSeeder.php
use App\Models\User;
use Illuminate\Support\Facades\Hash;
...
public function run(): void
{
// Creating Super Admin User
$superAdmin = User::create([
'name' => 'Langutor',
'email' => 'langutor@hamatoma.de',
'password' => Hash::make('topSecret')
]);
$superAdmin->assignRole('Super Admin');
// Creating Admin User
$admin = User::create([
'name' => 'administrator',
'email' => 'langutor@hamatoma.de',
'password' => Hash::make('topSecret')
]);
$admin->assignRole('Admin');
// Creating Product Manager User
$manager = User::create([
'name' => 'Alice',
'email' => 'alice@hamatoma.de',
'password' => Hash::make('topSecret')
]);
$manager->assignRole('Manager');
}
database\seeders\DatabaseSeeder.php
use Database\Seeders\RoleSeeder;
use Database\Seeders\PermissionSeeder;
use Database\Seeders\SuperAdminSeeder;
...
public function run(): void
{
// \App\Models\User::factory(10)->create();
// \App\Models\User::factory()->create([
// 'name' => 'Test User',
// 'email' => 'test@example.com',
// ]);
$this->call([
PermissionSeeder::class,
RoleSeeder::class,
SuperAdminSeeder::class,
]);
}
Terminal
php artisan migrate:fresh --seed
app\Providers\AuthServiceProvider.php
use Illuminate\Support\Facades\Gate;
...
public function boot(): void
{
Gate::before(function ($user, $ability) {
return $user->hasRole('Super Admin') ? true : null;
});
}
Enable Bootstrap 5
- app\Providers\AppServiceProvider.php
use Illuminate\Pagination\Paginator;
...
public function boot(): void
{
Paginator::useBootstrapFive();
}
routes/web.php
Route::resources([
'roles' => RoleController::class,
'users' => UserController::class,
]);
Controller für Role und Resources
php artisan make:controller RoleController --resource php artisan make:controller UserController --resource
- app/http/Controllers/RoleController:
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StoreRoleRequest;
use App\Http\Requests\UpdateRoleRequest;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use DB;
class RoleController extends Controller
{
public function __construct()
{
$this->middleware('auth');
$this->middleware('permission:create-role|edit-role|delete-role', ['only' => ['index', 'show']]);
$this->middleware('permission:create-role', ['only' => ['create', 'store']]);
$this->middleware('permission:edit-role', ['only' => ['edit', 'update']]);
$this->middleware('permission:delete-role', ['only' => ['destroy']]);
}
/**
* Display a listing of the resource.
*/
public function index(): View
{
return view('roles.index', [
'roles' => Role::orderBy('id', 'DESC')->paginate(3)
]);
}
/**
* Show the form for creating a new resource.
*/
public function create(): View
{
return view('roles.create', [
'permissions' => Permission::get()
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(StoreRoleRequest $request): RedirectResponse
{
$role = Role::create(['name' => $request->name]);
$role->syncPermissions($request->permissions);
return redirect()->route('roles.index')
->withSuccess('New role is added successfully.');
}
/**
* Display the specified resource.
*/
public function show(Role $role): View
{
$rolePermissions = Permission::join("role_has_permissions", "permission_id", "=", "id")
->where("role_id", $role->id)
->select('name')
->get();
return view('roles.show', [
'role' => $role,
'rolePermissions' => $rolePermissions
]);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Role $role): View
{
if ($role->name == 'Super Admin') {
abort(403, 'SUPER ADMIN ROLE CAN NOT BE EDITED');
}
$rolePermissions = DB::table("role_has_permissions")->where("role_id", $role->id)
->pluck('permission_id')
->all();
return view('roles.edit', [
'role' => $role,
'permissions' => Permission::get(),
'rolePermissions' => $rolePermissions
]);
}
/**
* Update the specified resource in storage.
*/
public function update(UpdateRoleRequest $request, Role $role): RedirectResponse
{
$input = $request->only('name');
$role->update($input);
$role->syncPermissions($request->permissions);
return redirect()->back()
->withSuccess('Role is updated successfully.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Role $role): RedirectResponse
{
if ($role->name == 'Super Admin') {
abort(403, 'SUPER ADMIN ROLE CAN NOT BE DELETED');
}
if (auth()->user()->hasRole($role->name)) {
abort(403, 'CAN NOT DELETE SELF ASSIGNED ROLE');
}
$role->delete();
return redirect()->route('roles.index')
->withSuccess('Role is deleted successfully.');
}
}
- App/http/Controllers/UserController
<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Http\Requests\StoreUserRequest;
use App\Http\Requests\UpdateUserRequest;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Spatie\Permission\Models\Role;
use Illuminate\Support\Facades\Hash;
class UserController extends Controller
{
/**
* Instantiate a new UserController instance.
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('permission:create-user|edit-user|delete-user', ['only' => ['index','show']]);
$this->middleware('permission:create-user', ['only' => ['create','store']]);
$this->middleware('permission:edit-user', ['only' => ['edit','update']]);
$this->middleware('permission:delete-user', ['only' => ['destroy']]);
}
/**
* Display a listing of the resource.
*/
public function index(): View
{
return view('users.index', [
'users' => User::latest('id')->paginate(3)
]);
}
/**
* Show the form for creating a new resource.
*/
public function create(): View
{
return view('users.create', [
'roles' => Role::pluck('name')->all()
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(StoreUserRequest $request): RedirectResponse
{
$input = $request->all();
$input['password'] = Hash::make($request->password);
$user = User::create($input);
$user->assignRole($request->roles);
return redirect()->route('users.index')
->withSuccess('New user is added successfully.');
}
/**
* Display the specified resource.
*/
public function show(User $user): View
{
return view('users.show', [
'user' => $user
]);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(User $user): View
{
// Check Only Super Admin can update his own Profile
if ($user->hasRole('Super Admin')){
if($user->id != auth()->user()->id){
abort(403, 'USER DOES NOT HAVE THE RIGHT PERMISSIONS');
}
}
return view('users.edit', [
'user' => $user,
'roles' => Role::pluck('name')->all(),
'userRoles' => $user->roles->pluck('name')->all()
]);
}
/**
* Update the specified resource in storage.
*/
public function update(UpdateUserRequest $request, User $user): RedirectResponse
{
$input = $request->all();
if(!empty($request->password)){
$input['password'] = Hash::make($request->password);
}else{
$input = $request->except('password');
}
$user->update($input);
$user->syncRoles($request->roles);
return redirect()->back()
->withSuccess('User is updated successfully.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(User $user): RedirectResponse
{
// About if user is Super Admin or User ID belongs to Auth User
if ($user->hasRole('Super Admin') || $user->id == auth()->user()->id)
{
abort(403, 'USER DOES NOT HAVE THE RIGHT PERMISSIONS');
}
$user->syncRoles([]);
$user->delete();
return redirect()->route('users.index')
->withSuccess('User is deleted successfully.');
}
}
Requests für User und Role
php artisan make:request StoreRoleRequest php artisan make:request UpdateRoleRequest php artisan make:request StoreUserRequest php artisan make:request UpdateUserRequest
app/Http/Requests/StoreRoleRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreRoleRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' => 'required|string|max:250|unique:roles,name',
'permissions' => 'required',
];
}
}
app/Http/Requests/UpdateRoleRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdateRoleRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' => 'required|string|max:250|unique:roles,name,'.$this->role->id,
'permissions' => 'required',
];
}
}
app/Http/Requests/StoreUserRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreUserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' => 'required|string|max:250',
'email' => 'required|string|email:rfc,dns|max:250|unique:users,email',
'password' => 'required|string|min:8|confirmed',
'roles' => 'required'
];
}
}
app/Http/Requests/UpdateUserRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdateUserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' => 'required|string|max:250',
'email' => 'required|string|email:rfc,dns|max:250|unique:users,email,'.$this->user->id,
'password' => 'nullable|string|min:8|confirmed',
'roles' => 'required'
];
}
}
Views für Role und User
php artisan make:view users.index php artisan make:view users.create php artisan make:view users.edit php artisan make:view users.show php artisan make:view roles.index php artisan make:view roles.create php artisan make:view roles.edit php artisan make:view roles.show
resources/views/roles/index.blade.php
@extends('layouts.app')
@section('content')
<div class="card">
<div class="card-header">Manage Roles</div>
<div class="card-body">
@can('create-role')
<a href="{{ route('roles.create') }}" class="btn btn-success btn-sm my-2"><i class="bi bi-plus-circle"></i> Add New Role</a>
@endcan
<table class="table table-striped table-bordered">
<thead>
<tr>
<th scope="col">S#</th>
<th scope="col">Name</th>
<th scope="col" style="width: 250px;">Action</th>
</tr>
</thead>
<tbody>
@forelse ($roles as $role)
<tr>
<th scope="row">{{ $loop->iteration }}</th>
<td>{{ $role->name }}</td>
<td>
<form action="{{ route('roles.destroy', $role->id) }}" method="post">
@csrf
@method('DELETE')
<a href="{{ route('roles.show', $role->id) }}" class="btn btn-warning btn-sm"><i class="bi bi-eye"></i> Show</a>
@if ($role->name!='Super Admin')
@can('edit-role')
<a href="{{ route('roles.edit', $role->id) }}" class="btn btn-primary btn-sm"><i class="bi bi-pencil-square"></i> Edit</a>
@endcan
@can('delete-role')
@if ($role->name!=Auth::user()->hasRole($role->name))
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Do you want to delete this role?');"><i class="bi bi-trash"></i> Delete</button>
@endif
@endcan
@endif
</form>
</td>
</tr>
@empty
<td colspan="3">
<span class="text-danger">
<strong>No Role Found!</strong>
</span>
</td>
@endforelse
</tbody>
</table>
{{ $roles->links() }}
</div>
</div>
@endsection
resources/views/roles/create.blade.php
@extends('layouts.app')
@section('content')
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<div class="float-start">
Add New Role
</div>
<div class="float-end">
<a href="{{ route('roles.index') }}" class="btn btn-primary btn-sm">← Back</a>
</div>
</div>
<div class="card-body">
<form action="{{ route('roles.store') }}" method="post">
@csrf
<div class="mb-3 row">
<label for="name" class="col-md-4 col-form-label text-md-end text-start">Name</label>
<div class="col-md-6">
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" name="name" value="{{ old('name') }}">
@if ($errors->has('name'))
<span class="text-danger">{{ $errors->first('name') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<label for="permissions" class="col-md-4 col-form-label text-md-end text-start">Permissions</label>
<div class="col-md-6">
<select class="form-select @error('permissions') is-invalid @enderror" multiple aria-label="Permissions" id="permissions" name="permissions[]" style="height: 210px;">
@forelse ($permissions as $permission)
<option value="{{ $permission->id }}" {{ in_array($permission->id, old('permissions') ?? []) ? 'selected' : '' }}>
{{ $permission->name }}
</option>
@empty
@endforelse
</select>
@if ($errors->has('permissions'))
<span class="text-danger">{{ $errors->first('permissions') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<input type="submit" class="col-md-3 offset-md-5 btn btn-primary" value="Add Role">
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
resources/views/roles/edit.blade.php
@extends('layouts.app')
@section('content')
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<div class="float-start">
Edit Role
</div>
<div class="float-end">
<a href="{{ route('roles.index') }}" class="btn btn-primary btn-sm">← Back</a>
</div>
</div>
<div class="card-body">
<form action="{{ route('roles.update', $role->id) }}" method="post">
@csrf
@method("PUT")
<div class="mb-3 row">
<label for="name" class="col-md-4 col-form-label text-md-end text-start">Name</label>
<div class="col-md-6">
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" name="name" value="{{ $role->name }}">
@if ($errors->has('name'))
<span class="text-danger">{{ $errors->first('name') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<label for="permissions" class="col-md-4 col-form-label text-md-end text-start">Permissions</label>
<div class="col-md-6">
<select class="form-select @error('permissions') is-invalid @enderror" multiple aria-label="Permissions" id="permissions" name="permissions[]" style="height: 210px;">
@forelse ($permissions as $permission)
<option value="{{ $permission->id }}" {{ in_array($permission->id, $rolePermissions ?? []) ? 'selected' : '' }}>
{{ $permission->name }}
</option>
@empty
@endforelse
</select>
@if ($errors->has('permissions'))
<span class="text-danger">{{ $errors->first('permissions') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<input type="submit" class="col-md-3 offset-md-5 btn btn-primary" value="Update Role">
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
resources/views/roles/show.blade.php
@extends('layouts.app')
@section('content')
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<div class="float-start">
Role Information
</div>
<div class="float-end">
<a href="{{ route('roles.index') }}" class="btn btn-primary btn-sm">← Back</a>
</div>
</div>
<div class="card-body">
<div class="mb-3 row">
<label for="name" class="col-md-4 col-form-label text-md-end text-start"><strong>Name:</strong></label>
<div class="col-md-6" style="line-height: 35px;">
{{ $role->name }}
</div>
</div>
<div class="mb-3 row">
<label for="roles" class="col-md-4 col-form-label text-md-end text-start"><strong>Permissions:</strong></label>
<div class="col-md-6" style="line-height: 35px;">
@if ($role->name=='Super Admin')
<span class="badge bg-primary">All</span>
@else
@forelse ($rolePermissions as $permission)
<span class="badge bg-primary">{{ $permission->name }}</span>
@empty
@endforelse
@endif
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
resources/views/users/index.blade.php
@extends('layouts.app')
@section('content')
<div class="card">
<div class="card-header">Manage Users</div>
<div class="card-body">
@can('create-user')
<a href="{{ route('users.create') }}" class="btn btn-success btn-sm my-2"><i class="bi bi-plus-circle"></i> Add New User</a>
@endcan
<table class="table table-striped table-bordered">
<thead>
<tr>
<th scope="col">S#</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Roles</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
@forelse ($users as $user)
<tr>
<th scope="row">{{ $loop->iteration }}</th>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>
@forelse ($user->getRoleNames() as $role)
<span class="badge bg-primary">{{ $role }}</span>
@empty
@endforelse
</td>
<td>
<form action="{{ route('users.destroy', $user->id) }}" method="post">
@csrf
@method('DELETE')
<a href="{{ route('users.show', $user->id) }}" class="btn btn-warning btn-sm"><i class="bi bi-eye"></i> Show</a>
@if (in_array('Super Admin', $user->getRoleNames()->toArray() ?? []) )
@if (Auth::user()->hasRole('Super Admin'))
<a href="{{ route('users.edit', $user->id) }}" class="btn btn-primary btn-sm"><i class="bi bi-pencil-square"></i> Edit</a>
@endif
@else
@can('edit-user')
<a href="{{ route('users.edit', $user->id) }}" class="btn btn-primary btn-sm"><i class="bi bi-pencil-square"></i> Edit</a>
@endcan
@can('delete-user')
@if (Auth::user()->id!=$user->id)
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Do you want to delete this user?');"><i class="bi bi-trash"></i> Delete</button>
@endif
@endcan
@endif
</form>
</td>
</tr>
@empty
<td colspan="5">
<span class="text-danger">
<strong>No User Found!</strong>
</span>
</td>
@endforelse
</tbody>
</table>
{{ $users->links() }}
</div>
</div>
@endsection
resources/views/users/create.blade.php
@extends('layouts.app')
@section('content')
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<div class="float-start">
Add New User
</div>
<div class="float-end">
<a href="{{ route('users.index') }}" class="btn btn-primary btn-sm">← Back</a>
</div>
</div>
<div class="card-body">
<form action="{{ route('users.store') }}" method="post">
@csrf
<div class="mb-3 row">
<label for="name" class="col-md-4 col-form-label text-md-end text-start">Name</label>
<div class="col-md-6">
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" name="name" value="{{ old('name') }}">
@if ($errors->has('name'))
<span class="text-danger">{{ $errors->first('name') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<label for="email" class="col-md-4 col-form-label text-md-end text-start">Email Address</label>
<div class="col-md-6">
<input type="email" class="form-control @error('email') is-invalid @enderror" id="email" name="email" value="{{ old('email') }}">
@if ($errors->has('email'))
<span class="text-danger">{{ $errors->first('email') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<label for="password" class="col-md-4 col-form-label text-md-end text-start">Password</label>
<div class="col-md-6">
<input type="password" class="form-control @error('password') is-invalid @enderror" id="password" name="password">
@if ($errors->has('password'))
<span class="text-danger">{{ $errors->first('password') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<label for="password_confirmation" class="col-md-4 col-form-label text-md-end text-start">Confirm Password</label>
<div class="col-md-6">
<input type="password" class="form-control" id="password_confirmation" name="password_confirmation">
</div>
</div>
<div class="mb-3 row">
<label for="roles" class="col-md-4 col-form-label text-md-end text-start">Roles</label>
<div class="col-md-6">
<select class="form-select @error('roles') is-invalid @enderror" multiple aria-label="Roles" id="roles" name="roles[]">
@forelse ($roles as $role)
@if ($role!='Super Admin')
<option value="{{ $role }}" {{ in_array($role, old('roles') ?? []) ? 'selected' : '' }}>
{{ $role }}
</option>
@else
@if (Auth::user()->hasRole('Super Admin'))
<option value="{{ $role }}" {{ in_array($role, old('roles') ?? []) ? 'selected' : '' }}>
{{ $role }}
</option>
@endif
@endif
@empty
@endforelse
</select>
@if ($errors->has('roles'))
<span class="text-danger">{{ $errors->first('roles') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<input type="submit" class="col-md-3 offset-md-5 btn btn-primary" value="Add User">
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
resources/views/users/edit.blade.php
@extends('layouts.app')
@section('content')
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<div class="float-start">
Edit User
</div>
<div class="float-end">
<a href="{{ route('users.index') }}" class="btn btn-primary btn-sm">← Back</a>
</div>
</div>
<div class="card-body">
<form action="{{ route('users.update', $user->id) }}" method="post">
@csrf
@method("PUT")
<div class="mb-3 row">
<label for="name" class="col-md-4 col-form-label text-md-end text-start">Name</label>
<div class="col-md-6">
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" name="name" value="{{ $user->name }}">
@if ($errors->has('name'))
<span class="text-danger">{{ $errors->first('name') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<label for="email" class="col-md-4 col-form-label text-md-end text-start">Email Address</label>
<div class="col-md-6">
<input type="email" class="form-control @error('email') is-invalid @enderror" id="email" name="email" value="{{ $user->email }}">
@if ($errors->has('email'))
<span class="text-danger">{{ $errors->first('email') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<label for="password" class="col-md-4 col-form-label text-md-end text-start">Password</label>
<div class="col-md-6">
<input type="password" class="form-control @error('password') is-invalid @enderror" id="password" name="password">
@if ($errors->has('password'))
<span class="text-danger">{{ $errors->first('password') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<label for="password_confirmation" class="col-md-4 col-form-label text-md-end text-start">Confirm Password</label>
<div class="col-md-6">
<input type="password" class="form-control" id="password_confirmation" name="password_confirmation">
</div>
</div>
<div class="mb-3 row">
<label for="roles" class="col-md-4 col-form-label text-md-end text-start">Roles</label>
<div class="col-md-6">
<select class="form-select @error('roles') is-invalid @enderror" multiple aria-label="Roles" id="roles" name="roles[]">
@forelse ($roles as $role)
@if ($role!='Super Admin')
<option value="{{ $role }}" {{ in_array($role, $userRoles ?? []) ? 'selected' : '' }}>
{{ $role }}
</option>
@else
@if (Auth::user()->hasRole('Super Admin'))
<option value="{{ $role }}" {{ in_array($role, $userRoles ?? []) ? 'selected' : '' }}>
{{ $role }}
</option>
@endif
@endif
@empty
@endforelse
</select>
@if ($errors->has('roles'))
<span class="text-danger">{{ $errors->first('roles') }}</span>
@endif
</div>
</div>
<div class="mb-3 row">
<input type="submit" class="col-md-3 offset-md-5 btn btn-primary" value="Update User">
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
resources/views/users/show.blade.php
@extends('layouts.app')
@section('content')
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<div class="float-start">
User Information
</div>
<div class="float-end">
<a href="{{ route('users.index') }}" class="btn btn-primary btn-sm">← Back</a>
</div>
</div>
<div class="card-body">
<div class="mb-3 row">
<label for="name" class="col-md-4 col-form-label text-md-end text-start"><strong>Name:</strong></label>
<div class="col-md-6" style="line-height: 35px;">
{{ $user->name }}
</div>
</div>
<div class="mb-3 row">
<label for="email" class="col-md-4 col-form-label text-md-end text-start"><strong>Email Address:</strong></label>
<div class="col-md-6" style="line-height: 35px;">
{{ $user->email }}
</div>
</div>
<div class="mb-3 row">
<label for="roles" class="col-md-4 col-form-label text-md-end text-start"><strong>Roles:</strong></label>
<div class="col-md-6" style="line-height: 35px;">
@forelse ($user->getRoleNames() as $role)
<span class="badge bg-primary">{{ $role }}</span>
@empty
@endforelse
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
resources/views/layhouts/app.blade.php
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Simple Laravel 10 User Roles and Permissions - AllPHPTricks.com</title>
<!-- Fonts -->
<link rel="dns-prefetch" href="//fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
<!-- Scripts -->
@vite(['resources/sass/app.scss', 'resources/js/app.js'])
</head>
<body>
<div id="app">
<nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
<div class="container">
<a class="navbar-brand" href="{{ url('/') }}">
AllPHPTricks.com
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<!-- Left Side Of Navbar -->
<ul class="navbar-nav me-auto">
</ul>
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ms-auto">
<!-- Authentication Links -->
@guest
@if (Route::has('login'))
<li class="nav-item">
<a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
</li>
@endif
@if (Route::has('register'))
<li class="nav-item">
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
</li>
@endif
@else
@canany(['create-role', 'edit-role', 'delete-role'])
<li><a class="nav-link" href="{{ route('roles.index') }}">Manage Roles</a></li>
@endcanany
@canany(['create-user', 'edit-user', 'delete-user'])
<li><a class="nav-link" href="{{ route('users.index') }}">Manage Users</a></li>
@endcanany
@canany(['create-product', 'edit-product', 'delete-product'])
<li><a class="nav-link" href="{{ route('products.index') }}">Manage Products</a></li>
@endcanany
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
{{ Auth::user()->name }}
</a>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Logout') }}
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
@csrf
</form>
</div>
</li>
@endguest
</ul>
</div>
</div>
</nav>
<main class="py-4">
<div class="container">
<div class="row justify-content-center mt-3">
<div class="col-md-12">
@if ($message = Session::get('success'))
<div class="alert alert-success text-center" role="alert">
{{ $message }}
</div>
@endif
<h3 class="text-center mt-3 mb-3">Simple Laravel 10 User Roles and Permissions - <a href="https://www.allphptricks.com/">AllPHPTricks.com</a></h3>
@yield('content')
<div class="row justify-content-center text-center mt-3">
<div class="col-md-12">
<p>Back to Tutorial:
<a href="https://www.allphptricks.com/simple-laravel-10-user-roles-and-permissions/"><strong>Tutorial Link</strong></a>
</p>
<p>
For More Web Development Tutorials Visit: <a href="https://www.allphptricks.com/"><strong>AllPHPTricks.com</strong></a>
</p>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</body>
</html>
resources/views/home.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-12">
<div class="card">
<div class="card-header">{{ __('Dashboard') }}</div>
<div class="card-body">
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
{{ __('You are logged in!') }}
<p>This is your application dashboard.</p>
@canany(['create-role', 'edit-role', 'delete-role'])
<a class="btn btn-primary" href="{{ route('roles.index') }}">
<i class="bi bi-person-fill-gear"></i> Manage Roles</a>
@endcanany
@canany(['create-user', 'edit-user', 'delete-user'])
<a class="btn btn-success" href="{{ route('users.index') }}">
<i class="bi bi-people"></i> Manage Users</a>
@endcanany
@canany(['create-product', 'edit-product', 'delete-product'])
<a class="btn btn-warning" href="{{ route('products.index') }}">
<i class="bi bi-bag"></i> Manage Products</a>
@endcanany
<p> </p>
</div>
</div>
</div>
</div>
</div>
@endsection